Skip to content

Coupons

Flow ID: CF-13 | Module(s): coupons, Promotion domain | Complexity: High

Business Overview

Coupons offer percentage or fixed-amount discounts with hierarchical targeting. A master template defines the discount; individual codes are generated from it. Validation checks date ranges, usage limits, audience restrictions, cart totals, and product/category/vendor/tag restrictions with configurable AND/OR logic.

Key business behaviors:

  • Percentage discount: hierarchical cascade — vendor → product → category → tag → all items
  • Fixed discount: direct subtraction from cart total (no targeting)
  • Coupon codes tracked individually: each has is_sent and is_used counters
  • Auto-applied default coupon: is_default=1 coupon applied automatically if valid
  • Audience targeting: coupon can restrict to specific customer segments

API Reference

REST Endpoints

MethodPathAuthDescription
GET/rest/promotion/couponBackendList coupons
POST/rest/promotion/couponBackendCreate coupon
GET/rest/promotion/coupon-codeBackendList coupon codes
GET/rest/promotion/coupon-ruleBackendList rules
POST/rest/checkout/coupon/validateGuest/CustomerValidate coupon against cart

CouponCode, CouponProduct, CouponRule, CouponVendor — all in src/Rest/Promotion/Controllers/


Validation Chain (isValidCoupon())

Sequential checks (returns false on first failure):

  1. Code exists in coupons table
  2. is_sent = 1 (distributed)
  3. is_used < max_count_usage
  4. Date range: date_start <= NOW <= date_end
  5. Audience: customer in coupon's audience segment
  6. Cart subtotal: total_cart_from <= cartTotal <= total_cart_to
  7. Vendor restrictions (AND/OR logic)
  8. Category restrictions (AND/OR logic, includes children)
  9. Tag restrictions (AND/OR logic)
  10. Product restrictions (AND/OR logic)

New features (2024 migrations): categories_rule_type and tags_rule_type columns added to coupon_rules — support AND/OR logic for category and tag restrictions.


Discount Calculation

Percentage (calculateCartDiscountPercent())

Priority cascade — first match wins:

  1. Vendor-restricted items → apply discount
  2. Product-restricted items → apply discount
  3. Category-restricted items → apply discount
  4. Tag-restricted items → apply discount
  5. All cart items → apply discount (no restrictions)

Formula per item: round(final_price × quantity × discount_percent / 100, 2)

Fixed (calculateCartDiscountPrice())

Simple: cart_total_vat -= discount_price. No product/vendor filtering.


Client Extension Points

  • Validation: Override isValidCoupon() for custom rules
  • Discount calculation: Override calculateCartDiscountPercent() for custom logic
  • Registry: Audience targeting via audienceId field
  • REST Validator: Custom rules in Domain layer

Data Model

TablePurpose
couponMaster template (discount %, price, max usage, is_default)
couponsIndividual codes (code, is_sent, is_used)
coupon_rulesDate range, cart/price thresholds, AND/OR logic
coupon_vendors/categories/product_tags/productsRestriction targets

For full column-level schema details, see AD-08 Coupon Management.