Files
jsowell-charger-web/docs/feature-tracker-无交易记录自动结算-附录.md
jsowell 864d04ccfb docs: 补充无交易记录自动结算功能文档
新增文档:
- feature-tracker-无交易记录自动结算-实施总结.md - 完整实施总结,包含部署指南、监控方案、风险应对
- feature-tracker-无交易记录自动结算-附录.md - 功能设计附录

文档内容:
- 开发进度总结(8个任务全部完成)
- 核心实现详解(配置、数据转换、业务逻辑、定时任务、幂等保护、数据校验)
- 文件清单(3个新增文件、7个修改文件)
- 部署指南(代码合并、配置更新、定时任务添加、4阶段灰度发布流程)
- 监控方案(日志监控、数据库监控、Redis监控)
- 风险点与应对(6类风险及解决方案)
- 后续优化建议(5个方向)
- 验收标准(功能、性能、稳定性)
2026-08-11 16:48:41 +08:00

9.8 KiB
Raw Blame History

附录:无交易记录自动结算功能

本文档为 feature-tracker-无交易记录自动结算.md 的附录部分


八、附录

8.1 关键代码位置索引

代码位置 说明 行号
TransactionRecordsRequestHandler.processOrder() 交易记录触发结算入口 jsowell-netty/.../TransactionRecordsRequestHandler.java:683
OrderService.manualSettlementOrder() 人工结算逻辑(可复用实时数据构造) jsowell-admin/.../OrderService.java:1008-1027
YKCBusinessServiceImpl 桩离线标记异常订单 jsowell-netty/.../YKCBusinessServiceImpl.java:166
ChargeEndHandler 0x19充电结束帧处理 jsowell-netty/.../ChargeEndHandler.java
RealTimeMonitorData 实时检测数据实体类 jsowell-common/.../domain/RealTimeMonitorData.java
order_monitor_data 实时数据落库 MySQL
Redis PILE_REAL_TIME_MONITOR_DATA 实时数据缓存 Redis
settle_order_ 锁前缀 结算分布式锁 Redis

8.2 数据流程图

sequenceDiagram
    participant Timer as 定时任务
    participant DB as 数据库
    participant Redis as Redis
    participant OrderLogic as 结算逻辑
    participant Alert as 告警系统

    Timer->>Timer: 检查配置开关
    alt 开关关闭
        Timer->>Timer: 退出
    end

    Timer->>DB: 查询待结算订单<br/>(状态=待结算 + 桩在线 + 停止>10min)
    DB-->>Timer: 订单列表限batch-size条

    loop 遍历每个订单
        Timer->>Redis: 尝试获取锁<br/>settle_order_{orderId}
        alt 获取锁失败
            Timer->>Timer: 跳过该订单
        end

        Timer->>DB: 查询最后一条实时数据
        alt 数据异常检查
            Timer->>Timer: 检查 chargingDegree > 0
            Timer->>Timer: 检查 chargingAmount > 0
            Timer->>Timer: 检查金额阈值
            alt 任一检查不通过
                Timer->>Alert: 发送告警
                Timer->>Timer: 跳过该订单
            end
        end

        Timer->>Timer: 构造 TransactionRecordsData
        Timer->>OrderLogic: settleOrder(data, orderInfo)
        OrderLogic-->>Timer: 结算结果

        alt 结算成功
            Timer->>Timer: 记录成功日志
        else 结算失败
            Timer->>Alert: 发送告警
            Timer->>Timer: 记录失败日志
        end

        Timer->>Redis: 释放锁
    end

8.3 状态流转图

stateDiagram-v2
    [*] --> 充电中: 开始充电
    充电中 --> 待结算: 收到0x19结束帧<br/>或桩停止上报
    
    待结算 --> 已结算: 收到交易记录帧<br/>(现有逻辑)
    待结算 --> 已结算: 定时任务自动结算<br/>(新增逻辑)
    待结算 --> 已结算: 人工结算
    
    待结算 --> 异常订单: 桩离线<br/>(现有逻辑)
    
    已结算 --> [*]
    异常订单 --> [*]
    
    note right of 待结算
        定时任务触发条件:
        1. 桩在线
        2. 停止>10分钟
        3. 有实时数据
        4. 在灰度站点范围内
    end note

8.4 配置项完整清单

# application.yml 或 application-{env}.yml
auto-settle:
  # ========== 基础配置 ==========
  enabled: false                        # 总开关,默认关闭
  timeout-minutes: 10                   # 停止超时阈值(分钟)
  interval: '0 */10 * * * ?'           # 扫描周期Cron表达式每10分钟
  grayscale-station-ids:                # 灰度站点白名单
    - 1001
    - 1002
  
  # ========== 金额与数据校验 ==========
  amount-threshold-ratio: 1.5           # 金额异常阈值倍数chargingAmount > payAmount * 1.5 时告警)
  batch-size: 100                       # 单次扫描订单数量上限
  data-freshness-minutes: 30            # 实时数据新鲜度阈值(分钟)
  
  # ========== 并发与容错 ==========
  alert-enabled: true                   # 告警开关
  lock-timeout-seconds: 60              # redis分布式锁超时时间
  retry-on-failure: false               # 失败是否重试建议false等下一轮
  
  # ========== 监控指标 ==========
  metrics:
    enabled: true                       # 是否启用Prometheus指标
    prefix: "auto_settle"               # 指标前缀

8.5 数据库查询SQL示例

查询待结算订单方案D直接JOIN

