Skip to content

CAP-COM-CAT-016Choose the best permitted promotional result

Markdown

CAP-COM-CAT-016

Choose the best permitted promotional result

Markdown
  • DocumentDraft
  • Product intentProposed
  • ImplementationObserved

KindCapabilityProduct areaCommerceModuleCatalog and Selling ConfigurationRevision1

Read atservices-commerce c8b66a98

The Formal Contract

The narrative above explains; the sections below are authoritative — the rules, scenarios and tests this document binds.

Outcomes
A buyer is does not worse off for entering a code.Line-level allocations retain a common monetary basis for tax and later financial processing.A use is counted exclusively when a promotion actually gave something.
Surfaces
portalconsoleapi
Intent sources
services-commerce:docs/milestones/decisions/COMM-M1-D12-andrew-2026-10-19.mdservices-commerce:docs/milestones/decisions/COMM-M1-D12-evaluation-algorithm.md#7. Andrew’s answersservices-commerce:docs/milestones/COMM-M1-set-up-what-you-sell.md#D12-F1 to D12-F5services-commerce:docs/milestones/COMM-M1b-promotions-and-codes.md#Decisions (D-R3)

Controls

29 controls apply, from the corpus control catalogue.

TC-IAM-006 TC-AZ-001 TC-AZ-002 TC-AZ-003 TC-AZ-004 TC-AZ-006 TC-TEN-001 TC-TEN-002 TC-TEN-003 TC-TEN-004 TC-CRY-001 TC-CRY-004 TC-DAT-001 TC-DAT-002 TC-DAT-003 TC-LOG-004 TC-LOG-005 TC-AVL-004 TC-AVL-005 TC-MON-001 TC-MON-002 TC-MON-004 TC-PI-001 TC-PI-002 TC-PI-003 TC-PI-004 TC-PI-005 TC-PRV-001 TC-PRV-002

Permissions

KeyChecked atScope
commerce.checkouts.updateapitenant
commerce.orders.createapitenant

Business Rules

15 rules, 15 to be proved before approval. A rule's product intent is derived from its origin: 10 confirmed by a product decision, the rest inheriting this capability's proposed.

