99 lines
3.2 KiB
Markdown
99 lines
3.2 KiB
Markdown
# Pricing Catalog Architecture
|
|
|
|
> **Documentation only.** No pricing engine, tax engine, or coupon service.
|
|
> ADR: [ADR-023](../architecture/adr/ADR-023.md)
|
|
> Contract version: `pricing-catalog.v1`
|
|
|
|
---
|
|
|
|
## 1. Purpose
|
|
|
|
The **Pricing Catalog** is the sole commercial source for sellable price definitions.
|
|
**Business Bundles reference pricing; they never embed it.**
|
|
|
|
---
|
|
|
|
## 2. Supported commercial models (v1 documented)
|
|
|
|
| Model | `pricing_model` | Notes |
|
|
| --- | --- | --- |
|
|
| Monthly | `monthly` | Recurring calendar month |
|
|
| Yearly | `yearly` | Recurring year |
|
|
| Usage | `usage` | Metered; unit defined on item |
|
|
| Trial | `trial` | Time-boxed; converts via policy |
|
|
| Promotional | `promotional` | Time/window limited offer |
|
|
| Enterprise Quote | `enterprise_quote` | No public amount; sales-assisted |
|
|
|
|
---
|
|
|
|
## 3. Future-reserved (document fields only — no implementation)
|
|
|
|
| Concern | Reserved fields / notes |
|
|
| --- | --- |
|
|
| Regional pricing | `region_code`, `currency_override` |
|
|
| Taxes | `tax_class_code`, `tax_inclusive` |
|
|
| Coupons | `coupon_eligible`, external coupon service ref |
|
|
| Discounts | `discount_class_code` |
|
|
| Reseller pricing | `channel_code=reseller`, `partner_price_book_ref` |
|
|
|
|
Implementations MUST accept unknown additive fields.
|
|
|
|
---
|
|
|
|
## 4. Contracts
|
|
|
|
### 4.1 PricingCatalogItem
|
|
|
|
| Field | Type | Meaning |
|
|
| --- | --- | --- |
|
|
| `pricing_item_code` | string | Stable unique code |
|
|
| `display_name` | string | |
|
|
| `pricing_model` | enum | See §2 |
|
|
| `currency` | string | ISO-like code (e.g. `IRR`, `IRT`) — logical |
|
|
| `amount_minor` | int? | Null for `enterprise_quote` |
|
|
| `usage_unit` | string? | e.g. `sms`, `seat`, `order` |
|
|
| `trial_days` | int? | For `trial` |
|
|
| `promotional_window` | object? | `{ starts_at, ends_at }` |
|
|
| `region_code` | string? | Future |
|
|
| `tax_class_code` | string? | Future |
|
|
| `channel_code` | string? | `direct` \| `reseller` \| … (future) |
|
|
| `status` | enum | `draft` \| `active` \| `retired` |
|
|
| `ext` | object | Additive |
|
|
|
|
### 4.2 PricingCatalogVersion
|
|
|
|
Optional catalog publication version for admin change control (logical).
|
|
|
|
| Field | Meaning |
|
|
| --- | --- |
|
|
| `catalog_version` | e.g. `2026.07` |
|
|
| `item_codes[]` | Included items |
|
|
| `published_at` | |
|
|
|
|
### 4.3 PriceBook (future)
|
|
|
|
Logical grouping for reseller / enterprise — **reserved**, not implemented.
|
|
|
|
---
|
|
|
|
## 5. Invariants
|
|
|
|
1. Bundle definitions store **only** `pricing_item_code` references.
|
|
2. Subscription items bind to `pricing_item_code` at request time (snapshot policy is a future implementation concern).
|
|
3. Payment may charge using Payment contracts; **list price truth** remains Pricing Catalog.
|
|
4. No frontend hardcoding of amounts as source of truth.
|
|
|
|
---
|
|
|
|
## 6. Example codes (illustrative — not live billing)
|
|
|
|
| Code | Model | Intent |
|
|
| --- | --- | --- |
|
|
| `price.restaurant.starter.monthly` | monthly | Starter restaurant |
|
|
| `price.restaurant.starter.yearly` | yearly | |
|
|
| `price.clinic.starter.monthly` | monthly | |
|
|
| `price.platform.trial.14d` | trial | 14-day trial |
|
|
| `price.enterprise.custom` | enterprise_quote | Custom |
|
|
|
|
Canonical human matrix: [business-bundles.md](business-bundles.md).
|