SaaS subscriptions
Tiered plan
Section titled “Tiered plan”import { Access, Billing, Limits, Offer, Purchase } from "@byfungsi/sapa";import { Effect } from "effect";
export const proPlan = Effect.gen(function* () { const access = yield* Access.entitlements({ entitlements: ["workspace.use"], duration: "purchased_period", }); const limit = yield* Limits.resource({ resource: "workspace.project", quantity: 100, entitlement: "workspace.use", }); const purchase = yield* Purchase.parse({ key: "workspace.plan", revision: 2, provides: [access, limit], }); const billing = yield* Billing.subscription({ family: "workspace", price: { currency: "IDR", amount: 300_000n }, interval: "month", }); return yield* Offer.parse({ key: "workspace.pro", revision: 1, purchase, billing, });});Basic and Pro can share purchase key workspace.plan but must use different
purchase revisions because they promise different limits.
Per-seat team plan
Section titled “Per-seat team plan”import { Seats } from "@byfungsi/sapa";
export const teamPlan = Effect.gen(function* () { const access = yield* Access.entitlements({ entitlements: ["workspace.use"], duration: "purchased_period", }); const capacity = yield* Seats.capacity({ pool: "workspace.members", quantity: "purchase_quantity", entitlement: "workspace.use", }); const purchase = yield* Purchase.parse({ key: "workspace.team.access", revision: 1, provides: [access, capacity], }); const billing = yield* Billing.perSeatSubscription({ family: "workspace", price: { currency: "IDR", amount: 75_000n }, minimumQuantity: 1, maximumQuantity: 100, interval: "month", }); return yield* Offer.parse({ key: "workspace.team", revision: 1, purchase, billing, });});At checkout, set the beneficiary to the workspace and quantity to the purchased seat count. After settlement, use seat assignment operations for individual members. Schedule decreases only when current assignments fit the target.