Files
HiveGrid-Wireframes/hivegrid-cloud/apps/web/app/application/pricing/plans.server.ts
T

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;