IdRuleKindEnforced atProvenance
01must prove
Confirmed
Price selection returns the cheapest result permitted by the customer’s pricing and promotion combination rules.
origin: COMM-M1 D12 (docs/milestones/decisions/COMM-M1-D12-andrew-2026-10-19.md)
no proof recorded yet
invariantservicetest
02must prove
Confirmed
Combinable promotions discount audience prices; noncombinable promotions discount Standard instead, with the cheaper valid outcome retained for every audience.
origin: COMM-M1 D12 (docs/milestones/decisions/COMM-M1-D12-andrew-2026-10-19.md)
no proof recorded yet
calculationservicetest
services-commerce:modules/promotions/tests/unit/pricing/alternatives.spec.js#2. combine = no, member: audience pricing $80.00 against $100.00 less 25 % = $75.00; the promotional price wins
03must prove
Confirmed
The evaluator explores all combinations of up to four noncombinable promotions, then considers additional promotions in entry order and retains only improvements.
origin: COMM-M1 D12 Q1 (docs/milestones/decisions/COMM-M1-D12-evaluation-algorithm.md)
no proof recorded yet
calculationservicetest
services-commerce:modules/promotions/tests/unit/pricing/alternatives.spec.js#tries the fifth and later one at a time in entry order
04must prove
Confirmed
Line benefits precede order benefits, and each group applies priority-ordered automatic promotions before entry-ordered codes against the previous result.
origin: COMM-M1 D12 Q2 (docs/milestones/decisions/COMM-M1-D12-evaluation-algorithm.md)
no proof recorded yet
calculationservicetest
services-commerce:modules/promotions/tests/unit/pricing/stacking.spec.js#D12 Q2: puts the line-level promotions before the order-level amounts, each group automatic then codes
05must prove
Confirmed
Exclusive benefits replace automatic discounts on their covered lines and cannot share a line with another code; combinations of up to four exclusive codes compete only when they reduce the total.
origin: COMM-M1 D12 Q5 (docs/milestones/decisions/COMM-M1-D12-evaluation-algorithm.md)
no proof recorded yet
calculationservicetest
services-commerce:modules/promotions/tests/unit/pricing/alternatives.spec.js#Q5: every combination of the exclusive codes: the better of two exclusive codes wins whatever the order entered
06must prove
Confirmed
Alternatives compare totals before tax and shipping, minimum purchase uses qualifying lines after line discounts, and tied results retain audience pricing without consuming the code.
origin: COMM-M1 D12 Q3, Q4, Q7 (docs/milestones/decisions/COMM-M1-D12-evaluation-algorithm.md)
no proof recorded yet
calculationservicetest
services-commerce:modules/promotions/tests/unit/pricing/alternatives.spec.js#Q4: a tie goes to audience pricing, and the tied code is not used up
08must prove
Proposed
Percentage benefits round to whole minor units with exact halves increasing the discount in the buyer’s favour.
origin: COMM-M1 D12-F3 (docs/milestones/COMM-M1-set-up-what-you-sell.md)
no proof recorded yet
calculationservicetest
services-commerce:modules/promotions/tests/unit/pricing/benefits.spec.js#takes 15% off 3333 as 500 (499.95 rounded half up)
09must prove
Confirmed
Order discounts and caps allocate proportionally to eligible lines by largest remainder, with earlier lines breaking ties and each allocation retained for tax and accounting.
origin: COMM-M1 D12 point 6 (docs/milestones/decisions/COMM-M1-D12-andrew-2026-10-19.md)
no proof recorded yet
calculationservice, databasetest
services-commerce:modules/promotions/tests/unit/pricing/allocation.spec.js#shares 3000 over 10000, 5000 and 2500 as 1714, 857, 429: the largest fraction gets the unit
10must prove
Proposed
Tax, shipping and fee lines and promotion-excluded products receive no ordinary discount; shipping benefits reduce the rated shipping charge to no less than zero, with tax on its net amount.
origin: COMM-M1 D4 (docs/milestones/COMM-M1-set-up-what-you-sell.md)
no proof recorded yet
policyservicetest
services-commerce:modules/promotions/tests/unit/pricing/apply-promotions.spec.js#never touches a tax, shipping or fee line, nor a product excluded from promotions
11must prove
Proposed
Code refusal follows the defined sequence of identity, state, dates, currency, usage, purchaser restrictions, authentication, eligibility, matching lines and minimum purchase, using customer messages that conceal private limits and rules.
no proof recorded yet
validationservicetest
services-commerce:modules/promotions/tests/unit/pricing/validation.spec.js#answers the first refusal in the order of 10.3: an inactive code before an exhausted one
12must prove
Confirmed
Valid but ineffective codes remain recorded as unapplied without consuming usage, including line conflicts and business-unit mismatch; invalid codes prevent placement.
origin: COMM-M1 D12 point 8 (docs/milestones/decisions/COMM-M1-D12-andrew-2026-10-19.md)
no proof recorded yet
policyservicetest
services-commerce:modules/promotions/tests/unit/pricing/apply-promotions.spec.js#refuses a promotion whose benefit is zero on every qualifying line (an amount off a line already free)
13must prove
Proposed
Unavailable eligibility decisions refuse qualification, and restricted anonymous buyers receive a sign-in request before eligibility rejection.
no proof recorded yet
policyservicetest
services-commerce:modules/promotions/tests/unit/pricing/validation.spec.js#fails closed on an indeterminate verdict, for must_match and for must_not_match alike
14must prove
Confirmed
The breakdown identifies line discounts and better audience or automatic alternatives, while invoice discount descriptions use customer-facing promotion names.
origin: COMM-M1 D12 point 8 (docs/milestones/decisions/COMM-M1-D12-andrew-2026-10-19.md)
no proof recorded yet
policyservicetest
services-commerce:modules/promotions/tests/unit/pricing/reason-codes.spec.js#says in the customer’s words that the audience price was better, with both totals
15must prove
Proposed
Unavailable selling-area checks leave parts unapplied during preview and prevent placement with a retry message and no saved sale.
origin: COMM-M1b D-R3 (docs/milestones/COMM-M1b-promotions-and-codes.md)
no proof recorded yet
policyservicetest
services-commerce:modules/promotions/tests/unit/pricing/parts.spec.js#refuses a code promotion_check_unavailable when a part is listed unavailable, and discounts nothing
16must prove
Confirmed
Concurrent placement respects usage limits, with exactly one hundred successful uses when two hundred placements compete for one hundred available uses.
origin: COMM-M1 plan A15 (promotions D-05) (docs/milestones/plans/COMM-M1-plan.md)
no proof recorded yet
invariantservice, databasetest

Scenarios

IdGivenWhenThenProvenance
01The buyer holds Member pricing and enters a noncombinable quarter-off codeCompare the audience amount with the discounted Standard amountSeventy-five-dollar promotional pricing beats the eighty-dollar audience amounttest
services-commerce:modules/promotions/tests/unit/pricing/alternatives.spec.js#2. combine = no, member: audience pricing $80.00 against $100.00 less 25 % = $75.00; the promotional price wins
02Student pricing is sixty dollars against a seventy-five-dollar promotional alternativeEnter the same noncombinable code as StudentAudience pricing remains selected, usage stays unchanged and an explanation is returnedtest
services-commerce:modules/promotions/tests/unit/pricing/alternatives.spec.js#3. combine = no, student at $60.00: audience pricing wins, EARLY25 consumes no use, and the buyer is told why
03Automatic Fall pricing beats the exclusive VIP5 benefitEvaluate the entered VIP5 codeFall remains applied and VIP5 is unused with its reasontest
services-commerce:modules/promotions/tests/unit/pricing/alternatives.spec.js#5. exclusive code against the automatic outcome: VIP5 (5 %) would give $76.00, Fall 10 % gives $72.00; VIP5 is dropped and consumes no use

Edge Cases

IdGivenWhenThenProvenance
04The code has capacity for one hundred usesRun two hundred simultaneous placementsOne hundred apply and the others receive exhausted-capacity refusalstest

The Markdown files under specs/ in rhythmsoftware/rhythm-v2-docs are the canonical source of truth. This reader is a generated, read-only projection of them.