SELECT 
    obi.order_id,
    obi.order_no,
    obi.pile_connector_id,
    obi.pay_amount,
    obi.charge_end_time,
    obi.station_id,
    pci.connector_status,
    omd.charging_degree,
    omd.charging_amount,
    omd.date_time as last_monitor_time
FROM order_basic_info obi
INNER JOIN pile_connector_info pci 
    ON obi.pile_connector_id = pci.connector_id
LEFT JOIN (
    SELECT 
        order_id,
        charging_degree,
        charging_amount,
        date_time,
        ROW_NUMBER() OVER (PARTITION BY order_id ORDER BY date_time DESC, id DESC) as rn
    FROM order_monitor_data
) omd ON obi.order_id = omd.order_id AND omd.rn = 1
WHERE obi.order_status = 'STAY_SETTLEMENT'          -- 待结算
  AND pci.connector_status != '0'                   -- 桩在线
  AND obi.station_id IN (?, ?, ...)                 -- 灰度站点
  AND (
      -- 依据1有充电结束时间且超过10分钟
      (obi.charge_end_time IS NOT NULL 
       AND obi.charge_end_time < DATE_SUB(NOW(), INTERVAL 10 MINUTE))
      OR
      -- 依据2最后实时数据超过10分钟
      (omd.date_time IS NOT NULL 
       AND omd.date_time < DATE_SUB(NOW(), INTERVAL 10 MINUTE))
  )
  AND omd.charging_degree > 0                       -- 有充电度数
  AND omd.charging_amount > 0                       -- 有充电金额
  AND omd.date_time > DATE_SUB(NOW(), INTERVAL 30 MINUTE)  -- 数据新鲜度
LIMIT 100;

查询最后一条实时数据

SELECT * 
FROM order_monitor_data 
WHERE order_id = ? 
ORDER BY date_time DESC, id DESC 
LIMIT 1;

8.6 Redis Key 设计

Key 模式 说明 过期时间 示例值
settle_order_{orderId} 结算分布式锁 60秒 settle_order_123456
PILE_REAL_TIME_MONITOR_DATA:{connectorId} 实时数据缓存 持久化 PILE_REAL_TIME_MONITOR_DATA:ABC001-1
auto_settle_alert:{orderId} 告警去重(可选) 3600秒 auto_settle_alert_123456

8.7 日志规范

INFO 级别日志

log.info("[自动结算] 开始扫描待结算订单,灰度站点数量:{}", stationIds.size());
log.info("[自动结算] 扫描到{}个待结算订单", orders.size());
log.info("[自动结算] 订单{}自动结算成功,金额:{}元,耗时:{}ms", 
         orderId, chargingAmount, duration);

WARN 级别日志

log.warn("[自动结算] 订单{}充电度数异常:{},跳过结算", orderId, chargingDegree);
log.warn("[自动结算] 订单{}充电金额异常:{},跳过结算", orderId, chargingAmount);
log.warn("[自动结算] 订单{}状态已变更,跳过结算", orderId);
log.warn("[自动结算] 订单{}获取锁失败,跳过", orderId);

ERROR 级别日志(需发送告警)

log.error("[自动结算] 订单{}金额异常:实际{}元 > 预付{}元 * {},跳过结算", 
          orderId, chargingAmount, payAmount, threshold);
log.error("[自动结算] 订单{}结算失败:{}", orderId, e.getMessage(), e);
log.error("[自动结算] 定时任务执行失败:{}", e.getMessage(), e);

8.8 Prometheus 监控指标

// 建议采集的指标
auto_settle_scan_count                      // 扫描次数
auto_settle_order_found_count               // 发现待结算订单数
auto_settle_success_count                   // 结算成功数
auto_settle_skip_count{reason="lock_failed"}        // 跳过数(锁失败)
auto_settle_skip_count{reason="data_invalid"}       // 跳过数(数据异常)
auto_settle_skip_count{reason="amount_exceed"}      // 跳过数(金额超限)
auto_settle_failure_count                   // 结算失败数
auto_settle_duration_seconds                // 扫描耗时
auto_settle_order_duration_seconds          // 单个订单结算耗时

九、审查意见总结

文档优点

  1. 风险识别全面6个风险点覆盖了金额准确性、并发、影响面等核心问题
  2. 决策清晰对R1金额策略、R4停止判定都有明确决策并记录
  3. 实现思路稳健:不改核心链路,新增入口,灰度上线
  4. 业务条件合理桩在线、停止超10分钟、有实时数据三个条件都是必要的

⚠️ 需补充内容(已在第六章列出)

类别 问题编号 状态 优先级
并发幂等 6.1, 6.5 待回答 P0
数据校验 6.2, 6.4, 6.7 待回答 P0
性能优化 6.3 待回答 P1
业务逻辑 6.6 待回答 P0
配置设计 6.8 待回答 P1

建议行动路径

  1. 步骤1需求评审确认已完成
  2. 🔴 步骤2回答第六章的8个待明确问题当前阻塞
  3. 步骤3更新文档版本号为 v0.4
  4. 步骤4进入开发阶段第五章进度追踪

十、版本历史

版本 日期 变更内容 作者
v0.1 2026-08-11 初稿:需求分析、风险点、实现方案、开发进度追踪框架 -
v0.2 2026-08-11 确认决策:金额以桩端 chargingAmount 为准;双依据判定都启用;特定站点灰度 -
v0.3 2026-08-11 新增8个待明确问题第六章扩充测试计划至29个场景第七章新增附录 Claude
v0.4 2026-08-11 完成8个问题的决策回答更新已决策问题列表11个决策状态更新为"方案已确认,待开发" Claude

文档结束