Kaynağa Gözat

制定闪送费用与物品信息实施计划

顺延现有计划和任务,明确统一分时段运价、比例加急费、报价校验、完整物品字段、平台页面及验证批次。
qmj 1 saat önce
ebeveyn
işleme
147c287cb8

+ 126 - 0
specs/024-flash-delivery/plan.md

@@ -547,3 +547,129 @@ The staged list must not contain `.claude/homunculus/observations.jsonl`、`.tmp
 ### 测试与交付
 
 先写并运行失败测试,再实现生产代码。测试覆盖手机号唯一/零个/多个匹配、幂等创建、角色分页、参与者权限、取消边界、急送双向互斥、终态释放和同骑手并发接单。数据库变更只追加到 `updatesql/sql.md`,不直接执行。最后使用 JDK 21 运行定向测试和模块构建,并执行 `git diff --check`。
+
+## 设计稿费用与物品信息对齐计划(2026-09-07)
+
+> **执行要求**:在当前会话按测试驱动方式依次完成下列任务;每个任务先运行指定测试确认旧实现失败,再实现最小改动并重新运行。数据库 SQL 只追加到 `updatesql/sql.md`,不得执行。
+
+**目标**:拆分帮送/帮取业务场景与普通/加急配送等级,让两种业务场景共享统一分时段运价,按普通配送费比例和最低金额计算加急费,支持骑手小费、预约时段计价、客户端报价回传校验及设计稿中的完整物品信息。
+
+**架构**:`flash_delivery_pricing` 改为全局时间段配置,计价器负责纯函数费用计算,应用服务负责选择立即或预约计价时刻、路线编排和报价一致性校验。订单持久化完整物品及费用快照;`delivery_type` 成为急送独占的唯一判断字段。平台管理端只维护一组时间段,不再展示三类服务价格。
+
+**技术栈**:Java 21、Spring Boot、MyBatis-Plus/MyBatis XML、MySQL、JUnit 5、Mockito、Vue 2、Element UI、Node 测试。
+
+### 全局约束
+
+- Controller 继续使用明确 DTO、`@RequestBody`、`@RequestParam`、`@PathVariable` 和 `@RequestHeader String token`,不接收 Map。
+- 所有 TWD 费用为整数 `Long`;比例和重量使用 `BigDecimal`,计算使用 `RoundingMode.HALF_UP`。
+- `serviceType` 只接受 `HELP_SEND/HELP_PICKUP`,`deliveryType` 只接受 `NORMAL/URGENT`,`deliveryMode` 只接受 `NOW/SCHEDULED`。
+- 立即订单按报价时刻、预约订单按 `scheduledPickupStartAt` 的业务当地时分匹配统一运价。
+- 不接入支付、退款或结算;小费仅作为应付费用快照。
+- 平台新增可见文本同步简中、繁中、英文和越南文;前端文件保持 CRLF。
+- 不执行数据库迁移,只把可人工执行 SQL 追加到 `updatesql/sql.md`。
+
+### Task 1:计价模型与数据层
+
+**文件:**
+
+- 修改:`ruoyi-system/src/main/java/com/ruoyi/system/domain/flash/FlashDeliveryPricing.java`
+- 修改:`ruoyi-system/src/main/java/com/ruoyi/system/domain/flash/FlashDeliveryOrder.java`
+- 修改:`ruoyi-system/src/main/java/com/ruoyi/system/mapper/flash/FlashDeliveryPricingMapper.java`
+- 修改:`ruoyi-system/src/main/resources/mapper/flash/FlashDeliveryOrderMapper.xml`
+- 修改:`ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryPriceBreakdown.java`
+- 修改:`ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/service/FlashDeliveryPricingCalculator.java`
+- 测试:`ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/service/FlashDeliveryPricingCalculatorTest.java`
+- 测试:`ruoyi-system/src/test/java/com/ruoyi/system/mapper/flash/FlashDeliveryPricingMapperContractTest.java`
+- 测试:`ruoyi-system/src/test/java/com/ruoyi/system/mapper/flash/FlashDeliveryMapperXmlTest.java`
+
+**接口:**
+
+- `FlashDeliveryPricingCalculator.calculateBreakdown(FlashDeliveryPricing pricing, int distanceMeters, String deliveryType, Long tipAmount)` 返回 `distanceFee/baseDeliveryFee/urgentFee/tipAmount/amount`。
+- `FlashDeliveryPricingMapper.selectAtTime(String targetTime)` 返回目标 `HH:mm` 命中的全部配置;`countOverlapping(String startTime,String endTime,Long excludedId)` 全局查重;`lockPricing()` 获取单行全局锁。
+- `FlashDeliveryOrder` 新增 `deliveryType,quantity,totalWeightKg,specification,baseDeliveryFee,urgentRate,minimumUrgentFee,urgentFee,tipAmount`。
+
+- [ ] 先扩展计价器和 Mapper 契约测试,覆盖普通加急费为 0、比例费高于最低值、最低值兜底、HALF_UP、小费相加、全局时段查询/查重和订单字段映射,并运行测试确认旧实现失败。
+- [ ] 修改实体、Mapper 和纯计价器;删除运价配置的 `serviceType` 依赖,使上述测试通过。
+- [ ] 运行:`mvn -pl ruoyi-admin -am -Dtest='FlashDeliveryPricingCalculatorTest,FlashDeliveryPricingMapperContractTest,FlashDeliveryMapperXmlTest' -Dsurefire.failIfNoSpecifiedTests=false test`。
+
+### Task 2:报价、创建校验与物品信息
+
+**文件:**
+
+- 修改:`ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryQuoteRequest.java`
+- 修改:`ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryCreateRequest.java`
+- 修改:`ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryQuoteView.java`
+- 修改:`ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryHomeView.java`
+- 修改:`ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryOrderView.java`
+- 修改:`ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryUserOrderListView.java`
+- 修改:`ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryRiderOrderListView.java`
+- 新增:`ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/exception/FlashDeliveryQuoteChangedException.java`
+- 修改:`ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/service/FlashDeliveryApplicationService.java`
+- 修改:`ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/controller/FlashDeliveryUserController.java`
+- 修改:`ruoyi-admin/src/main/java/com/ruoyi/app/order/RiderDeliveryExclusivityService.java`
+- 测试:`ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/service/FlashDeliveryApplicationServiceTest.java`
+- 测试:`ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/controller/FlashDeliveryControllerContractTest.java`
+- 测试:`ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryOrderViewTest.java`
+- 测试:`ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryRiderOrderListViewTest.java`
+
+**接口:**
+
+- 报价请求新增 `deliveryType,deliveryMode,scheduledPickupStartAt,scheduledPickupEndAt,quantity,totalWeightKg,specification,tipAmount`,移除客户端 `packageSize`。
+- 创建请求新增 `pricingId,pricingVersion,quotedBaseDeliveryFee,quotedDistanceFee,quotedUrgentFee,quotedAmount`。
+- 报价和订单视图新增业务、物品与费用明细;`packageSize` 由服务端按 `<=5/<=12/<=20kg` 生成。
+- 报价变化异常携带 `FlashDeliveryQuoteView latestQuote`;Controller 返回国际化错误和 `data=latestQuote`。
+
+- [ ] 先扩展应用服务、Controller 和 DTO 测试,覆盖业务/配送维度校验、完整物品校验、立即与预约时段匹配、报价费用字段、创建逐项一致、配置或金额变化拒绝并返回最新报价、订单费用快照和 `deliveryType=URGENT` 独占,并确认旧实现失败。
+- [ ] 实现请求/响应 DTO、目标计价时刻选择、统一运价查询、报价复算比较、重量档生成、快照保存和报价变化错误响应。
+- [ ] 将所有急送独占查询从 `service_type='URGENT'` 改为 `delivery_type='URGENT'`,保持既有骑手锁和状态边界不变。
+- [ ] 运行:`mvn -pl ruoyi-admin -am -Dtest='FlashDeliveryApplicationServiceTest,FlashDeliveryControllerContractTest,FlashDeliveryOrderViewTest,FlashDeliveryRiderOrderListViewTest' -Dsurefire.failIfNoSpecifiedTests=false test`。
+
+### Task 3:平台配置接口和管理页面
+
+**文件:**
+
+- 修改:`ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryPricingRequest.java`
+- 修改:`ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/service/FlashDeliveryApplicationService.java`
+- 修改:`ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/controller/FlashDeliveryAdminController.java`
+- 修改:`E:/QtwCode/foodie/foodie-admin-vue/src/api/flashDelivery/contracts.js`
+- 修改:`E:/QtwCode/foodie/foodie-admin-vue/src/views/flashDelivery/shared.js`
+- 修改:`E:/QtwCode/foodie/foodie-admin-vue/src/views/flashDelivery/pricing/index.vue`
+- 修改:`E:/QtwCode/foodie/foodie-admin-vue/src/views/flashDelivery/orders/OrderDetail.vue`
+- 修改:`E:/QtwCode/foodie/foodie-admin-vue/src/api/language/language.zh.js`
+- 修改:`E:/QtwCode/foodie/foodie-admin-vue/src/api/language/language.tw.js`
+- 修改:`E:/QtwCode/foodie/foodie-admin-vue/src/api/language/language.en.js`
+- 修改:`E:/QtwCode/foodie/foodie-admin-vue/src/api/language/language.vi.js`
+- 测试:`E:/QtwCode/foodie/foodie-admin-vue/tests/flash-delivery.test.cjs`
+
+**接口:**
+
+- 平台运价请求为 `startTime,endTime,startingDistance,startingFare,distance,freight,urgentRate,minimumUrgentFee,configVersion?`,不再含 `serviceType`。
+- 列表按 `startTime` 排序,所有时段全局重叠校验;平台订单详情展示业务场景、配送等级、物品和五项费用。
+
+- [ ] 先修改后端平台契约测试和前端定向测试,确认旧三服务配置结构失败。
+- [ ] 实现统一时段 CRUD、全局锁和字段校验;更新平台价格表单、订单详情及四语言文案。
+- [ ] 运行后端平台定向测试和 `npm run test:flash-delivery`,再对修改的前端文件运行 ESLint。
+
+### Task 4:SQL、App 文档和规格任务状态
+
+**文件:**
+
+- 修改:`updatesql/sql.md`
+- 修改:`docs/flash-delivery-app-api.md`
+- 修改:`specs/024-flash-delivery/quickstart.md`
+- 修改:`specs/024-flash-delivery/tasks.md`
+- 修改:五个 `ruoyi-admin/src/main/resources/i18n/messages*.properties`
+- 测试:`ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/service/FlashDeliveryI18nContractTest.java`
+
+- [ ] 在 `updatesql/sql.md` 追加 2026-09-07 人工迁移脚本:统一运价时段、全局锁、订单业务/物品/费用字段和相关索引;不得连接或修改数据库。
+- [ ] 重写 App 文档的枚举、首页、报价、创建、列表、详情和费用示例,明确报价变化响应及非支付边界。
+- [ ] 添加物品、配送等级、报价变化和运价字段错误的五语言 key,并运行 i18n 契约测试。
+- [ ] 更新 `tasks.md` 实际完成状态,不提前勾选未运行验证的任务。
+
+### Task 5:统一验证与提交
+
+- [ ] 临时设置 `JAVA_HOME=C:\Users\qmj\.jdks\graalvm-jdk-21.0.7`,运行闪送、外卖独占和 i18n 定向测试。
+- [ ] 运行 `mvn -pl ruoyi-admin -am -DskipTests package`。
+- [ ] 在平台前端运行 `npm run test:flash-delivery`、修改文件 ESLint 和 `npm run build:prod`。
+- [ ] 运行两个仓库的 `git diff --check`,核对编码、换行和暂存文件清单。
+- [ ] 后端与平台前端分别形成中文独立提交;最终报告两个 SHA、实际检查结果和任何未执行项。

+ 12 - 0
specs/024-flash-delivery/tasks.md

@@ -104,3 +104,15 @@
 - [x] T059 以共享锁键 `lock:delivery:rider:{riderId}` 实现 `URGENT` 跨订单独占,事务完成后释放锁,并在当前有效外卖与闪送接单入口返回一致的国际化业务错误
 - [x] T060 在 `updatesql/sql.md` 追加 `receiver_user_id` 字段和索引迁移,仅记录不执行;同步 App 接口文档和五语言错误文案
 - [ ] T061 使用 JDK 21 运行闪送、外卖接单和 i18n 定向测试、模块构建与差异检查,核对暂存范围后使用中文提交
+
+## Phase 13:设计稿费用与物品信息对齐
+
+- [x] T062 修正规格、设计、数据模型和 API 契约,确认帮送/帮取与普通/加急正交、统一分时段运价、比例加急费、最低加急费、小费、预约计价时刻、报价回传校验及完整物品字段
+- [ ] T063 先扩展计价器、运价 Mapper 和订单 XML 测试,覆盖比例加急费、最低值、小费、全局时段与新增快照字段并确认旧实现红灯
+- [ ] T064 修改运价/订单实体、Mapper、XML 和计价器,移除按服务类型分价并使数据层与计价测试转绿
+- [ ] T065 先扩展应用服务、Controller、DTO 和独占测试,覆盖完整请求响应、立即/预约计价、前端报价逐项校验、最新报价错误、物品校验及 `deliveryType=URGENT` 并确认旧实现红灯
+- [ ] T066 实现报价、创建、列表、详情和独占逻辑,保存业务场景、配送等级、物品与完整费用快照,使 App 定向测试转绿
+- [ ] T067 先更新平台后端契约和 `foodie-admin-vue` 闪送测试,确认旧三服务运价页面红灯;再实现统一时段配置、加急比例、最低加急费、订单明细及四语言
+- [ ] T068 在 `updatesql/sql.md` 追加迁移 SQL,不执行数据库;同步五语言后端错误、App 接入文档和 quickstart
+- [ ] T069 使用 JDK 21 运行后端定向测试与模块构建,运行平台前端定向测试、ESLint、生产构建及两个仓库差异检查
+- [ ] T070 核对后端与平台前端暂存范围,分别使用中文提交并记录 SHA 与未执行项