Files
ruoyi-vue-pro/docs/education/migration/issues/EDU-028-native-checkout-promotions.md

37 lines
3.3 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-028 — Activate native checkout Promotion activities
- **Status:** done — tenant-owned discount/reward persistence, native APIs/UI, RBAC, and PostgreSQL evidence delivered
- **Type:** native module takeover / checkout dependency / tenant isolation
- **Phase:** 5 / commercialization foundation
- **Blockers:** EDU-025, EDU-026, EDU-027, PostgreSQL Flyway
## Problem
Every normal RuoYi Trade price calculation invokes the native limited-time discount and reward calculators. Those calculators call `DiscountActivityApi` and `RewardActivityApi` even when no activity is configured, so V4390's order core still failed with missing Promotion tables before it could return an empty promotion result. Replacing these APIs inside Education would duplicate Promotion ownership and bypass the native administration UI.
## Delivered contract
- `DiscountActivityDO`, `DiscountProductDO`, and `RewardActivityDO` extend `TenantBaseDO`; their existing services, mappers, controllers, and public APIs remain authoritative.
- V4400 creates tenant-scoped `promotion_discount_activity`, `promotion_discount_product`, and `promotion_reward_activity` tables with explicit PostgreSQL sequences and `(tenant_id,id)` ownership keys.
- Discount Product → Activity/SPU/SKU references are tenant-qualified. Active SKU uniqueness, status/time, discount type/value, reward condition/scope, and JSON reward-rule checks fail closed in PostgreSQL.
- The native cross-database `MyBatisUtils.findInSetWithParamIndex` already renders PostgreSQL `POSITION(...)` against the comma-separated `LongListTypeHandler` value; no mapper fork or Education shadow interface is introduced.
- Menu IDs 69706982 mount the existing `mall/promotion/discountActivity/index` and `mall/promotion/rewardActivity/index` Vben pages with the exact ten native controller permissions.
## Legacy data decision
V4400 starts both activity families empty. Legacy coupon/code campaigns are not equivalent to time-boxed SKU discounts or structured full-reduction/gift rules, and no activity, product scope, time range, or reward rule is inferred.
## Verification
- The Promotion tenant contract proves all three activated records participate in framework tenant isolation.
- The focused V4400 scenario proves cross-tenant identifier reuse, composite reference rejection, active-SKU uniqueness, PostgreSQL scope membership semantics, reward-rule/scope rejection, three explicit sequences, exact routes/permissions, and fail-closed global-table adoption.
- A Spring/MyBatis integration test invokes the real `DiscountActivityApiImpl` and `RewardActivityApiImpl` against migrated PostgreSQL tables and proves empty normal-checkout lookups return empty lists rather than missing-table errors.
- The full PostgreSQL Flyway suite passes 47 scenarios through V4400.
## Explicitly open
- This slice removes the normal price pipeline's discount/reward missing-table blocker; it does not claim end-to-end order creation. Delivery express/template/pick-up persistence and configured Pay App/Channel runtime data remain prerequisites for applicable checkout modes.
- Seckill, bargain, combination, point, and other special-order Promotion tables remain separate tenant-safe activations.
- Legacy Product/campaign/order import, purchase-driven Education entitlement fulfillment, refund-driven revocation, and production API/browser smoke evidence remain separate work.