775 lines
31 KiB
Markdown
775 lines
31 KiB
Markdown
|
|
# 代理配置表分析和优化建议
|
|||
|
|
|
|||
|
|
## 一、当前配置表结构分析
|
|||
|
|
|
|||
|
|
### 1.1 数据库表结构
|
|||
|
|
|
|||
|
|
**表名**: `agent_config`
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
CREATE TABLE `agent_config` (
|
|||
|
|
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
|||
|
|
`config_key` varchar(100) NOT NULL COMMENT '配置键(唯一)',
|
|||
|
|
`config_value` varchar(500) NOT NULL COMMENT '配置值',
|
|||
|
|
`config_type` varchar(50) NOT NULL COMMENT '配置类型:price=价格,bonus=等级加成,upgrade=升级费用,rebate=返佣,tax=税费',
|
|||
|
|
`description` varchar(500) DEFAULT NULL COMMENT '配置描述',
|
|||
|
|
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|||
|
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|||
|
|
`delete_time` datetime DEFAULT NULL,
|
|||
|
|
`del_state` tinyint NOT NULL DEFAULT 0,
|
|||
|
|
`version` bigint NOT NULL DEFAULT 0,
|
|||
|
|
PRIMARY KEY (`id`),
|
|||
|
|
UNIQUE KEY `uk_config_key` (`config_key`),
|
|||
|
|
KEY `idx_config_type` (`config_type`)
|
|||
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 1.2 配置表设计评估
|
|||
|
|
|
|||
|
|
**优点**:
|
|||
|
|
✅ **键值对存储灵活**:使用 `config_key` 和 `config_value` 的键值对模式,易于扩展新配置项
|
|||
|
|
✅ **类型分类清晰**:`config_type` 字段将配置分为 price、bonus、upgrade、rebate、tax 等类型,便于管理
|
|||
|
|
✅ **唯一索引合理**:`config_key` 的唯一索引确保配置键不重复
|
|||
|
|
✅ **版本控制**:包含 `version` 字段支持乐观锁,适合配置更新场景
|
|||
|
|
✅ **软删除支持**:支持软删除,保留历史配置记录
|
|||
|
|
|
|||
|
|
**缺点/问题**:
|
|||
|
|
❌ **配置值类型限制**:`config_value` 为 `varchar(500)`,所有值都存储为字符串,需要在使用时转换
|
|||
|
|
❌ **缺少验证机制**:数据库层面无法验证配置值的格式和范围
|
|||
|
|
❌ **配置值长度限制**:对于复杂配置(如JSON对象),500字符可能不够
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 二、当前配置项清单
|
|||
|
|
|
|||
|
|
### 2.1 SQL初始化脚本中的配置项
|
|||
|
|
|
|||
|
|
根据 `agent_system_migration.sql` 文件,当前初始化的配置项:
|
|||
|
|
|
|||
|
|
| 配置键 | 配置值 | 类型 | 说明 |
|
|||
|
|
| ------------------------------- | ------- | ------- | ------------------------ |
|
|||
|
|
| `base_price` | 0.00 | price | 系统基础底价 |
|
|||
|
|
| `system_max_price` | 9999.99 | price | 系统价格上限 |
|
|||
|
|
| `price_threshold` | 0.00 | price | 提价标准阈值 |
|
|||
|
|
| `price_fee_rate` | 0.0000 | price | 提价手续费比例 |
|
|||
|
|
| `level_bonus_normal` | 6.00 | bonus | 普通代理等级加成 |
|
|||
|
|
| `level_bonus_gold` | 3.00 | bonus | 黄金代理等级加成 |
|
|||
|
|
| `level_bonus_diamond` | 0.00 | bonus | 钻石代理等级加成 |
|
|||
|
|
| `upgrade_fee_normal_to_gold` | 199.00 | upgrade | 普通→黄金升级费用 |
|
|||
|
|
| `upgrade_fee_to_diamond` | 980.00 | upgrade | 升级为钻石费用 |
|
|||
|
|
| `upgrade_rebate_normal_to_gold` | 139.00 | upgrade | 普通→黄金返佣金额 |
|
|||
|
|
| `upgrade_rebate_to_diamond` | 680.00 | upgrade | 升级为钻石返佣金额 |
|
|||
|
|
| `direct_parent_amount_diamond` | 6.00 | rebate | 直接上级是钻石的返佣金额 |
|
|||
|
|
| `direct_parent_amount_gold` | 3.00 | rebate | 直接上级是黄金的返佣金额 |
|
|||
|
|
| `direct_parent_amount_normal` | 2.00 | rebate | 直接上级是普通的返佣金额 |
|
|||
|
|
| `max_gold_rebate_amount` | 3.00 | rebate | 黄金代理最大返佣金额 |
|
|||
|
|
| `tax_rate` | 0.0600 | tax | 提现税率(6%) |
|
|||
|
|
|
|||
|
|
**共15个配置项**
|
|||
|
|
|
|||
|
|
### 2.2 代码中使用的配置键
|
|||
|
|
|
|||
|
|
#### 2.2.1 AgentService 中使用的配置键
|
|||
|
|
|
|||
|
|
- `base_price` - 基础底价 ✅
|
|||
|
|
- `price_threshold` - 提价标准阈值 ✅
|
|||
|
|
- `price_fee_rate` - 提价手续费比例 ✅
|
|||
|
|
- `level_bonus` - **硬编码,未从配置表读取** ❌
|
|||
|
|
|
|||
|
|
#### 2.2.2 AdminGetAgentConfigLogic 中使用的配置键
|
|||
|
|
|
|||
|
|
- `level_1_bonus` - 普通代理等级加成 ❌ **配置键不匹配**
|
|||
|
|
- `level_2_bonus` - 黄金代理等级加成 ❌ **配置键不匹配**
|
|||
|
|
- `level_3_bonus` - 钻石代理等级加成 ❌ **配置键不匹配**
|
|||
|
|
- `upgrade_to_gold_fee` - 升级为黄金费用 ❌ **配置键不匹配**
|
|||
|
|
- `upgrade_to_diamond_fee` - 升级为钻石费用 ❌ **配置键不匹配**
|
|||
|
|
- `upgrade_to_gold_rebate` - 升级为黄金返佣 ❌ **配置键不匹配**
|
|||
|
|
- `upgrade_to_diamond_rebate` - 升级为钻石返佣 ❌ **配置键不匹配**
|
|||
|
|
- `tax_rate` - 税率 ✅
|
|||
|
|
- `tax_exemption_amount` - 免税额度 ❌ **配置项缺失**
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 三、发现的问题
|
|||
|
|
|
|||
|
|
### 3.1 🔴 严重问题:价格配置不应在系统配置表中
|
|||
|
|
|
|||
|
|
**问题描述**:
|
|||
|
|
价格相关配置(底价、上限、提价阈值、手续费比例)应该按产品配置,而不是全局系统配置。当前这些配置同时存在于 `agent_config` 和 `agent_product_config` 表中,但代码只从系统配置表读取,没有实现产品级别的配置覆盖。
|
|||
|
|
|
|||
|
|
**问题影响**:
|
|||
|
|
- ❌ 不同产品无法设置不同的底价和价格策略
|
|||
|
|
- ❌ 代码中只读取系统配置,忽略了产品配置(`AgentService.AgentProcess`、`PaymentLogic`)
|
|||
|
|
- ❌ 产品配置表虽然存在,但在订单处理逻辑中未被使用
|
|||
|
|
|
|||
|
|
**应该移除的系统配置项**:
|
|||
|
|
- `base_price` - 应该只在产品配置表中
|
|||
|
|
- `system_max_price` - 应该只在产品配置表中
|
|||
|
|
- `price_threshold` - 应该只在产品配置表中(可选)
|
|||
|
|
- `price_fee_rate` - 应该只在产品配置表中(可选)
|
|||
|
|
|
|||
|
|
**正确的设计**:
|
|||
|
|
- ✅ 所有价格相关配置都应该在 `agent_product_config` 表中按产品配置
|
|||
|
|
- ✅ 系统配置表只保留全局配置(等级加成、升级费用、税费等)
|
|||
|
|
- ✅ 代码应该优先从产品配置读取,如果产品未配置,则使用默认值
|
|||
|
|
|
|||
|
|
### 3.2 🔴 严重问题:配置键命名不一致
|
|||
|
|
|
|||
|
|
**问题描述**:
|
|||
|
|
SQL初始化脚本和代码逻辑中使用的配置键命名不一致,导致配置无法正确读取。
|
|||
|
|
|
|||
|
|
**具体情况**:
|
|||
|
|
|
|||
|
|
| 配置项 | SQL初始化脚本 | 代码逻辑期望 | 状态 |
|
|||
|
|
| ---------------- | ------------------------------- | --------------------------- | -------- |
|
|||
|
|
| 普通代理等级加成 | `level_bonus_normal` | `level_1_bonus` | ❌ 不匹配 |
|
|||
|
|
| 黄金代理等级加成 | `level_bonus_gold` | `level_2_bonus` | ❌ 不匹配 |
|
|||
|
|
| 钻石代理等级加成 | `level_bonus_diamond` | `level_3_bonus` | ❌ 不匹配 |
|
|||
|
|
| 升级为黄金费用 | `upgrade_fee_normal_to_gold` | `upgrade_to_gold_fee` | ❌ 不匹配 |
|
|||
|
|
| 升级为钻石费用 | `upgrade_fee_to_diamond` | `upgrade_to_diamond_fee` | ❌ 不匹配 |
|
|||
|
|
| 升级为黄金返佣 | `upgrade_rebate_normal_to_gold` | `upgrade_to_gold_rebate` | ❌ 不匹配 |
|
|||
|
|
| 升级为钻石返佣 | `upgrade_rebate_to_diamond` | `upgrade_to_diamond_rebate` | ❌ 不匹配 |
|
|||
|
|
|
|||
|
|
**影响**:
|
|||
|
|
- 后台管理系统无法正确读取和显示配置值
|
|||
|
|
- 配置更新可能无法正常工作
|
|||
|
|
|
|||
|
|
### 3.3 🔴 严重问题:代码中硬编码等级加成
|
|||
|
|
|
|||
|
|
**问题位置**:
|
|||
|
|
```go
|
|||
|
|
// agentService.go:144-155
|
|||
|
|
func (s *AgentService) getLevelBonus(level int64) int64 {
|
|||
|
|
switch level {
|
|||
|
|
case 1: // 普通
|
|||
|
|
return 6 // ❌ 硬编码,应该从配置表读取
|
|||
|
|
case 2: // 黄金
|
|||
|
|
return 3 // ❌ 硬编码,应该从配置表读取
|
|||
|
|
case 3: // 钻石
|
|||
|
|
return 0 // ❌ 硬编码,应该从配置表读取
|
|||
|
|
default:
|
|||
|
|
return 0
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**问题影响**:
|
|||
|
|
- 等级加成值无法通过后台配置动态调整
|
|||
|
|
- 必须修改代码才能更改等级加成
|
|||
|
|
- 违反了配置化的设计原则
|
|||
|
|
|
|||
|
|
### 3.4 🟡 中等问题:缺少配置项
|
|||
|
|
|
|||
|
|
**缺失的配置项**:
|
|||
|
|
1. `tax_exemption_amount` - 免税额度(前端接口需要,但SQL初始化脚本中未包含)
|
|||
|
|
2. `upgrade_fee_gold_to_diamond` - 黄金→钻石升级费用(如果独立配置)
|
|||
|
|
|
|||
|
|
### 3.5 🟡 中等问题:配置键命名规范不统一
|
|||
|
|
|
|||
|
|
**当前问题**:
|
|||
|
|
- 部分使用下划线分隔:`level_bonus_normal`
|
|||
|
|
- 部分使用数字后缀:`level_1_bonus`
|
|||
|
|
- 部分使用驼峰式:`upgrade_fee_normal_to_gold`
|
|||
|
|
|
|||
|
|
**建议**:统一命名规范
|
|||
|
|
|
|||
|
|
### 3.6 🟢 轻微问题:配置值存储方式
|
|||
|
|
|
|||
|
|
**当前方式**:所有配置值以字符串形式存储,需要在使用时转换
|
|||
|
|
- `strconv.ParseFloat()` 转换为浮点数
|
|||
|
|
- `strconv.ParseInt()` 转换为整数
|
|||
|
|
|
|||
|
|
**影响**:每次读取都需要类型转换,性能影响较小,但容易出错
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 四、配置使用情况分析
|
|||
|
|
|
|||
|
|
### 4.1 实际使用的配置项
|
|||
|
|
|
|||
|
|
**在业务逻辑中使用的配置**:
|
|||
|
|
1. ✅ `base_price` - 订单处理时使用
|
|||
|
|
2. ✅ `price_threshold` - 计算提价成本时使用
|
|||
|
|
3. ✅ `price_fee_rate` - 计算提价成本时使用
|
|||
|
|
4. ❌ `level_bonus_*` - **未使用,代码中硬编码**
|
|||
|
|
|
|||
|
|
**在后台管理中使用的配置**:
|
|||
|
|
1. ❌ `level_1_bonus` - 读取配置(但键名不匹配)
|
|||
|
|
2. ❌ `level_2_bonus` - 读取配置(但键名不匹配)
|
|||
|
|
3. ❌ `level_3_bonus` - 读取配置(但键名不匹配)
|
|||
|
|
4. ❌ `upgrade_to_gold_fee` - 读取配置(但键名不匹配)
|
|||
|
|
5. ❌ `upgrade_to_diamond_fee` - 读取配置(但键名不匹配)
|
|||
|
|
6. ❌ `upgrade_to_gold_rebate` - 读取配置(但键名不匹配)
|
|||
|
|
7. ❌ `upgrade_to_diamond_rebate` - 读取配置(但键名不匹配)
|
|||
|
|
8. ✅ `tax_rate` - 读取配置
|
|||
|
|
9. ❌ `tax_exemption_amount` - 读取配置(但配置项缺失)
|
|||
|
|
|
|||
|
|
### 4.2 未使用的配置项
|
|||
|
|
|
|||
|
|
以下配置项在SQL中初始化了,但在代码中**似乎未使用**:
|
|||
|
|
- `direct_parent_amount_diamond` - 直接上级是钻石的返佣金额
|
|||
|
|
- `direct_parent_amount_gold` - 直接上级是黄金的返佣金额
|
|||
|
|
- `direct_parent_amount_normal` - 直接上级是普通的返佣金额
|
|||
|
|
- `max_gold_rebate_amount` - 黄金代理最大返佣金额
|
|||
|
|
|
|||
|
|
**说明**:这些配置项可能被硬编码在 `distributeNormalAgentBonus` 等函数中,需要确认是否需要配置化。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 五、优化建议
|
|||
|
|
|
|||
|
|
### 5.1 🔴 立即修复:移除系统配置表中的价格配置
|
|||
|
|
|
|||
|
|
**问题**:
|
|||
|
|
价格相关配置(`base_price`、`system_max_price`、`price_threshold`、`price_fee_rate`)应该完全由产品配置表管理,系统配置表中不应该存在这些配置。
|
|||
|
|
|
|||
|
|
**修复步骤**:
|
|||
|
|
|
|||
|
|
1. **从系统配置表中删除价格相关配置**:
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- 删除系统配置表中的价格相关配置
|
|||
|
|
DELETE FROM `agent_config` WHERE `config_key` IN (
|
|||
|
|
'base_price',
|
|||
|
|
'system_max_price',
|
|||
|
|
'price_threshold',
|
|||
|
|
'price_fee_rate'
|
|||
|
|
);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
2. **修改订单处理逻辑,从产品配置表读取**:
|
|||
|
|
|
|||
|
|
需要修改的文件:
|
|||
|
|
- `app/main/api/internal/service/agentService.go` - `AgentProcess` 方法
|
|||
|
|
- `app/main/api/internal/logic/pay/paymentlogic.go` - 创建订单时的价格计算
|
|||
|
|
|
|||
|
|
**示例代码修改**(`agentService.go`):
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// AgentProcess 处理代理订单(新系统)
|
|||
|
|
func (s *AgentService) AgentProcess(ctx context.Context, order *model.Order) error {
|
|||
|
|
// ... 前面的代码不变 ...
|
|||
|
|
|
|||
|
|
// 4. 获取产品配置(优先使用产品配置,如果不存在则使用默认值)
|
|||
|
|
productConfig, err := s.AgentProductConfigModel.FindOneByProductId(ctx, order.ProductId)
|
|||
|
|
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
|||
|
|
return errors.Wrapf(err, "查询产品配置失败, productId: %d", order.ProductId)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 使用产品配置的底价,如果产品未配置则使用默认值0
|
|||
|
|
basePrice := 0.0
|
|||
|
|
if productConfig != nil {
|
|||
|
|
basePrice = productConfig.BasePrice
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ... 使用basePrice计算实际底价 ...
|
|||
|
|
|
|||
|
|
// 6.2 计算提价成本(使用产品配置)
|
|||
|
|
priceThreshold := 0.0
|
|||
|
|
priceFeeRate := 0.0
|
|||
|
|
if productConfig != nil {
|
|||
|
|
if productConfig.PriceThreshold.Valid {
|
|||
|
|
priceThreshold = productConfig.PriceThreshold.Float64
|
|||
|
|
}
|
|||
|
|
if productConfig.PriceFeeRate.Valid {
|
|||
|
|
priceFeeRate = productConfig.PriceFeeRate.Float64
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
priceCost := s.calculatePriceCost(agentOrder.SetPrice, priceThreshold, priceFeeRate)
|
|||
|
|
|
|||
|
|
// ... 后续代码 ...
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
3. **更新后台管理系统**:
|
|||
|
|
|
|||
|
|
- 移除系统配置页面中的价格相关配置项
|
|||
|
|
- 确保产品配置页面可以正确配置这些价格参数
|
|||
|
|
|
|||
|
|
### 5.2 🔴 立即修复:统一配置键命名
|
|||
|
|
|
|||
|
|
**方案一:修改SQL初始化脚本,使用代码期望的键名**
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- 修改等级加成配置键
|
|||
|
|
UPDATE `agent_config` SET `config_key` = 'level_1_bonus' WHERE `config_key` = 'level_bonus_normal';
|
|||
|
|
UPDATE `agent_config` SET `config_key` = 'level_2_bonus' WHERE `config_key` = 'level_bonus_gold';
|
|||
|
|
UPDATE `agent_config` SET `config_key` = 'level_3_bonus' WHERE `config_key` = 'level_bonus_diamond';
|
|||
|
|
|
|||
|
|
-- 修改升级费用配置键
|
|||
|
|
UPDATE `agent_config` SET `config_key` = 'upgrade_to_gold_fee' WHERE `config_key` = 'upgrade_fee_normal_to_gold';
|
|||
|
|
UPDATE `agent_config` SET `config_key` = 'upgrade_to_diamond_fee' WHERE `config_key` = 'upgrade_fee_to_diamond';
|
|||
|
|
|
|||
|
|
-- 修改升级返佣配置键
|
|||
|
|
UPDATE `agent_config` SET `config_key` = 'upgrade_to_gold_rebate' WHERE `config_key` = 'upgrade_rebate_normal_to_gold';
|
|||
|
|
UPDATE `agent_config` SET `config_key` = 'upgrade_to_diamond_rebate' WHERE `config_key` = 'upgrade_rebate_to_diamond';
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**方案二:修改代码逻辑,使用SQL中的键名**
|
|||
|
|
|
|||
|
|
需要修改的文件:
|
|||
|
|
- `app/main/api/internal/logic/admin_agent/admingetagentconfiglogic.go`
|
|||
|
|
- `app/main/api/internal/logic/admin_agent/adminupdateagentconfiglogic.go`
|
|||
|
|
|
|||
|
|
**推荐方案一**,因为:
|
|||
|
|
- 代码中的命名更清晰(`level_1_bonus` 比 `level_bonus_normal` 更直观)
|
|||
|
|
- 数字后缀与等级数字(1/2/3)对应,易于理解
|
|||
|
|
|
|||
|
|
### 5.3 🔴 立即修复:从配置表读取等级加成
|
|||
|
|
|
|||
|
|
**修改 `agentService.go` 中的 `getLevelBonus` 函数**:
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// getLevelBonus 获取等级加成(从配置表读取)
|
|||
|
|
func (s *AgentService) getLevelBonus(ctx context.Context, level int64) (int64, error) {
|
|||
|
|
var configKey string
|
|||
|
|
switch level {
|
|||
|
|
case 1:
|
|||
|
|
configKey = "level_1_bonus"
|
|||
|
|
case 2:
|
|||
|
|
configKey = "level_2_bonus"
|
|||
|
|
case 3:
|
|||
|
|
configKey = "level_3_bonus"
|
|||
|
|
default:
|
|||
|
|
return 0, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bonus, err := s.getConfigFloat(ctx, configKey)
|
|||
|
|
if err != nil {
|
|||
|
|
// 配置不存在时返回默认值
|
|||
|
|
switch level {
|
|||
|
|
case 1:
|
|||
|
|
return 6, nil
|
|||
|
|
case 2:
|
|||
|
|
return 3, nil
|
|||
|
|
case 3:
|
|||
|
|
return 0, nil
|
|||
|
|
}
|
|||
|
|
return 0, nil
|
|||
|
|
}
|
|||
|
|
return int64(bonus), nil
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**修改调用处**:
|
|||
|
|
```go
|
|||
|
|
// agentService.go:108
|
|||
|
|
levelBonus, err := s.getLevelBonus(ctx, agent.Level)
|
|||
|
|
if err != nil {
|
|||
|
|
return errors.Wrapf(err, "获取等级加成配置失败")
|
|||
|
|
}
|
|||
|
|
actualBasePrice := basePrice + float64(levelBonus)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5.4 🟡 补充缺失的配置项
|
|||
|
|
|
|||
|
|
**添加 `tax_exemption_amount` 配置**:
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
INSERT INTO `agent_config` (`config_key`, `config_value`, `config_type`, `description`)
|
|||
|
|
VALUES ('tax_exemption_amount', '0.00', 'tax', '提现免税额度(元,默认0)');
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5.5 🟡 规范化配置键命名
|
|||
|
|
|
|||
|
|
**建议统一使用以下命名规范**:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
{类型}_{编号/级别}_{属性}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**示例**:
|
|||
|
|
- ✅ `level_1_bonus` - 等级1的加成
|
|||
|
|
- ✅ `level_2_bonus` - 等级2的加成
|
|||
|
|
- ✅ `level_3_bonus` - 等级3的加成
|
|||
|
|
- ✅ `upgrade_to_gold_fee` - 升级到黄金的费用
|
|||
|
|
- ✅ `upgrade_to_diamond_fee` - 升级到钻石的费用
|
|||
|
|
- ✅ `upgrade_to_gold_rebate` - 升级到黄金的返佣
|
|||
|
|
- ✅ `upgrade_to_diamond_rebate` - 升级到钻石的返佣
|
|||
|
|
|
|||
|
|
### 5.6 🟢 优化建议:添加配置验证
|
|||
|
|
|
|||
|
|
**在更新配置时添加验证逻辑**:
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 验证配置值的合理性
|
|||
|
|
func validateConfigValue(key string, value float64) error {
|
|||
|
|
switch key {
|
|||
|
|
case "tax_rate":
|
|||
|
|
if value < 0 || value > 1 {
|
|||
|
|
return errors.New("税率必须在0-1之间")
|
|||
|
|
}
|
|||
|
|
case "price_fee_rate":
|
|||
|
|
if value < 0 || value > 1 {
|
|||
|
|
return errors.New("提价费率必须在0-1之间")
|
|||
|
|
}
|
|||
|
|
case "base_price", "system_max_price":
|
|||
|
|
if value < 0 {
|
|||
|
|
return errors.New("价格配置不能为负数")
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 六、配置项完整清单(修正后)
|
|||
|
|
|
|||
|
|
### 6.1 价格相关配置(应移除,改为产品配置)
|
|||
|
|
|
|||
|
|
**⚠️ 重要说明**:以下配置项应该从系统配置表(`agent_config`)中移除,改为在产品配置表(`agent_product_config`)中按产品配置。
|
|||
|
|
|
|||
|
|
| 配置键 | 说明 | 配置位置 |
|
|||
|
|
| ---------------------- | ----------------------------- | ----------------------------- |
|
|||
|
|
| ~~`base_price`~~ | ~~系统基础底价~~ | ✅ 应在 `agent_product_config` |
|
|||
|
|
| ~~`system_max_price`~~ | ~~系统价格上限~~ | ✅ 应在 `agent_product_config` |
|
|||
|
|
| ~~`price_threshold`~~ | ~~提价标准阈值~~ | ✅ 应在 `agent_product_config` |
|
|||
|
|
| ~~`price_fee_rate`~~ | ~~提价手续费比例(0-1之间)~~ | ✅ 应在 `agent_product_config` |
|
|||
|
|
|
|||
|
|
**产品配置表结构**(`agent_product_config`):
|
|||
|
|
- `base_price` - 产品基础底价(必填)
|
|||
|
|
- `system_max_price` - 产品价格上限(必填)
|
|||
|
|
- `price_threshold` - 提价标准阈值(可选,NULL时表示不设阈值)
|
|||
|
|
- `price_fee_rate` - 提价手续费比例(可选,NULL时表示不收费)
|
|||
|
|
|
|||
|
|
### 6.2 等级加成配置(bonus类型)
|
|||
|
|
|
|||
|
|
| 配置键 | 默认值 | 说明 |
|
|||
|
|
| --------------- | ------ | ---------------------- |
|
|||
|
|
| `level_1_bonus` | 6.00 | 普通代理等级加成(元) |
|
|||
|
|
| `level_2_bonus` | 3.00 | 黄金代理等级加成(元) |
|
|||
|
|
| `level_3_bonus` | 0.00 | 钻石代理等级加成(元) |
|
|||
|
|
|
|||
|
|
### 6.3 升级费用配置(upgrade类型)
|
|||
|
|
|
|||
|
|
| 配置键 | 默认值 | 说明 |
|
|||
|
|
| --------------------------- | ------ | ------------------------ |
|
|||
|
|
| `upgrade_to_gold_fee` | 199.00 | 普通→黄金升级费用(元) |
|
|||
|
|
| `upgrade_to_diamond_fee` | 980.00 | 升级为钻石费用(元) |
|
|||
|
|
| `upgrade_to_gold_rebate` | 139.00 | 普通→黄金返佣金额(元) |
|
|||
|
|
| `upgrade_to_diamond_rebate` | 680.00 | 升级为钻石返佣金额(元) |
|
|||
|
|
|
|||
|
|
**注意**:`gold_to_diamond` 的费用和返佣可以通过计算得出:
|
|||
|
|
- 费用:`upgrade_to_diamond_fee - upgrade_to_gold_fee = 980 - 199 = 781元`
|
|||
|
|
- 返佣:可以通过前端或后端计算,不单独存储
|
|||
|
|
|
|||
|
|
### 6.4 返佣规则配置(rebate类型)
|
|||
|
|
|
|||
|
|
| 配置键 | 默认值 | 说明 |
|
|||
|
|
| ------------------------------ | ------ | ------------------------------ |
|
|||
|
|
| `direct_parent_amount_diamond` | 6.00 | 直接上级是钻石的返佣金额(元) |
|
|||
|
|
| `direct_parent_amount_gold` | 3.00 | 直接上级是黄金的返佣金额(元) |
|
|||
|
|
| `direct_parent_amount_normal` | 2.00 | 直接上级是普通的返佣金额(元) |
|
|||
|
|
| `max_gold_rebate_amount` | 3.00 | 黄金代理最大返佣金额(元) |
|
|||
|
|
|
|||
|
|
**建议**:这些配置项目前在代码中硬编码,建议配置化。
|
|||
|
|
|
|||
|
|
### 6.5 税费配置(tax类型)
|
|||
|
|
|
|||
|
|
| 配置键 | 默认值 | 说明 |
|
|||
|
|
| ---------------------- | ------ | ---------------------- |
|
|||
|
|
| `tax_rate` | 0.0600 | 提现税率(6%,即0.06) |
|
|||
|
|
| `tax_exemption_amount` | 0.00 | 免税额度(元,默认0) |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 七、配置表的合理性评估
|
|||
|
|
|
|||
|
|
### 7.1 表结构设计
|
|||
|
|
|
|||
|
|
| 评估项 | 评分 | 说明 |
|
|||
|
|
| ------------ | ----- | ---------------------------- |
|
|||
|
|
| **灵活性** | ⭐⭐⭐⭐⭐ | 键值对设计非常灵活,易于扩展 |
|
|||
|
|
| **可维护性** | ⭐⭐⭐⭐ | 类型分类清晰,便于管理 |
|
|||
|
|
| **性能** | ⭐⭐⭐⭐ | 唯一索引优化查询,缓存支持 |
|
|||
|
|
| **类型安全** | ⭐⭐⭐ | 所有值都是字符串,需要转换 |
|
|||
|
|
| **验证机制** | ⭐⭐ | 缺少数据库层面的验证 |
|
|||
|
|
|
|||
|
|
### 7.2 总体评价
|
|||
|
|
|
|||
|
|
**设计优点**:
|
|||
|
|
✅ 采用键值对存储,扩展性强
|
|||
|
|
✅ 类型分类清晰,便于管理
|
|||
|
|
✅ 支持版本控制和软删除
|
|||
|
|
|
|||
|
|
**存在的问题**:
|
|||
|
|
❌ **价格配置应该在产品配置表,而不是系统配置表**(严重设计问题)
|
|||
|
|
❌ 配置键命名不一致(严重)
|
|||
|
|
❌ 部分配置硬编码(严重)
|
|||
|
|
❌ 缺少部分配置项(中等)
|
|||
|
|
❌ 缺少配置验证机制(中等)
|
|||
|
|
|
|||
|
|
**总体评分**:⭐⭐⭐(3/5)
|
|||
|
|
|
|||
|
|
**结论**:配置表的设计思路基本合理,但存在**价格配置位置设计错误**的严重问题。价格相关配置应该完全由产品配置表管理,系统配置表只应该包含全局配置(等级加成、升级费用、税费等)。修复这些问题后,配置表设计将更加完善和符合项目规范。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 八、修复后的完整配置SQL
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- ============================================
|
|||
|
|
-- 代理系统配置初始化(修正版)
|
|||
|
|
-- ============================================
|
|||
|
|
|
|||
|
|
-- 删除价格相关配置(应该在产品配置表中)
|
|||
|
|
DELETE FROM `agent_config` WHERE `config_key` IN (
|
|||
|
|
'base_price',
|
|||
|
|
'system_max_price',
|
|||
|
|
'price_threshold',
|
|||
|
|
'price_fee_rate'
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
-- 删除旧的不一致配置(如果存在)
|
|||
|
|
DELETE FROM `agent_config` WHERE `config_key` IN (
|
|||
|
|
'level_bonus_normal',
|
|||
|
|
'level_bonus_gold',
|
|||
|
|
'level_bonus_diamond',
|
|||
|
|
'upgrade_fee_normal_to_gold',
|
|||
|
|
'upgrade_fee_to_diamond',
|
|||
|
|
'upgrade_rebate_normal_to_gold',
|
|||
|
|
'upgrade_rebate_to_diamond'
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
-- 插入修正后的配置项
|
|||
|
|
INSERT INTO `agent_config` (`config_key`, `config_value`, `config_type`, `description`) VALUES
|
|||
|
|
-- 注意:价格相关配置(base_price, system_max_price, price_threshold, price_fee_rate)
|
|||
|
|
-- 已从系统配置表中移除,改为在产品配置表(agent_product_config)中按产品配置
|
|||
|
|
|
|||
|
|
-- 等级加成配置(修正键名)
|
|||
|
|
('level_1_bonus', '6.00', 'bonus', '普通代理等级加成(6元)'),
|
|||
|
|
('level_2_bonus', '3.00', 'bonus', '黄金代理等级加成(3元)'),
|
|||
|
|
('level_3_bonus', '0.00', 'bonus', '钻石代理等级加成(0元)'),
|
|||
|
|
|
|||
|
|
-- 升级费用配置(修正键名)
|
|||
|
|
('upgrade_to_gold_fee', '199.00', 'upgrade', '普通→黄金升级费用(199元)'),
|
|||
|
|
('upgrade_to_diamond_fee', '980.00', 'upgrade', '升级为钻石费用(980元)'),
|
|||
|
|
|
|||
|
|
-- 升级返佣配置(修正键名)
|
|||
|
|
('upgrade_to_gold_rebate', '139.00', 'upgrade', '普通→黄金返佣金额(139元)'),
|
|||
|
|
('upgrade_to_diamond_rebate', '680.00', 'upgrade', '升级为钻石返佣金额(680元)'),
|
|||
|
|
|
|||
|
|
-- 返佣规则配置
|
|||
|
|
('direct_parent_amount_diamond', '6.00', 'rebate', '直接上级是钻石的返佣金额(6元)'),
|
|||
|
|
('direct_parent_amount_gold', '3.00', 'rebate', '直接上级是黄金的返佣金额(3元)'),
|
|||
|
|
('direct_parent_amount_normal', '2.00', 'rebate', '直接上级是普通的返佣金额(2元)'),
|
|||
|
|
('max_gold_rebate_amount', '3.00', 'rebate', '黄金代理最大返佣金额(3元)'),
|
|||
|
|
|
|||
|
|
-- 税费配置
|
|||
|
|
('tax_rate', '0.0600', 'tax', '提现税率(6%,即0.06)'),
|
|||
|
|
('tax_exemption_amount', '0.00', 'tax', '提现免税额度(元,默认0)')
|
|||
|
|
ON DUPLICATE KEY UPDATE
|
|||
|
|
`config_value` = VALUES(`config_value`),
|
|||
|
|
`update_time` = NOW();
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 九、建议的改进方案
|
|||
|
|
|
|||
|
|
### 方案A:保持当前键值对设计(推荐)
|
|||
|
|
|
|||
|
|
**优点**:
|
|||
|
|
- 灵活性强,易于扩展
|
|||
|
|
- 不需要修改表结构
|
|||
|
|
- 符合项目当前架构
|
|||
|
|
|
|||
|
|
**需要做的修改**:
|
|||
|
|
1. 统一配置键命名
|
|||
|
|
2. 修复代码硬编码问题
|
|||
|
|
3. 补充缺失的配置项
|
|||
|
|
4. 添加配置验证逻辑
|
|||
|
|
|
|||
|
|
### 方案B:改为结构化JSON配置(可选)
|
|||
|
|
|
|||
|
|
**如果配置项继续增长,可以考虑**:
|
|||
|
|
- 将相关配置组合成JSON对象存储在 `config_value` 中
|
|||
|
|
- 例如:`level_bonus_config` 存储 `{"1": 6, "2": 3, "3": 0}`
|
|||
|
|
|
|||
|
|
**缺点**:
|
|||
|
|
- 需要修改所有读取配置的代码
|
|||
|
|
- 不利于单个配置项的独立更新
|
|||
|
|
|
|||
|
|
**建议**:当前配置项数量不多(约15个),保持键值对设计更合适。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 十、总结
|
|||
|
|
|
|||
|
|
### 当前状态
|
|||
|
|
- ✅ 配置表设计思路合理
|
|||
|
|
- ❌ **价格配置设计错误**(应该在产品配置表,不在系统配置表)
|
|||
|
|
- ❌ 配置键命名不一致(需要立即修复)
|
|||
|
|
- ❌ 部分配置硬编码(需要立即修复)
|
|||
|
|
- ⚠️ 缺少部分配置项(需要补充)
|
|||
|
|
|
|||
|
|
### 修复优先级
|
|||
|
|
1. **P0(紧急)**:移除系统配置表中的价格配置,改为完全由产品配置表管理
|
|||
|
|
2. **P0(紧急)**:修改订单处理逻辑,从产品配置表读取价格参数
|
|||
|
|
3. **P0(紧急)**:统一配置键命名,修复不一致问题
|
|||
|
|
4. **P0(紧急)**:修改代码,从配置表读取等级加成,移除硬编码
|
|||
|
|
5. **P1(重要)**:补充缺失的配置项(`tax_exemption_amount`)
|
|||
|
|
6. **P2(建议)**:添加配置验证逻辑
|
|||
|
|
7. **P2(建议)**:将返佣规则配置化(当前硬编码)
|
|||
|
|
|
|||
|
|
### 是否符合项目
|
|||
|
|
|
|||
|
|
**配置表设计**:✅ 基本符合,但价格配置的位置设计错误
|
|||
|
|
|
|||
|
|
**存在的问题**:
|
|||
|
|
1. ❌ **价格配置应该在产品配置表中,而不是系统配置表**(严重设计问题)
|
|||
|
|
2. ❌ 配置键命名不一致
|
|||
|
|
3. ❌ 部分配置硬编码
|
|||
|
|
4. ⚠️ 缺少部分配置项
|
|||
|
|
|
|||
|
|
**结论**:需要修复上述问题后才能完全符合项目的配置化设计理念。**最重要的是将价格配置从系统配置表移除,改为完全由产品配置表管理。**
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 十一、产品配置表使用规范
|
|||
|
|
|
|||
|
|
### 11.1 产品配置表结构
|
|||
|
|
|
|||
|
|
**表名**: `agent_product_config`
|
|||
|
|
|
|||
|
|
每个产品都应该有对应的配置记录,包含以下字段:
|
|||
|
|
|
|||
|
|
| 字段 | 类型 | 必填 | 说明 |
|
|||
|
|
| ------------------ | ------------- | ---- | ----------------------------------------- |
|
|||
|
|
| `product_id` | bigint | ✅ 是 | 产品ID(唯一) |
|
|||
|
|
| `product_name` | varchar(100) | ✅ 是 | 产品名称 |
|
|||
|
|
| `base_price` | decimal(10,2) | ✅ 是 | 产品基础底价 |
|
|||
|
|
| `system_max_price` | decimal(10,2) | ✅ 是 | 产品价格上限 |
|
|||
|
|
| `price_threshold` | decimal(10,2) | ❌ 否 | 提价标准阈值(NULL表示不设阈值) |
|
|||
|
|
| `price_fee_rate` | decimal(5,4) | ❌ 否 | 提价手续费比例(NULL表示不收费,0-1之间) |
|
|||
|
|
|
|||
|
|
### 11.2 配置优先级和默认值
|
|||
|
|
|
|||
|
|
**规则**:
|
|||
|
|
1. 所有价格参数必须从产品配置表读取
|
|||
|
|
2. 如果产品配置记录不存在,应该报错或使用合理的默认值(建议报错,强制每个产品必须配置)
|
|||
|
|
3. 可选字段(`price_threshold`、`price_fee_rate`)如果为NULL,表示不启用该功能
|
|||
|
|
- `price_threshold = NULL` → 不设提价阈值
|
|||
|
|
- `price_fee_rate = NULL` → 不收取提价手续费
|
|||
|
|
|
|||
|
|
### 11.3 代码修改示例
|
|||
|
|
|
|||
|
|
#### 修改 AgentService.AgentProcess 方法
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// AgentProcess 处理代理订单(新系统)
|
|||
|
|
func (s *AgentService) AgentProcess(ctx context.Context, order *model.Order) error {
|
|||
|
|
// 1-3. 前面的代码不变...
|
|||
|
|
|
|||
|
|
// 4. 获取产品配置(必须存在)
|
|||
|
|
productConfig, err := s.AgentProductConfigModel.FindOneByProductId(ctx, order.ProductId)
|
|||
|
|
if err != nil {
|
|||
|
|
if errors.Is(err, model.ErrNotFound) {
|
|||
|
|
return errors.Wrapf(err, "产品配置不存在, productId: %d,请先在后台配置产品价格参数", order.ProductId)
|
|||
|
|
}
|
|||
|
|
return errors.Wrapf(err, "查询产品配置失败, productId: %d", order.ProductId)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 使用产品配置的底价
|
|||
|
|
basePrice := productConfig.BasePrice
|
|||
|
|
|
|||
|
|
// 6. 使用事务处理订单
|
|||
|
|
return s.AgentWalletModel.Trans(ctx, func(transCtx context.Context, session sqlx.Session) error {
|
|||
|
|
// 6.1 计算实际底价和代理收益
|
|||
|
|
levelBonus, err := s.getLevelBonus(ctx, agent.Level)
|
|||
|
|
if err != nil {
|
|||
|
|
return errors.Wrapf(err, "获取等级加成配置失败")
|
|||
|
|
}
|
|||
|
|
actualBasePrice := basePrice + float64(levelBonus)
|
|||
|
|
|
|||
|
|
// 6.2 计算提价成本(使用产品配置)
|
|||
|
|
priceThreshold := 0.0
|
|||
|
|
priceFeeRate := 0.0
|
|||
|
|
if productConfig.PriceThreshold.Valid {
|
|||
|
|
priceThreshold = productConfig.PriceThreshold.Float64
|
|||
|
|
}
|
|||
|
|
if productConfig.PriceFeeRate.Valid {
|
|||
|
|
priceFeeRate = productConfig.PriceFeeRate.Float64
|
|||
|
|
}
|
|||
|
|
priceCost := s.calculatePriceCost(agentOrder.SetPrice, priceThreshold, priceFeeRate)
|
|||
|
|
|
|||
|
|
// 6.3 计算代理收益
|
|||
|
|
agentProfit := agentOrder.SetPrice - actualBasePrice - priceCost
|
|||
|
|
|
|||
|
|
// ... 后续代码不变 ...
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 修改 PaymentLogic 创建订单时的价格计算
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 如果是代理推广订单,创建完整的代理订单记录
|
|||
|
|
if data.AgentIdentifier != "" && agentLinkModel != nil {
|
|||
|
|
// ... 获取代理信息 ...
|
|||
|
|
|
|||
|
|
// 获取产品配置(必须存在)
|
|||
|
|
productConfig, err := l.svcCtx.AgentProductConfigModel.FindOneByProductId(l.ctx, product.Id)
|
|||
|
|
if err != nil {
|
|||
|
|
if errors.Is(err, model.ErrNotFound) {
|
|||
|
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
|
|||
|
|
"生成订单失败,产品配置不存在, productId: %d,请先在后台配置产品价格参数", product.Id)
|
|||
|
|
}
|
|||
|
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
|
|||
|
|
"生成订单, 查询产品配置失败: %+v", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 使用产品配置的底价
|
|||
|
|
basePrice := productConfig.BasePrice
|
|||
|
|
|
|||
|
|
// 计算实际底价(基础底价+等级加成)
|
|||
|
|
levelBonus, _ := l.getLevelBonus(agent.Level)
|
|||
|
|
actualBasePrice := basePrice + float64(levelBonus)
|
|||
|
|
|
|||
|
|
// 计算提价成本(使用产品配置)
|
|||
|
|
priceThreshold := 0.0
|
|||
|
|
priceFeeRate := 0.0
|
|||
|
|
if productConfig.PriceThreshold.Valid {
|
|||
|
|
priceThreshold = productConfig.PriceThreshold.Float64
|
|||
|
|
}
|
|||
|
|
if productConfig.PriceFeeRate.Valid {
|
|||
|
|
priceFeeRate = productConfig.PriceFeeRate.Float64
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
priceCost := 0.0
|
|||
|
|
if agentLinkModel.SetPrice > priceThreshold {
|
|||
|
|
priceCost = (agentLinkModel.SetPrice - priceThreshold) * priceFeeRate
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 计算代理收益
|
|||
|
|
agentProfit := agentLinkModel.SetPrice - actualBasePrice - priceCost
|
|||
|
|
|
|||
|
|
// ... 创建代理订单记录 ...
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 11.4 需要修改的文件清单
|
|||
|
|
|
|||
|
|
需要修改以支持产品配置的代码文件:
|
|||
|
|
|
|||
|
|
1. **`app/main/api/internal/service/agentService.go`**
|
|||
|
|
- `AgentProcess()` 方法:从产品配置表读取价格参数
|
|||
|
|
|
|||
|
|
2. **`app/main/api/internal/logic/pay/paymentlogic.go`**
|
|||
|
|
- 创建订单时的价格计算:从产品配置表读取价格参数
|
|||
|
|
|
|||
|
|
3. **`app/main/api/internal/logic/agent/getagentproductconfiglogic.go`**
|
|||
|
|
- 移除从系统配置表读取价格参数的逻辑(只保留从产品配置表读取)
|
|||
|
|
|
|||
|
|
4. **`app/main/api/internal/logic/admin_agent/admingetagentconfiglogic.go`**
|
|||
|
|
- 移除价格相关配置项的返回
|
|||
|
|
|
|||
|
|
5. **`app/main/api/internal/logic/admin_agent/adminupdateagentconfiglogic.go`**
|
|||
|
|
- 移除价格相关配置项的更新逻辑
|
|||
|
|
|
|||
|
|
6. **后台管理系统前端**
|
|||
|
|
- 系统配置页面:移除价格相关配置项
|
|||
|
|
- 产品配置页面:确保可以正确配置所有价格参数
|
|||
|
|
|