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>
1.7 KiB
1.7 KiB
1. Coupon domain and contract
- 1.1 Add additive Postgres migrations for coupon templates, owned coupon snapshots, order coupon binding, and realized discount minor values.
- 1.2 Implement the Rust coupon module (DTOs, repository, service, handlers, router registration) with customer and shop RBAC/ownership boundaries.
- 1.3 Add
@vmall/sharedcoupon types, API-client methods, localized UI strings, and matching fixed-data adapter methods.
2. Atomic claims and checkout redemption
- 2.1 Implement conditional template stock claim and per-customer duplicate protection with valid-window checks.
- 2.2 Extend checkout request handling with per-shop coupon choices, server-side currency conversion and threshold validation, and persisted discounts.
- 2.3 Restore redeemed coupons atomically with stock when a pending-payment order is cancelled.
- 2.4 Add API integration coverage for claim contention, cross-shop/expired/ineligible rejection, multi-shop redemption, and cancellation restoration.
3. Merchant and customer surfaces
- 3.1 Add shop-admin coupon-template management and a coupons nav entry scoped to the authenticated shop.
- 3.2 Replace mall product-detail coupon strip, buyer coupon list, and checkout coupon selection with shared live-client calls; show persisted discount on payment and order-detail views.
- 3.3 Remove the affected direct coupon fixture imports while retaining the complete fixed-data adapter rollback surface.
4. Verification and specification
- 4.1 Seed deterministic coupon templates and verify the live claim-to-checkout-to-cancel flow against the API.
- 4.2 Run cargo test for vmall-api, builds for mall and shop-admin, and strict validation for this OpenSpec change.