All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m29s
主要变更: - 新增 tb_shop_series_allocation 表,存储系列级别的一次性佣金配置 - ShopPackageAllocation 移除 one_time_commission_amount 字段 - PackageSeries 新增 enable_one_time_commission 字段控制是否启用一次性佣金 - 新增 /api/admin/shop-series-allocations CRUD 接口 - 佣金计算逻辑改为从 ShopSeriesAllocation 获取一次性佣金金额 - 删除废弃的 ShopSeriesOneTimeCommissionTier 模型 - OpenAPI Tag '系列分配' 和 '单套餐分配' 合并为 '套餐分配' 迁移脚本: - 000042: 重构佣金套餐模型 - 000043: 简化佣金分配 - 000044: 一次性佣金分配重构 - 000045: PackageSeries 添加 enable_one_time_commission 字段 测试: - 新增验收测试 (shop_series_allocation, commission_calculation) - 新增流程测试 (one_time_commission_chain) - 删除过时的单元测试(已被验收测试覆盖)
6.0 KiB
6.0 KiB
Why
当前套餐与佣金系统存在概念模型与实现错位的问题:套餐价格字段过多且语义不清(Price、SuggestedCostPrice、SuggestedRetailPrice 三个字段用途混乱),流量字段设计不支持真流量/虚流量共存机制,一次性佣金缺少链式分配能力(无法设置"给下级多少"),套餐分配与系列分配的关系不清晰。这导致接口入参混乱、不同模块的一致性被破坏、操作流程不是线性的。需要基于梳理清楚的业务模型进行系统性重构。
What Changes
套餐模型简化
- BREAKING 移除
Package.Price字段,只保留cost_price(成本价)和suggested_retail_price(建议售价) - BREAKING 重构流量字段:
real_data_mb(必填)+enable_virtual_data(开关)+virtual_data_mb(可选,≤真流量) - 移除
data_type字段(不再是二选一) - 移除
data_amount_mb字段(语义不清)
一次性佣金重构
- BREAKING 修改触发条件命名:
single_recharge→first_recharge(首充) - BREAKING 新增链式分配能力:套餐分配时设置"给下级的一次性佣金金额"
- 新增一次性佣金时效配置(永久/固定日期/相对时长)
- 优化强充金额计算:首充时
max(首充要求, 套餐售价);累计充值时支持固定/动态差额两种模式 - 新增梯度佣金统计范围开关(仅自己/自己+下级)
套餐分配统一
- BREAKING 统一套餐分配模型:将一次性佣金额度配置移入套餐分配
- 套餐系列仅定义一次性佣金"规则",分配时设置"给谁多少"
- 代理只能看到自己能拿到的一次性佣金额度,不能看到总规则
累计充值机制完善
- 明确累计范围:按卡/设备在该套餐系列下累计
- 明确累计操作:只有"充值"操作累计,"直接购买套餐"不累计
- 一次性佣金每张卡/设备只触发一次
代理视角优化
- 不同用户调用同一套餐列表接口,看到不同的成本价(自己的成本价)
- 不同用户看到不同的一次性佣金额度(自己能拿到的)
Capabilities
New Capabilities
commission-chain-distribution: 一次性佣金链式分配能力,支持在套餐分配时设置给下级的佣金金额,自动计算各级代理分得的佣金package-virtual-data: 套餐真流量/虚流量共存机制,支持开关控制虚流量,停机判断基于配置选择使用哪个流量值one-time-commission-validity: 一次性佣金时效管理,支持永久、固定到期日期、相对时长三种时效类型accumulated-recharge-tracking: 累计充值追踪,按卡/设备在套餐系列下累计充值金额,只统计充值操作
Modified Capabilities
package-management: 移除Price、data_type、data_amount_mb字段,简化为cost_price+suggested_retail_price+ 真流量/虚流量共存package-series-management: 一次性佣金规则仅在系列层面定义,分配时不再复制完整配置shop-series-allocation: 移除完整的一次性佣金配置,改为引用系列规则 + 设置给下级的金额one-time-commission-trigger: 触发条件从single_recharge改为first_recharge,首充定义为该卡/设备在该系列下的第一次充值commission-calculation: 适配链式分配逻辑,上级佣金 = 自己能拿的 - 给下级的force-recharge-check: 首充强充金额改为max(首充要求, 套餐售价),累计充值强充支持固定/动态两种计算方式agent-available-packages: 返回代理视角的成本价和一次性佣金额度,而非原始配置shop-commission-tier: 新增统计范围开关(仅自己/自己+下级),统计周期与一次性佣金时效一致
Impact
数据库变更
tb_package: 移除price、data_type、data_amount_mb字段,新增enable_virtual_data字段tb_package_series: 新增一次性佣金时效字段(validity_type、validity_value)tb_shop_series_allocation: 移除大部分一次性佣金配置字段,仅保留one_time_commission_amount(给下级的金额)tb_shop_package_allocation: 新增one_time_commission_amount字段tb_iot_card/tb_device: 新增accumulated_recharge_amount(累计充值)、first_recharge_triggered(首充已触发)字段tb_shop_series_one_time_commission_tier: 新增stat_scope字段
API 变更(BREAKING)
POST /api/admin/packages: 移除price、data_type、data_amount_mb参数PUT /api/admin/packages/:id: 同上POST /api/admin/shop-series-allocations: 移除one_time_commission_type/trigger/threshold/mode/value等字段,新增one_time_commission_amountPOST /api/admin/shop-package-allocations: 新增one_time_commission_amount字段GET /api/admin/packages: 返回结构变化,成本价和一次性佣金按用户视角返回
代码变更
internal/model/package.go: Package 结构体字段调整internal/model/shop_series_allocation.go: 移除一次性佣金配置字段internal/model/shop_package_allocation.go: 新增一次性佣金金额字段internal/model/dto/package_dto.go: 请求/响应 DTO 调整internal/model/dto/shop_series_allocation.go: DTO 简化internal/service/commission/: 佣金计算逻辑适配链式分配internal/handler/admin/package.go: 套餐列表按用户视角返回internal/task/commission_calculation.go: 异步任务适配新逻辑
前端影响
- 套餐管理页面:移除价格字段,调整流量配置 UI
- 套餐分配页面:简化一次性佣金配置,改为只设置"给下级多少"
- 套餐列表页面:显示的成本价和一次性佣金需要理解为"自己视角"
数据迁移
- 需要迁移脚本处理历史数据:
Package.SuggestedCostPrice→Package.cost_price(如果Price有值需要决定保留哪个)- 已有的
ShopSeriesAllocation一次性佣金配置需要迁移到新结构