Shop-scoped threshold rules with bilingual names, integer threshold/reduction (reduction < threshold), active windows and display order. Checkout applies the best eligible rule per shop with currency conversion; coupon/threshold/activity pricing are mutually exclusive per shop order. Reduction persists in orders.discount_minor + threshold_promotion_id and flows into payment totals; checkout idempotency covers the threshold selection. Delete archives referenced rules, hard-deletes unreferenced ones. - migration 0026: threshold_promotions + orders.threshold_promotion_id + coupon/threshold exclusivity CHECK - api: modules/promotion (CRUD, preview, checkout integration) - shared: ThresholdPromotion types, shop CRUD + preview client methods, checkout threshold_by_shop - shop-admin: promotions page + nav + en/zh locales - mall: exclusive promotion radio on checkout, live preview wiring, threshold label on order detail - tests: promotions.rs (scoping, validation, best-rule, exclusivity, activity-priced 409, totals, replay, archive-vs-delete) - openspec: archived 2026-10-19-add-threshold-promotions; spec threshold-promotions created, order/frontend specs updated
3.5 KiB
3.5 KiB
Index: Order & Freight
Domain design: docs/domains/orders.md. Specs: openspec/specs/order/,
shipment/, shipping/, payment/ (change add-configurable-payments).
Backend (apps/api)
| File | Holds |
|---|---|
src/modules/order/service.rs |
checkout transaction (payment membership + header-hash idempotency), cancel, shipping quote |
src/modules/order/repo.rs |
ORDER_COLS/ORDER_ITEM_COLS, insert_order/insert_item, locks, status transitions |
src/modules/order/handlers.rs |
/orders* customer routes, /shop/orders*, /admin/orders |
src/modules/order/dto.rs |
OrderView, AddressBody, ShippingQuoteView |
src/modules/payment/service.rs |
payment resolution, eligible methods, attempts, wallet collection, group cancellation |
src/modules/payment/repo.rs |
payments/memberships/checkout_requests/attempts/receipts/refunds/commands/events rows |
src/modules/payment/adapters.rs |
wallet + Stripe crypto-only Checkout adapter boundary, capabilities |
src/modules/payment/worker.rs |
durable command lease/execute/recovery, supervised worker |
src/modules/payment/webhooks.rs |
raw-body Stripe signature/timestamp verification, dedup inbox |
src/modules/payment/refunds.rs |
original-method refund budgets, wallet/Stripe refund submission |
src/modules/payment/admin.rs |
channel CRUD/revisions/audit/verify, operations list/detail, reconcile |
src/modules/payment/handlers.rs |
/payments* owner routes, /admin/payments*, /payments/webhooks/stripe/{id} |
src/modules/payment/dto.rs |
payment DTOs, text enums, config shapes |
src/modules/fulfillment/ |
shipments: create (company-validated), ship, confirm-delivered |
src/modules/freight/service.rs |
template CRUD, region rules, shop_fee() calculation, company dictionary |
src/modules/freight/handlers.rs |
/shop/freight-templates*, /shipping/companies |
migrations/0004_orders.sql |
orders/order_items/shipments base schema |
migrations/0017_freight_templates.sql |
freight tables, orders.shipping_fee_minor, item snapshots, skus.weight_grams |
migrations/0024_payments.sql |
payments domain, legacy-demo provenance, aftersale refund states |
migrations/0025_checkout_request_header_hash.sql |
cart-independent header hash for checkout idempotency |
migrations/0026_threshold_promotions.sql |
threshold rules, orders.threshold_promotion_id, coupon/threshold exclusivity check |
tests/orders.rs, tests/freight.rs, tests/payments.rs |
integration coverage |
Shared contract (packages/shared/src)
types.ts: Order, OrderItem, Shipment, FreightTemplate*,
ShippingCompany, ShippingQuote, Payment, CheckoutResult,
PaymentAttemptResult, EligibleMethod, NextAction, PaymentChannel*,
PaymentOperation*, RefundOperation. api.ts: checkout,
resolvePayment, getPayment, listPaymentMethods, createPaymentAttempt,
cancelPayment, quoteShipping, listShippingCompanies, shop freight CRUD,
createShipment, admin channel/operations/reconcile methods.
Frontends
- Mall:
pages/checkout/{index,pay,success}.vue,pages/user/orders/,pages/user/addresses.vue - Mobile:
pages/checkout/,pages/orders/(configured payment + return handling) - Shop-admin:
pages/orders/,pages/shipments.vue,pages/freight-templates.vue,components/ProductForm.vue(freight template + SKU weight) - Admin:
pages/orders.vue(read-only),pages/payment-channels.vue,pages/payments.vue(operations list/detail/reconcile)