import { PlanPeriod } from './plan'; import { formatUSD } from './pricingModel'; /** A priced voucher the merchant applied on the pricing page, waiting for checkout. */ export type AppliedVoucher = { code: string; type: 'PERCENTAGE' | 'FIXED_AMOUNT'; value: number; /** Plan keys it applies to; empty or "ALL" means every plan. */ plans: string[]; /** Billing cycles it discounts on the subscription; null is every cycle. */ durationMonths: number | null; }; /** Said when a priced code has no Stripe promotion code behind it. */ export const VOUCHER_NOT_HERE_MESSAGE = "This code can't be used on this checkout yet."; /** * Whether the voucher takes money off a given plan. * @param {AppliedVoucher | null} voucher - The applied voucher, if any. * @param {string} planKey - The plan the merchant is looking at. * @return {boolean} True when the voucher names the plan, or every plan. */ export const voucherAppliesTo = ( voucher: AppliedVoucher | null, planKey: string ): boolean => !!voucher && (voucher.plans.length === 0 || voucher.plans.includes('ALL') || voucher.plans.includes(planKey)); /** * The monthly figure a plan comes to with the voucher on it. A percentage * takes its share off the monthly figure; a fixed amount comes off each * charge, so on the annual plan it is spread over the twelve months. * @param {number} monthly - The plan's monthly figure before the voucher. * @param {PlanPeriod} period - The period the figure is billed on. * @param {AppliedVoucher} voucher - The voucher. * @return {number} The discounted monthly figure, never below zero. */ export const voucherMonthlyPrice = ( monthly: number, period: PlanPeriod, voucher: AppliedVoucher ): number => { if (voucher.type === 'PERCENTAGE') { return Math.max(0, Math.round(monthly * (100 - voucher.value)) / 100); } const perMonth = period === PlanPeriod.YEARLY ? voucher.value / 12 : voucher.value; return Math.max(0, Math.round((monthly - perMonth) * 100) / 100); }; /** * The voucher in a few words: what it takes off. * @param {AppliedVoucher} voucher - The voucher. * @return {string} "15% off" or "$38 off". */ export const voucherLabel = (voucher: AppliedVoucher): string => voucher.type === 'PERCENTAGE' ? `${voucher.value}% off` : `${formatUSD(voucher.value)} off`; /** * How long the voucher lasts, for the line under the price. * @param {AppliedVoucher} voucher - The voucher. * @return {string} "on every payment", "on your first payment" or "for your first N months". */ export const voucherDurationNote = (voucher: AppliedVoucher): string => { if (voucher.durationMonths === null) return 'on every payment'; if (voucher.durationMonths <= 1) return 'on your first payment'; return `for your first ${voucher.durationMonths} months`; };