332 lines
11 KiB
TypeScript
332 lines
11 KiB
TypeScript
import { SubscriptionBillingPeriod } from "~/application/enums/subscriptions/SubscriptionBillingPeriod";
|
|
import { SubscriptionPriceType } from "~/application/enums/subscriptions/SubscriptionPriceType";
|
|
import { DefaultFeatures } from "../dtos/shared/DefaultFeatures";
|
|
import { SubscriptionPriceDto } from "../dtos/subscriptions/SubscriptionPriceDto";
|
|
import { SubscriptionProductDto } from "../dtos/subscriptions/SubscriptionProductDto";
|
|
import { SubscriptionUsageBasedPriceDto } from "../dtos/subscriptions/SubscriptionUsageBasedPriceDto";
|
|
import { SubscriptionUsageBasedTierDto } from "../dtos/subscriptions/SubscriptionUsageBasedTierDto";
|
|
import { PricingModel } from "../enums/subscriptions/PricingModel";
|
|
import { SubscriptionFeatureLimitType } from "../enums/subscriptions/SubscriptionFeatureLimitType";
|
|
|
|
const UNIT_API_CALL = {
|
|
name: "api",
|
|
title: "API Call",
|
|
titlePlural: "API Calls",
|
|
};
|
|
|
|
function generatePrice(currency: string, price: number, billingPeriod: SubscriptionBillingPeriod): SubscriptionPriceDto {
|
|
return {
|
|
stripeId: "",
|
|
subscriptionProductId: "",
|
|
type: billingPeriod === SubscriptionBillingPeriod.ONCE ? SubscriptionPriceType.ONE_TIME : SubscriptionPriceType.RECURRING,
|
|
billingPeriod,
|
|
price: Math.round(price * 100) / 100,
|
|
currency,
|
|
trialDays: 0,
|
|
active: true,
|
|
usageBasedPrices: [],
|
|
};
|
|
}
|
|
|
|
function generateUsageBasedPrice(
|
|
currency: string,
|
|
unit: {
|
|
name: string;
|
|
title: string;
|
|
titlePlural: string;
|
|
},
|
|
usageType: "licensed" | "metered",
|
|
aggregateUsage: "last_during_period" | "last_ever" | "max" | "sum",
|
|
tiersMode: "graduated" | "volume",
|
|
billingScheme: "per_unit" | "tiered",
|
|
tiers: {
|
|
from: number;
|
|
to: undefined | number;
|
|
perUnitPrice: number | undefined;
|
|
flatFeePrice: number | undefined;
|
|
}[]
|
|
): SubscriptionUsageBasedPriceDto {
|
|
const usageBasedPriceTiers: SubscriptionUsageBasedTierDto[] = [];
|
|
tiers.forEach((tier) => {
|
|
usageBasedPriceTiers.push({
|
|
id: "",
|
|
subscriptionUsageBasedPriceId: "",
|
|
...tier,
|
|
});
|
|
});
|
|
return {
|
|
id: "",
|
|
stripeId: "",
|
|
subscriptionProductId: "",
|
|
billingPeriod: SubscriptionBillingPeriod.MONTHLY,
|
|
currency,
|
|
unit: unit.name,
|
|
unitTitle: unit.title,
|
|
unitTitlePlural: unit.titlePlural,
|
|
usageType,
|
|
aggregateUsage,
|
|
tiersMode,
|
|
billingScheme,
|
|
tiers: usageBasedPriceTiers,
|
|
};
|
|
}
|
|
|
|
function generateCommonPlan(order: number, model: PricingModel) {
|
|
if (order === 1) {
|
|
return {
|
|
stripeId: "",
|
|
order,
|
|
title: "pricing.products.plan1.title",
|
|
description: "pricing.products.plan1.description",
|
|
model,
|
|
public: true,
|
|
features: [
|
|
{
|
|
order: 1,
|
|
title: "pricing.features.users.max",
|
|
name: DefaultFeatures.Users,
|
|
value: 2,
|
|
type: SubscriptionFeatureLimitType.MAX,
|
|
accumulate: false,
|
|
},
|
|
{
|
|
order: 3,
|
|
title: "pricing.features.apiCalls.units",
|
|
name: DefaultFeatures.API,
|
|
value: 0,
|
|
type: SubscriptionFeatureLimitType.NOT_INCLUDED,
|
|
accumulate: false,
|
|
},
|
|
{
|
|
order: 4,
|
|
title: "pricing.features.prioritySupport.none",
|
|
name: DefaultFeatures.PrioritySupport,
|
|
value: 0,
|
|
type: SubscriptionFeatureLimitType.NOT_INCLUDED,
|
|
accumulate: false,
|
|
},
|
|
],
|
|
badge: "",
|
|
active: true,
|
|
prices: [],
|
|
};
|
|
} else if (order === 2) {
|
|
return {
|
|
stripeId: "",
|
|
order,
|
|
title: "pricing.products.plan2.title",
|
|
description: "pricing.products.plan2.description",
|
|
public: true,
|
|
model,
|
|
features: [
|
|
{
|
|
order: 1,
|
|
title: "pricing.features.users.max",
|
|
name: DefaultFeatures.Users,
|
|
value: 5,
|
|
type: SubscriptionFeatureLimitType.MAX,
|
|
accumulate: false,
|
|
},
|
|
{
|
|
order: 3,
|
|
title: "pricing.features.apiCalls.monthly",
|
|
name: DefaultFeatures.API,
|
|
value: 100,
|
|
type: SubscriptionFeatureLimitType.MONTHLY,
|
|
accumulate: false,
|
|
},
|
|
{
|
|
order: 4,
|
|
title: "pricing.features.prioritySupport.basic",
|
|
name: DefaultFeatures.PrioritySupport,
|
|
value: 0,
|
|
type: SubscriptionFeatureLimitType.INCLUDED,
|
|
accumulate: false,
|
|
},
|
|
],
|
|
badge: "pricing.recommended",
|
|
active: true,
|
|
};
|
|
} else if (order === 3) {
|
|
return {
|
|
stripeId: "",
|
|
order,
|
|
title: "pricing.products.plan3.title",
|
|
description: "pricing.products.plan3.description",
|
|
public: true,
|
|
model,
|
|
features: [
|
|
{
|
|
order: 1,
|
|
title: "pricing.features.users.max",
|
|
name: DefaultFeatures.Users,
|
|
value: 12,
|
|
type: SubscriptionFeatureLimitType.MAX,
|
|
accumulate: false,
|
|
},
|
|
{
|
|
order: 3,
|
|
title: "pricing.features.apiCalls.unlimited",
|
|
name: DefaultFeatures.API,
|
|
value: 0,
|
|
type: SubscriptionFeatureLimitType.UNLIMITED,
|
|
accumulate: false,
|
|
},
|
|
{
|
|
order: 4,
|
|
title: "pricing.features.prioritySupport.priority",
|
|
name: DefaultFeatures.PrioritySupport,
|
|
value: 0,
|
|
type: SubscriptionFeatureLimitType.INCLUDED,
|
|
accumulate: false,
|
|
},
|
|
],
|
|
badge: "",
|
|
active: true,
|
|
};
|
|
}
|
|
|
|
return {
|
|
stripeId: "",
|
|
order,
|
|
title: "pricing.products.plan1.title",
|
|
description: "pricing.products.plan1.description",
|
|
model,
|
|
public: true,
|
|
features: [
|
|
{
|
|
order: 1,
|
|
title: "pricing.features.users.one",
|
|
name: DefaultFeatures.Users,
|
|
value: 1,
|
|
type: SubscriptionFeatureLimitType.MAX,
|
|
accumulate: false,
|
|
},
|
|
],
|
|
badge: "",
|
|
active: true,
|
|
};
|
|
}
|
|
|
|
const FLAT_RATE_PRICES: SubscriptionProductDto[] = [
|
|
{
|
|
...generateCommonPlan(1, PricingModel.FLAT_RATE),
|
|
prices: [
|
|
generatePrice("usd", 9, SubscriptionBillingPeriod.MONTHLY),
|
|
generatePrice("usd", 90, SubscriptionBillingPeriod.YEARLY),
|
|
generatePrice("mxn", 199, SubscriptionBillingPeriod.MONTHLY),
|
|
generatePrice("mxn", 1990, SubscriptionBillingPeriod.YEARLY),
|
|
],
|
|
usageBasedPrices: [],
|
|
},
|
|
{
|
|
...generateCommonPlan(2, PricingModel.FLAT_RATE),
|
|
prices: [
|
|
generatePrice("usd", 199, SubscriptionBillingPeriod.MONTHLY),
|
|
generatePrice("usd", 1990, SubscriptionBillingPeriod.YEARLY),
|
|
generatePrice("mxn", 3999, SubscriptionBillingPeriod.MONTHLY),
|
|
generatePrice("mxn", 39990, SubscriptionBillingPeriod.YEARLY),
|
|
],
|
|
usageBasedPrices: [],
|
|
},
|
|
{
|
|
...generateCommonPlan(3, PricingModel.FLAT_RATE),
|
|
prices: [
|
|
generatePrice("usd", 399, SubscriptionBillingPeriod.MONTHLY),
|
|
generatePrice("usd", 3990, SubscriptionBillingPeriod.YEARLY),
|
|
generatePrice("mxn", 7999, SubscriptionBillingPeriod.MONTHLY),
|
|
generatePrice("mxn", 79990, SubscriptionBillingPeriod.YEARLY),
|
|
],
|
|
usageBasedPrices: [],
|
|
},
|
|
];
|
|
|
|
const PER_SEAT_PRICES: SubscriptionProductDto[] = [
|
|
...FLAT_RATE_PRICES.map((item) => {
|
|
return { ...item, model: PricingModel.PER_SEAT };
|
|
}),
|
|
];
|
|
|
|
const USAGE_BASED_PRICES: SubscriptionProductDto[] = [
|
|
{
|
|
...generateCommonPlan(1, PricingModel.USAGE_BASED),
|
|
prices: [],
|
|
usageBasedPrices: [
|
|
generateUsageBasedPrice("usd", UNIT_API_CALL, "metered", "sum", "volume", "tiered", [
|
|
{ from: 0, to: 10, perUnitPrice: 0.0, flatFeePrice: undefined },
|
|
{ from: 11, to: 20, perUnitPrice: 0.02, flatFeePrice: 5 },
|
|
{ from: 21, to: undefined, perUnitPrice: 0.01, flatFeePrice: 10 },
|
|
]),
|
|
generateUsageBasedPrice("mxn", UNIT_API_CALL, "metered", "sum", "volume", "tiered", [
|
|
{ from: 0, to: 10, perUnitPrice: 0.0, flatFeePrice: undefined },
|
|
{ from: 11, to: 20, perUnitPrice: 0.4, flatFeePrice: 100 },
|
|
{ from: 21, to: undefined, perUnitPrice: 0.2, flatFeePrice: 200 },
|
|
]),
|
|
],
|
|
},
|
|
{
|
|
...generateCommonPlan(2, PricingModel.USAGE_BASED),
|
|
prices: [],
|
|
usageBasedPrices: [
|
|
generateUsageBasedPrice("usd", UNIT_API_CALL, "metered", "sum", "volume", "tiered", [
|
|
{ from: 0, to: 10, perUnitPrice: 0.0, flatFeePrice: undefined },
|
|
{ from: 11, to: 20, perUnitPrice: 0.04, flatFeePrice: 10 },
|
|
{ from: 21, to: undefined, perUnitPrice: 0.02, flatFeePrice: 20 },
|
|
]),
|
|
generateUsageBasedPrice("mxn", UNIT_API_CALL, "metered", "sum", "volume", "tiered", [
|
|
{ from: 0, to: 10, perUnitPrice: 0.0, flatFeePrice: undefined },
|
|
{ from: 11, to: 20, perUnitPrice: 0.8, flatFeePrice: 200 },
|
|
{ from: 21, to: undefined, perUnitPrice: 0.4, flatFeePrice: 400 },
|
|
]),
|
|
],
|
|
},
|
|
{
|
|
...generateCommonPlan(3, PricingModel.USAGE_BASED),
|
|
prices: [],
|
|
usageBasedPrices: [
|
|
generateUsageBasedPrice("usd", UNIT_API_CALL, "metered", "sum", "volume", "tiered", [
|
|
{ from: 0, to: 10, perUnitPrice: 0.0, flatFeePrice: undefined },
|
|
{ from: 11, to: 20, perUnitPrice: 0.06, flatFeePrice: 15 },
|
|
{ from: 21, to: undefined, perUnitPrice: 0.03, flatFeePrice: 30 },
|
|
]),
|
|
generateUsageBasedPrice("mxn", UNIT_API_CALL, "metered", "sum", "volume", "tiered", [
|
|
{ from: 0, to: 10, perUnitPrice: 0.0, flatFeePrice: undefined },
|
|
{ from: 11, to: 20, perUnitPrice: 1.2, flatFeePrice: 300 },
|
|
{ from: 21, to: undefined, perUnitPrice: 0.6, flatFeePrice: 600 },
|
|
]),
|
|
],
|
|
},
|
|
];
|
|
|
|
const FLAT_RATE_PLUS_USAGE_BASED_PRICES: SubscriptionProductDto[] = [
|
|
...FLAT_RATE_PRICES.map((flatRate) => {
|
|
const usageBasedPrices = USAGE_BASED_PRICES.find((f) => f.order === flatRate.order)?.usageBasedPrices ?? [];
|
|
return {
|
|
...flatRate,
|
|
usageBasedPrices,
|
|
model: PricingModel.FLAT_RATE_USAGE_BASED,
|
|
};
|
|
}),
|
|
];
|
|
|
|
const ONE_TIME_PRICES: SubscriptionProductDto[] = [
|
|
{
|
|
...generateCommonPlan(1, PricingModel.ONCE),
|
|
prices: [generatePrice("usd", 99 * 2, SubscriptionBillingPeriod.ONCE), generatePrice("mxn", 1999 * 2, SubscriptionBillingPeriod.ONCE)],
|
|
usageBasedPrices: [],
|
|
},
|
|
{
|
|
...generateCommonPlan(2, PricingModel.ONCE),
|
|
prices: [generatePrice("usd", 499 * 2, SubscriptionBillingPeriod.ONCE), generatePrice("mxn", 9999 * 2, SubscriptionBillingPeriod.ONCE)],
|
|
usageBasedPrices: [],
|
|
},
|
|
{
|
|
...generateCommonPlan(3, PricingModel.ONCE),
|
|
prices: [generatePrice("usd", 1999 * 2, SubscriptionBillingPeriod.ONCE), generatePrice("mxn", 4999 * 2, SubscriptionBillingPeriod.ONCE)],
|
|
usageBasedPrices: [],
|
|
},
|
|
];
|
|
|
|
const plans = [...FLAT_RATE_PRICES, ...PER_SEAT_PRICES, ...USAGE_BASED_PRICES, ...FLAT_RATE_PLUS_USAGE_BASED_PRICES, ...ONE_TIME_PRICES];
|
|
export default plans;
|