peixue-dev/Archive/[一次性]服务商提现功能优化-2026-01-31.md

181 lines
4.5 KiB
Markdown
Raw Normal View History

2026-02-28 17:26:03 +08:00
# 服务商提现功能优化
**日期:** 2026-01-31
**功能:** 服务商提现申请后,可提取金额立即减少
---
## 问题描述
用户反馈:提交提现申请后,可提取金额没有变化。
### 原因分析
**修改前的逻辑:**
```
可提取金额 = 总收益(所有已完成订单的金额)
```
问题:
- 提现申请只创建了记录,没有扣减可提现余额
- 无论提现多少次,可提取金额始终等于总收益
---
## 解决方案
### 修改后的逻辑
```
可提取金额 = 总收益 - 已提现金额 - 提现中金额
```
其中:
- **总收益**: 所有已完成订单(status=4)的金额总和
- **已提现金额**: 状态为 `approved``completed` 的提现记录金额总和
- **提现中金额**: 状态为 `pending` 的提现记录金额总和
### 状态流转
```
pending (待审核) → approved (已通过) → completed (已完成)
↘ rejected (已拒绝)
```
- **pending**: 用户提交提现申请,金额从"可提取"转为"提现中"
- **approved**: 管理员审核通过,金额仍在"已提现"
- **rejected**: 管理员拒绝,金额回到"可提取"
- **completed**: 提现完成,金额在"已提现"
---
## 修改内容
### 文件: `ProviderServiceImpl.java`
**方法:** `getEarningsStats(Long providerId)`
**修改点:**
1. **计算已提现金额**
```java
// 查询状态为 approved 或 completed 的提现记录
LambdaQueryWrapper<Withdraw> withdrawnWrapper = new LambdaQueryWrapper<>();
withdrawnWrapper.eq(Withdraw::getTeacherId, providerId)
.in(Withdraw::getStatus, "approved", "completed");
List<Withdraw> withdrawnRecords = withdrawMapper.selectList(withdrawnWrapper);
BigDecimal withdrawnAmount = withdrawnRecords.stream()
.map(Withdraw::getAmount)
.filter(amount -> amount != null)
.reduce(BigDecimal.ZERO, BigDecimal::add);
```
2. **计算提现中金额**
```java
// 查询状态为 pending 的提现记录
LambdaQueryWrapper<Withdraw> withdrawingWrapper = new LambdaQueryWrapper<>();
withdrawingWrapper.eq(Withdraw::getTeacherId, providerId)
.eq(Withdraw::getStatus, "pending");
List<Withdraw> withdrawingRecords = withdrawMapper.selectList(withdrawingWrapper);
BigDecimal withdrawingAmount = withdrawingRecords.stream()
.map(Withdraw::getAmount)
.filter(amount -> amount != null)
.reduce(BigDecimal.ZERO, BigDecimal::add);
```
3. **计算可提现余额**
```java
// 可提现余额 = 总收益 - 已提现金额 - 提现中金额
BigDecimal availableBalance = totalEarnings
.subtract(withdrawnAmount)
.subtract(withdrawingAmount);
// 确保可提现余额不为负数
if (availableBalance.compareTo(BigDecimal.ZERO) < 0) {
availableBalance = BigDecimal.ZERO;
}
```
---
## 测试步骤
### 1. 查看当前收益状态
```sql
-- 查看服务商的订单收益
SELECT SUM(pay_amount) as total_earnings
FROM `order`
WHERE teacher_id = ? AND status = 4;
-- 查看提现记录
SELECT status, SUM(amount) as total
FROM withdraw
WHERE teacher_id = ?
GROUP BY status;
```
### 2. 提交提现申请
- 前端: 进入"收益查看"页面 → 点击"提取收益"
- 输入提现金额 → 提交
### 3. 验证可提取金额变化
- 提交后,刷新页面
- 可提取金额应该减少(扣除提现申请的金额)
- 提现中金额应该增加
### 4. 测试审核流程
- 管理员审核通过: 金额从"提现中"转为"已提现"
- 管理员拒绝: 金额回到"可提取"
---
## 预期效果
### 场景1: 提交提现申请
**操作前:**
- 总收益: ¥1000
- 可提取: ¥1000
- 提现中: ¥0
- 已提现: ¥0
**提交¥300提现申请后:**
- 总收益: ¥1000
- 可提取: ¥700 ✅
- 提现中: ¥300 ✅
- 已提现: ¥0
### 场景2: 审核通过
**审核通过后:**
- 总收益: ¥1000
- 可提取: ¥700
- 提现中: ¥0 ✅
- 已提现: ¥300 ✅
### 场景3: 审核拒绝
**审核拒绝后:**
- 总收益: ¥1000
- 可提取: ¥1000 ✅ (金额回到可提取)
- 提现中: ¥0 ✅
- 已提现: ¥0
---
## 注意事项
1. **数据一致性**: 确保提现记录的状态正确更新
2. **并发控制**: 多次提现申请时,需要确保余额计算正确
3. **负数保护**: 可提现余额不能为负数
4. **日志记录**: 关键操作都有日志输出,便于排查问题
---
## 相关文件
- `peidu/backend/src/main/java/com/peidu/service/impl/ProviderServiceImpl.java`
- `peidu/backend/src/main/java/com/peidu/entity/Withdraw.java`
- `peidu/uniapp/src/provider-package/pages/provider/earnings.vue`
- `peidu/uniapp/src/provider-package/pages/provider/withdraw.vue`