This commit is contained in:
283
docs/commission-quick-reference.md
Normal file
283
docs/commission-quick-reference.md
Normal file
@@ -0,0 +1,283 @@
|
||||
# 差价佣金快速参考指南
|
||||
|
||||
## 快速查询表
|
||||
|
||||
### 1. 关键文件位置
|
||||
|
||||
| 功能 | 文件 | 行号 |
|
||||
|------|------|------|
|
||||
| 差价佣金计算 | `internal/service/commission_calculation/service.go` | 121-225 |
|
||||
| 佣金入账 | `internal/service/commission_calculation/service.go` | 641-687 |
|
||||
| 佣金计算触发 | `internal/service/order/service.go` | 2132-2150 |
|
||||
| 订单支付完成 | `internal/service/order/service.go` | 1431-1623 |
|
||||
| 异步任务处理 | `internal/task/commission_calculation.go` | 40-62 |
|
||||
| 订单模型 | `internal/model/order.go` | 1-138 |
|
||||
| 佣金记录模型 | `internal/model/commission.go` | 1-46 |
|
||||
| 业务文档 | `docs/commission-package-model.md` | - |
|
||||
|
||||
### 2. 关键常量
|
||||
|
||||
```go
|
||||
// 任务类型
|
||||
constants.TaskTypeCommission = "commission:calculate"
|
||||
|
||||
// 佣金来源
|
||||
model.CommissionSourceCostDiff = "cost_diff" // 成本价差
|
||||
model.CommissionSourceOneTime = "one_time" // 一次性佣金
|
||||
|
||||
// 订单佣金状态
|
||||
model.CommissionStatusPending = 1 // 待计算
|
||||
model.CommissionStatusCalculated = 2 // 已计算
|
||||
|
||||
// 订单支付状态
|
||||
model.PaymentStatusPending = 1 // 待支付
|
||||
model.PaymentStatusPaid = 2 // 已支付
|
||||
model.PaymentStatusCancelled = 3 // 已取消
|
||||
model.PaymentStatusRefunded = 4 // 已退款
|
||||
|
||||
// 佣金记录状态
|
||||
constants.CommissionStatusReleased = 3 // 已发放
|
||||
constants.CommissionStatusInvalid = 4 // 已失效
|
||||
constants.CommissionStatusPendingReview = 99 // 待人工修正
|
||||
```
|
||||
|
||||
### 3. 关键数据库表
|
||||
|
||||
| 表名 | 用途 | 关键字段 |
|
||||
|------|------|---------|
|
||||
| `tb_order` | 订单 | `commission_status`, `payment_status`, `seller_shop_id`, `seller_cost_price` |
|
||||
| `tb_commission_record` | 佣金记录 | `shop_id`, `order_id`, `amount`, `status`, `released_at` |
|
||||
| `tb_agent_wallet` | 代理钱包 | `shop_id`, `balance`, `wallet_type` |
|
||||
| `tb_agent_wallet_transaction` | 钱包交易 | `agent_wallet_id`, `transaction_type`, `amount` |
|
||||
| `tb_shop_package_allocation` | 套餐分配 | `shop_id`, `package_id`, `cost_price` |
|
||||
|
||||
---
|
||||
|
||||
## 常见问题快速查询
|
||||
|
||||
### Q1: 差价佣金什么时候计算?
|
||||
|
||||
**A**: 订单支付成功后立即入队异步任务,由 Worker 异步计算。
|
||||
|
||||
**代码位置**: `internal/service/order/service.go:1621`
|
||||
|
||||
```go
|
||||
s.enqueueCommissionCalculation(ctx, orderID)
|
||||
```
|
||||
|
||||
### Q2: 差价佣金的计算公式是什么?
|
||||
|
||||
**A**: `差价佣金 = 下级成本价 - 自己成本价`
|
||||
|
||||
**代码位置**: `internal/service/commission_calculation/service.go:203`
|
||||
|
||||
```go
|
||||
profit := childCostPrice - myCostPrice
|
||||
```
|
||||
|
||||
### Q3: 如何查询某个订单的佣金记录?
|
||||
|
||||
**A**: 查询 `tb_commission_record` 表,按 `order_id` 过滤。
|
||||
|
||||
```sql
|
||||
SELECT * FROM tb_commission_record
|
||||
WHERE order_id = ?
|
||||
ORDER BY created_at DESC;
|
||||
```
|
||||
|
||||
### Q4: 佣金什么时候入账到代理钱包?
|
||||
|
||||
**A**: 佣金记录创建后立即入账,通过 `creditCommissionInTx()` 方法。
|
||||
|
||||
**代码位置**: `internal/service/commission_calculation/service.go:641-687`
|
||||
|
||||
### Q5: 链路断裂是什么意思?
|
||||
|
||||
**A**: 上级代理未分配该套餐,导致佣金链中断。此时创建待审佣金记录(status=99),需平台人工处理。
|
||||
|
||||
**代码位置**: `internal/service/commission_calculation/service.go:173-200`
|
||||
|
||||
### Q6: 如何追踪一个订单的佣金计算过程?
|
||||
|
||||
**A**:
|
||||
1. 查询订单:`SELECT * FROM tb_order WHERE id = ?`
|
||||
2. 检查 `commission_status` 字段(1=待计算, 2=已计算)
|
||||
3. 查询佣金记录:`SELECT * FROM tb_commission_record WHERE order_id = ?`
|
||||
4. 查询钱包交易:`SELECT * FROM tb_agent_wallet_transaction WHERE reference_id = ? AND reference_type = 'commission'`
|
||||
|
||||
### Q7: 代理钱包余额如何更新?
|
||||
|
||||
**A**: 通过 `AgentWalletStore.AddBalanceWithTx()` 方法,使用乐观锁防并发。
|
||||
|
||||
**代码位置**: `internal/service/commission_calculation/service.go:651`
|
||||
|
||||
```go
|
||||
s.agentWalletStore.AddBalanceWithTx(ctx, tx, wallet.ID, record.Amount)
|
||||
```
|
||||
|
||||
### Q8: 如何处理佣金计算失败?
|
||||
|
||||
**A**: Asynq 会自动重试,最多重试次数由队列配置决定。如果最终失败,任务会进入死信队列。
|
||||
|
||||
**代码位置**: `internal/task/commission_calculation.go:40-62`
|
||||
|
||||
### Q9: 一个订单可能产生多少条佣金记录?
|
||||
|
||||
**A**: 取决于代理链的深度。最多为:销售店铺 + 所有上级店铺。
|
||||
|
||||
**示例**: 4级代理链 → 最多4条佣金记录
|
||||
|
||||
### Q10: 如何验证佣金计算的正确性?
|
||||
|
||||
**A**:
|
||||
1. 验证总金额:所有佣金记录的 `amount` 之和 = 订单总金额 - 平台成本价
|
||||
2. 验证链路:每条佣金记录的 `shop_id` 应该是代理链中的一个
|
||||
3. 验证状态:所有佣金记录的 `status` 应该是 3(已发放)或 99(待审)
|
||||
|
||||
---
|
||||
|
||||
## 调试技巧
|
||||
|
||||
### 1. 查看订单的佣金计算状态
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
id, order_no, commission_status, payment_status,
|
||||
seller_shop_id, seller_cost_price, total_amount
|
||||
FROM tb_order
|
||||
WHERE id = ?;
|
||||
```
|
||||
|
||||
### 2. 查看订单的所有佣金记录
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
id, shop_id, amount, commission_source, status, released_at
|
||||
FROM tb_commission_record
|
||||
WHERE order_id = ?
|
||||
ORDER BY shop_id;
|
||||
```
|
||||
|
||||
### 3. 查看代理的钱包余额变化
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
id, shop_id, balance, wallet_type, version
|
||||
FROM tb_agent_wallet
|
||||
WHERE shop_id = ?;
|
||||
```
|
||||
|
||||
### 4. 查看代理的钱包交易记录
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
id, agent_wallet_id, transaction_type, amount,
|
||||
balance_before, balance_after, reference_type, reference_id
|
||||
FROM tb_agent_wallet_transaction
|
||||
WHERE shop_id = ? AND transaction_type = 'commission'
|
||||
ORDER BY created_at DESC;
|
||||
```
|
||||
|
||||
### 5. 查看待审佣金记录(链路断裂)
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
id, shop_id, order_id, amount, status, remark
|
||||
FROM tb_commission_record
|
||||
WHERE status = 99
|
||||
ORDER BY created_at DESC;
|
||||
```
|
||||
|
||||
### 6. 查看异步任务队列状态
|
||||
|
||||
```bash
|
||||
# 查看待处理任务
|
||||
redis-cli LRANGE asynq:queues:default 0 -1
|
||||
|
||||
# 查看已完成任务
|
||||
redis-cli LRANGE asynq:queues:completed 0 -1
|
||||
|
||||
# 查看失败任务
|
||||
redis-cli LRANGE asynq:queues:failed 0 -1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 性能优化建议
|
||||
|
||||
### 1. 批量查询优化
|
||||
|
||||
避免在循环中逐条查询,使用 `IN` 子句批量查询:
|
||||
|
||||
```go
|
||||
// ❌ 不好:N+1 查询
|
||||
for _, shopID := range shopIDs {
|
||||
allocation, _ := store.GetByShopAndPackage(ctx, shopID, packageID)
|
||||
}
|
||||
|
||||
// ✅ 好:批量查询
|
||||
allocations, _ := store.GetByShopsAndPackage(ctx, shopIDs, packageID)
|
||||
```
|
||||
|
||||
### 2. 事务优化
|
||||
|
||||
确保事务范围最小化,避免长事务:
|
||||
|
||||
```go
|
||||
// ✅ 好:事务只包含必要操作
|
||||
err = s.db.Transaction(func(tx *gorm.DB) error {
|
||||
// 创建佣金记录
|
||||
// 更新钱包余额
|
||||
// 创建交易记录
|
||||
return nil
|
||||
})
|
||||
```
|
||||
|
||||
### 3. 索引优化
|
||||
|
||||
确保以下字段有索引:
|
||||
- `tb_order.id`, `tb_order.commission_status`, `tb_order.payment_status`
|
||||
- `tb_commission_record.order_id`, `tb_commission_record.shop_id`, `tb_commission_record.status`
|
||||
- `tb_agent_wallet.shop_id`, `tb_agent_wallet.wallet_type`
|
||||
|
||||
---
|
||||
|
||||
## 常见错误排查
|
||||
|
||||
### 错误1: 佣金未入账
|
||||
|
||||
**症状**: `commission_status = 2` 但钱包余额未增加
|
||||
|
||||
**排查步骤**:
|
||||
1. 检查 `tb_commission_record` 中是否有记录
|
||||
2. 检查记录的 `status` 是否为 3(已发放)
|
||||
3. 检查 `tb_agent_wallet_transaction` 中是否有对应交易
|
||||
4. 查看应用日志中的错误信息
|
||||
|
||||
### 错误2: 链路断裂
|
||||
|
||||
**症状**: `tb_commission_record.status = 99`,`remark` 包含"套餐系列未分配"
|
||||
|
||||
**排查步骤**:
|
||||
1. 检查上级代理是否分配了该套餐
|
||||
2. 检查 `tb_shop_package_allocation` 表中是否有记录
|
||||
3. 平台管理员需要手动分配套餐或修正佣金记录
|
||||
|
||||
### 错误3: 佣金计算失败
|
||||
|
||||
**症状**: 异步任务失败,订单 `commission_status` 仍为 1
|
||||
|
||||
**排查步骤**:
|
||||
1. 查看应用日志中的错误信息
|
||||
2. 检查订单数据是否完整(`seller_shop_id`, `seller_cost_price` 等)
|
||||
3. 检查数据库连接是否正常
|
||||
4. 手动重试任务或联系技术支持
|
||||
|
||||
---
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [套餐与佣金业务模型](commission-package-model.md) - 完整的业务规则说明
|
||||
- [差价佣金搜索结果](commission-search-result.md) - 详细的代码位置和实现说明
|
||||
- [差价佣金流程图](commission-flow-diagram.md) - 可视化的流程图
|
||||
|
||||
Reference in New Issue
Block a user