## 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_amount` - `POST /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` 一次性佣金配置需要迁移到新结构