清理冗余的梯度返佣(TierCommission)配置
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m46s

- 移除 Model 层:删除 ShopSeriesCommissionTier 模型及相关字段
- 更新 DTO:删除 TierCommissionConfig、TierEntry 类型及相关请求/响应字段
- 删除 Store 层:移除 ShopSeriesCommissionTierStore 及相关查询逻辑
- 简化 Service 层:删除梯度返佣处理逻辑,统计查询移除 tier_bonus 字段
- 数据库迁移:创建 000034_remove_tier_commission 移除相关表和字段
- 更新测试:移除梯度返佣相关测试用例,更新集成测试
- OpenAPI 文档:删除梯度返佣相关 schema 和枚举值
- 归档变更:归档 remove-tier-commission-redundancy 到 archive/2026-01-30-
- 同步规范:更新 4 个主 specs,标记废弃功能并添加迁移指引

原因:梯度返佣功能与一次性梯度佣金功能重复,且从未实现实际计算逻辑
迁移:使用一次性佣金的梯度模式 (OneTimeCommissionConfig.type = "tiered") 替代
This commit is contained in:
2026-01-30 14:57:24 +08:00
parent 409a68d60b
commit 1cf17e8f14
39 changed files with 978 additions and 407 deletions

View File

@@ -387,25 +387,21 @@ func (s *Service) GetStats(ctx context.Context, req *dto.CommissionStatsRequest)
return &dto.CommissionStatsResponse{}, nil
}
var costDiffPercent, oneTimePercent, tierBonusPercent int64
var costDiffPercent, oneTimePercent int64
if stats.TotalAmount > 0 {
costDiffPercent = stats.CostDiffAmount * 1000 / stats.TotalAmount
oneTimePercent = stats.OneTimeAmount * 1000 / stats.TotalAmount
tierBonusPercent = stats.TierBonusAmount * 1000 / stats.TotalAmount
}
return &dto.CommissionStatsResponse{
TotalAmount: stats.TotalAmount,
CostDiffAmount: stats.CostDiffAmount,
OneTimeAmount: stats.OneTimeAmount,
TierBonusAmount: stats.TierBonusAmount,
CostDiffPercent: costDiffPercent,
OneTimePercent: oneTimePercent,
TierBonusPercent: tierBonusPercent,
TotalCount: stats.TotalCount,
CostDiffCount: stats.CostDiffCount,
OneTimeCount: stats.OneTimeCount,
TierBonusCount: stats.TierBonusCount,
TotalAmount: stats.TotalAmount,
CostDiffAmount: stats.CostDiffAmount,
OneTimeAmount: stats.OneTimeAmount,
CostDiffPercent: costDiffPercent,
OneTimePercent: oneTimePercent,
TotalCount: stats.TotalCount,
CostDiffCount: stats.CostDiffCount,
OneTimeCount: stats.OneTimeCount,
}, nil
}

View File

@@ -21,7 +21,6 @@ type Service struct {
packageSeriesStore *postgres.PackageSeriesStore
packageAllocationStore *postgres.ShopPackageAllocationStore
seriesAllocationStore *postgres.ShopSeriesAllocationStore
commissionTierStore *postgres.ShopSeriesCommissionTierStore
}
func New(
@@ -29,14 +28,12 @@ func New(
packageSeriesStore *postgres.PackageSeriesStore,
packageAllocationStore *postgres.ShopPackageAllocationStore,
seriesAllocationStore *postgres.ShopSeriesAllocationStore,
commissionTierStore *postgres.ShopSeriesCommissionTierStore,
) *Service {
return &Service{
packageStore: packageStore,
packageSeriesStore: packageSeriesStore,
packageAllocationStore: packageAllocationStore,
seriesAllocationStore: seriesAllocationStore,
commissionTierStore: commissionTierStore,
}
}
@@ -404,20 +401,5 @@ func (s *Service) getCommissionInfo(ctx context.Context, allocationID uint) *dto
info.CurrentRate = fmt.Sprintf("%.1f%%", float64(seriesAllocation.BaseCommissionValue)/10)
}
if seriesAllocation.EnableTierCommission {
tiers, err := s.commissionTierStore.ListByAllocationID(ctx, allocationID)
if err == nil && len(tiers) > 0 {
tier := tiers[0]
info.NextThreshold = &tier.ThresholdValue
if tier.CommissionMode == constants.CommissionModeFixed {
nextRate := fmt.Sprintf("%.2f元/单", float64(tier.CommissionValue)/100)
info.NextRate = nextRate
} else {
nextRate := fmt.Sprintf("%.1f%%", float64(tier.CommissionValue)/10)
info.NextRate = nextRate
}
}
}
return info
}

