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

4.0 KiB
Raw Blame History

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.