docs: 补充无交易记录自动结算功能文档

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

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

View File

@@ -0,0 +1,533 @@
# 无交易记录自动结算功能 - 实施总结
## 版本信息
- **功能版本**: v1.0
- **开发分支**: feature/auto-settle-no-transaction
- **提交哈希**: 121b357a2
- **完成日期**: 2026-08-11
- **开发者**: jsowell
---
## 实施概览
本次开发完成了"无交易记录自动结算"功能的完整实现,包括配置管理、定时任务、核心业务逻辑、幂等保护、数据校验、告警日志和单元测试。
### 开发进度
| 任务 | 状态 | 完成时间 |
|------|------|---------|
| ✅ 配置开关11个配置项 | 已完成 | 2026-08-11 |
| ✅ 创建配置属性类 | 已完成 | 2026-08-11 |
| ✅ 实时数据→结算数据构造方法 | 已完成 | 2026-08-11 |
| ✅ 待结算订单查询 SQL | 已完成 | 2026-08-11 |
| ✅ 定时任务实现 | 已完成 | 2026-08-11 |
| ✅ 幂等保护redis锁+乐观锁) | 已完成 | 2026-08-11 |
| ✅ 数据校验与告警日志 | 已完成 | 2026-08-11 |
| ✅ 单元测试 / 集成测试 | 已完成 | 2026-08-11 |
---
## 核心实现
### 1. 配置管理
**文件**: `jsowell-pile/src/main/java/com/jsowell/pile/config/AutoSettleConfig.java`
```java
@ConfigurationProperties(prefix = "auto-settle")
public class AutoSettleConfig {
private Boolean enabled = false; // 功能总开关
private Integer timeoutMinutes = 10; // 停止超时阈值(分钟)
private String interval = "0 */10 * * * ?"; // 定时任务间隔
private List<Long> grayscaleStationIds; // 灰度站点ID列表
private Integer batchSize = 100; // 单次扫描订单数量上限
private Double amountThresholdRatio = 1.5; // 异常金额阈值比例
private Integer dataFreshnessMinutes = 30; // 实时数据新鲜度阈值(分钟)
private Boolean alertEnabled = true; // 告警开关
private Long lockTimeout = 300L; // Redis锁超时时间
}
```
**配置示例** (application.yml):
```yaml
auto-settle:
enabled: false # 默认关闭,生产环境需手动开启
timeout-minutes: 10
interval: "0 */10 * * * ?"
grayscale-station-ids: [] # 空数组表示全量
batch-size: 100
amount-threshold-ratio: 1.5
data-freshness-minutes: 30
alert-enabled: true
lock-timeout: 300
```
### 2. 数据转换工具
**文件**: `jsowell-pile/src/main/java/com/jsowell/pile/util/SettlementDataConverter.java`
核心功能:
-`RealTimeMonitorData` 提取充电数据
- 构造 `TransactionRecordsData` 结算数据
- 时间格式转换Date ↔ String
- 默认值设置(所有电量归为平段)
### 3. 数据库层
**Mapper 接口**: `OrderBasicInfoMapper.java`
```java
// 查询待结算订单
List<OrderBasicInfo> selectPendingAutoSettleOrders(
@Param("cutoffTime") LocalDateTime cutoffTime,
@Param("stationIds") List<Long> stationIds,
@Param("limit") int limit);
// 乐观锁更新订单
int updateOrderWithOptimisticLock(
@Param("order") OrderBasicInfo order,
@Param("orderId") Integer orderId,
@Param("expectedStatus") String expectedStatus,
@Param("expectedSettlementTime") java.util.Date expectedSettlementTime);
```
**SQL 实现**: `OrderBasicInfoMapper.xml`
- 查询条件del_flag='0', order_status='3', pay_status='1', transaction_code IS NULL/空字符串, charge_end_time < 截止时间
- 灰度过滤支持按站点ID列表过滤
- 分页限制LIMIT 限制单次查询数量
- 乐观锁WHERE order_status='3' AND settlement_time IS NULL
### 4. 业务逻辑
**核心方法**: `OrderBasicInfoServiceImpl.autoSettleOrdersWithoutTransactionRecord()`
**执行流程**
1. **功能开关检查** - 如果未启用直接返回
2. **计算截止时间** - 当前时间 - 超时阈值
3. **查询待结算订单** - 支持灰度站点过滤
4. **逐个处理订单**
- 获取 Redis 分布式锁key: `settle_order_{orderId}`
- 重新查询订单最新状态(防止并发)
- 检查灰度范围
- 获取充电桩连接器状态Redis优先
- 检查充电桩在线状态
- 获取最后一条实时数据
- 检查数据新鲜度(< 30分钟
- 数据校验:电量和金额格式、非空、非零
- 构造结算数据
- 金额异常检测chargingAmount > payAmount × 1.5倍)
- 调用结算方法(`returnUpdateOrderBasicInfo` + `returnUpdateOrderDetail`
- 乐观锁更新订单状态
- 处理退款(如果结算金额 < 已支付金额)
- 释放 Redis 锁
**统计信息**
- successCount - 成功结算数量
- skipCount - 跳过数量
- failCount - 失败数量
### 5. 定时任务
**文件**: `jsowell-quartz/src/main/java/com/jsowell/quartz/task/JsowellTask.java`
```java
public void autoSettleOrdersWithoutTransactionRecord() {
if (skipInPre("无交易记录自动结算")) {
return; // 预发布环境跳过
}
log.info("【无交易记录自动结算】定时任务开始执行");
try {
orderBasicInfoService.autoSettleOrdersWithoutTransactionRecord();
log.info("【无交易记录自动结算】定时任务执行完成");
} catch (Exception e) {
log.error("【无交易记录自动结算】定时任务执行失败", e);
}
}
```
**调用字符串**: `jsowellTask.autoSettleOrdersWithoutTransactionRecord()`
**推荐配置**:
- 执行周期每10分钟执行一次
- Cron 表达式:`0 */10 * * * ?`
### 6. 幂等保护
#### Redis 分布式锁
- **锁键**: `settle_order_{orderId}`
- **锁值**: "1"
- **超时时间**: 300秒可配置
- **获取方式**: `redisCache.setCacheObject()` + 检查返回值
#### 数据库乐观锁
- **WHERE 条件**: `order_status = '3' AND settlement_time IS NULL`
- **更新失败处理**: 记录警告日志,跳过该订单
- **防止并发**: 重新查询订单最新状态
### 7. 数据校验与告警
#### 充电桩在线检测
```java
// 从 Redis 获取充电枪状态
String connectorKey = "CONNECTOR_STATUS:" + connectorId;
Integer status = redisCache.getCacheObject(connectorKey);
// 状态 3=充电中4=已连接未充电 为在线状态
if (status == null || (status != 3 && status != 4)) {
logger.warn("充电桩可能已离线,跳过");
continue;
}
```
#### 数据新鲜度检测
```java
long minutesSinceUpdate = Duration.between(
lastUpdateTime, LocalDateTime.now()
).toMinutes();
if (minutesSinceUpdate > dataFreshnessMinutes) {
logger.warn("实时数据过期({}分钟前),跳过", minutesSinceUpdate);
continue;
}
```
#### 金额异常告警
```java
BigDecimal threshold = payAmount.multiply(amountThresholdRatio);
if (chargingAmount.compareTo(threshold) > 0) {
String alertMsg = String.format(
"【金额异常】订单号:%s站点ID%s充电桩%s" +
"实时充电金额:%.2f 元,已支付金额:%.2f 元,阈值倍数:%.1f",
orderCode, stationId, pileSn,
chargingAmount, payAmount, amountThresholdRatio
);
logger.error(alertMsg);
// TODO: 发送告警通知(邮件/短信/钉钉/企业微信)
}
```
#### 数据格式校验
- 充电电量非空、格式正确、大于0
- 充电金额非空、格式正确
- 异常时记录错误日志,跳过该订单
### 8. 单元测试
**文件**: `jsowell-admin/src/test/java/com/jsowell/AutoSettleOrdersWithoutTransactionTest.java`
**测试用例**
1. **testSelectPendingAutoSettleOrders** - 查询待结算订单
2. **testGrayscaleConfiguration** - 灰度配置测试
3. **testAmountThresholdValidation** - 金额阈值检测
4. **testFeatureToggle** - 配置开关测试
5. **testAutoSettleMainFlow** - 完整流程测试
6. **testDataFreshness** - 数据新鲜度判断
---
## 文件清单
### 新增文件3个
```
jsowell-pile/src/main/java/com/jsowell/pile/config/AutoSettleConfig.java
jsowell-pile/src/main/java/com/jsowell/pile/util/SettlementDataConverter.java
jsowell-admin/src/test/java/com/jsowell/AutoSettleOrdersWithoutTransactionTest.java
```
### 修改文件7个
```
docs/feature-tracker-无交易记录自动结算.md
jsowell-admin/src/main/resources/application.yml
jsowell-pile/src/main/java/com/jsowell/pile/service/OrderBasicInfoService.java
jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java
jsowell-pile/src/main/java/com/jsowell/pile/mapper/OrderBasicInfoMapper.java
jsowell-pile/src/main/resources/mapper/pile/OrderBasicInfoMapper.xml
jsowell-quartz/src/main/java/com/jsowell/quartz/task/JsowellTask.java
```
### 代码统计
- 新增代码:约 500 行(核心业务逻辑)
- 配置类95 行
- 工具类180 行
- 单元测试180 行
- SQL 语句2 个
---
## 部署指南
### 1. 代码合并
```bash
# 切换到目标分支(通常是 dev 或 master
git checkout dev
# 合并功能分支
git merge feature/auto-settle-no-transaction
# 推送到远程仓库
git push origin dev
```
### 2. 配置更新
`application-{env}.yml` 中添加配置:
```yaml
# 无交易记录自动结算配置
auto-settle:
# 功能总开关(默认关闭,需手动开启)
enabled: false
# 停止超时阈值(分钟)- 订单停止超过该时间才触发自动结算
timeout-minutes: 10
# 定时任务执行间隔cron表达式
interval: "0 */10 * * * ?"
# 灰度站点ID列表为空表示全量上线
# 示例:[1001, 1002, 1003]
grayscale-station-ids: []
# 单次扫描订单数量上限
batch-size: 100
# 异常金额阈值比例chargingAmount > payAmount * 该比例时告警跳过)
amount-threshold-ratio: 1.5
# 实时数据新鲜度阈值(分钟)
data-freshness-minutes: 30
# 告警开关
alert-enabled: true
# Redis锁超时时间
lock-timeout: 300
```
### 3. 添加定时任务
在管理后台的"定时任务"菜单中添加任务:
| 字段 | 值 |
|------|-----|
| 任务名称 | 无交易记录自动结算 |
| 任务组名 | DEFAULT |
| 调用目标字符串 | jsowellTask.autoSettleOrdersWithoutTransactionRecord() |
| cron表达式 | 0 */10 * * * ? |
| 执行策略 | 立即执行 |
| 是否并发 | 否 |
| 状态 | 暂停(灰度期间) |
### 4. 灰度发布流程
#### 阶段1单站点灰度第1-3天
```yaml
auto-settle:
enabled: true
grayscale-station-ids: [1001] # 选择1个业务量适中的站点
```
**观察指标**
- 成功结算数量
- 跳过数量(及原因)
- 失败数量(及异常)
- 金额异常告警
- Redis锁竞争情况
- 数据库慢查询
#### 阶段2小范围灰度第4-7天
```yaml
auto-settle:
enabled: true
grayscale-station-ids: [1001, 1002, 1003, 1004, 1005] # 扩展到5个站点
```
#### 阶段3大范围灰度第8-14天
```yaml
auto-settle:
enabled: true
grayscale-station-ids: [...] # 扩展到30%的站点
```
#### 阶段4全量上线第15天+
```yaml
auto-settle:
enabled: true
grayscale-station-ids: [] # 空数组 = 全量
```
### 5. 监控指标
#### 日志监控
```bash
# 查看执行日志
tail -f logs/jsowell-admin.log | grep "无交易记录自动结算"
# 统计成功数量
grep "【无交易记录自动结算】执行完成,成功" logs/jsowell-admin.log | tail -20
# 查看告警日志
grep "【无交易记录自动结算-金额异常】" logs/jsowell-admin.log
grep "【无交易记录自动结算-处理异常】" logs/jsowell-admin.log
```
#### 数据库监控
```sql
-- 查看待结算订单数量
SELECT COUNT(*)
FROM order_basic_info
WHERE del_flag = '0'
AND order_status = '3'
AND pay_status = '1'
AND (transaction_code IS NULL OR transaction_code = '')
AND charge_end_time < DATE_SUB(NOW(), INTERVAL 10 MINUTE);
-- 查看最近自动结算的订单
SELECT order_code, station_id, pile_sn,
charge_end_time, settlement_time,
order_amount, refund_amount
FROM order_basic_info
WHERE reason = '无交易记录自动结算'
AND settlement_time > DATE_SUB(NOW(), INTERVAL 1 DAY)
ORDER BY settlement_time DESC
LIMIT 100;
```
#### Redis监控
```bash
# 查看当前锁数量
redis-cli KEYS "settle_order_*" | wc -l
# 检查是否有死锁TTL < 0
redis-cli KEYS "settle_order_*" | xargs -I {} redis-cli TTL {}
```
---
## 风险点与应对
### 1. 并发冲突
**风险**: 多个定时任务实例同时处理同一订单
**应对**:
- Redis 分布式锁 + 乐观锁双重保护
- 锁超时时间设置为5分钟防止死锁
- 乐观锁更新失败时记录日志,不抛出异常
### 2. 金额异常
**风险**: 实时数据的充电金额远大于预付金额
**应对**:
- 设置金额阈值默认1.5倍)
- 超过阈值告警跳过,人工介入
- 详细记录订单信息、站点ID、充电桩SN
### 3. 数据不新鲜
**风险**: 充电桩"假在线"(最后一条实时数据很久之前)
**应对**:
- 检查实时数据更新时间
- 超过30分钟的数据视为陈旧跳过结算
- 记录警告日志
### 4. 充电桩离线
**风险**: 充电桩实际已离线,但订单未正常结束
**应对**:
- 从 Redis 检查充电枪状态
- 状态非"充电中"或"已连接"时跳过
- 依赖设备心跳机制更新状态
### 5. 退款失败
**风险**: 结算成功但退款失败,用户损失
**应对**:
- 退款失败记录错误日志
- 告警通知运营人员
- 支持后台手动发起退款
### 6. 性能问题
**风险**: 单次扫描订单过多,影响数据库性能
**应对**:
- 限制单次查询数量默认100
- 使用索引优化查询charge_end_time, order_status, pay_status
- 定时任务间隔可调整默认10分钟
---
## 后续优化建议
### 1. 告警系统集成
- 对接现有告警系统(邮件/短信/钉钉/企业微信)
- 金额异常、处理失败立即通知
- 每日汇总报告(成功数、失败数、异常数)
### 2. 监控大盘
- Grafana 可视化监控
- 实时展示待结算订单数量
- 自动结算成功率、平均处理时长
- 金额异常趋势图
### 3. 智能调度
- 根据待结算订单数量动态调整执行频率
- 业务高峰期降低频率,低谷期提高频率
- 避免影响正常业务
### 4. 数据分析
- 统计哪些站点、哪些充电桩频繁出现无交易记录
- 分析根本原因(设备故障、网络问题、协议异常)
- 针对性优化设备通信逻辑
### 5. 手动补结算
- 后台管理页面添加"手动自动结算"按钮
- 支持批量选择订单执行结算
- 提供详细的执行日志和结果反馈
---
## 验收标准
### 功能验收
- [x] 配置开关正常工作
- [x] 定时任务正常调度执行
- [x] 查询待结算订单准确
- [x] 结算逻辑正确(金额、电量、时间)
- [x] 退款逻辑正确
- [x] 幂等保护有效
- [x] 数据校验完整
- [x] 告警日志记录详细
- [x] 单元测试通过
### 性能验收
- [ ] 单次处理100个订单耗时 < 30秒
- [ ] Redis 锁无死锁现象
- [ ] 数据库慢查询 < 5%
### 稳定性验收
- [ ] 灰度期间7天无P0/P1故障
- [ ] 并发场景下无数据不一致
- [ ] 异常场景正常降级(记录日志、跳过订单)
---
## 附录
### A. 相关文档
- [功能设计文档](./feature-tracker-无交易记录自动结算.md)
- [功能设计附录](./feature-tracker-无交易记录自动结算-附录.md)
- [项目架构文档](../CLAUDE.md)
- [jsowell-pile 模块文档](../jsowell-pile/CLAUDE.md)
- [jsowell-quartz 模块文档](../jsowell-quartz/CLAUDE.md)
### B. 联系方式
- 开发负责人: jsowell
- Git 分支: feature/auto-settle-no-transaction
- 提交哈希: 121b357a2
---
**文档版本**: v1.0
**最后更新**: 2026-08-11
**状态**: ✅ 开发完成,待灰度发布

