Coupon test matrix

Standing cases for the dev coupon flow. Source of truth for payloads is the coupon test sheet, tab test result - dev website. Run them with run-coupon-test-matrix.

Status as of 2026-07-29 (deploy 094bd0c)

#TypeCouponStatus
1, 2bogo, same / different SKU1260002128, 1260002754pass
5, 6buy 2 get 1, same / different SKU1260002828, 1260002848pass
7two-for-X, same SKU1260002784pass — was “no discount”
8two-for-X, different SKU1260002613pass — was “no discount”
9fixed, min 2000 save 50MINDIS50pass
10specific SKU, 150 offHACOD150pass — was “no discount”
11shipping discount 50TSHIPDISpass — was waiving all 90
11bshipping discount 50, expressTSHIPDISpass — was waiving all 90
12, 13free shipping, regular / expressFREESHIPpass

Fixes behind the four recoveries: 2026-07-29-coupon-test-sheet-failures.

The assertion that catches everything

Every response must balance. Both bugs above showed up as a failure of this identity before anyone looked at a coupon:

expected = subTotal + deliveryFee + expressShippingCost - totalDiscount - shippingDiscount
assert abs(grandTotal - expected) < 0.01

Omitting expressShippingCost makes correct express orders look wrong by exactly 50 baht — that is a bug in the check, not in the response.

Gaps worth adding

The current sheet exercises one coupon type at a time, almost always on NATIONWIDE. These are untested and each maps to a plausible failure:

Percentage with maxDiscountAmount. The same capped-amount shape that broke TSHIPDIS. A percentage coupon that hits its cap should discount the cap, not the raw percentage.

Shipping discount larger than the delivery fee. Should clamp at the fee. A negative delivery fee would flow straight into the grand total.

Two-for-X where the set subtotal is below the discount. Per-set cap should bind, so the discount never exceeds what the items cost.

The same coupon across all three shipping modes. Fees differ (90 regular, 90+50 express, 115 nationwide) and only nationwide is covered today.

appOnly / webOnly with the wrong orderSource. Should land in failedCoupons, not apply silently.

Expired and not-yet-started coupons. This was the original report that started the July investigation and still isn’t a standing case.

Controlled products with excludeControlledProducts. Alcohol should drop out of the applicable total.

Stacking — bogo + two-for-X + free shipping on one basket, asserting the Discount line in the UI equals the drop in Total. Every bug so far has been a single-coupon case; the stacked path is unexercised.

Below minOrderAmount. Should produce no discount and no error. Distinguishing this from a broken coupon is currently guesswork for testers.

UI checks the API cannot cover

The API being right does not mean the customer sees it right — row 10 was correct at the API level for weeks while the UI showed 0.

  • The Discount line equals the drop in Total
  • Shipping discount appears as its own line
  • Regular is selectable for a Bangkok address (2026-07-29-shipping-forced-nationwide)
  • Network calls go to /api/calculatePrice/calculateCost2, never to m4q33ulvm9