plan.md 5.9 KB

Implementation Plan: 用户端统一订单列表

Branch: 030-unified-order-list | Date: 2026-09-20 | Spec: spec.md

Input: Feature specification from /specs/030-unified-order-list/spec.md

Summary

用户端外卖(pos_order)与闪送(flash_delivery_order)订单合并为一个统一列表:Java 读时聚合(否决中间表/视图),新包 com.ruoyi.app.unifiedorder 提供独立接口 GET /system/unifiedOrder/list,支持 6 tab(沿用外卖现有枚举 all/unpaid/active/completed/cancelled/refund)+ 来源筛选(all/takeaway/dinein/pickup/flash,2026-09-21 扩堂食/自取:takeaway=type0 仅外送、dinein=type2、pickup=type1)+ 游标滚动分页(严格 keyset,同秒跨源决胜:source 字典序 + id DESC)。两路各查 size+1 条内存归并;闪送路含收件人视角(user_id OR receiver_user_id,role 字段区分);unpaid/refund tab 跳过闪送路。tab 归类做成表驱动谓词(同一份规则生成 SQL 条件与内存判定)。零数据库结构变更(唯一条件项:核实/补两表查询索引)。

Technical Context

Language/Version: Java 21(Maven 多模块:ruoyi-admin / ruoyi-system / ruoyi-common)

Primary Dependencies: Spring Boot、MyBatis-Plus(分页用 Page<> 构造,游标模式下 searchCount=false)、Lombok;复用现有 PosOrderMapper / FlashDeliveryOrderMapper(只读,不新增写路径)

Storage: 无新表无视图。只读两张源表:pos_order(时间字段 cretim,Date)、flash_delivery_order(时间字段 create_time,Date;两表均为秒级 datetime,同秒并列真实存在,决胜规则必须确定性)。条件项:pos_order(user_id, cretim)flash_delivery_order(user_id, create_time)(receiver_user_id) 索引上线前核实,缺则按流程补(updatesql/sql.md)

Testing: JUnit 5 + Mockito,沿用 029 建立的 SpringUtils 静态桩 + MockHttpServletRequest 模式;测试位于 ruoyi-admin/src/test/java/com/ruoyi/app/unifiedorder/。构建:JAVA_HOME=%USERPROFILE%\.jdks\graalvm-jdk-21.0.12+7.1 + mvn -pl ruoyi-admin -am test -Dtest='Xxx' -Dsurefire.failIfNoSpecifiedTests=false

Target Platform: Linux 服务器 Spring Boot(越南用户端 uni-app 的后端)

Project Type: web-service(单体多模块 Maven)

Performance Goals: 单次滚动请求每源至多一次索引查询(各取 size+1 行,无 count 查询);耗时与现有单域列表同量级

Constraints: Controller 参数规范(GET 全 @RequestParam + @RequestHeader token);不触碰 CLAUDE.md 废弃代码;现有两个列表接口零改动;保留 CRLF

Scale/Scope: 新包约 6 个主文件 + 3 个测试文件 + 1 条条件性索引 SQL;不动任何既有订单写路径

Constitution Check

GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.

.specify/memory/constitution.md 为空模板;以 CLAUDE.md 项目规范替代核对:

约束 结果
Controller 请求参数规范(GET 显式 @RequestParam、token @RequestHeader、无 Map 入参) PASS
模块依赖方向 ruoyi-admin → ruoyi-system PASS — 新包在 ruoyi-admin,仅用 ruoyi-system 实体/Mapper
数据库变更管理(不直接执行,写 sql.md) PASS — 仅条件性索引补充
废弃代码清单不触碰 PASS — 只读现有表,不参考 PayController/TestTask 等
Java 注释安全 PASS
后端错误消息走 MessageUtils PASS — 非法 cursor 等错误用消息 key

Phase 1 设计后复核:全部 PASS,无违规项。

Project Structure

Documentation (this feature)

specs/030-unified-order-list/
├── plan.md              # This file
├── research.md          # Phase 0 output
├── data-model.md        # Phase 1 output(DTO/cursor/谓词规则)
├── quickstart.md        # Phase 1 output
├── contracts/
│   └── api-contract.md  # 前端契约
└── tasks.md             # Phase 2 output (/speckit-tasks)

Source Code (repository root)

ruoyi-admin/src/main/java/com/ruoyi/app/unifiedorder/
├── UnifiedOrderQueryController.java   # GET /system/unifiedOrder/list
├── UnifiedOrderQueryService.java      # 两路查询 + 归并 + 游标推进 + 店铺名批量回填
├── UnifiedOrderTab.java               # tab 枚举 + 表驱动谓词(wrapper 条件构造 & 实体内存判定同源)
├── OrderSource.java                   # takeaway/dinein/pickup/flash 枚举(字典序决胜依据;dinein/pickup 为 pos_order type 子集)
├── UnifiedCursor.java                 # 游标:生成/解析/校验(时间_source_id)
└── dto/
    ├── UnifiedOrderListItem.java      # 公共字段 + takeaway 渲染块 + flash 渲染块
    └── UnifiedOrderPageView.java      # 分页信封:list/hasMore/nextCursor

ruoyi-admin/src/test/java/com/ruoyi/app/unifiedorder/
├── UnifiedOrderTabTest.java          # 两域×6 tab×边界样本归类 + wrapper SQL 片段断言
├── UnifiedCursorTest.java             # 生成/解析/非法输入/同秒并列
├── UnifiedOrderQueryServiceTest.java  # 归并排序、翻页完整性、hasMore、tab 跳过闪送路、role 判定
└── UnifiedOrderQueryControllerTest.java # 参数契约 + 组合查询

updatesql/sql.md                      # 条件性索引补充(标注"核实后执行")
(复用只读)ruoyi-system: PosOrderMapper / FlashDeliveryOrderMapper / InfoUser(店铺名回填)

Structure Decision: 新功能独立成包(不向 700+ 行的 UserOrderController 继续堆叠);两源表的查询直接走各自 MP Mapper(游标模式下 new Page<>(1, limit, false) 固定第一页,天然无 count 开销);tab 谓词集中在一个枚举类里同时服务 SQL 构造与内存判定(唯一事实源,FR-007)。

Complexity Tracking

Fill ONLY if Constitution Check has violations that must be justified

无违规项。