plan.md 5.4 KB

Implementation Plan: 闪送订单状态变更消息推送

Branch: 028-flash-delivery-push | Date: 2026-09-17 | Spec: spec.md

Input: Feature specification from /specs/028-flash-delivery-push/spec.md

Summary

在闪送订单五个状态变更点(骑手抢单、取件、送达、用户取消、平台取消)接入既有推送通道:新建 FlashDeliveryNotificationService(镜像 DeliveryOrderNotificationService 的 afterCommit + AsyncManager + PayPush 模式),由 FlashDeliveryApplicationService 在条件更新成功后调用。履约事件推寄件用户、取消事件推接单骑手;复用现有 i18n 文案 key 与 OrderPushBodyDto payload(pushType=3)。零新表、零新接口、零新翻译(详见 research.md)。

Technical Context

Language/Version: Java 21(Spring Boot + MyBatis-Plus)

Primary Dependencies: Spring 事务同步(TransactionSynchronizationManager)、AsyncManagerPayPush(uni 云函数推送)、PushEventService(push_message 入库)、fastjson(payload 序列化)

Storage: MySQL(只读 flash_delivery_orderinfo_user;只写既有 push_message,经由 PushEventService)

Testing: JUnit 5 + Mockito(spy+doNothing 打断网络发送,验证路由决策;仓库先例 DeliveryOrderNotificationServiceTest

Target Platform: Windows 开发 / Linux 部署的 Spring Boot 服务

Project Type: web-service(多模块 Maven:ruoyi-adminruoyi-system

Performance Goals: 推送异步执行,不增加订单接口耗时(SC-004 零传导)

Constraints: 推送失败不得影响状态流转(FR-009);仅事务提交后触发(FR-011);不新增 Android 通道

Scale/Scope: 1 个新服务类 + 1 个应用服务的 5 个方法加钩子 + 2 个测试类

Constitution Check

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

.specify/memory/constitution.md 为未定制的占位模板,无项目级原则可引用;改按仓库 CLAUDE.md 约束逐条核对:

约束 结论
Controller 参数规范 不涉及(无新 Controller/接口改动)
模块边界:集成代码放 ruoyi-admin ✅ 通知服务放 ruoyi-admincom.ruoyi.app.flashdelivery.service,不进 ruoyi-system
数据库变更须写 updatesql/sql.md ✅ 本特性零数据库变更
全栈字段清单 ✅ 无新字段
Java 注释安全(无 */ 序列) ✅ 实现时遵守
前端 i18n 规范 不涉及(复用后端既有文案 key,无前端改动)
CRLF 保留、不格式化整文件 ✅ 实现时遵守

无违规,无需 Complexity Tracking 条目。

Project Structure

Documentation (this feature)

specs/028-flash-delivery-push/
├── plan.md              # This file (/speckit-plan command output)
├── research.md          # Phase 0 output (/speckit-plan command)
├── data-model.md        # Phase 1 output (/speckit-plan command)
├── quickstart.md        # Phase 1 output (/speckit-plan command)
├── contracts/
│   └── push.md          # 推送 payload 契约(Phase 1 output)
└── tasks.md             # Phase 2 output (/speckit-tasks command - NOT created by /speckit-plan)

Source Code (repository root)

ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/
└── service/
    ├── FlashDeliveryApplicationService.java   # 修改:构造器 + 5 个方法的成功路径加通知钩子
    └── FlashDeliveryNotificationService.java  # 新增:推送路由(afterCommit + AsyncManager + PayPush)

ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/
└── service/
    ├── FlashDeliveryApplicationServiceTest.java       # 修改:构造器新参 + 推送触发/不触发断言
    └── FlashDeliveryNotificationServiceTest.java      # 新增:接收人判定与跳过逻辑

Structure Decision: 完全落在闪送模块既有目录结构内,不新增包、不动 ruoyi-system、不动 Controller 层。

关键设计点(供 tasks 生成引用)

  1. 通知服务 APInotifyAccepted(order) / notifyPickedUp(order) / notifyDelivered(order) / notifyCancelled(order);入参用事务前读到的 FlashDeliveryOrder(只消费 orderNo/userId/riderId 等不可变字段,不依赖其 status 快照)。
  2. 钩子位置
    • acceptwithLockwriteLog(...) 之后、return 之前;
    • pickup/deliver:共用 transitionWithProofwriteLog(...) 之后,按 next 参数分派(PICKED_UP/DELIVERED);
    • userCancel/adminCancelwriteLog(...) 之后,notifyCancelled 内部判 riderId 判空。
  3. 构造器FlashDeliveryApplicationService 追加第 10 个依赖 FlashDeliveryNotificationService;同步更新既有测试的构造调用。
  4. 发送实现runAfterCommituserMapper.selectById 取 cid → AsyncManager.me().executePayPush.userPushHandleLocal / qsPushHandleLocal(title=no.message.push.message,content key 见 research.md D2,body=OrderPushBodyDto.getJson(orderNo, status, -1, 3))。
  5. 不触发清单(对应 FR-010):createtipAddcompleteFlashDeliveryAutoCompleteTaskcancelExpiredScheduledOrder 一律不调用通知服务。

Complexity Tracking

无 Constitution Check 违规,本节为空。