diff --git a/server/src/internal/customers/attach/attachUtils/attachParams/attachParamsUtils/getCusAndProducts.ts b/server/src/internal/customers/attach/attachUtils/attachParams/attachParamsUtils/getCusAndProducts.ts index a76c257c7..27549bade 100644 --- a/server/src/internal/customers/attach/attachUtils/attachParams/attachParamsUtils/getCusAndProducts.ts +++ b/server/src/internal/customers/attach/attachUtils/attachParams/attachParamsUtils/getCusAndProducts.ts @@ -37,6 +37,14 @@ const getProductsForAttach = async ({ version, }); + const archivedProducts = products.filter((prod) => prod.archived); + if (archivedProducts.length > 0) { + throw new RecaseError({ + message: `Cannot attach archived product${archivedProducts.length > 1 ? "s" : ""}: ${archivedProducts.map((p) => p.id).join(", ")}`, + code: ErrCode.InvalidRequest, + }); + } + if (notNullish(product_ids)) { const freeTrialProds = products.filter((prod) => notNullish(prod.free_trial), diff --git a/server/src/internal/misc/components/handlers/handleGetPricingTable.ts b/server/src/internal/misc/components/handlers/handleGetPricingTable.ts index fa50d115e..68bd666b3 100644 --- a/server/src/internal/misc/components/handlers/handleGetPricingTable.ts +++ b/server/src/internal/misc/components/handlers/handleGetPricingTable.ts @@ -23,7 +23,7 @@ export const handleGetPricingTable = createRoute({ const { customer_id: customerId } = c.req.valid("query"); const [products, customer] = await Promise.all([ - ProductService.listFull({ db, orgId: org.id, env }), + ProductService.listFull({ db, orgId: org.id, env, archived: false }), (async () => { if (!customerId) { return undefined; diff --git a/server/src/internal/product/actions/createProduct.ts b/server/src/internal/product/actions/createProduct.ts index 52065f4df..cfd292f3d 100644 --- a/server/src/internal/product/actions/createProduct.ts +++ b/server/src/internal/product/actions/createProduct.ts @@ -36,8 +36,8 @@ export const createProduct = async ({ id: data.id, }); - // 1. If existing product, throw error - if (existing) throw new ProductAlreadyExistsError({ productId: data.id }); + // 1. If existing non-archived product, throw error + if (existing && !existing.archived) throw new ProductAlreadyExistsError({ productId: data.id }); await validateDefaultFlag({ ctx, diff --git a/server/src/internal/products/ProductService.ts b/server/src/internal/products/ProductService.ts index 04d896267..98e7db615 100644 --- a/server/src/internal/products/ProductService.ts +++ b/server/src/internal/products/ProductService.ts @@ -63,16 +63,19 @@ export class ProductService { internalFeatureId: string; }) { const fullProducts = (await db.query.products.findMany({ - where: exists( - db - .select() - .from(entitlements) - .where( - and( - eq(entitlements.internal_product_id, products.internal_id), - eq(entitlements.internal_feature_id, internalFeatureId), + where: and( + ne(products.archived, true), + exists( + db + .select() + .from(entitlements) + .where( + and( + eq(entitlements.internal_product_id, products.internal_id), + eq(entitlements.internal_feature_id, internalFeatureId), + ), ), - ), + ), ), with: { entitlements: { diff --git a/server/src/internal/products/handlers/handleCreateProduct/handleCreatePlan.ts b/server/src/internal/products/handlers/handleCreateProduct/handleCreatePlan.ts index d377bb107..9fab3d84a 100644 --- a/server/src/internal/products/handlers/handleCreateProduct/handleCreatePlan.ts +++ b/server/src/internal/products/handlers/handleCreateProduct/handleCreatePlan.ts @@ -59,8 +59,8 @@ export const handleCreatePlan = createRoute({ id: body.id, }); - // 1. If existing product, throw error - if (existing) throw new ProductAlreadyExistsError({ productId: body.id }); + // 1. If existing non-archived product, throw error + if (existing && !existing.archived) throw new ProductAlreadyExistsError({ productId: body.id }); await validateDefaultFlag({ ctx,