Files
vmall/openspec/changes/add-flash-sales/specs/order/spec.md
T
james cc07ac3230 chore(openspec): archive add-shop-coupons
Sync the shop-coupons capability plus the order, frontend-mall, and
frontend-shop-admin requirements into the main specs, and write the capability
Purpose the archive leaves as a placeholder.

Renaming the coupon scenario in the flash-sales and group-buying order deltas
to the exact name now in the main order spec keeps those changes archivable,
since a MODIFIED requirement replaces the whole block.
2026-09-18 12:13:49 +00:00

3.1 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, active flash-sale resolution, and requested coupon redemption when eligible. All amounts use the cart's SKU currencies converted into the buyer-chosen display currency at checkout time. For each cart line the server SHALL resolve an eligible active flash-sale item, enforce its remaining stock and customer limit, snapshot the final unit price and applied activity identity, and charge standard price for quantity not eligible for the activity. A SKU that is also eligible for group-buying in an overlapping window SHALL cause checkout to return 409. The request MAY select at most one owned coupon per generated shop order; the server SHALL validate 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. If any line on that shop order applied flash-sale pricing, the server SHALL reject a coupon for that shop with 409.

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 or applicable flash-sale stock
  • THEN the whole checkout returns 409 and no order is created and stock is unchanged

Scenario: active flash price applied

  • WHEN checkout contains a SKU with an active eligible flash-sale item
  • THEN the order item records the server-calculated flash-sale price and activity identity

Scenario: coupon applies to one matching shop

  • WHEN the customer selects an eligible shop coupon and that shop's generated order has no flash-priced lines
  • THEN the order records that coupon and its server-calculated discount

Scenario: coupon rejected on a flash-priced shop order

  • WHEN the customer selects a coupon for a shop whose generated order applied flash-sale pricing on any line
  • THEN checkout returns 409 and creates no orders

Requirement: Order lifecycle

Status transitions SHALL be: pending_payment → paid → fulfilling → shipped → completed; cancellable only from pending_payment, which MUST restore SKU stock, any reserved flash-sale activity stock consumed by the order, and 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 and its applied flash-sale activity 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