diff --git a/server/tests/utils/fixtures/itemsV2.ts b/server/tests/utils/fixtures/itemsV2.ts index 696cf48df..493e7900c 100644 --- a/server/tests/utils/fixtures/itemsV2.ts +++ b/server/tests/utils/fixtures/itemsV2.ts @@ -122,6 +122,63 @@ const allocatedUsers = ({ }, }); +const allocatedWorkflows = ({ + amount = 10, + included = 0, +}: { + amount?: number; + included?: number; +} = {}) => ({ + feature_id: TestFeature.Workflows, + included, + price: { + amount, + interval: BillingInterval.Month, + billing_method: BillingMethod.UsageBased, + billing_units: 1, + }, + proration: { + on_increase: OnIncrease.BillImmediately, + on_decrease: OnDecrease.None, + }, +}); + +const prepaidUsers = ({ + amount = 10, + billingUnits = 1, + included = 0, +}: { + amount?: number; + billingUnits?: number; + included?: number; +} = {}) => ({ + feature_id: TestFeature.Users, + included, + price: { + amount, + interval: BillingInterval.Month, + billing_method: BillingMethod.Prepaid, + billing_units: billingUnits, + }, +}); + +const consumableWords = ({ + amount = 0.05, + included = 0, +}: { + amount?: number; + included?: number; +} = {}) => ({ + feature_id: TestFeature.Words, + included, + price: { + amount, + interval: BillingInterval.Month, + billing_method: BillingMethod.UsageBased, + billing_units: 1, + }, +}); + /** * Tiered prepaid messages - tier `to` values INCLUDE the included amount. * Default: included=100, tiers=[{to:600, amount:10}, {to:"inf", amount:5}] @@ -184,9 +241,12 @@ export const itemsV2 = { monthlyWords, dashboard, prepaidMessages, + prepaidUsers, prepaidWords, consumableMessages, + consumableWords, allocatedUsers, + allocatedWorkflows, tieredPrepaidMessages, volumePrepaidMessages, } as const; diff --git a/server/tests/utils/productUtils.ts b/server/tests/utils/productUtils.ts index 914e9351c..cbbc4e28d 100644 --- a/server/tests/utils/productUtils.ts +++ b/server/tests/utils/productUtils.ts @@ -15,6 +15,7 @@ export const createProduct = async ({ autumn, product, prefix, + createInStripe, }: { db: DrizzleCli; orgId: string; @@ -22,6 +23,7 @@ export const createProduct = async ({ autumn: AutumnInt; product: any; prefix?: string; + createInStripe?: boolean; }) => { try { const products = await ProductService.listFull({ @@ -60,6 +62,10 @@ export const createProduct = async ({ clone.name = `${clone.name} ${prefix}`; } + if (createInStripe === false) { + clone.create_in_stripe = false; + } + try { await autumn.products.create(clone); } catch (error: any) { @@ -83,6 +89,7 @@ export const createProducts = async ({ products, prefix, customerId, + createInStripe, }: { db: DrizzleCli; orgId: string; @@ -91,6 +98,7 @@ export const createProducts = async ({ products: any[]; prefix?: string; customerId?: string; + createInStripe?: boolean; }) => { if (customerId) { try { @@ -101,7 +109,7 @@ export const createProducts = async ({ const batchCreate = []; for (const product of products) { batchCreate.push( - createProduct({ db, orgId, env, autumn, product, prefix }), + createProduct({ db, orgId, env, autumn, product, prefix, createInStripe }), ); } diff --git a/server/tests/utils/testInitUtils/initScenario.ts b/server/tests/utils/testInitUtils/initScenario.ts index f2cb87e8f..41fb656f0 100644 --- a/server/tests/utils/testInitUtils/initScenario.ts +++ b/server/tests/utils/testInitUtils/initScenario.ts @@ -242,6 +242,7 @@ type ScenarioConfig = { stripeCustomerOverrides?: Partial; products: ProductV2[]; productPrefix?: string; + productCreateInStripe?: boolean; entityConfig?: EntityConfig; customerIds?: string[]; cleanup: CleanupConfig; @@ -326,16 +327,19 @@ const products = ({ list, prefix, customerIdsToDelete, + createInStripe, }: { list: ProductV2[]; prefix?: string; customerIdsToDelete?: string[]; + createInStripe?: boolean; }): ConfigFn => { return (config) => ({ ...config, products: list, productPrefix: prefix, customerIds: customerIdsToDelete, + productCreateInStripe: createInStripe, }); }; @@ -1104,6 +1108,7 @@ export async function initScenario({ products: config.products, prefix: productPrefix, customerIds: allCustomerIds, + createInStripe: config.productCreateInStripe, }); } diff --git a/shared/api/products/crud/createPlanParamsV1.ts b/shared/api/products/crud/createPlanParamsV1.ts index f97a578b4..258b40bf7 100644 --- a/shared/api/products/crud/createPlanParamsV1.ts +++ b/shared/api/products/crud/createPlanParamsV1.ts @@ -46,6 +46,10 @@ export const CreatePlanParamsV1Schema = z.object({ config: ProductConfigParamsSchema.optional().meta({ description: "Miscellaneous plan-level configuration flags.", }), + + create_in_stripe: z.boolean().default(true).meta({ + internal: true, + }), }); export const CreatePlanParamsV2Schema = z diff --git a/shared/api/products/crud/mappers/planParamsV1ToProductV2.ts b/shared/api/products/crud/mappers/planParamsV1ToProductV2.ts index 57da6a97c..9dddd0f9c 100644 --- a/shared/api/products/crud/mappers/planParamsV1ToProductV2.ts +++ b/shared/api/products/crud/mappers/planParamsV1ToProductV2.ts @@ -44,6 +44,11 @@ export function planParamsV1ToProductV2({ ? params.config : undefined; + const createInStripe = + "create_in_stripe" in params && params.create_in_stripe !== undefined + ? params.create_in_stripe + : undefined; + return { id: params.id, // fallback just for placeholders... name: params.name, @@ -63,5 +68,6 @@ export function planParamsV1ToProductV2({ : params.free_trial, ...(archived !== undefined && { archived }), ...(config !== undefined && { config }), + ...(createInStripe !== undefined && { create_in_stripe: createInStripe }), }; } diff --git a/shared/api/products/productOpModels.ts b/shared/api/products/productOpModels.ts index faab01772..dd69394d2 100644 --- a/shared/api/products/productOpModels.ts +++ b/shared/api/products/productOpModels.ts @@ -99,6 +99,10 @@ export const CreateProductV2ParamsSchema = z config: ProductConfigParamsSchema.optional().meta({ description: "Miscellaneous product-level configuration flags.", }), + + create_in_stripe: z.boolean().optional().meta({ + internal: true, + }), }) .meta({ examples: [CREATE_PRODUCT_EXAMPLE],