Files
soul-yongping/开发文档/8、部署/可提现金额计算修复.md

360 lines
10 KiB
Markdown
Raw Normal View History

# 可提现金额计算修复
## 问题总结
### 发现的问题
**当前逻辑(错误)**
```javascript
可提现金额 = 累计佣金 - 待审核金额
```
**问题场景**
1. 用户累计佣金 ¥100申请提现 ¥50
2. 此时:可提现 = 100 - 50 = ¥50 ✅ 正确
3. 审核通过后,提现记录状态改为 completed
4. 此时:可提现 = 100 - 0 = ¥100 ❌ 错误!
**根本原因**:审核通过后,`pendingWithdrawAmount` 归零,但没有减去"已提现金额",导致可提现金额"回血"。
## 正确方案
### 计算公式
```javascript
可提现金额 = 累计佣金 - 已提现金额 - 待审核金额
```
### 字段说明
| 字段 | 说明 | 来源 | 变化规律 |
|------|------|------|----------|
| `totalCommission` | 累计佣金总额 | `SUM(orders.amount) × distributorShare` | 有新订单就增加,只增不减 |
| `withdrawnEarnings` | 已提现金额 | `users.withdrawn_earnings` | 审核通过时累加 |
| `pendingWithdrawAmount` | 待审核金额 | `SUM(withdrawals.amount WHERE status='pending')` | 申请时增加,审核后归零 |
| `availableEarnings` | 可提现金额 | 前端计算 | 动态变化 |
## 修复内容
### 1. 前端计算逻辑修正
**文件**`miniprogram/pages/referral/referral.js`
**修改前**
```javascript
// ❌ 错误:只减去待审核,没减去已提现
const totalCommissionNum = realData?.totalCommission || 0
const pendingWithdrawNum = realData?.pendingWithdrawAmount || 0
const availableEarningsNum = totalCommissionNum - pendingWithdrawNum
```
**修改后**
```javascript
// ✅ 正确:三元素完整计算
const totalCommissionNum = realData?.totalCommission || 0
const withdrawnNum = realData?.withdrawnEarnings || 0
const pendingWithdrawNum = realData?.pendingWithdrawAmount || 0
const availableEarningsNum = totalCommissionNum - withdrawnNum - pendingWithdrawNum
```
### 2. 详细日志输出
```javascript
console.log('=== [Referral] 收益计算(完整版)===')
console.log('累计佣金 (totalCommission):', totalCommissionNum)
console.log('已提现金额 (withdrawnEarnings):', withdrawnNum)
console.log('待审核金额 (pendingWithdrawAmount):', pendingWithdrawNum)
console.log('可提现金额 = 累计 - 已提现 - 待审核 =', totalCommissionNum, '-', withdrawnNum, '-', pendingWithdrawNum, '=', availableEarningsNum)
console.log('最低提现金额 (minWithdrawAmount):', minWithdrawAmount)
console.log('按钮判断:', availableEarningsNum, '>=', minWithdrawAmount, '=', availableEarningsNum >= minWithdrawAmount)
console.log('✅ 按钮应该:', availableEarningsNum >= minWithdrawAmount ? '🟢 启用(绿色)' : '⚫ 禁用(灰色)')
```
## 验证流程
### 完整场景测试
#### 场景1初始状态
```
数据:
- 累计佣金: ¥100
- 已提现: ¥0
- 待审核: ¥0
计算:
availableEarnings = 100 - 0 - 0 = ¥100
验证:✅ 可提现 ¥100
```
#### 场景2申请提现
```
操作:申请提现 ¥50
数据:
- 累计佣金: ¥100 (不变)
- 已提现: ¥0 (不变)
- 待审核: ¥50 (新增)
计算:
availableEarnings = 100 - 0 - 50 = ¥50
验证:✅ 可提现 ¥50
```
#### 场景3审核通过关键
```
操作:管理员审核通过
数据:
- 累计佣金: ¥100 (不变)
- 已提现: ¥50 (users.withdrawn_earnings += 50)
- 待审核: ¥0 (状态改为 completed)
计算:
availableEarnings = 100 - 50 - 0 = ¥50
验证:✅ 可提现 ¥50不会回血
```
#### 场景4新订单产生
```
操作:用户购买新商品,产生佣金 ¥20
数据:
- 累计佣金: ¥120 (100 + 20)
- 已提现: ¥50 (不变)
- 待审核: ¥0 (不变)
计算:
availableEarnings = 120 - 50 - 0 = ¥70
验证:✅ 可提现 ¥70
```
#### 场景5二次提现
```
操作:申请提现 ¥30
数据:
- 累计佣金: ¥120 (不变)
- 已提现: ¥50 (不变)
- 待审核: ¥30 (新增)
计算:
availableEarnings = 120 - 50 - 30 = ¥40
验证:✅ 可提现 ¥40
```
### 数据库验证
#### 1. 检查 users 表
```sql
SELECT
id,
nickname,
withdrawn_earnings
FROM users
WHERE id = 'YOUR_USER_ID';
```
#### 2. 检查 withdrawals 表
```sql
SELECT
id,
amount,
status,
created_at
FROM withdrawals
WHERE user_id = 'YOUR_USER_ID'
ORDER BY created_at DESC;
```
#### 3. 检查 orders 表
```sql
SELECT
SUM(amount) as total_amount
FROM orders
WHERE referrer_id = 'YOUR_USER_ID'
AND status = 'paid';
```
#### 4. 手动验证计算
```sql
-- 1. 累计佣金
SET @total_orders = (SELECT SUM(amount) FROM orders WHERE referrer_id = 'YOUR_USER_ID' AND status = 'paid');
SET @distributor_share = 0.9;
SET @total_commission = @total_orders * @distributor_share;
-- 2. 已提现
SET @withdrawn = (SELECT withdrawn_earnings FROM users WHERE id = 'YOUR_USER_ID');
-- 3. 待审核
SET @pending = (SELECT SUM(amount) FROM withdrawals WHERE user_id = 'YOUR_USER_ID' AND status = 'pending');
-- 4. 可提现
SET @available = @total_commission - @withdrawn - IFNULL(@pending, 0);
-- 显示结果
SELECT
@total_commission as '累计佣金',
@withdrawn as '已提现',
@pending as '待审核',
@available as '可提现';
```
## 测试步骤
### 1. 清除缓存重新编译
微信开发者工具:
```
工具 → 清除缓存 → 清除全部缓存数据
点击 编译 按钮
```
### 2. 查看控制台日志
进入分销中心页面,查看日志输出:
```
=== [Referral] 收益计算(完整版)===
累计佣金 (totalCommission): 100
已提现金额 (withdrawnEarnings): 0
待审核金额 (pendingWithdrawAmount): 0
可提现金额 = 累计 - 已提现 - 待审核 = 100 - 0 - 0 = 100
最低提现金额 (minWithdrawAmount): 5
按钮判断: 100 >= 5 = true
✅ 按钮应该: 🟢 启用(绿色)
```
### 3. 测试提现流程
1. **申请提现**:点击提现按钮,申请提现
2. **查看变化**
- 累计佣金不变
- 待审核金额增加
- 可提现金额减少
3. **审核通过**:在管理后台审核通过
4. **再次查看**
- 累计佣金不变
- 已提现金额增加
- 待审核金额归零
- **可提现金额不应该回血**
### 4. 验证按钮状态
不同情况下按钮的状态:
| 可提现金额 | 最低提现 | 按钮状态 | 按钮文本 |
|-----------|---------|---------|---------|
| ¥10 | ¥5 | 启用 | 申请提现 ¥10 |
| ¥3 | ¥5 | 禁用 | 满5元可提现 |
| ¥0 | ¥5 | 禁用 | 满5元可提现 |
## 常见问题
### Q1: 为什么要分"累计佣金"和"可提现金额"
**A**:
- **累计佣金**:用户的成就感,"我总共赚了多少"
- **可提现金额**:用户的可操作余额,"我现在能提多少"
### Q2: 已提现的钱还算在累计佣金里吗?
**A**: 是的。累计佣金是历史总和,只增不减。已提现只是资金流向,不影响累计数字。
示例:
- 累计赚了 ¥100成就
- 已提现 ¥50已到手
- 还能提现 ¥50余额
### Q3: 如果审核拒绝会怎样?
**A**:
1. 待审核金额归零(提现申请被取消)
2. 已提现金额不变
3. 可提现金额恢复(用户可以重新申请)
### Q4: users.withdrawn_earnings 会自动更新吗?
**A**: 是的,在两个地方会更新:
- `app/api/withdraw/route.ts` - 自动审核通过时
- `app/api/admin/withdrawals/route.ts` - 管理员审核通过时
### Q5: 为什么不直接从数据库读取可提现金额?
**A**:
- 可提现金额是**动态计算值**,不是固定字段
- 实时计算确保数据准确
- 便于调试和验证逻辑
## 相关文件
- `miniprogram/pages/referral/referral.js` - 前端计算(已修改)✅
- `app/api/referral/data/route.ts` - 数据查询(无需修改)
- `app/api/withdraw/route.ts` - 提现接口(无需修改)
- `app/api/admin/withdrawals/route.ts` - 审核接口(无需修改)
## 数据流图
```
┌────────────────────────────────────────────┐
│ 订单产生佣金 │
│ ↓ │
│ 累计佣金 (totalCommission) │
│ 持续累加,只增不减 │
│ ↓ │
│ ┌─────────────┴─────────────┐ │
│ ↓ ↓ │
│ 申请提现 继续积累 │
│ ↓ │
│ 待审核 (pendingWithdrawAmount) │
│ 暂时冻结 │
│ ↓ │
│ 审核通过 │
│ ↓ │
│ 已提现 (withdrawnEarnings) │
│ 累加记录 │
│ │
│ ┌─────────────────────────┐ │
│ │ 可提现金额(实时计算) │ │
│ │ = 累计佣金 │ │
│ │ - 已提现金额 │ │
│ │ - 待审核金额 │ │
│ └─────────────────────────┘ │
└────────────────────────────────────────────┘
```
## 总结
### 修改前的问题
```javascript
❌ 可提现 = 累计佣金 - 待审核金额
问题:审核通过后,待审核归零,可提现"回血"
```
### 修改后的正确逻辑
```javascript
✅ 可提现 = 累计佣金 - 已提现金额 - 待审核金额
优点:
1. 审核通过后,可提现金额不会增加
2. 只有新订单产生佣金时,可提现金额才会增加
3. 逻辑清晰,符合资金流向
```
### 业务含义
- **累计佣金**:成就感 - "我赚了多少"
- **已提现**:安全感 - "我拿到了多少"
- **待审核**:期待感 - "我正在提多少"
- **可提现**:行动力 - "我能提多少"
这样的设计既满足了用户查看历史成就的需求,又确保了资金安全和准确性。