4.1 KiB
4.1 KiB
1. Persistence and shared contract
- 1.1 Add migration
0017_aftersales.sqlwithaftersalesand append-onlyaftersale_messagestables, order/customer/shop/order-item foreign keys,refund_only/return_refundtype checks, status checks, i64 minor-unit amounts, evidence URL arrays, localized JSONB reason/content fields, timestamps, ownership indexes, and a partial unique index allowing only one active aftersale perorder_item_id. - 1.2 Add shared aftersale enums, DTOs, paginated summaries, state/action types, bilingual reason/message fields, and API client methods for customer, shop-admin, and platform-admin flows. Keep all money as integer minor units and expose
refund_total_minor/remaining refundable amounts from the contract.
2. Rust aftersale module and behavioral proof
- 2.1 Implement
apps/api/src/modules/aftersale/repository, service, DTO, handlers, routes, and module registration for customer applications/list/detail/cancel/reopen/messages/return tracking, shop processing, and platform arbitration. - 2.2 Enforce paid-or-shipped order-item eligibility, configured post-confirmation window, amount not exceeding the guarded remaining refundable amount, evidence URL validation, one active aftersale per line, customer ownership,
own_shopscope for shop roles, and platform-admin arbitration. - 2.3 Implement guarded state transitions:
pendingtoapprovedorrejected; return-refundapprovedtobuyer_shippingtomerchant_confirmedtorefunded; cancellation from any non-terminal pending state; one rejected-to-pendingreopen appeal. Reject stale transitions with 409. - 2.4 Complete refunds transactionally: conditionally update the aftersale and order refund total, append one
customer_accountsledger credit, emit the hookablerefund_completedevent, and make retries idempotent so no duplicate credit is possible. - 2.5 Add focused API integration tests under
apps/api/tests/reusingtests/common/mod.rsfor eligibility/window boundaries, amount guards, uniqueness, ownership/RBAC, every transition and illegal transition, one-time reopen, messages, ledger/order totals, concurrent completion, and idempotent retry.
3. Mall customer surfaces and adapter parity
- 3.1 Add the aftersale methods and deterministic mutable fixtures to
apps/mall/mock/api.ts, preserving the shared contract for applications, messages, cancellation, reopen, return tracking, and refund totals. - 3.2 Add the aftersale domain and exact method picks to Mall
LIVE_PICKS; keep fixed fallback behavior and localized en/zh labels in@vmall/shared. - 3.3 Add Mall order-detail eligible-item entry, aftersale list/detail, reason/amount/evidence form, bilateral message thread, cancel/reopen actions, and return-shipping tracking form, with sign-in redirect and reload-safe state.
4. Merchant and platform console surfaces
- 4.1 Add shop-admin aftersale workspace with shop-scoped list/detail filters, item and evidence display, bilingual messages, approve/reject actions, return-receipt-and-refund action, and guarded error states.
- 4.2 Add platform-admin read-only aftersale list/detail and dispute arbitration actions for terminal refund or rejection, with role-protected routes and visible ledger/order-total outcomes.
- 4.3 Route all three frontends through
@vmall/sharedcontracts and@vmall/uiprimitives; do not duplicate API types or bypassown_shopauthorization.
5. Verification
- 5.1 Run the aftersale integration tests in
apps/api/tests/with the sharedtests/common/mod.rsfixtures and exercise customer, merchant, and platform paths. - 5.2 Build affected frontends:
pnpm --filter @vmall/mall build,pnpm --filter @vmall/shop-admin build, andpnpm --filter @vmall/admin build. - 5.3 Browser-smoke the Mall application/detail/message/cancel/return-tracking/refund-history flow, shop-admin processing, and platform arbitration against the local stack, including fixed-adapter fallback.
- 5.4 Run
openspec change validate add-aftersale-refunds --strictandopenspec validate --all --strict.