[ {"name": "plan, seats and usage with no coupons", "args": [{"description": "Pro plan", "unitPrice": {"minor": 4900, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}, [{"description": "Extra seats", "unitPrice": {"minor": 1000, "currency": "GBP"}, "quantity": 3, "discountBasisPoints": 0, "taxCategory": "STANDARD"}], [{"description": "API calls", "unitPrice": {"minor": 1250, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}], [], 5, "GB", "2026-09-01"], "expect": {"currency": "GBP", "lines": [{"description": "Pro plan", "net": {"minor": 4900, "currency": "GBP"}, "tax": {"minor": 980, "currency": "GBP"}, "gross": {"minor": 5880, "currency": "GBP"}, "basisPoints": 2000}, {"description": "Extra seats", "net": {"minor": 3000, "currency": "GBP"}, "tax": {"minor": 600, "currency": "GBP"}, "gross": {"minor": 3600, "currency": "GBP"}, "basisPoints": 2000}, {"description": "API calls", "net": {"minor": 1250, "currency": "GBP"}, "tax": {"minor": 250, "currency": "GBP"}, "gross": {"minor": 1500, "currency": "GBP"}, "basisPoints": 2000}], "subtotal": {"minor": 9150, "currency": "GBP"}, "taxTotal": {"minor": 1830, "currency": "GBP"}, "total": {"minor": 10980, "currency": "GBP"}, "taxBreakdown": [{"basisPoints": 2000, "taxable": {"minor": 9150, "currency": "GBP"}, "tax": {"minor": 1830, "currency": "GBP"}}]}}, {"name": "a 20% forever coupon becomes one discount line, taxed like the lines it reduces", "args": [{"description": "Pro plan", "unitPrice": {"minor": 4900, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}, [{"description": "Extra seats", "unitPrice": {"minor": 1000, "currency": "GBP"}, "quantity": 3, "discountBasisPoints": 0, "taxCategory": "STANDARD"}], [{"description": "API calls", "unitPrice": {"minor": 1250, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}], [{"description": "Launch offer 20%", "basisPoints": 2000, "amountOff": null, "duration": "forever", "durationPeriods": null, "startPeriod": 1}], 5, "GB", "2026-09-01"], "expect": {"currency": "GBP", "lines": [{"description": "Pro plan", "net": {"minor": 4900, "currency": "GBP"}, "tax": {"minor": 980, "currency": "GBP"}, "gross": {"minor": 5880, "currency": "GBP"}, "basisPoints": 2000}, {"description": "Extra seats", "net": {"minor": 3000, "currency": "GBP"}, "tax": {"minor": 600, "currency": "GBP"}, "gross": {"minor": 3600, "currency": "GBP"}, "basisPoints": 2000}, {"description": "API calls", "net": {"minor": 1250, "currency": "GBP"}, "tax": {"minor": 250, "currency": "GBP"}, "gross": {"minor": 1500, "currency": "GBP"}, "basisPoints": 2000}, {"description": "Launch offer 20%", "net": {"minor": -1830, "currency": "GBP"}, "tax": {"minor": -366, "currency": "GBP"}, "gross": {"minor": -2196, "currency": "GBP"}, "basisPoints": 2000}], "subtotal": {"minor": 7320, "currency": "GBP"}, "taxTotal": {"minor": 1464, "currency": "GBP"}, "total": {"minor": 8784, "currency": "GBP"}, "taxBreakdown": [{"basisPoints": 2000, "taxable": {"minor": 7320, "currency": "GBP"}, "tax": {"minor": 1464, "currency": "GBP"}}]}}, {"name": "a 3-period coupon from period 2 still applies in period 4", "args": [{"description": "Pro plan", "unitPrice": {"minor": 4900, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}, [{"description": "Extra seats", "unitPrice": {"minor": 1000, "currency": "GBP"}, "quantity": 3, "discountBasisPoints": 0, "taxCategory": "STANDARD"}], [{"description": "API calls", "unitPrice": {"minor": 1250, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}], [{"description": "First quarter 10%", "basisPoints": 1000, "amountOff": null, "duration": "repeating", "durationPeriods": 3, "startPeriod": 2}], 4, "GB", "2026-09-01"], "expect": {"currency": "GBP", "lines": [{"description": "Pro plan", "net": {"minor": 4900, "currency": "GBP"}, "tax": {"minor": 980, "currency": "GBP"}, "gross": {"minor": 5880, "currency": "GBP"}, "basisPoints": 2000}, {"description": "Extra seats", "net": {"minor": 3000, "currency": "GBP"}, "tax": {"minor": 600, "currency": "GBP"}, "gross": {"minor": 3600, "currency": "GBP"}, "basisPoints": 2000}, {"description": "API calls", "net": {"minor": 1250, "currency": "GBP"}, "tax": {"minor": 250, "currency": "GBP"}, "gross": {"minor": 1500, "currency": "GBP"}, "basisPoints": 2000}, {"description": "First quarter 10%", "net": {"minor": -915, "currency": "GBP"}, "tax": {"minor": -183, "currency": "GBP"}, "gross": {"minor": -1098, "currency": "GBP"}, "basisPoints": 2000}], "subtotal": {"minor": 8235, "currency": "GBP"}, "taxTotal": {"minor": 1647, "currency": "GBP"}, "total": {"minor": 9882, "currency": "GBP"}, "taxBreakdown": [{"basisPoints": 2000, "taxable": {"minor": 8235, "currency": "GBP"}, "tax": {"minor": 1647, "currency": "GBP"}}]}}, {"name": "the same coupon has run out by period 5", "args": [{"description": "Pro plan", "unitPrice": {"minor": 4900, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}, [{"description": "Extra seats", "unitPrice": {"minor": 1000, "currency": "GBP"}, "quantity": 3, "discountBasisPoints": 0, "taxCategory": "STANDARD"}], [{"description": "API calls", "unitPrice": {"minor": 1250, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}], [{"description": "First quarter 10%", "basisPoints": 1000, "amountOff": null, "duration": "repeating", "durationPeriods": 3, "startPeriod": 2}], 5, "GB", "2026-09-01"], "expect": {"currency": "GBP", "lines": [{"description": "Pro plan", "net": {"minor": 4900, "currency": "GBP"}, "tax": {"minor": 980, "currency": "GBP"}, "gross": {"minor": 5880, "currency": "GBP"}, "basisPoints": 2000}, {"description": "Extra seats", "net": {"minor": 3000, "currency": "GBP"}, "tax": {"minor": 600, "currency": "GBP"}, "gross": {"minor": 3600, "currency": "GBP"}, "basisPoints": 2000}, {"description": "API calls", "net": {"minor": 1250, "currency": "GBP"}, "tax": {"minor": 250, "currency": "GBP"}, "gross": {"minor": 1500, "currency": "GBP"}, "basisPoints": 2000}], "subtotal": {"minor": 9150, "currency": "GBP"}, "taxTotal": {"minor": 1830, "currency": "GBP"}, "total": {"minor": 10980, "currency": "GBP"}, "taxBreakdown": [{"basisPoints": 2000, "taxable": {"minor": 9150, "currency": "GBP"}, "tax": {"minor": 1830, "currency": "GBP"}}]}}, {"name": "a once coupon applies in its start period", "args": [{"description": "Pro plan", "unitPrice": {"minor": 4900, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}, [{"description": "Extra seats", "unitPrice": {"minor": 1000, "currency": "GBP"}, "quantity": 3, "discountBasisPoints": 0, "taxCategory": "STANDARD"}], [{"description": "API calls", "unitPrice": {"minor": 1250, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}], [{"description": "Welcome back", "basisPoints": null, "amountOff": {"minor": 500, "currency": "GBP"}, "duration": "once", "durationPeriods": null, "startPeriod": 5}], 5, "GB", "2026-09-01"], "expect": {"currency": "GBP", "lines": [{"description": "Pro plan", "net": {"minor": 4900, "currency": "GBP"}, "tax": {"minor": 980, "currency": "GBP"}, "gross": {"minor": 5880, "currency": "GBP"}, "basisPoints": 2000}, {"description": "Extra seats", "net": {"minor": 3000, "currency": "GBP"}, "tax": {"minor": 600, "currency": "GBP"}, "gross": {"minor": 3600, "currency": "GBP"}, "basisPoints": 2000}, {"description": "API calls", "net": {"minor": 1250, "currency": "GBP"}, "tax": {"minor": 250, "currency": "GBP"}, "gross": {"minor": 1500, "currency": "GBP"}, "basisPoints": 2000}, {"description": "Welcome back", "net": {"minor": -500, "currency": "GBP"}, "tax": {"minor": -100, "currency": "GBP"}, "gross": {"minor": -600, "currency": "GBP"}, "basisPoints": 2000}], "subtotal": {"minor": 8650, "currency": "GBP"}, "taxTotal": {"minor": 1730, "currency": "GBP"}, "total": {"minor": 10380, "currency": "GBP"}, "taxBreakdown": [{"basisPoints": 2000, "taxable": {"minor": 8650, "currency": "GBP"}, "tax": {"minor": 1730, "currency": "GBP"}}]}}, {"name": "a once coupon does not apply in the period after", "args": [{"description": "Pro plan", "unitPrice": {"minor": 4900, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}, [{"description": "Extra seats", "unitPrice": {"minor": 1000, "currency": "GBP"}, "quantity": 3, "discountBasisPoints": 0, "taxCategory": "STANDARD"}], [{"description": "API calls", "unitPrice": {"minor": 1250, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}], [{"description": "Welcome back", "basisPoints": null, "amountOff": {"minor": 500, "currency": "GBP"}, "duration": "once", "durationPeriods": null, "startPeriod": 4}], 5, "GB", "2026-09-01"], "expect": {"currency": "GBP", "lines": [{"description": "Pro plan", "net": {"minor": 4900, "currency": "GBP"}, "tax": {"minor": 980, "currency": "GBP"}, "gross": {"minor": 5880, "currency": "GBP"}, "basisPoints": 2000}, {"description": "Extra seats", "net": {"minor": 3000, "currency": "GBP"}, "tax": {"minor": 600, "currency": "GBP"}, "gross": {"minor": 3600, "currency": "GBP"}, "basisPoints": 2000}, {"description": "API calls", "net": {"minor": 1250, "currency": "GBP"}, "tax": {"minor": 250, "currency": "GBP"}, "gross": {"minor": 1500, "currency": "GBP"}, "basisPoints": 2000}], "subtotal": {"minor": 9150, "currency": "GBP"}, "taxTotal": {"minor": 1830, "currency": "GBP"}, "total": {"minor": 10980, "currency": "GBP"}, "taxBreakdown": [{"basisPoints": 2000, "taxable": {"minor": 9150, "currency": "GBP"}, "tax": {"minor": 1830, "currency": "GBP"}}]}}, {"name": "a forever coupon does not apply before its start period", "args": [{"description": "Pro plan", "unitPrice": {"minor": 4900, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}, [{"description": "Extra seats", "unitPrice": {"minor": 1000, "currency": "GBP"}, "quantity": 3, "discountBasisPoints": 0, "taxCategory": "STANDARD"}], [{"description": "API calls", "unitPrice": {"minor": 1250, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}], [{"description": "Annual loyalty", "basisPoints": 1000, "amountOff": null, "duration": "forever", "durationPeriods": null, "startPeriod": 6}], 5, "GB", "2026-09-01"], "expect": {"currency": "GBP", "lines": [{"description": "Pro plan", "net": {"minor": 4900, "currency": "GBP"}, "tax": {"minor": 980, "currency": "GBP"}, "gross": {"minor": 5880, "currency": "GBP"}, "basisPoints": 2000}, {"description": "Extra seats", "net": {"minor": 3000, "currency": "GBP"}, "tax": {"minor": 600, "currency": "GBP"}, "gross": {"minor": 3600, "currency": "GBP"}, "basisPoints": 2000}, {"description": "API calls", "net": {"minor": 1250, "currency": "GBP"}, "tax": {"minor": 250, "currency": "GBP"}, "gross": {"minor": 1500, "currency": "GBP"}, "basisPoints": 2000}], "subtotal": {"minor": 9150, "currency": "GBP"}, "taxTotal": {"minor": 1830, "currency": "GBP"}, "total": {"minor": 10980, "currency": "GBP"}, "taxBreakdown": [{"basisPoints": 2000, "taxable": {"minor": 9150, "currency": "GBP"}, "tax": {"minor": 1830, "currency": "GBP"}}]}}, {"name": "an amount coupon larger than the invoice takes it to zero, not below", "args": [{"description": "Starter plan", "unitPrice": {"minor": 1000, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}, [], [], [{"description": "Referral credit", "basisPoints": null, "amountOff": {"minor": 2500, "currency": "GBP"}, "duration": "forever", "durationPeriods": null, "startPeriod": 1}], 1, "GB", "2026-09-01"], "expect": {"currency": "GBP", "lines": [{"description": "Starter plan", "net": {"minor": 1000, "currency": "GBP"}, "tax": {"minor": 200, "currency": "GBP"}, "gross": {"minor": 1200, "currency": "GBP"}, "basisPoints": 2000}, {"description": "Referral credit", "net": {"minor": -1000, "currency": "GBP"}, "tax": {"minor": -200, "currency": "GBP"}, "gross": {"minor": -1200, "currency": "GBP"}, "basisPoints": 2000}], "subtotal": {"minor": 0, "currency": "GBP"}, "taxTotal": {"minor": 0, "currency": "GBP"}, "total": {"minor": 0, "currency": "GBP"}, "taxBreakdown": [{"basisPoints": 2000, "taxable": {"minor": 0, "currency": "GBP"}, "tax": {"minor": 0, "currency": "GBP"}}]}}, {"name": "a coupon across standard and zero-rated lines splits by net and is taxed per category", "args": [{"description": "Team plan", "unitPrice": {"minor": 10000, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}, [{"description": "Printed manual", "unitPrice": {"minor": 2500, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "ZERO"}], [], [{"description": "10% off", "basisPoints": 1000, "amountOff": null, "duration": "forever", "durationPeriods": null, "startPeriod": 1}], 3, "GB", "2026-09-01"], "expect": {"currency": "GBP", "lines": [{"description": "Team plan", "net": {"minor": 10000, "currency": "GBP"}, "tax": {"minor": 2000, "currency": "GBP"}, "gross": {"minor": 12000, "currency": "GBP"}, "basisPoints": 2000}, {"description": "Printed manual", "net": {"minor": 2500, "currency": "GBP"}, "tax": {"minor": 0, "currency": "GBP"}, "gross": {"minor": 2500, "currency": "GBP"}, "basisPoints": 0}, {"description": "10% off", "net": {"minor": -1000, "currency": "GBP"}, "tax": {"minor": -200, "currency": "GBP"}, "gross": {"minor": -1200, "currency": "GBP"}, "basisPoints": 2000}, {"description": "10% off", "net": {"minor": -250, "currency": "GBP"}, "tax": {"minor": 0, "currency": "GBP"}, "gross": {"minor": -250, "currency": "GBP"}, "basisPoints": 0}], "subtotal": {"minor": 11250, "currency": "GBP"}, "taxTotal": {"minor": 1800, "currency": "GBP"}, "total": {"minor": 13050, "currency": "GBP"}, "taxBreakdown": [{"basisPoints": 0, "taxable": {"minor": 2250, "currency": "GBP"}, "tax": {"minor": 0, "currency": "GBP"}}, {"basisPoints": 2000, "taxable": {"minor": 9000, "currency": "GBP"}, "tax": {"minor": 1800, "currency": "GBP"}}]}}, {"name": "coupons apply in order: half price then 10.00 off is 35.00, not 40.00", "args": [{"description": "Business plan", "unitPrice": {"minor": 9000, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}, [], [], [{"description": "Half price", "basisPoints": 5000, "amountOff": null, "duration": "forever", "durationPeriods": null, "startPeriod": 1}, {"description": "Loyalty credit", "basisPoints": null, "amountOff": {"minor": 1000, "currency": "GBP"}, "duration": "forever", "durationPeriods": null, "startPeriod": 1}], 2, "GB", "2026-09-01"], "expect": {"currency": "GBP", "lines": [{"description": "Business plan", "net": {"minor": 9000, "currency": "GBP"}, "tax": {"minor": 1800, "currency": "GBP"}, "gross": {"minor": 10800, "currency": "GBP"}, "basisPoints": 2000}, {"description": "Half price", "net": {"minor": -4500, "currency": "GBP"}, "tax": {"minor": -900, "currency": "GBP"}, "gross": {"minor": -5400, "currency": "GBP"}, "basisPoints": 2000}, {"description": "Loyalty credit", "net": {"minor": -1000, "currency": "GBP"}, "tax": {"minor": -200, "currency": "GBP"}, "gross": {"minor": -1200, "currency": "GBP"}, "basisPoints": 2000}], "subtotal": {"minor": 3500, "currency": "GBP"}, "taxTotal": {"minor": 700, "currency": "GBP"}, "total": {"minor": 4200, "currency": "GBP"}, "taxBreakdown": [{"basisPoints": 2000, "taxable": {"minor": 3500, "currency": "GBP"}, "tax": {"minor": 700, "currency": "GBP"}}]}}, {"name": "a percentage coupon rounds half-up to the penny: 15% of 9.99 is 1.50", "args": [{"description": "Solo plan", "unitPrice": {"minor": 999, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}, [], [], [{"description": "15% off", "basisPoints": 1500, "amountOff": null, "duration": "forever", "durationPeriods": null, "startPeriod": 1}], 1, "GB", "2026-09-01"], "expect": {"currency": "GBP", "lines": [{"description": "Solo plan", "net": {"minor": 999, "currency": "GBP"}, "tax": {"minor": 200, "currency": "GBP"}, "gross": {"minor": 1199, "currency": "GBP"}, "basisPoints": 2000}, {"description": "15% off", "net": {"minor": -150, "currency": "GBP"}, "tax": {"minor": -30, "currency": "GBP"}, "gross": {"minor": -180, "currency": "GBP"}, "basisPoints": 2000}], "subtotal": {"minor": 849, "currency": "GBP"}, "taxTotal": {"minor": 170, "currency": "GBP"}, "total": {"minor": 1019, "currency": "GBP"}, "taxBreakdown": [{"basisPoints": 2000, "taxable": {"minor": 849, "currency": "GBP"}, "tax": {"minor": 170, "currency": "GBP"}}]}}, {"name": "a proration credit goes in as an add-on and the coupon applies to what is left", "args": [{"description": "Pro plan", "unitPrice": {"minor": 2000, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}, [{"description": "Unused time on Basic", "unitPrice": {"minor": -500, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}], [], [{"description": "10% off", "basisPoints": 1000, "amountOff": null, "duration": "forever", "durationPeriods": null, "startPeriod": 1}], 7, "GB", "2026-09-01"], "expect": {"currency": "GBP", "lines": [{"description": "Pro plan", "net": {"minor": 2000, "currency": "GBP"}, "tax": {"minor": 400, "currency": "GBP"}, "gross": {"minor": 2400, "currency": "GBP"}, "basisPoints": 2000}, {"description": "Unused time on Basic", "net": {"minor": -500, "currency": "GBP"}, "tax": {"minor": -100, "currency": "GBP"}, "gross": {"minor": -600, "currency": "GBP"}, "basisPoints": 2000}, {"description": "10% off", "net": {"minor": -150, "currency": "GBP"}, "tax": {"minor": -30, "currency": "GBP"}, "gross": {"minor": -180, "currency": "GBP"}, "basisPoints": 2000}], "subtotal": {"minor": 1350, "currency": "GBP"}, "taxTotal": {"minor": 270, "currency": "GBP"}, "total": {"minor": 1620, "currency": "GBP"}, "taxBreakdown": [{"basisPoints": 2000, "taxable": {"minor": 1350, "currency": "GBP"}, "tax": {"minor": 270, "currency": "GBP"}}]}}, {"name": "a usage line keeps its own per-line discount", "args": [{"description": "Pro plan", "unitPrice": {"minor": 4900, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}, [], [{"description": "API calls (volume discount)", "unitPrice": {"minor": 100, "currency": "GBP"}, "quantity": 50, "discountBasisPoints": 1000, "taxCategory": "STANDARD"}], [], 1, "GB", "2026-09-01"], "expect": {"currency": "GBP", "lines": [{"description": "Pro plan", "net": {"minor": 4900, "currency": "GBP"}, "tax": {"minor": 980, "currency": "GBP"}, "gross": {"minor": 5880, "currency": "GBP"}, "basisPoints": 2000}, {"description": "API calls (volume discount)", "net": {"minor": 4500, "currency": "GBP"}, "tax": {"minor": 900, "currency": "GBP"}, "gross": {"minor": 5400, "currency": "GBP"}, "basisPoints": 2000}], "subtotal": {"minor": 9400, "currency": "GBP"}, "taxTotal": {"minor": 1880, "currency": "GBP"}, "total": {"minor": 11280, "currency": "GBP"}, "taxBreakdown": [{"basisPoints": 2000, "taxable": {"minor": 9400, "currency": "GBP"}, "tax": {"minor": 1880, "currency": "GBP"}}]}}, {"name": "a coupon with both a percentage and an amount is an error", "args": [{"description": "Pro plan", "unitPrice": {"minor": 4900, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}, [], [], [{"description": "Confused", "basisPoints": 1000, "amountOff": {"minor": 500, "currency": "GBP"}, "duration": "forever", "durationPeriods": null, "startPeriod": 1}], 1, "GB", "2026-09-01"], "expectError": "a discount needs exactly one of basisPoints and amountOff"}, {"name": "a coupon with neither is an error", "args": [{"description": "Pro plan", "unitPrice": {"minor": 4900, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}, [], [], [{"description": "Empty", "basisPoints": null, "amountOff": null, "duration": "forever", "durationPeriods": null, "startPeriod": 1}], 1, "GB", "2026-09-01"], "expectError": "a discount needs exactly one of basisPoints and amountOff"}, {"name": "a repeating coupon without a duration is an error", "args": [{"description": "Pro plan", "unitPrice": {"minor": 4900, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}, [], [], [{"description": "Forgot", "basisPoints": 1000, "amountOff": null, "duration": "repeating", "durationPeriods": null, "startPeriod": 1}], 1, "GB", "2026-09-01"], "expectError": "a repeating discount needs durationPeriods of 1 or more"}, {"name": "a percentage above 100% is an error", "args": [{"description": "Pro plan", "unitPrice": {"minor": 4900, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}, [], [], [{"description": "Too generous", "basisPoints": 12000, "amountOff": null, "duration": "forever", "durationPeriods": null, "startPeriod": 1}], 1, "GB", "2026-09-01"], "expectError": "discount basis points must be between 0 and 10000"}, {"name": "an amount coupon in another currency is an error", "args": [{"description": "Pro plan", "unitPrice": {"minor": 4900, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}, [], [], [{"description": "Euro credit", "basisPoints": null, "amountOff": {"minor": 500, "currency": "EUR"}, "duration": "forever", "durationPeriods": null, "startPeriod": 1}], 1, "GB", "2026-09-01"], "expectError": "currency mismatch"}, {"name": "period zero is an error", "args": [{"description": "Pro plan", "unitPrice": {"minor": 4900, "currency": "GBP"}, "quantity": 1, "discountBasisPoints": 0, "taxCategory": "STANDARD"}, [], [], [], 0, "GB", "2026-09-01"], "expectError": "period number must be 1 or more"} ]