Files
wordpress-theme-aksrt/.specs/plans/frontend-modal-orders-vip.md
T
2026-08-04 20:40:59 +08:00

84 lines
8.8 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.
# Plan: Frontend Modal Orders and VIP
## Architectural Decisions
- **Dependency**: This plan starts only after `frontend-modal-runtime` Phase 2 supplies the canonical shell, loader, cache/state, cancellation, and telemetry contracts.
- **Order view model**: `UserOrders` and `OrderCenterRest` return a minimal list/detail view model with server-derived `allowed_actions`, status version, updated time, and invalidation tags. The front end never derives payment/cancel/after-sale eligibility from local status.
- **Order query shape**: Combine list/stat work where possible, batch resource decoration, and add the missing `user_id/status/created_at` index through `AKSRT_DB_Migrator` with a schema version bump. No new order table or duplicate fact store.
- **Reconciliation boundary**: `Gateway::reconcile_order()` remains the authority for pending external orders but runs after the detail shell is visible and only when needed. A normal completed/non-external detail must not wait for remote provider HTTP.
- **VIP JSON path**: Replace server-generated full HTML from `VipServiceModal` with a minimal JSON view model. `pay-vip.js` and the VIP shop in `credits.js` share one purchase coordinator; catalog, member state, order object, and payment attempt are reused within a request.
- **Payment safety**: Payment gateways and `PaymentOrchestrator` stay server-side. Client polling is bounded, backoff-aware, visibility-aware, cancellable, and terminated by a terminal order state. Core price, eligibility, ledger, callback, and VIP fulfillment rules are unchanged.
- **API configuration**: All order/VIP requests use the globally injected API root and REST nonce. Remove `order-center.js` hard-coded REST construction and do not add compatibility route aliases.
- **Release**: Order and VIP rollout switches are independent. Old paths may remain inactive while a domain is not released, but each domain has one canonical implementation after its switch is permanently enabled.
---
## Phase 1 — Order details appear before remote state reconciliation
**User stories**: US6, US7, US11, US13.
### What to build
Optimize `src/Payment/UserOrders.php` and `src/Payment/OrderRepositoryCore.php` so the order list does not perform a fixed list plus four COUNT queries and resource rows do not cause post/meta N+1 work. Add the composite order index in `src/Core/DBMigratorPart2.php` and bump the schema version through the existing migrator. Shape `src/Payment/OrderCenterRest.php` responses around minimal list/detail view models and preserve owner checks. Update `src/Payment/Gateway.php` so pending external reconciliation is deferred or represented as a refresh state after the shell is visible. Replace `order-center.js` hard-coded `siteUrl/wp-json` construction with injected `apiUrl/restUrl`, then move detail, pay, cancel, refresh, and invalidation through `AksrtModalRuntime`.
### Done when
- [ ] `SAVEQUERIES` scenario `order-list-query-count` verifies that the normal first page no longer issues list + four independent COUNT queries and that resource-order decoration has no per-row post/meta N+1; empty/overflow pages remain correct.
- [ ] `DBMigratorPart2` defines the `user_id/status/created_at` query index and the active schema version is bumped; after migration, `SHOW INDEX` or the WordPress DB harness verifies the index.
- [ ] Browser scenario `order-detail-shell` verifies summary skeleton first, ordinary detail does not wait for provider HTTP, pending reconciliation reports refresh state, and detail/status/list update after pay/cancel/after-sale responses.
- [ ] `order-center.js` reads the injected API root, and `php -l src/Payment/UserOrders.php src/Payment/OrderRepositoryCore.php src/Payment/OrderCenterRest.php src/Payment/Gateway.php src/Core/DBMigratorPart2.php` plus `node --check assets/js/order-center.js` pass.
- [ ] API/browser cases cover another-tab status changes, unauthorized order numbers, duplicate action clicks, timeout/retry, pagination, and no cross-user cache reuse.
---
## Phase 2 — VIP purchase reaches payment result through one coordinator
**User stories**: US4, US5, US11, US13.
### What to build
Change `src/Content/VipServiceRest.php` and `src/Content/VipServiceModal.php` from full HTML modal responses to a minimal JSON view model that contains the server-calculated catalog, member state, payment methods, allowed actions, and version metadata. Refactor `src/Content/VipServicePurchase.php` and `src/Payment/PaymentOrchestrator.php` to reuse the catalog/member/order context instead of reading the same data after create and again during pay. Consolidate the remote modal path in `assets/js/pay-vip.js` and the embedded shop path in `assets/js/credits.js` into one purchase/poll coordinator; keep the existing `credits-vip.php` and `vip-tab.php` entry points but route their actions through it. Replace the fixed 40 × 3-second loop with bounded backoff, visibility handling, abort, and terminal-state invalidation.
### Done when
- [ ] `SAVEQUERIES` scenario `vip-purchase-query-count` shows no duplicate member-level/catalog/order reads for modal load and purchase create/pay; `VipServiceRest` reuses the catalog user level instead of recomputing it.
- [ ] `pay-vip.js` and `credits.js` share one VIP purchase/poll coordinator; `git grep -n "setInterval\|pay/content/order\|pay-vip/modal" assets/js/pay-vip.js assets/js/credits.js` shows no second fixed 40 × 3-second loop or old full-HTML injection path.
- [ ] Browser scenario `vip-purchase-flow` covers not-enrolled, active, expired, renewal/upgrade, package/price, points exchange, gateway redirect, cancel, failure, async success, duplicate click, and return to order detail.
- [ ] Payment response inspection confirms no gateway secret reaches the browser; existing gateway, order callback, VIP fulfillment, core price, and entitlement rules pass regression scenarios.
- [ ] `php -l src/Content/VipServiceRest.php src/Content/VipServiceModal.php src/Content/VipServicePurchase.php src/Payment/PaymentOrchestrator.php` and `node --check assets/js/pay-vip.js assets/js/credits.js` pass.
---
## Phase 3 — Orders and VIP are independently gray-releasable
**User stories**: US1–US7, US11–US14.
### What to build
Connect order and VIP coordinators to the independent rollout switches, invalidate user-center order/VIP summaries after successful writes, and verify native order/after-sale operations remain the operational backend. Release orders first, measure shell/ready/error/status mismatch, then release VIP payment only after the order slice is stable. Remove each domain's old modal calls once its switch is permanently enabled.
### Done when
- [ ] Order and VIP rollout values independently select the new loaders; toggling one does not change the other or create a second order/member fact store.
- [ ] `php tools/audit-admin-contracts.php` exits 0, all changed PHP files pass `php -l`, and `node --check assets/js/order-center.js assets/js/pay-vip.js assets/js/credits.js` passes.
- [ ] Desktop/mobile scenarios verify shell/ready budgets, cache-hit and cold-load p75/p95, payment/order state synchronization, permission errors, retry behavior, focus, and no horizontal overflow.
- [ ] Gray-release evidence shows orders reaching the agreed 100ms shell, 200ms cache-hit, p75 ≤800ms, and p95 ≤1.5s initial budgets before VIP is enabled; rollback is demonstrated by disabling only the affected domain switch.
---
## Out of Scope
- 修改会员价格、会员权益、支付网关规则、订单账务、退款核算、认证资格/审核政策或徽章授予条件;这些规则只允许被新的流程正确调用和展示。
- 新增支付渠道、替换支付供应商、在浏览器保存支付凭证,或改变支付回调/异步结算机制。
- 新增公开认证资料库、向其他用户暴露认证文档、跨用户查看订单或徽章数据。
- 把订单、售后、认证审核或徽章运营工作台迁移进配置型 SPA;日常运营仍属于原生 WordPress 后台。
- 全站页面导航、用户中心信息架构、品牌设计系统或所有非弹窗页面的全面重做;本期只统一弹窗运行时和四类流程所需的轻量体验。
- 强制页面加载时预取所有弹窗数据、长期持久化敏感弹窗数据、建立订单/认证/徽章的第二套事实存储或长期保留旧新双路实现。
- 以新增兼容别名、旧 option 双读、静默降级或数据迁移层解决旧实现问题;流程切换后以新的规范化链路为唯一实现。
- 建立独立的数据仓库、复杂转化漏斗或第三方用户行为追踪系统;本期观测只服务于弹窗性能、错误和业务状态闭环。
## Open Questions
- 订单/支付环境是否提供现有 Server-Timing 或网关状态监控收集端;默认使用响应头和现有部署观测,不新增主题内指标表。
- 复合订单索引在生产大表上的部署窗口需要由发布流程确认;迁移必须遵循现有 `AKSRT_DB_Migrator` 原子升级约束。