Files
vmall/openspec/changes/add-shop-coupons/specs/order/spec.md
T
Chengdong ZhangandCursor 53548196f8 docs(openspec): plan shop coupons, accounts, points, flash sales, and group buying
Capture exclusive promotion composition, empty-group cancel, and mall surface scope so the five marketing changes can be implemented without stacking or lifecycle ambiguity.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 17:32:08 +08:00

2.2 KiB

MODIFIED Requirements

Requirement: Checkout splits by shop

POST /api/orders/checkout SHALL create one order per distinct shop in the cart, in a single database transaction: stock decrement, order + item insert with price snapshots, cart clear, and requested coupon redemption. All amounts use the cart's SKU currencies converted into the buyer-chosen display currency at checkout time. The request MAY select at most one owned coupon per generated shop order; the server SHALL validate its ownership, shop, status, validity window, threshold, and converted amount, then persist coupon_id, discount_minor, and the post-discount total_minor. The client SHALL NOT provide a discount amount. This requirement does not define activity prices; a later flash-sale or group-buying change that rewrites checkout SHALL restate these coupon clauses and SHALL reject a coupon on any shop order that applied an activity price.

Scenario: two shops → two orders

  • WHEN the cart contains SKUs from shops A and B
  • THEN two orders are created, each with only its shop's items, and the cart is empty

Scenario: insufficient stock

  • WHEN any line's qty exceeds SKU stock
  • THEN the whole checkout returns 409 and no order is created and stock is unchanged

Scenario: coupon applies to one matching shop

  • WHEN the customer selects an eligible coupon issued by shop A for a cart containing shops A and B
  • THEN only shop A's order records that coupon and its server-calculated discount

Requirement: Order lifecycle

Status transitions SHALL be: pending_payment → paid → fulfilling → shipped → completed; cancellable only from pending_payment, which MUST restore stock and restore a redeemed coupon to claimed status when the order has one.

Scenario: cancel restores stock

  • WHEN a customer cancels a pending_payment order
  • THEN stock of each SKU increases by the ordered qty and status is cancelled

Scenario: cancel restores coupon

  • WHEN a customer cancels a pending_payment order with a redeemed coupon
  • THEN the coupon is detached from the order and becomes claimed

Scenario: illegal transition rejected

  • WHEN cancelling a paid order via the customer endpoint
  • THEN the API returns 409