Configuration fields
| Field | Description | Required | Default |
|---|---|---|---|
value | Percentage to discount (e.g., 20 = 20%) | Yes | — |
max_per_period | Dollar cap on discount within a cadence window | No | Unlimited |
cadence | Cap refresh period (P1M, P3M, P1Y, etc.) | No | None (falls back to billing cadence) |
max_lifetime | Cumulative dollar cap on discount across all periods | No | Unlimited |
label | Display label on invoice | No | — |
order | Execution order when stacking multiple discounts | No | — |
Validation rules
| Rule | Valid | Invalid |
|---|---|---|
value between 0 and 100 | 20 | −5, 150 |
max_per_period non-negative if set | 500 | −1 |
max_lifetime non-negative if set | 5000 | −1 |
| Caps are dollar amounts, not percentages | max_per_period=100 means a $100 cap | Not a 100% cap |
max_per_period requires a period reference | With cadence or a billing cadence | Neither means invalid |
Core calculation
- Calculate the gross bill amount, after quantity discounts, the pricing model, and commitments.
- Apply the percentage: discount = value% × gross_amount.
- Cap the discount, if configured: discount = min(discount, remaining_period_cap, remaining_lifetime).
- Subtract: invoice_amount = gross_amount − discount, floored at $0.
Cadence resolution order for max_per_period
cadence, if set.- Billing cadence, as a fallback.
- If neither is available,
max_per_periodis invalid.
Cadence relationships
| Relationship | Example | Behavior |
|---|---|---|
| Cadence = billing | Monthly/monthly | Each period independent |
| Cadence larger than billing | Quarterly/monthly | Three months grouped; cap applies to the quarterly total |
| Cadence smaller than billing | Weekly/monthly | About four cap windows per billing period |
| No cadence | — | Each billing period independent |
Proportional distribution formula (cadence grouping)
Cap summary
| Level | Field | State | Refreshes |
|---|---|---|---|
| Per-period | max_per_period + optional cadence | Within window | At cadence boundary |
| Lifetime | max_lifetime | Forever | Never |
Order of operations (full calculation stack)
Natural ordering when stacking discount types
| Step | Discount type | Reduces |
|---|---|---|
| 1 | Quantity discount | Units |
| 2 | Fixed discount | Dollars (flat) |
| 3 | Percent discount | Remainder (%) |
Invoice presentation
The discount appears as a line item on the invoice using the configured label. Each period produces a breakdown record tracking: amounts before and after, discount applied, raw discount (pre-cap), percentage, period and lifetime cap remaining, and whether any cap was hit.Risks and edge cases
| Scenario | Handling |
|---|---|
| 100% discount without a cap | Customer pays $0 indefinitely; confirm this is intentional |
| Lifetime cap exhaustion | Not visible to the customer in advance unless entitlement tracking is separately surfaced |
Glossary
| Term | Definition |
|---|---|
| Percent discount | Percentage deduction from gross bill amount; stateless |
| Gross amount | Bill total after quantity discount, pricing model, and commitments — before percent or fixed discounts |
| Breakpoint | Bill amount where the per-period cap starts to bite: max_per_period ÷ (value/100) |
| Cadence | Refresh frequency for max_per_period; groups billing periods into cap windows |
| Cadence window | Time span covered by one max_per_period cycle |
| Proportional distribution | Group discount allocated to periods proportional to their gross amounts |
| Degressive discount | Declining effective rate when caps limit the dollar discount on larger bills |
| Compounding | Two sequential percent discounts multiply: 20% + 10% = 28%, not 30% |
Out of scope / deferred
| Feature | Description |
|---|---|
max_per_event | Per-event dollar cap; requires event-level data |
| Event breakdown integration | Per-event discount tracking within a billing period |
| Three-level cap stack | max_per_event + max_per_period + max_lifetime; only two levels currently |
| Percentage-based caps | Current caps are dollar amounts only, not “at most 50% off” style caps |
| Cross-product discounts | A shared percent discount across multiple products |
| Discount validity / expiry | Independent start and end dates on the discount itself |
Open questions
| # | Question | Status |
|---|---|---|
| 1 | Should discount validity be a separate start/end date, or follow the line item’s lifecycle? | Needs clarification |
| 2 | If discount duration is shorter than the subscription, how is it applied across product and quantity types? | Needs clarification |
| 3 | When discount cadence is larger than billing cadence, is the discount applied at the end of the discount cadence or the end of the billing period? | Needs eng validation |
| 4 | When a cadence-distributed discount is capped, are there retrospective adjustments as later periods change the proportional distribution? | Needs eng validation |