Files
ruoyi-vue-pro/docs/education/migration/issues/EDU-030-native-trade-after-sale.md

37 lines
4.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# EDU-030 — Activate native Trade after-sale
- **Status:** done — tenant-owned after-sale persistence, native state machine, Pay Refund bridge, RBAC, corrected Vben UI, and PostgreSQL evidence delivered
- **Type:** native module takeover / refund lifecycle / tenant isolation
- **Phase:** 5 / commercialization foundation
- **Blockers:** EDU-022, EDU-025, EDU-027, EDU-029, PostgreSQL Flyway
## Problem
The source backend stores order-level UUID rows in `public.commerce_refund_requests` and append-only `public.commerce_refund_events`, with statuses `requested`, `approved`, `processing`, `succeeded`, `failed`, `rejected`, and `cancelled`. RuoYi already owns a richer line-item after-sale state machine: Member application, administrator agree/disagree, return logistics, receipt/refusal, Pay Refund creation/callback, order-item state updates, immutable operation logs, exact RBAC, and an existing Vben list/detail page. Reimplementing that lifecycle in Education would create a second refund ledger and bypass native Trade/Pay coordination.
## Delivered contract
- `AfterSaleDO` and `AfterSaleLogDO` extend `TenantBaseDO`; existing app/admin controllers, `AfterSaleServiceImpl`, `AfterSaleLogServiceImpl`, order updates, and `PayRefundApi` remain authoritative.
- V4420 creates `trade_after_sale` and `trade_after_sale_log` with explicit sequences and `(tenant_id,id)` ownership. Order, order item, SPU, SKU, Pay Refund, delivery express, log, and order-item back-reference constraints are tenant-qualified.
- Database checks enforce native status/type/way values, non-negative amounts, required audit/return/refund facts, JSON arrays, valid log actor/operation/status values, unique tenant numbers, and at most one active after-sale per order item.
- Menu IDs 70107015 reuse `mall/trade/afterSale/index` with exactly `trade:after-sale:query`, `agree`, `disagree`, `receive`, and `refund` permissions.
- The Vben page sends the backend's `auditReason` field, requires `refuseMemo` in a locked/validated refusal modal, displays the actual application `createTime`, and guards every action with its exact permission. Backend request validation now rejects blank refusal notes and the detail response exposes `createTime`.
## Legacy data decision
V4420 starts the native after-sale ledger empty. A source request identifies an aggregate UUID order but does not identify a verified native Member, `trade_order_item`, SPU/SKU allocation, return quantity, delivery company, or Pay Refund row. Its status history also does not prove the native line-item and return-logistics transitions. Automatic import would invent ownership and lifecycle facts, so explicit legacy refund import is deferred until legacy Product, Order, Order Item, and Member mappings are reviewed.
## Verification
- The after-sale tenant contract proves both native records participate in framework tenant isolation.
- The focused V4420 Flyway scenario proves cross-tenant identifier reuse, tenant-qualified ownership/back-references, two explicit sequences, audit/log rejection, exact route/permissions, and fail-closed adoption of a pre-existing global table.
- A Spring/MyBatis PostgreSQL integration test imports the real services and production tenant SQL interceptor, creates same-ID Product/Order/Order Item fixtures in tenants 10 and 20, and proves isolated create, page, detail, and log reads plus order-item update calls.
- The full PostgreSQL Flyway suite passes 49 scenarios through V4420. The server reactor compiles, and the corrected Vben page passes typecheck plus scoped oxlint/oxfmt checks.
## Explicitly open
- Trade brokerage and special-order Promotion families remain separate native activation slices.
- Legacy Product/coupon/order/refund import requires explicit UUID-to-native mappings and reconciliation artifacts; V4420 does not reinterpret source refunds.
- Configured target Pay App/Channel data and a deployed order/payment/refund smoke are still required for end-to-end production evidence.
- Purchase-driven Education entitlement fulfillment and refund-driven entitlement revocation remain separate orchestration work.