Discount Scope Rules
Discounts support two explicit application scopes:-
Total purchase
- Applies to registration rates, products, and custom amount fields.
- Service fees (organizer / platform commission) are never discounted and are always calculated on the pre-discount item base (including any configured minimum, e.g. 3 EUR).
- If the discount amount exceeds the sum of cart items, the surplus is not applied against the service fee.
-
Rates only
- Applies exclusively to registration rates.
- Products, booking add-ons, and custom amount inputs remain untouched.
- Organizer fees are not affected.
is_free_code) waives the service fee. A
100% (or higher) percentage discount that is not flagged as free still zeroes its
discounted base but leaves the service fee untouched, exactly like any other percentage
(e.g. 25%). Whether a free code leaves the whole order at 0 still depends on the chosen
scope: with Total purchase the whole cart (rates, products, add-ons) is zeroed, plus
the fee; with Rates only just the registration rate and the fee are zeroed, and any
store products or add-ons in the cart are still charged. The scope selector is
independent of the free-code flag — marking a code as free no longer forces or locks
the scope.
If neither flag is selected (legacy data), the behaviour matches the previous
implementation: the discount targets the sum of cart items but not organizer fees.
When creating or editing a discount, the UI enforces mutual exclusivity between the two
options and defaults to Rates only for new entries.
Interaction with the unreconciled-subtotal payment guard
Order creation is protected byOrder::hasUnreconciledSubtotal(), which blocks the
payment step (Redsys and Stripe alike) if a non-group, non-rate-change order has
exactly one order item with qty == 1 and subtotal exceeds that item’s line_amount
by more than 0.02. A valid discount can only ever lower the subtotal relative to the
line amount, never raise it, so an order with a correctly applied discount will never
trip this guard. If a payment fails with this guard’s error while a discount is applied,
the discount calculation itself is very unlikely to be the cause — check for a
duplicated or stale subtotal on the order instead.
Note: this document covers scope rules only. For discount types, combination
(cumulative) and multi-event general coupons, see the organizer guide at
Discounts and codes.