View File

@@ -0,0 +1,274 @@
# 附录:无交易记录自动结算功能
本文档为 `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 数据流程图
```mermaid
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 状态流转图
```mermaid
stateDiagram-v2
[*] --> 充电中: 开始充电
充电中 --> 待结算: 收到0x19结束帧<br/>或桩停止上报
待结算 --> 已结算: 收到交易记录帧<br/>(现有逻辑)
待结算 --> 已结算: 定时任务自动结算<br/>(新增逻辑)
待结算 --> 已结算: 人工结算
待结算 --> 异常订单: 桩离线<br/>(现有逻辑)
已结算 --> [*]
异常订单 --> [*]
note right of 待结算
定时任务触发条件:
1. 桩在线
2. 停止>10分钟
3. 有实时数据
4. 在灰度站点范围内
end note
```
### 8.4 配置项完整清单
```yaml
# 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
```sql
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;
```
#### 查询最后一条实时数据
```sql
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 级别日志
```java
log.info("[自动结算] 开始扫描待结算订单,灰度站点数量:{}", stationIds.size());
log.info("[自动结算] 扫描到{}个待结算订单", orders.size());
log.info("[自动结算] 订单{}自动结算成功,金额:{}元,耗时:{}ms",
orderId, chargingAmount, duration);
```
#### WARN 级别日志
```java
log.warn("[自动结算] 订单{}充电度数异常:{},跳过结算", orderId, chargingDegree);
log.warn("[自动结算] 订单{}充电金额异常:{},跳过结算", orderId, chargingAmount);
log.warn("[自动结算] 订单{}状态已变更,跳过结算", orderId);
log.warn("[自动结算] 订单{}获取锁失败,跳过", orderId);
```
#### ERROR 级别日志(需发送告警)
```java
log.error("[自动结算] 订单{}金额异常:实际{}元 > 预付{}元 * {},跳过结算",
orderId, chargingAmount, payAmount, threshold);
log.error("[自动结算] 订单{}结算失败:{}", orderId, e.getMessage(), e);
log.error("[自动结算] 定时任务执行失败:{}", e.getMessage(), e);
```
### 8.8 Prometheus 监控指标
```java
// 建议采集的指标
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 |
---
**文档结束**