Files
cfw-autumn/shared/models/billingModels/context/billingContext.ts
2026-06-04 19:18:17 +01:00

125 lines
3.8 KiB
TypeScript

import type {
BillingBehavior,
CancelAction,
CheckoutMode,
Entitlement,
FeatureOptions,
FreeTrial,
Price,
TrialOnEnd,
} from "@autumn/shared";
import type { PaymentBehaviorIntent } from "@models/billingModels/context/paymentBehaviorIntent";
import type { TransitionConfig } from "@models/billingModels/context/transitionConfig";
import type { DbInvoiceLineItem } from "@models/cusModels/invoiceModels/invoiceLineItemTable";
import type { EntInterval } from "@models/productModels/intervals/entitlementInterval";
import type Stripe from "stripe";
import { z } from "zod/v4";
import type { FullCustomer } from "../../cusModels/fullCusModel";
import type { FullProduct } from "../../productModels/productModels";
import type { StripeDiscountWithCoupon } from "../stripe/stripeDiscountWithCoupon";
const InvoiceModeSchema = z.object({
finalizeInvoice: z.boolean().default(false),
enableProductImmediately: z.boolean().default(true),
footer: z.string().optional(),
memo: z.string().optional(),
daysUntilDue: z.number().optional(),
});
export type InvoiceMode = z.infer<typeof InvoiceModeSchema>;
export enum BillingVersion {
V1 = "v1",
V2 = "v2",
}
export const LATEST_BILLING_VERSION = BillingVersion.V2;
export interface TrialContext {
freeTrial?: FreeTrial | null;
trialEndsAt: number | null;
customFreeTrial?: FreeTrial;
appliesToBilling: boolean;
cardRequired: boolean;
onEnd?: TrialOnEnd;
}
export interface AnchorResetRefund {
noPartialRefund: boolean;
refundCycle?: {
interval: EntInterval;
intervalCount: number;
};
}
export interface BillingContext {
fullCustomer: FullCustomer;
fullProducts: FullProduct[];
featureQuantities: FeatureOptions[];
adjustableFeatureQuantities?: string[];
transitionConfig?: TransitionConfig;
invoiceMode?: InvoiceMode;
// Timestamps...
currentEpochMs: number;
billingCycleAnchorMs: number | "now";
resetCycleAnchorMs: number | "now";
billingStartsAt?: number;
subscriptionBackdateStartMs?: number;
requestedBillingCycleAnchor?: number | "now";
requestedProrationBehavior?: BillingBehavior;
// Stripe context
stripeCustomer?: Stripe.Customer;
stripeSubscription?: Stripe.Subscription;
stripeSubscriptionSchedule?: Stripe.SubscriptionSchedule;
stripeDiscounts?: StripeDiscountWithCoupon[];
stripeTaxRate?: Stripe.TaxRate;
paymentMethod?: Stripe.PaymentMethod;
// Unforunately, need to add custom prices, custom entitlements and free trial here, because it's determined in the setup step.
// Optional - only needed for custom plan flows
customPrices?: Price[];
customEnts?: Entitlement[];
// Trial context
trialContext?: TrialContext;
isCustom?: boolean;
// Cancel action (used by update subscription for uncancel)
cancelAction?: CancelAction;
billingVersion: BillingVersion;
successUrl?: string;
checkoutSessionParams?: Record<string, unknown>;
userMetadata?: Record<string, string>;
taxRateId?: string;
skipBillingChanges?: boolean;
dryRunStripe?: boolean;
checkoutMode?: CheckoutMode;
// When true, the cusProduct is activated immediately even if a Stripe checkout
// session is required. Mirrors invoice-mode enable_plan_immediately for the
// stripe_checkout flow.
enablePlanImmediately?: boolean;
// When set, Autumn access starts at this time while billing may start later.
accessStartsAt?: number;
/** Identifies the Autumn action driving this billing context. Stamped onto Stripe
* subscription metadata so downstream webhook handlers can recognise Autumn-driven
* subscription mutations and skip auto-sync. */
actionSource?: string;
anchorResetRefund?: AnchorResetRefund;
storedChargeLineItems?: DbInvoiceLineItem[];
storedRefundLineItems?: DbInvoiceLineItem[];
refundLastPayment?: "prorated" | "full";
paymentBehaviorIntent?: PaymentBehaviorIntent;
shouldFinalizeFirstInvoice?: boolean;
skipCustomPaymentMethodGuard?: boolean;
}