tasks.md 6.1 KB

Tasks: 線下轉賬支付(payType=6)

Feature: specs/027-offline-transfer-payment | Generated: 2026-09-03

参考: plan.md(改动文件清单)、research.md(D1-D9 决策)、contracts/api.md(接口契约)、quickstart.md(冒烟场景)

通用约束(每个任务遵守)

  • 后端/前端文件均为 CRLF,用 Python 脚本编辑(python << 'PYEOF'),锚点唯一性校验后再写
  • Java 注释禁出现 */ 序列;Controller 规范(@RequestHeader token + 显式 @RequestParam,禁 Map 入参)
  • 每个后端任务完成后 mvn -q -pl ruoyi-system,ruoyi-admin -am compile -DskipTests(JAVA_HOME=C:\Users\qmj.jdks\graalvm-jdk-21.0.7)验证
  • 不执行任何数据库变更(本功能零 DDL)

Phase 1: Setup

  • T001 [P] 在 ruoyi-admin/src/main/java/com/ruoyi/app/order/OrderLifecycleService.java 增加常量 public static final String PAY_TYPE_TRANSFER = "6";(紧邻 PAY_TYPE_CASH,带 Javadoc:線下轉賬支付,商家线下确认收款后解锁配送),编译验证

Phase 2: Foundational(无)

Phase 3: US1 收银台收款账户查询(P1)

目标:App 依据接口决定「線下支付」选项显隐与账户展示。独立测试:齐全商家门店返回三字段;缺任一字段返回 data=null;连锁多店返回同一份。

  • T002 [P] [US1] 在 ruoyi-admin/src/main/java/com/ruoyi/app/mendian/PosStoreController.java 新增 GET /chanting/store/bankInfo@Anonymous@RequestParam Integer id):按门店查 pos_store.user_idinfo_user 的 bankAccountName/bankName/bankAccountNo;三项均非空返回 {accountName, bankName, accountNo},任一为空返回 success(null);参考 getstore 风格,Javadoc 注明「商家收款账户(線下轉賬收银台展示用),商家级、连锁共享」,编译验证
  • T003(null分支与不存在门店已curl验证;正向数据待商家银行资料填写后复验) [US1] 冒烟验证 T002:curl 三种情形(三字段齐全 / 缺银行账号 / 不存在门店 id→data=null),对照 contracts/api.md 场景 1

Phase 4: US2 商家确认收款 + 骑手门禁(P1)

目标:确认收款解锁配送。独立测试:未确认时骑手接单被拒(提示「商家确认收款后骑手才能接单」)、newTask 列表不可见;确认后接单成功、附近骑手收到推送、日志记录;重复确认/已取消被拒;现金单 confirmCashPayment 行为不变。

  • T004 [US2] 在 ruoyi-admin/src/main/resources/i18n/ 的五份 properties(messages.properties、messages_zh_CN、messages_zh_TW、messages_en_US、messages_vi)追加 4 个 key:no.order.paytype.not.transfer / no.order.transfer.cancelled / no.order.transfer.already.paid / no.order.transfer.not.paid(文案见 contracts/api.md,tw 繁体自拟同义),Python 脚本逐份插入(锚点用 no.order.cash.already.paid 所在行),编译验证
  • T005 [US2] 在 ruoyi-admin/src/main/java/com/ruoyi/app/order/PosOrderShOprateController.java 新增 GET /confirmTransferPayment@RequestHeader token + @RequestParam Long id),镜像 confirmCashPayment(397行):requireMerchantOrderAccess → 校验 payType==PAY_TYPE_TRANSFER(否则 no.order.paytype.not.transfer)→ state==4 拒绝(no.order.transfer.cancelled)→ payStatus==1 拒绝(no.order.transfer.already.paid)→ payStatus 置 1 + orderLogHelper 记「商家{名}确认转账收款」;外送单(type=0)保存后调用 deliveryOrderNotificationService.notifyOrderAvailable(order)(注入方式照 PosOrderController:130),编译验证
  • T006 [US2] 在 ruoyi-admin/src/main/java/com/ruoyi/app/order/PosOrderQsOprateController.java 的 acceptOrder(76行)校验区增加门禁:PAY_TYPE_TRANSFER.equals(payType) && payStatus != 1 → 抛 ServiceException(no.order.transfer.not.paid),编译验证
  • T007(无token冒烟已验:接口注册+鉴权拦截;完整链路待测试账号token) [US2] 冒烟验证 US2 全链路:下单 paymentMethod=6 → 强行骑手接单被拒 → newTask 列表无此单 → confirmTransferPayment 成功(重复调用报已收款)→ 骑手接单成功 → 商家接单/出餐/取餐/送达正常;同时回归 confirmCashPayment 对非现金单仍报「不是现金支付订单」(quickstart.md 场景 2/3/4)

Phase 5: US3 商家 Web 支付标签(P2)

目标:转账单在商家 Web 正确显示标签。独立测试:到付/线上/转账三类标签互不混淆,四语言正确。

  • T008 [P] [US3] 在 foodie-store/src/views/index.vue 的 paymentTypeLabel 映射(388-396行)加 6: 'OfflineTransfer'
  • T009 [P] [US3] 在 foodie-store/src/lang/{zh,tw,en,vi}.js 的 index 命名空间(找 index:{ 的 CashOnDelivery/OMG/LinePay/cash 同级)加 OfflineTransfer: '线下转账' / '轉賬支付' / 'Transfer Payment' / 'Chuyển khoản'(Python 脚本,锚点取 index 命名空间内 cash 键行)
  • T010(paymentKeys与四语言已node校验通过;页面目测待前端构建) [US3] 验证:商家订单列表与详情弹窗对 payType=6 显示「线下转账」,四语言切换正确(quickstart.md 场景 5)

Phase 6: Polish

  • T011 对照 specs/027-offline-transfer-payment/spec.md 的 FR-001~FR-010 与 quickstart.md 五场景做完整核验(机械检查:编译 PASS + grep 确认 4 个 i18n key 在五份 properties、payType=6 无散落硬编码;冒烟:curl 走完场景 1-4),派 1 个 review 子代理逐 FR 核对改动点
  • T012 交付 App 团队对接说明:接口清单(bankInfo / confirmTransferPayment / acceptOrder 门禁 / createOrder 透传 6)与收银台交互稿要点(contracts/api.md 的 App 端小节),整理为简短消息发给用户转交

Dependencies

T001 ──> T005(常量)
T002 ──> T003(US1 冒烟)          [US1 与 US2/US3 并行]
T004 ──> T005/T006(提示 key)
T005,T006 ──> T007(US2 冒烟)
T008,T009 ──> T010                 [US3 与 US2 并行]
T007,T010 ──> T011 ──> T012

MVP

US2(T001+T004+T005+T006):确认收款 + 骑手门禁是资金闸门核心;US1 银行信息接口紧随其后(App 展示依赖),US3 标签纯展示可最后。