Appearance
Subscription payments (QRSETU / Digious direct)
Model A. A merchant pays Digious for a plan. No split, no Route, no marketplace: Digious is the seller and the merchant is the customer.
MEASURED STATE, 2026-08-17: THERE IS NO COLLECTION PATH
workspace_subscriptions exists and resolve_workspace_plan reads it, so the platform can grant a plan and gate features on it correctly. Nothing collects the money. There is no Razorpay subscription, no order, no checkout, no invoice, and no webhook handling for this model. A Business plan is activated by inserting a row by hand after payment is taken out of band.
This is a deliberate launch decision, not an oversight: the cohort is 12 vendors the owner visited personally, and taking ₹9,999 from twelve known people by bank transfer costs less than building a billing system two days before a festival. It is documented here so nobody reads the schema and concludes the flow is wired.
What exists
The red steps are the ones with no software behind them.
The plan catalogue
platform_plans, measured live:
key | name | price_minor | billing_period | rank | audience |
|---|---|---|---|---|---|
free | Free | 0 | none | 0 | solo |
pro | Pro | NULL (unpriced) | month | 100 | solo |
business | Business | 999900 (₹9,999) | none | 200 | solo |
enterprise | Enterprise | NULL | month | 300 | organization |
⚠ billing_period = 'none' on Business is a known vocabulary compromise. The commercial offer is per festival session, which is neither a month nor a year nor a perpetual licence. none plus a description is what the existing enum can express; the honest modelling of a session-scoped plan is deferred rather than faked. Rank 200 was left deliberately vacant for it by the 2026-08-08 plans seed.
Plan resolution
sql
-- resolve_workspace_plan(p_workspace_id uuid) -> text
select case
when p_workspace_id is null then null
else coalesce(
(select s.plan_key from public.workspace_subscriptions s
where s.workspace_id = p_workspace_id
and s.status = 'active'
and (s.ends_at is null or s.ends_at > now())),
'free')
end;One body, exactly as the function's own comment prescribed before it was written. free is the fallback, so a workspace with no subscription row is never NULL and never unresolvable.
workspace_subscriptions is one row per workspace (workspace_id is the PK), with status in ('active','ended') and workspace_subscriptions_ended_has_date forcing an ends_at on an ended row. plan_key is a real FK to platform_plans(key), so a typo cannot grant a plan that does not exist.
How this model must be built, when it is built
Recorded now because the shape is a decision, not a detail, and getting it wrong is expensive.
It is a different Razorpay product
Model B uses Payment Links with transfers[]. Model A needs either a plain Order (one-off, which fits billing_period = 'none') or a Subscription (recurring, for Pro/Enterprise). ⚠ It must never carry a transfers[] array: there is no vendor to pay, and a Route split on a subscription would move Digious's own revenue into someone else's linked account.
It must not reuse orders and payments
orders is a merchant's sales ledger: it has workspace_id, buyer_name, buyer_phone, collect_on, a fulfilment status machine, and RLS scoping every row to workspace members. A Digious invoice to a merchant is none of those things, and putting it there would mean a merchant's own order list contains the bill they were sent. The correct shape is a separate subscription_invoices / subscription_payments pair keyed to workspace_subscriptions.
payments.commission_minor and vendor_minor have no meaning here either. Forcing a subscription into that table would require commission_minor = 0, vendor_minor = amount_minor, which reads as "the merchant received this money" and is the exact opposite of what happened.
The store-compliance constraint is real and is not a preference
ADR-0002 makes the native app a free companion with no in-app purchase UI or CTA (Apple 3.1.3(d) / 3.1.1). An "Upgrade to Business" button that opens a web checkout inside the iOS app is what that guideline restricts.
⚠ This does not weaken discovery. CLAUDE.md's fifth rule requires that a plan-locked capability stay visible with a lock and a clear statement of value, on every surface. What differs is the action: web gets a real upgrade CTA, native states that plans are managed on the web and stops. The merchant still understands exactly what the product offers, which is the whole requirement.
Tax treatment differs from Model B, and by more than the rate
In Model B, Digious is an intermediary and the taxable supply is the merchant's; our own taxable supply is the commission. In Model A, Digious is the direct supplier of a service and the taxable supply is the whole ₹9,999, with place of supply determined by the merchant's state. That means:
- a statutory invoice is required, with a consecutive number per financial year, max 16 characters (Rule 46(b)). ⚠
orders.referencesatisfies neither limb: it is deliberately random so a per-workspace sequence cannot leak a vendor's order volume, and it is up to 32 characters. A subscription invoice needs its own numbering series. - the correct CGST/SGST versus IGST split follows from
workspaces.state_codeagainst Digious's own state, which is whyworkspace_tax_identity_historyrecords the merchant's GSTIN and state over time rather than as a mutable column.
See Reconciliation, settlement and finance for the full tax model and what is still blocked on a CA ruling.
Open decisions
| Decision | Why it is not settled |
|---|---|
| One-off Order vs recurring Subscription for Business | the offer is "per festival session", which is neither. The vocabulary question and the Razorpay product question are the same question. |
| Invoice numbering series | must be consecutive per FY and ≤16 chars; the design exists in the cut statutory_documents proposal but had two structural defects (see status page) |
| Whether Pro is ever sold self-serve | price_minor is NULL, so it is currently unpriced and unsellable by construction |
| Dunning and expiry behaviour | ends_at exists and is read by resolve_workspace_plan, but nothing writes it and nothing warns a merchant before it passes |