plan.md 7.2 KB

Implementation Plan: 商家自配送

Branch: test-202609v2(按用户要求不单独开分支) | Date: 2026-09-08 | Spec: spec.md

Input: Feature specification from /specs/029-merchant-self-delivery/spec.md

Summary

商家在门店信息开启自配送(全天/按星期自定义时段);下单时按快照判定(即时单按下单时刻、预约单按预约送达时间,区间 [开始,结束)),命中的外送单标记 self_delivery=1、不进骑手抢单池;商家接单/出餐后自行配送,可选"开始配送"、必点"确认送达"完成订单;运费全额(不抽成)入账 user_id=sh_id(普通商家=商家、夜市摊位单=夜市主),到付归因同步;夜市由夜市主在夜市主门店行统一配置、对旗下摊位生效;用户端与商家端显示"商家自配送/自配送"标识(四语言)。合并订单/同一配送人多单机制明确排除(另立需求)。

技术方案:pos_store 2 列 + 新表 pos_store_self_delivery_hours(镜像营业时段模式)+ pos_order 1 列快照;新增 SelfDeliveryUtil(时段判定,不复用边界语义不符的 isLegalTime)与 SelfDeliveryService(配置解析/入账);配送操作端点加在 PosOrderShOprateController;结算分支挂 OrderLifecycleService.completeSideEffects;骑手池过滤 + 三操作直调拒绝。详见 research.md、data-model.md、contracts/api.md。

Technical Context

Language/Version: Java 21(Spring Boot + MyBatis-Plus);前端 Vue2 + Element UI(foodie-store)

Primary Dependencies: MyBatis-Plus(新表 BaseMapper)、Redisson(配送操作并发锁)、PayPush/MerchantNotificationRouter(推送)、merchantStoreAccessService(022 门店权限)

Storage: MySQL(DDL 见 data-model.md,写入 updatesql/sql.md 由开发者手动执行)

Testing: JUnit5(SelfDeliveryUtil 边界单测、SelfDeliveryService 判定/入账单测、Controller 契约测试——仓库已有 PosOrderQsOprateControllerTest/PosOrderShOprateControllerTest 先例);接口级冒烟按 quickstart.md

Target Platform: Linux 服务器部署(Windows 开发机,JDK 用 C:\Users\qmj\.jdks\graalvm-jdk-21.0.7 临时设置 JAVA_HOME)

Project Type: web-service(后端)+ 商家端管理前端(外部路径 E:\QtwCode\foodie\foodie-store,CRLF 文件用 Python 脚本编辑)

Performance Goals: 无特殊要求(判定为 O(时段数) 纯内存计算;配置读取随下单批量查表)

Constraints: 模块依赖 admin→system 不可反向;Controller 参数规范(token/DTO/@RequestParam);i18n 后端 5 个 properties + 前端 4 个语言文件;不触碰废弃代码清单

Scale/Scope: 后端 ~8 个文件改动 + 4 个新文件;前端 1 个设置区块 + 订单标识 + i18n;1 张新表 + 3 列

Constitution Check

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

.specify/memory/constitution.md 为未填写的占位模板,无项目级 gates。以 CLAUDE.md 项目规范替代检查:

规范 状态
Controller 参数规范(token/DTO/显式 @RequestParam/禁 Map) ✅ contracts/api.md 全部 DTO 化
模块边界 admin→system ✅ 实体+Mapper 在 system,业务服务在 admin(data-model.md)
DDL 入 updatesql/sql.md 不直接执行 ✅ data-model.md 已给出待登记 SQL
前端 i18n 四语言、key 有意义、按对象层级插入 ✅ contracts §5/§6;CRLF 用 Python 编辑
废弃代码不触碰 ✅ research.md「涉及的废弃代码」节
Java 注释禁 */、主要注释规范 ✅ 实现阶段遵守
餐桌码先例:功能覆盖普通商家 ✅ 配置/判定/操作均含普通商家路径

Project Structure

Documentation (this feature)

specs/029-merchant-self-delivery/
├── plan.md              # This file
├── research.md          # Phase 0 output(现状事实 F1-F16 + 决策 D1-D10)
├── data-model.md        # Phase 1 output(DDL + 状态机 + 校验)
├── quickstart.md        # Phase 1 output(8 个验证场景)
├── contracts/
│   └── api.md           # Phase 1 output(接口契约 + i18n 清单)
└── tasks.md             # Phase 2 output (/speckit-tasks - NOT created yet)

Source Code (repository root)

foodie_server/
├── ruoyi-system/src/main/java/com/ruoyi/system/
│   ├── domain/
│   │   ├── PosStore.java                      # +selfDeliveryEnabled/selfDeliveryMode
│   │   ├── PosOrder.java                      # +selfDelivery
│   │   └── PosStoreSelfDeliveryHours.java     # 新实体
│   └── mapper/
│       └── PosStoreSelfDeliveryHoursMapper.java  # 新 BaseMapper(无 XML)
├── ruoyi-admin/src/main/java/com/ruoyi/app/
│   ├── utils/SelfDeliveryUtil.java            # 新:[start,end) 按星期判定
│   ├── order/
│   │   ├── SelfDeliveryService.java           # 新:配置解析(摊位→夜市主门店)/判定/运费入账
│   │   ├── UserOrderController.java           # createOrderChild 判定快照
│   │   ├── PosOrderShOprateController.java    # 商家端 createOrder 判定;requireRiderAssigned 放行;+selfDeliveryStart/Complete;chuCan 骑手推送跳过
│   │   ├── PosOrderQsOprateController.java    # newTask 过滤;三操作直调拒绝
│   │   ├── OrderLifecycleService.java         # completeSideEffects 增自配送运费分支
│   │   └── OrderService.java                  # setSelfDeliveryFreightBilling(type="5")
│   ├── mendian/PosStoreController.java        # +get/saveMdSelfDeliveryHours
│   └── order/dto/
│       ├── SelfDeliveryConfigInput.java       # 新(含 SelfDeliveryHourInput)
│       └── SelfDeliveryOperateInput.java      # 新
├── ruoyi-admin/src/main/resources/i18n/       # 5 个 properties 加 key
├── ruoyi-admin/src/test/java/...              # SelfDeliveryUtilTest / SelfDeliveryServiceTest / 契约测试
└── updatesql/sql.md                           # DDL 登记

foodie-store/(商家端 PC,E:\QtwCode\foodie\foodie-store)
├── src/views/...门店信息页                     # 自配送区块(复用营业时段编辑交互)
├── src/views/...订单列表/详情                  # "自配送"标签
└── src/lang/{zh,tw,en,vi}.js                  # selfDelivery.* keys

Structure Decision: 复用现有分层(system 实体 / admin 业务),新表走 MyBatis-Plus BaseMapper 不建 XML;前端仅 foodie-store,foodie-admin-vue 与客户端 uni-app 不在本功能改动范围(research D10、assumptions)。

Complexity Tracking

无 Constitution Check 违规需要辩护。

Violation Why Needed Simpler Alternative Rejected Because
— — —

遗留决策(不阻塞实施)

  • clarify Q2(配送操作界面的端覆盖):后端接口与 PC 配置/标识任务先行;"PC 配送操作按钮"单列为可独立裁剪任务,等用户决策后启用(research D9)。