View File

@@ -25,7 +25,7 @@ func TestPackageService_Create(t *testing.T) {
tx := testutils.NewTestTransaction(t)
packageStore := postgres.NewPackageStore(tx)
packageSeriesStore := postgres.NewPackageSeriesStore(tx)
svc := New(packageStore, packageSeriesStore, nil, nil, nil)
svc := New(packageStore, packageSeriesStore, nil, nil)
ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{
UserID: 1,
@@ -98,7 +98,7 @@ func TestPackageService_UpdateStatus(t *testing.T) {
tx := testutils.NewTestTransaction(t)
packageStore := postgres.NewPackageStore(tx)
packageSeriesStore := postgres.NewPackageSeriesStore(tx)
svc := New(packageStore, packageSeriesStore, nil, nil, nil)
svc := New(packageStore, packageSeriesStore, nil, nil)
ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{
UserID: 1,
@@ -168,7 +168,7 @@ func TestPackageService_UpdateShelfStatus(t *testing.T) {
tx := testutils.NewTestTransaction(t)
packageStore := postgres.NewPackageStore(tx)
packageSeriesStore := postgres.NewPackageSeriesStore(tx)
svc := New(packageStore, packageSeriesStore, nil, nil, nil)
svc := New(packageStore, packageSeriesStore, nil, nil)
ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{
UserID: 1,
@@ -255,7 +255,7 @@ func TestPackageService_Get(t *testing.T) {
tx := testutils.NewTestTransaction(t)
packageStore := postgres.NewPackageStore(tx)
packageSeriesStore := postgres.NewPackageSeriesStore(tx)
svc := New(packageStore, packageSeriesStore, nil, nil, nil)
svc := New(packageStore, packageSeriesStore, nil, nil)
ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{
UserID: 1,
@@ -293,7 +293,7 @@ func TestPackageService_Update(t *testing.T) {
tx := testutils.NewTestTransaction(t)
packageStore := postgres.NewPackageStore(tx)
packageSeriesStore := postgres.NewPackageSeriesStore(tx)
svc := New(packageStore, packageSeriesStore, nil, nil, nil)
svc := New(packageStore, packageSeriesStore, nil, nil)
ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{
UserID: 1,
@@ -342,7 +342,7 @@ func TestPackageService_Delete(t *testing.T) {
tx := testutils.NewTestTransaction(t)
packageStore := postgres.NewPackageStore(tx)
packageSeriesStore := postgres.NewPackageSeriesStore(tx)
svc := New(packageStore, packageSeriesStore, nil, nil, nil)
svc := New(packageStore, packageSeriesStore, nil, nil)
ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{
UserID: 1,
@@ -377,7 +377,7 @@ func TestPackageService_List(t *testing.T) {
tx := testutils.NewTestTransaction(t)
packageStore := postgres.NewPackageStore(tx)
packageSeriesStore := postgres.NewPackageSeriesStore(tx)
svc := New(packageStore, packageSeriesStore, nil, nil, nil)
svc := New(packageStore, packageSeriesStore, nil, nil)
ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{
UserID: 1,
@@ -460,7 +460,7 @@ func TestPackageService_SeriesNameInResponse(t *testing.T) {
tx := testutils.NewTestTransaction(t)
packageStore := postgres.NewPackageStore(tx)
packageSeriesStore := postgres.NewPackageSeriesStore(tx)
svc := New(packageStore, packageSeriesStore, nil, nil, nil)
svc := New(packageStore, packageSeriesStore, nil, nil)
ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{
UserID: 1,

View File

@@ -19,7 +19,6 @@ type Service struct {
seriesAllocationStore *postgres.ShopSeriesAllocationStore
packageAllocationStore *postgres.ShopPackageAllocationStore
configStore *postgres.ShopSeriesAllocationConfigStore
commissionTierStore *postgres.ShopSeriesCommissionTierStore
commissionStatsStore *postgres.ShopSeriesCommissionStatsStore
shopStore *postgres.ShopStore
}
@@ -30,7 +29,6 @@ func New(
seriesAllocationStore *postgres.ShopSeriesAllocationStore,
packageAllocationStore *postgres.ShopPackageAllocationStore,
configStore *postgres.ShopSeriesAllocationConfigStore,
commissionTierStore *postgres.ShopSeriesCommissionTierStore,
commissionStatsStore *postgres.ShopSeriesCommissionStatsStore,
shopStore *postgres.ShopStore,
) *Service {
@@ -40,7 +38,6 @@ func New(
seriesAllocationStore: seriesAllocationStore,
packageAllocationStore: packageAllocationStore,
configStore: configStore,
commissionTierStore: commissionTierStore,
commissionStatsStore: commissionStatsStore,
shopStore: shopStore,
}
@@ -84,14 +81,13 @@ func (s *Service) BatchAllocate(ctx context.Context, req *dto.BatchAllocatePacka
return s.db.Transaction(func(tx *gorm.DB) error {
seriesAllocation := &model.ShopSeriesAllocation{
BaseModel: model.BaseModel{Creator: currentUserID, Updater: currentUserID},
ShopID: req.ShopID,
SeriesID: req.SeriesID,
AllocatorShopID: allocatorShopID,
BaseCommissionMode: req.BaseCommission.Mode,
BaseCommissionValue: req.BaseCommission.Value,
EnableTierCommission: req.EnableTierCommission,
Status: constants.StatusEnabled,
BaseModel: model.BaseModel{Creator: currentUserID, Updater: currentUserID},
ShopID: req.ShopID,
SeriesID: req.SeriesID,
AllocatorShopID: allocatorShopID,
BaseCommissionMode: req.BaseCommission.Mode,
BaseCommissionValue: req.BaseCommission.Value,
Status: constants.StatusEnabled,
}
if err := tx.Create(seriesAllocation).Error; err != nil {
@@ -100,12 +96,11 @@ func (s *Service) BatchAllocate(ctx context.Context, req *dto.BatchAllocatePacka
now := time.Now()
config := &model.ShopSeriesAllocationConfig{
AllocationID: seriesAllocation.ID,
Version: 1,
BaseCommissionMode: req.BaseCommission.Mode,
BaseCommissionValue: req.BaseCommission.Value,
EnableTierCommission: req.EnableTierCommission,
EffectiveFrom: now,
AllocationID: seriesAllocation.ID,
Version: 1,
BaseCommissionMode: req.BaseCommission.Mode,
BaseCommissionValue: req.BaseCommission.Value,
EffectiveFrom: now,
}
if err := tx.Create(config).Error; err != nil {
@@ -134,12 +129,6 @@ func (s *Service) BatchAllocate(ctx context.Context, req *dto.BatchAllocatePacka
return errors.Wrap(errors.CodeInternalError, err, "批量创建套餐分配失败")
}
if req.EnableTierCommission && req.TierConfig != nil {
if err := s.createCommissionTiers(tx, seriesAllocation.ID, req.TierConfig, currentUserID); err != nil {
return err
}
}
return nil
})
}
@@ -170,23 +159,3 @@ func (s *Service) calculateAdjustedPrice(basePrice int64, adjustment *dto.PriceA
return basePrice + (basePrice * adjustment.Value / 1000)
}
func (s *Service) createCommissionTiers(tx *gorm.DB, allocationID uint, config *dto.TierCommissionConfig, creatorID uint) error {
for _, tierReq := range config.Tiers {
tier := &model.ShopSeriesCommissionTier{
BaseModel: model.BaseModel{Creator: creatorID, Updater: creatorID},
AllocationID: allocationID,
PeriodType: config.PeriodType,
TierType: config.TierType,
ThresholdValue: tierReq.Threshold,
CommissionMode: tierReq.Mode,
CommissionValue: tierReq.Value,
}
if err := tx.Create(tier).Error; err != nil {
return errors.Wrap(errors.CodeInternalError, err, "创建佣金梯度失败")
}
}
return nil
}

View File

@@ -16,7 +16,6 @@ import (
type Service struct {
allocationStore *postgres.ShopSeriesAllocationStore
tierStore *postgres.ShopSeriesCommissionTierStore
configStore *postgres.ShopSeriesAllocationConfigStore
oneTimeCommissionTierStore *postgres.ShopSeriesOneTimeCommissionTierStore
shopStore *postgres.ShopStore
@@ -26,7 +25,6 @@ type Service struct {
func New(
allocationStore *postgres.ShopSeriesAllocationStore,
tierStore *postgres.ShopSeriesCommissionTierStore,
configStore *postgres.ShopSeriesAllocationConfigStore,
oneTimeCommissionTierStore *postgres.ShopSeriesOneTimeCommissionTierStore,
shopStore *postgres.ShopStore,
@@ -35,7 +33,6 @@ func New(
) *Service {
return &Service{
allocationStore: allocationStore,
tierStore: tierStore,
configStore: configStore,
oneTimeCommissionTierStore: oneTimeCommissionTierStore,
shopStore: shopStore,
@@ -106,13 +103,12 @@ func (s *Service) Create(ctx context.Context, req *dto.CreateShopSeriesAllocatio
}
allocation := &model.ShopSeriesAllocation{
ShopID: req.ShopID,
SeriesID: req.SeriesID,
AllocatorShopID: allocatorShopID,
BaseCommissionMode: req.BaseCommission.Mode,
BaseCommissionValue: req.BaseCommission.Value,
EnableTierCommission: req.EnableTierCommission,
Status: constants.StatusEnabled,
ShopID: req.ShopID,
SeriesID: req.SeriesID,
AllocatorShopID: allocatorShopID,
BaseCommissionMode: req.BaseCommission.Mode,
BaseCommissionValue: req.BaseCommission.Value,
Status: constants.StatusEnabled,
}
// 处理一次性佣金配置
@@ -192,12 +188,6 @@ func (s *Service) Update(ctx context.Context, id uint, req *dto.UpdateShopSeries
allocation.BaseCommissionMode = req.BaseCommission.Mode
allocation.BaseCommissionValue = req.BaseCommission.Value
}
if req.EnableTierCommission != nil {
if allocation.EnableTierCommission != *req.EnableTierCommission {
configChanged = true
}
allocation.EnableTierCommission = *req.EnableTierCommission
}
enableOneTimeCommission := allocation.EnableOneTimeCommission
if req.EnableOneTimeCommission != nil {
@@ -409,7 +399,6 @@ func (s *Service) buildResponse(ctx context.Context, a *model.ShopSeriesAllocati
Mode: a.BaseCommissionMode,
Value: a.BaseCommissionValue,
},
EnableTierCommission: a.EnableTierCommission,
EnableOneTimeCommission: a.EnableOneTimeCommission,
Status: a.Status,
CreatedAt: a.CreatedAt.Format(time.RFC3339),
@@ -458,12 +447,11 @@ func (s *Service) createNewConfigVersion(ctx context.Context, allocation *model.
}
newConfig := &model.ShopSeriesAllocationConfig{
AllocationID: allocation.ID,
Version: newVersion,
BaseCommissionMode: allocation.BaseCommissionMode,
BaseCommissionValue: allocation.BaseCommissionValue,
EnableTierCommission: allocation.EnableTierCommission,
EffectiveFrom: now,
AllocationID: allocation.ID,
Version: newVersion,
BaseCommissionMode: allocation.BaseCommissionMode,
BaseCommissionValue: allocation.BaseCommissionValue,
EffectiveFrom: now,
}
if err := s.configStore.Create(ctx, newConfig); err != nil {