---
mode: plan
cwd: D:\jsowell\IdeaProjects\jsowell-charger-web
task: 白名单支付订单在异常/待结算时自动修正为订单完成
complexity: medium
planning_method: builtin
created_at: 2026-01-23T16:45:56.6767838+08:00
---

# Plan: 白名单支付订单状态修正（异常/待结算 -> 完成）

🎯 任务概述
当前系统中存在白名单支付（payMode=3）的订单，在某些场景下可能停留在“异常(4)”或“待结算(2)”状态。目标是在满足白名单支付条件时，将这些订单状态修正为“订单完成(6)”，并确保必要的结算时间/金额字段与后续流程（通知、解锁、分账/退款）保持一致或可控。

📋 执行计划
1. 需求澄清与验收口径
   - 明确“白名单支付”的判定字段：`order_basic_info.pay_mode` 是否恒为 `3`（参考 `OrderPayModeEnum.PAYMENT_OF_WHITELIST`），以及是否需要同时检查支付流水 `order_pay_record.pay_mode`。
   - 定义修正规则：仅对白名单支付订单，且当前状态 ∈ {`ABNORMAL(4)`, `STAY_SETTLEMENT(2)`} 时修正为 `ORDER_COMPLETE(6)`；确认是否需要同步设置 `settlement_time`、`order_amount`、`refund_amount`、`virtual_amount`、`settle_amount`、`pay_status` 等字段。

✅ 规则清单（可实现/可测试）
- 白名单判定：以 `order_basic_info.pay_mode == OrderPayModeEnum.PAYMENT_OF_WHITELIST(3)` 为主（系统业务字段）；若存在支付流水，可选做一致性校验 `order_pay_record.pay_mode == OrderPayRecordEnum.WHITELIST_PAYMENT(3)`，不一致时仅记录告警日志，不阻断补偿。
- 修正边界：仅当订单状态 ∈ {`ABNORMAL(4)`, `STAY_SETTLEMENT(2)`} 才允许修正为 `ORDER_COMPLETE(6)`；其余状态必须保持不变。
- 字段同步（补偿落库时）：
  - `order_status`：置为 `ORDER_COMPLETE(6)`
  - `settlement_time`：为空则置当前时间；非空保持原值
  - 金额字段默认策略（尽量沿用既有结算逻辑的语义）：
    - `order_amount`：优先保留已有值；为空则使用 `pay_amount`，仍为空则置 0；若 `order_amount > pay_amount` 则以 `pay_amount` 为准
    - `virtual_amount`：白名单支付场景置为 `order_amount`（不参与结算对账）
    - `settle_amount` / `actual_received_amount`：置为 `order_amount - virtual_amount`（白名单场景为 0）
    - `refund_amount`：为空则置为 `max(pay_amount - order_amount, 0)`
  - `pay_status`：优先保留原值；为空则置 `OrderPayStatusEnum.pay_nothing(2)`
- 副作用约束：补偿方法为 DB/缓存层修正，不应触发远程停机、拉交易记录、MQ 推送、解锁等额外链路（如需触发，应另起规则与验收）。
- 审计日志：至少记录 `orderCode`、原状态、目标状态（必要时补充关键字段快照）。

2. 代码定位与影响面梳理
   - 定位现有白名单异常订单批量处理入口：`jsowell-admin/src/main/java/com/jsowell/service/TempService.java` 的 `whiteListSettlement` 与 `jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/TempController.java` 的 `/whiteListSettlement`。
   - 查找订单状态被设置为异常/待结算的路径，确认修正应放在“状态写入点”还是“事后补偿点”。重点关注：
      - `jsowell-common/src/main/java/com/jsowell/common/enums/ykc/OrderStatusEnum.java`
      - `jsowell-admin/src/main/java/com/jsowell/service/OrderService.java`（存在将充电中订单标记为异常的逻辑）
      - `jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java`、`jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/AbstractProgramLogic.java`（结算后会落库为完成）

📌 影响面清单（可审计）
- 白名单批量入口（人工/管理接口）：`TempController#/whiteListSettlement` → `TempService#whiteListSettlement`（当前仅允许异常订单、且硬编码 payMode=3，并调用 `OrderService#manualSettlementOrder`，会触发远程停机/拉交易记录等外部依赖）。
- 订单标记异常（后管查询触发）：`OrderService#getOrderDetail` 在“充电中”但实时数据缺失/超时场景会将订单置为 `ABNORMAL(4)` 并落库。
- 待结算写入点（设备/交易链路）：
  - `RemoteStopChargingStrategy`：停机成功→`STAY_SETTLEMENT(2)`；停机失败→`ABNORMAL(4)`。
  - `TransactionRecordsStrategy`：收到交易记录后，若订单为 `ABNORMAL(4)` 会先改为 `STAY_SETTLEMENT(2)`，随后进入 `ProgramLogicFactory#getProgramLogic(...).settleOrder(...)` 完成结算落库。
  - 其他协议/平台（同类写入点）：`jsowell-netty` 的 yunkuaichong handlers、`jsowell-thirdparty` 的 Huawei 等也存在将订单置为 `STAY_SETTLEMENT(2)` 的路径（需避免在这些写入点引入“白名单直接完成”造成副作用扩散）。
