122 lines
3.8 KiB
Markdown
122 lines
3.8 KiB
Markdown
|
|
# 收益统计数据异常诊断 - 2026-01-31
|
|||
|
|
|
|||
|
|
## 问题描述
|
|||
|
|
|
|||
|
|
在收益查看页面中,**总收益(222元)** 比 **本月收益(1774元)** 要低,这不符合逻辑。
|
|||
|
|
|
|||
|
|
## 问题原因分析
|
|||
|
|
|
|||
|
|
### 1. 数据来源不一致
|
|||
|
|
|
|||
|
|
**总收益的计算逻辑:**
|
|||
|
|
```java
|
|||
|
|
// 文件:ProviderServiceImpl.java - getEarningsStats()
|
|||
|
|
// 只统计状态为4(已完成)的订单
|
|||
|
|
wrapper.eq(Order::getTeacherId, providerId)
|
|||
|
|
.eq(Order::getStatus, 4); // 已完成
|
|||
|
|
|
|||
|
|
BigDecimal totalEarnings = orders.stream()
|
|||
|
|
.map(Order::getPayAmount)
|
|||
|
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**本月收益的计算逻辑:**
|
|||
|
|
```java
|
|||
|
|
// 文件:ProviderController.java - getEarningsStats()
|
|||
|
|
// 统计本月所有订单(不限制状态)
|
|||
|
|
w.eq(Order::getTeacherId, providerId)
|
|||
|
|
.between(Order::getCreateTime, start, end);
|
|||
|
|
|
|||
|
|
BigDecimal earnings = periodOrders.stream()
|
|||
|
|
.map(Order::getPayAmount)
|
|||
|
|
.filter(amount -> amount != null)
|
|||
|
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 核心问题
|
|||
|
|
|
|||
|
|
**问题1:状态筛选不一致**
|
|||
|
|
- 总收益:只统计 `status = 4`(已完成)的订单
|
|||
|
|
- 本月收益:统计所有状态的订单
|
|||
|
|
|
|||
|
|
**问题2:时间筛选不一致**
|
|||
|
|
- 总收益:统计所有时间的已完成订单
|
|||
|
|
- 本月收益:只统计本月的订单(包括未完成的)
|
|||
|
|
|
|||
|
|
**问题3:月份判断错误**
|
|||
|
|
```java
|
|||
|
|
// getEarningsStats() 中的本月收益计算
|
|||
|
|
.filter(order -> order.getCreateTime().getMonth() == LocalDateTime.now().getMonth())
|
|||
|
|
```
|
|||
|
|
这个判断有问题:
|
|||
|
|
- 只比较月份,不比较年份
|
|||
|
|
- 会把去年同月的订单也算进来
|
|||
|
|
|
|||
|
|
## 数据示例分析
|
|||
|
|
|
|||
|
|
假设数据库中的订单:
|
|||
|
|
```
|
|||
|
|
订单1: 2026-01-15, status=4(已完成), 金额=100元
|
|||
|
|
订单2: 2026-01-20, status=4(已完成), 金额=122元
|
|||
|
|
订单3: 2026-01-25, status=1(待服务), 金额=500元
|
|||
|
|
订单4: 2026-01-28, status=2(服务中), 金额=1000元
|
|||
|
|
订单5: 2025-12-20, status=4(已完成), 金额=50元
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**当前计算结果:**
|
|||
|
|
- 总收益 = 100 + 122 + 50 = 272元(所有已完成订单)
|
|||
|
|
- 本月收益 = 100 + 122 + 500 + 1000 = 1722元(本月所有订单,包括未完成)
|
|||
|
|
|
|||
|
|
**正确应该是:**
|
|||
|
|
- 总收益 = 100 + 122 + 50 = 272元(所有已完成订单)
|
|||
|
|
- 本月收益 = 100 + 122 = 222元(本月已完成订单)
|
|||
|
|
|
|||
|
|
## 修复方案
|
|||
|
|
|
|||
|
|
### 方案1:统一状态筛选(推荐)
|
|||
|
|
|
|||
|
|
**原则:** 只统计已完成(status=4)的订单
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
// 修改 ProviderController.java 中的本月收益计算
|
|||
|
|
LambdaQueryWrapper<Order> w = new LambdaQueryWrapper<>();
|
|||
|
|
w.eq(Order::getTeacherId, providerId)
|
|||
|
|
.eq(Order::getStatus, 4) // 添加:只统计已完成订单
|
|||
|
|
.between(Order::getCreateTime, start, end);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 方案2:修复月份判断
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
// 修改 ProviderServiceImpl.java 中的本月收益计算
|
|||
|
|
BigDecimal monthEarnings = orders.stream()
|
|||
|
|
.filter(order -> {
|
|||
|
|
LocalDateTime createTime = order.getCreateTime();
|
|||
|
|
LocalDateTime now = LocalDateTime.now();
|
|||
|
|
return createTime.getYear() == now.getYear()
|
|||
|
|
&& createTime.getMonth() == now.getMonth();
|
|||
|
|
})
|
|||
|
|
.map(Order::getPayAmount)
|
|||
|
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 方案3:统一数据源
|
|||
|
|
|
|||
|
|
建议在 `ProviderController.java` 中直接调用数据库查询,而不是依赖 `getEarningsStats()` 方法。
|
|||
|
|
|
|||
|
|
## 建议的修复步骤
|
|||
|
|
|
|||
|
|
1. **统一状态筛选** - 所有收益统计都只计算 `status=4` 的订单
|
|||
|
|
2. **修复月份判断** - 同时比较年份和月份
|
|||
|
|
3. **添加日志** - 记录每次查询的订单数量和金额,便于调试
|
|||
|
|
4. **数据验证** - 确保总收益 >= 本月收益 >= 今日收益
|
|||
|
|
|
|||
|
|
## 相关文件
|
|||
|
|
|
|||
|
|
- `peidu/backend/src/main/java/com/peidu/service/impl/ProviderServiceImpl.java`
|
|||
|
|
- `peidu/backend/src/main/java/com/peidu/controller/ProviderController.java`
|
|||
|
|
- `peidu/backend/src/main/java/com/peidu/vo/EarningsStatsVO.java`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
*诊断时间:2026-01-31*
|