重构: 店铺套餐分配系统从加价模式改为返佣模式
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m18s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m18s
主要变更: - 重构分配模型:从加价模式(pricing_mode/pricing_value)改为返佣模式(base_commission + tier_commission) - 删除独立的 my_package 接口,统一到 /api/admin/packages(通过数据权限自动过滤) - 新增批量分配和批量调价功能,支持事务和性能优化 - 新增配置版本管理,订单创建时锁定返佣配置 - 新增成本价历史记录,支持审计和纠纷处理 - 新增统计缓存系统(Redis + 异步任务),优化梯度返佣计算性能 - 删除冗余的梯度佣金独立 CRUD 接口(合并到分配配置中) - 归档 3 个已完成的 OpenSpec changes 并同步 8 个新 capabilities 到 main specs 技术细节: - 数据库迁移:000026_refactor_shop_package_allocation - 新增 Store:AllocationConfigStore, PriceHistoryStore, CommissionStatsStore - 新增 Service:BatchAllocationService, BatchPricingService, CommissionStatsService - 新增异步任务:统计更新、定时同步、周期归档 - 测试覆盖:批量操作集成测试、梯度佣金 CRUD 清理验证 影响: - API 变更:删除 4 个梯度 CRUD 接口(POST/GET/PUT/DELETE /:id/tiers) - API 新增:批量分配、批量调价接口 - 数据模型:重构 shop_series_allocation 表结构 - 性能优化:批量操作使用 CreateInBatches,统计使用 Redis 缓存 相关文档: - openspec/changes/archive/2026-01-28-refactor-shop-package-allocation/ - openspec/specs/agent-available-packages/ - openspec/specs/allocation-config-versioning/ - 等 8 个新 capability specs
This commit is contained in:
@@ -18,6 +18,7 @@ import (
|
||||
type Service struct {
|
||||
packageAllocationStore *postgres.ShopPackageAllocationStore
|
||||
seriesAllocationStore *postgres.ShopSeriesAllocationStore
|
||||
priceHistoryStore *postgres.ShopPackageAllocationPriceHistoryStore
|
||||
shopStore *postgres.ShopStore
|
||||
packageStore *postgres.PackageStore
|
||||
}
|
||||
@@ -25,12 +26,14 @@ type Service struct {
|
||||
func New(
|
||||
packageAllocationStore *postgres.ShopPackageAllocationStore,
|
||||
seriesAllocationStore *postgres.ShopSeriesAllocationStore,
|
||||
priceHistoryStore *postgres.ShopPackageAllocationPriceHistoryStore,
|
||||
shopStore *postgres.ShopStore,
|
||||
packageStore *postgres.PackageStore,
|
||||
) *Service {
|
||||
return &Service{
|
||||
packageAllocationStore: packageAllocationStore,
|
||||
seriesAllocationStore: seriesAllocationStore,
|
||||
priceHistoryStore: priceHistoryStore,
|
||||
shopStore: shopStore,
|
||||
packageStore: packageStore,
|
||||
}
|
||||
@@ -271,3 +274,76 @@ func (s *Service) buildResponse(ctx context.Context, a *model.ShopPackageAllocat
|
||||
UpdatedAt: a.UpdatedAt.Format(time.RFC3339),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Service) UpdateCostPrice(ctx context.Context, id uint, newCostPrice int64, changeReason string) (*dto.ShopPackageAllocationResponse, error) {
|
||||
currentUserID := middleware.GetUserIDFromContext(ctx)
|
||||
if currentUserID == 0 {
|
||||
return nil, errors.New(errors.CodeUnauthorized, "未授权访问")
|
||||
}
|
||||
|
||||
allocation, err := s.packageAllocationStore.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, errors.New(errors.CodeNotFound, "分配记录不存在")
|
||||
}
|
||||
return nil, fmt.Errorf("获取分配记录失败: %w", err)
|
||||
}
|
||||
|
||||
if allocation.CostPrice == newCostPrice {
|
||||
return nil, errors.New(errors.CodeInvalidParam, "新成本价与当前成本价相同")
|
||||
}
|
||||
|
||||
oldCostPrice := allocation.CostPrice
|
||||
now := time.Now()
|
||||
|
||||
priceHistory := &model.ShopPackageAllocationPriceHistory{
|
||||
AllocationID: allocation.ID,
|
||||
OldCostPrice: oldCostPrice,
|
||||
NewCostPrice: newCostPrice,
|
||||
ChangeReason: changeReason,
|
||||
ChangedBy: currentUserID,
|
||||
EffectiveFrom: now,
|
||||
}
|
||||
if err := s.priceHistoryStore.Create(ctx, priceHistory); err != nil {
|
||||
return nil, fmt.Errorf("创建价格历史记录失败: %w", err)
|
||||
}
|
||||
|
||||
allocation.CostPrice = newCostPrice
|
||||
allocation.Updater = currentUserID
|
||||
if err := s.packageAllocationStore.Update(ctx, allocation); err != nil {
|
||||
return nil, fmt.Errorf("更新成本价失败: %w", err)
|
||||
}
|
||||
|
||||
shop, _ := s.shopStore.GetByID(ctx, allocation.ShopID)
|
||||
pkg, _ := s.packageStore.GetByID(ctx, allocation.PackageID)
|
||||
|
||||
shopName := ""
|
||||
packageName := ""
|
||||
packageCode := ""
|
||||
if shop != nil {
|
||||
shopName = shop.ShopName
|
||||
}
|
||||
if pkg != nil {
|
||||
packageName = pkg.PackageName
|
||||
packageCode = pkg.PackageCode
|
||||
}
|
||||
|
||||
return s.buildResponse(ctx, allocation, shopName, packageName, packageCode)
|
||||
}
|
||||
|
||||
func (s *Service) GetPriceHistory(ctx context.Context, allocationID uint) ([]*model.ShopPackageAllocationPriceHistory, error) {
|
||||
_, err := s.packageAllocationStore.GetByID(ctx, allocationID)
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, errors.New(errors.CodeNotFound, "分配记录不存在")
|
||||
}
|
||||
return nil, fmt.Errorf("获取分配记录失败: %w", err)
|
||||
}
|
||||
|
||||
history, err := s.priceHistoryStore.ListByAllocation(ctx, allocationID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取价格历史失败: %w", err)
|
||||
}
|
||||
|
||||
return history, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user