Rust discount function (one automatic discount evaluating all offers in priority order, parity with the Odoo engine), React Router admin with Polaris, theme app extension and app proxy pages, webhooks incl. GDPR, managed-pricing limits, and a Docker Compose stack (Postgres + Caddy HTTPS) for a single VPS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
55 lines
2.2 KiB
TypeScript
55 lines
2.2 KiB
TypeScript
// Plans (brief §18). Prices live in the Partner Dashboard (managed pricing); limits are enforced here,
|
|
// server-side, when publishing and when compiling the function configuration.
|
|
|
|
export type PlanCode = "free" | "starter" | "growth" | "plus";
|
|
|
|
export interface PlanLimits {
|
|
name: string;
|
|
price: string;
|
|
runningOffers: number; // Infinity = unlimited (within config size)
|
|
types: string[];
|
|
scheduling: boolean;
|
|
homepage: boolean;
|
|
cartHints: boolean;
|
|
branding: boolean;
|
|
monthlyOrders: number;
|
|
templates: boolean;
|
|
analytics: boolean;
|
|
markets: boolean;
|
|
translations: boolean;
|
|
}
|
|
|
|
const ALL_TYPES = ["fixed", "mix", "bxgy"];
|
|
|
|
export const PLANS: Record<PlanCode, PlanLimits> = {
|
|
free: {
|
|
name: "Free", price: "$0", runningOffers: 1, types: ["fixed"], scheduling: false, homepage: false,
|
|
cartHints: false, branding: true, monthlyOrders: 50, templates: false, analytics: false, markets: false, translations: false,
|
|
},
|
|
starter: {
|
|
name: "Starter", price: "$9.99/mo", runningOffers: 5, types: ALL_TYPES, scheduling: true, homepage: true,
|
|
cartHints: true, branding: false, monthlyOrders: Infinity, templates: false, analytics: false, markets: false, translations: false,
|
|
},
|
|
growth: {
|
|
name: "Growth", price: "$24.99/mo", runningOffers: Infinity, types: ALL_TYPES, scheduling: true, homepage: true,
|
|
cartHints: true, branding: false, monthlyOrders: Infinity, templates: true, analytics: true, markets: true, translations: true,
|
|
},
|
|
plus: {
|
|
name: "Plus", price: "$59.99/mo", runningOffers: Infinity, types: ALL_TYPES, scheduling: true, homepage: true,
|
|
cartHints: true, branding: false, monthlyOrders: Infinity, templates: true, analytics: true, markets: true, translations: true,
|
|
},
|
|
};
|
|
|
|
export function planOf(code: string | null | undefined): PlanLimits {
|
|
return PLANS[(code as PlanCode) in PLANS ? (code as PlanCode) : "free"];
|
|
}
|
|
|
|
/** Maps a managed-pricing subscription name (Partner Dashboard plan name) to a plan code. */
|
|
export function planCodeFromSubscription(name: string | null | undefined): PlanCode {
|
|
const n = (name || "").toLowerCase();
|
|
if (n.includes("plus")) return "plus";
|
|
if (n.includes("growth")) return "growth";
|
|
if (n.includes("starter")) return "starter";
|
|
return "free";
|
|
}
|