- 结算后落库完成（核心）：`AbstractProgramLogic#returnUpdateOrderBasicInfo` 会设置 `ORDER_COMPLETE(6)` 并写入结算时间/金额字段（及可能补 SOC）。

🧭 修正插入点选择（结论）
- 选择“事后补偿点”而不是在各类“状态写入点”分散修正：以统一补偿方法 + 白名单批量入口调用为主（后续可扩展定时任务/管理按钮复用该方法）。
- 理由：避免侵入设备协议/交易记录链路（风险大、场景多）；补偿方法可控、幂等、日志可追溯，且明确不触发远程停机/拉交易/MQ/解锁等外部副作用。

3. 设计修正策略（推荐“统一补偿方法”）
   - 在订单领域服务中新增一个可复用的方法（命名示例：`completeWhitelistOrderIfNeeded(orderCode)`），封装：
     - 判定：payMode=3 且状态为异常/待结算。
     - 修正：更新为 `ORDER_COMPLETE`，补齐 `settlement_time`（无则置当前时间），并根据现有数据填充金额字段（缺失时以 0 或合理默认值），确保幂等。
   - 选择调用点：
     - 扩展现有 `/whiteListSettlement`：允许处理 `ABNORMAL` 与 `STAY_SETTLEMENT` 两种状态；内部改为调用统一补偿方法。
     - 视业务需要补充一个定时任务/管理端按钮做批量修复（避免仅靠人工接口）。

4. 实现细节落地
   - 调整 `TempService.whiteListSettlement`：
     - 将“只允许异常订单”的校验扩展为“异常或待结算”。
     - 将硬编码 `payMode == "3"` 改为使用枚举 `OrderPayModeEnum.PAYMENT_OF_WHITELIST.getValue()`。
     - 明确是否继续调用 `orderService.manualSettlementOrder(...)`（它会尝试远程停机、拉取交易记录）；若目标仅是状态修正，优先走新的补偿方法，避免不必要的外部依赖。

5. 测试与回归
   - 增加单元/集成测试覆盖：
     - 白名单订单 + 状态=异常 -> 修正为完成。
     - 白名单订单 + 状态=待结算 -> 修正为完成。
     - 非白名单订单不应被修正。
   - 运行验证命令：`mvn -pl jsowell-admin test`（必要时指定测试类）。

6. 数据校验与上线准备
   - 演练入口：`POST /temp/whiteListSettlement`
     - body（示例）：`{"orderCodeList":["O1","O2"]}`
   - 演练前（务必留存快照，用于回滚/审计）：
     - DB 快照（示例 SQL）：
       - `SELECT order_code,pay_mode,order_status,pay_status,settlement_time,order_amount,virtual_amount,settle_amount,actual_received_amount,refund_amount,reason FROM order_basic_info WHERE order_code IN ('O1','O2');`
     - 将查询结果保存到工单/PR/运维记录（CSV/截图均可）。
   - 演练后（校验点）：
     - `order_basic_info.order_status = 6`
     - `settlement_time`：原为空则已填充；原非空保持不变
     - 金额字段符合“规则清单”默认策略（白名单虚拟金额/结算金额等）
     - 日志可追溯：搜索 `completeWhitelistOrderIfNeeded updated orderCode:`，应包含订单号与状态变更前后值
   - 回滚预案（可执行）：
     - 原则：以“演练前快照”为准逐单回退（避免盲目回退影响正常订单）。
     - 回滚 SQL（模板，按快照逐单生成）：
       - `UPDATE order_basic_info SET order_status='<before_status>', settlement_time='<before_settlement_time>', order_amount=<before_order_amount>, virtual_amount=<before_virtual_amount>, settle_amount=<before_settle_amount>, actual_received_amount=<before_actual_received_amount>, refund_amount=<before_refund_amount>, pay_status='<before_pay_status>' WHERE order_code='<order_code>';`

⚠️ 风险与注意事项
- 业务风险：将异常/待结算直接置为完成可能掩盖真实设备/交易异常；需确认是否仍需要保留异常原因字段或额外审计。
- 技术风险：如果修正流程绕过了“解锁卡/VIN、推送MQ、实时数据落库”等步骤，可能导致下游状态不一致；应明确是否需要补做这些副作用。
- 兼容性：`TempService.whiteListSettlement` 当前只允许异常订单，放宽后需确认调用方预期与权限控制。

📎 参考
- `jsowell-admin/src/main/java/com/jsowell/service/TempService.java`
- `jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/TempController.java`
- `jsowell-common/src/main/java/com/jsowell/common/enums/ykc/OrderStatusEnum.java`
- `jsowell-common/src/main/java/com/jsowell/common/enums/ykc/OrderPayModeEnum.java`
- `jsowell-admin/src/main/java/com/jsowell/service/OrderService.java`
- `jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/AbstractProgramLogic.java`
