Skip to content

Coupons (Khuyến mại)

  • What a coupon is and the four discount types it can carry.
  • How to scope a coupon (store, category, products, validity, max uses).
  • How to read redemption stats and act on poor ones.

The Messages screen is a separate preview surface — see Discounts & messages for that note.

A coupon is a code (e.g. SUMMER20) customers show at checkout. It maps to one of:

Discount typeExample
Percentage off20% off the order total.
Flat amount off30,000 VND off.
Buy X get YBuy 2 get 1 free.
Free shippingDelivery orders only.

Coupons can be limited to:

  • A store, a category, or specific products.
  • A time window (start / end date).
  • A usage count (max redemptions).

Sales activity → Discounts. The list shows:

Discounts list

  • Code (the customer-facing string).
  • Discount type + amount.
  • Validity window + status (Active / Inactive / Expired).
  • Redemptions (lifetime count + last used).
  1. + New coupon — give it a clear code the customer types or scans.
  2. Pick discount type and amount.
  3. Pick scope — applies to the whole order or restricted.
  4. Pick validity — start / end / max uses.
  5. Save.

Fields:

FieldRequired?Notes
CodeYesUppercase recommended. Unique per vendor.
Discount typeYesOne of the four above.
AmountYesPercent (1–100) or VND amount.
ScopeOptionalstore / category / product — leave empty for whole-order.
Min spendOptionalEnforce cart total ≥ X to apply.
Max usesOptionalHard cap on redemptions (per store / vendor).
Per-customer limitOptionalCap per phone / customer id.
ValidityOptionalStart + end date.
StatusDefault activeSet inactive to retire.

The create endpoint is POST /api/v1/vendor/coupons (see API catalog → “vendor-coupons”).

Open any coupon to see live usage:

  • Redeemed today / this week / all-time.
  • Discount given (sum).
  • Net revenue impact — sales tied to redemptions.
  • Average order size with vs without the coupon.

Set Status = Inactive from the coupon’s edit screen. Existing redemptions still count; new ones are blocked. The list still shows the row for history.

“Delete” is not exposed in the UI — instead set status to inactive to preserve audit history.

Both POS workspace and classic POS honour coupons:

  • Cashier pastes the code, or scans the printed barcode.
  • If the cart matches the scope, the discount line appears and the total drops.
  • If the cart does not match (no eligible items, expired, max uses hit), the POS shows a hint and refuses.

Coupon won’t apply at checkout. Check:

  • Status is Active.
  • Validity window covers today.
  • The order has at least one line that matches the scope (category / product).
  • The customer hasn’t hit the max uses rule.
  • Excluded items aren’t being discounted (the cashier app shows a hint).

Removing a coupon. Set status to Inactive. It stays in your list for history but cannot be redeemed.

Duplicate code on save. Codes are unique per vendor. Use a unique suffix (e.g. SUMMER20-HN).

Coupon applied but no discount shown. The cart line is in the excluded list — see the scope config on the coupon.

Coupons on refund. Refunds honor the original discount — see Step 4 — Returns.