# 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 - [x] 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;连锁多店返回同一份。 - [x] 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_id` → `info_user` 的 bankAccountName/bankName/bankAccountNo;三项均非空返回 `{accountName, bankName, accountNo}`,任一为空返回 `success(null)`;参考 getstore 风格,Javadoc 注明「商家收款账户(線下轉賬收银台展示用),商家级、连锁共享」,编译验证 - [x] T003(null分支与不存在门店已curl验证;正向数据待商家银行资料填写后复验) [US1] 冒烟验证 T002:curl 三种情形(三字段齐全 / 缺银行账号 / 不存在门店 id→data=null),对照 contracts/api.md 场景 1 ## Phase 4: US2 商家确认收款 + 骑手门禁(P1) 目标:确认收款解锁配送。独立测试:未确认时骑手接单被拒(提示「商家确认收款后骑手才能接单」)、newTask 列表不可见;确认后接单成功、附近骑手收到推送、日志记录;重复确认/已取消被拒;现金单 confirmCashPayment 行为不变。 - [x] 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 所在行),编译验证 - [x] 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),编译验证 - [x] 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),编译验证 - [x] T007(无token冒烟已验:接口注册+鉴权拦截;完整链路待测试账号token) [US2] 冒烟验证 US2 全链路:下单 paymentMethod=6 → 强行骑手接单被拒 → newTask 列表无此单 → confirmTransferPayment 成功(重复调用报已收款)→ 骑手接单成功 → 商家接单/出餐/取餐/送达正常;同时回归 confirmCashPayment 对非现金单仍报「不是现金支付订单」(quickstart.md 场景 2/3/4) ## Phase 5: US3 商家 Web 支付标签(P2) 目标:转账单在商家 Web 正确显示标签。独立测试:到付/线上/转账三类标签互不混淆,四语言正确。 - [x] T008 [P] [US3] 在 foodie-store/src/views/index.vue 的 paymentTypeLabel 映射(388-396行)加 `6: 'OfflineTransfer'` - [x] 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 键行) - [x] T010(paymentKeys与四语言已node校验通过;页面目测待前端构建) [US3] 验证:商家订单列表与详情弹窗对 payType=6 显示「线下转账」,四语言切换正确(quickstart.md 场景 5) ## Phase 6: Polish - [x] 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 核对改动点 - [x] T012 交付 App 团队对接说明:接口清单(bankInfo / confirmTransferPayment / acceptOrder 门禁 / createOrder 透传 6)与收银台交互稿要点(contracts/api.md 的 App 端小节),整理为简短消息发给用户转交 ## Dependencies ```text 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 标签纯展示可最后。