refactor: 一次性佣金配置从套餐级别提升到系列级别
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m29s
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) - 删除过时的单元测试(已被验收测试覆盖)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
@@ -10,11 +11,13 @@ import (
|
||||
// 套餐的分组,用于一次性分佣规则配置
|
||||
type PackageSeries struct {
|
||||
gorm.Model
|
||||
BaseModel `gorm:"embedded"`
|
||||
SeriesCode string `gorm:"column:series_code;type:varchar(100);uniqueIndex:idx_package_series_code,where:deleted_at IS NULL;not null;comment:系列编码" json:"series_code"`
|
||||
SeriesName string `gorm:"column:series_name;type:varchar(255);not null;comment:系列名称" json:"series_name"`
|
||||
Description string `gorm:"column:description;type:text;comment:描述" json:"description"`
|
||||
Status int `gorm:"column:status;type:int;default:1;not null;comment:状态 1-启用 2-禁用" json:"status"`
|
||||
BaseModel `gorm:"embedded"`
|
||||
SeriesCode string `gorm:"column:series_code;type:varchar(100);uniqueIndex:idx_package_series_code,where:deleted_at IS NULL;not null;comment:系列编码" json:"series_code"`
|
||||
SeriesName string `gorm:"column:series_name;type:varchar(255);not null;comment:系列名称" json:"series_name"`
|
||||
Description string `gorm:"column:description;type:text;comment:描述" json:"description"`
|
||||
Status int `gorm:"column:status;type:int;default:1;not null;comment:状态 1-启用 2-禁用" json:"status"`
|
||||
OneTimeCommissionConfigJSON string `gorm:"column:one_time_commission_config;type:jsonb;default:'{}';comment:一次性佣金规则配置" json:"-"`
|
||||
EnableOneTimeCommission bool `gorm:"column:enable_one_time_commission;default:false;comment:是否启用一次性佣金(顶层字段,支持SQL索引)" json:"enable_one_time_commission"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
@@ -32,13 +35,11 @@ type Package struct {
|
||||
SeriesID uint `gorm:"column:series_id;index;comment:套餐系列ID" json:"series_id"`
|
||||
PackageType string `gorm:"column:package_type;type:varchar(50);not null;comment:套餐类型 formal-正式套餐 addon-附加套餐" json:"package_type"`
|
||||
DurationMonths int `gorm:"column:duration_months;type:int;not null;comment:套餐时长(月数) 1-月套餐 12-年套餐" json:"duration_months"`
|
||||
DataType string `gorm:"column:data_type;type:varchar(20);comment:流量类型 real-真流量 virtual-虚流量" json:"data_type"`
|
||||
RealDataMB int64 `gorm:"column:real_data_mb;type:bigint;default:0;comment:真流量额度(MB)" json:"real_data_mb"`
|
||||
VirtualDataMB int64 `gorm:"column:virtual_data_mb;type:bigint;default:0;comment:虚流量额度(MB,用于停机判断)" json:"virtual_data_mb"`
|
||||
DataAmountMB int64 `gorm:"column:data_amount_mb;type:bigint;default:0;comment:总流量额度(MB)" json:"data_amount_mb"`
|
||||
Price int64 `gorm:"column:price;type:bigint;not null;comment:套餐价格(分为单位)" json:"price"`
|
||||
EnableVirtualData bool `gorm:"column:enable_virtual_data;type:boolean;default:false;not null;comment:是否启用虚流量" json:"enable_virtual_data"`
|
||||
Status int `gorm:"column:status;type:int;default:1;not null;comment:状态 1-启用 2-禁用" json:"status"`
|
||||
SuggestedCostPrice int64 `gorm:"column:suggested_cost_price;type:bigint;default:0;comment:建议成本价(分为单位)" json:"suggested_cost_price"`
|
||||
CostPrice int64 `gorm:"column:cost_price;type:bigint;default:0;comment:成本价(分为单位)" json:"cost_price"`
|
||||
SuggestedRetailPrice int64 `gorm:"column:suggested_retail_price;type:bigint;default:0;comment:建议售价(分为单位)" json:"suggested_retail_price"`
|
||||
ShelfStatus int `gorm:"column:shelf_status;type:int;default:2;not null;comment:上架状态 1-上架 2-下架" json:"shelf_status"`
|
||||
}
|
||||
@@ -72,3 +73,68 @@ type PackageUsage struct {
|
||||
func (PackageUsage) TableName() string {
|
||||
return "tb_package_usage"
|
||||
}
|
||||
|
||||
// OneTimeCommissionConfig 一次性佣金规则配置
|
||||
type OneTimeCommissionConfig struct {
|
||||
Enable bool `json:"enable"`
|
||||
TriggerType string `json:"trigger_type"`
|
||||
Threshold int64 `json:"threshold"`
|
||||
CommissionType string `json:"commission_type"`
|
||||
CommissionAmount int64 `json:"commission_amount"`
|
||||
Tiers []OneTimeCommissionTier `json:"tiers,omitempty"`
|
||||
ValidityType string `json:"validity_type"`
|
||||
ValidityValue string `json:"validity_value"`
|
||||
EnableForceRecharge bool `json:"enable_force_recharge"`
|
||||
ForceCalcType string `json:"force_calc_type"`
|
||||
ForceAmount int64 `json:"force_amount"`
|
||||
}
|
||||
|
||||
// OneTimeCommissionTier 一次性佣金梯度配置
|
||||
type OneTimeCommissionTier struct {
|
||||
Dimension string `json:"dimension"`
|
||||
StatScope string `json:"stat_scope"`
|
||||
Threshold int64 `json:"threshold"`
|
||||
Amount int64 `json:"amount"`
|
||||
}
|
||||
|
||||
const (
|
||||
OneTimeCommissionTriggerFirstRecharge = "first_recharge"
|
||||
OneTimeCommissionTriggerAccumulatedRecharge = "accumulated_recharge"
|
||||
|
||||
OneTimeCommissionValidityPermanent = "permanent"
|
||||
OneTimeCommissionValidityFixedDate = "fixed_date"
|
||||
OneTimeCommissionValidityRelative = "relative"
|
||||
|
||||
OneTimeCommissionForceCalcFixed = "fixed"
|
||||
OneTimeCommissionForceCalcDynamic = "dynamic"
|
||||
|
||||
OneTimeCommissionStatScopeSelf = "self"
|
||||
OneTimeCommissionStatScopeSelfAndSub = "self_and_sub"
|
||||
|
||||
TierTypeSalesCount = "sales_count"
|
||||
TierTypeSalesAmount = "sales_amount"
|
||||
)
|
||||
|
||||
func (ps *PackageSeries) GetOneTimeCommissionConfig() (*OneTimeCommissionConfig, error) {
|
||||
if ps.OneTimeCommissionConfigJSON == "" {
|
||||
return nil, nil
|
||||
}
|
||||
var config OneTimeCommissionConfig
|
||||
if err := json.Unmarshal([]byte(ps.OneTimeCommissionConfigJSON), &config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
func (ps *PackageSeries) SetOneTimeCommissionConfig(config *OneTimeCommissionConfig) error {
|
||||
if config == nil {
|
||||
ps.OneTimeCommissionConfigJSON = ""
|
||||
return nil
|
||||
}
|
||||
data, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ps.OneTimeCommissionConfigJSON = string(data)
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user