package package_series import ( "context" "time" "gorm.io/gorm" "github.com/break/junhong_cmp_fiber/internal/model" "github.com/break/junhong_cmp_fiber/internal/model/dto" "github.com/break/junhong_cmp_fiber/internal/store" "github.com/break/junhong_cmp_fiber/internal/store/postgres" "github.com/break/junhong_cmp_fiber/pkg/constants" "github.com/break/junhong_cmp_fiber/pkg/errors" "github.com/break/junhong_cmp_fiber/pkg/middleware" ) type Service struct { packageSeriesStore *postgres.PackageSeriesStore shopSeriesAllocationStore *postgres.ShopSeriesAllocationStore } func New(packageSeriesStore *postgres.PackageSeriesStore, shopSeriesAllocationStore *postgres.ShopSeriesAllocationStore) *Service { return &Service{ packageSeriesStore: packageSeriesStore, shopSeriesAllocationStore: shopSeriesAllocationStore, } } func (s *Service) Create(ctx context.Context, req *dto.CreatePackageSeriesRequest) (*dto.PackageSeriesResponse, error) { currentUserID := middleware.GetUserIDFromContext(ctx) if currentUserID == 0 { return nil, errors.New(errors.CodeUnauthorized, "未授权访问") } existing, _ := s.packageSeriesStore.GetByCode(ctx, req.SeriesCode) if existing != nil { return nil, errors.New(errors.CodeConflict, "系列编码已存在") } series := &model.PackageSeries{ SeriesCode: req.SeriesCode, SeriesName: req.SeriesName, Description: req.Description, Status: constants.StatusEnabled, OneTimeCommissionConfigJSON: "{}", } series.Creator = currentUserID if req.EnableOneTimeCommission != nil { series.EnableOneTimeCommission = *req.EnableOneTimeCommission } if req.OneTimeCommissionConfig != nil { config := s.dtoToModelConfig(req.OneTimeCommissionConfig) config.Enable = series.EnableOneTimeCommission if err := series.SetOneTimeCommissionConfig(config); err != nil { return nil, errors.Wrap(errors.CodeInternalError, err, "设置一次性佣金配置失败") } } else if series.EnableOneTimeCommission { config := &model.OneTimeCommissionConfig{Enable: true} if err := series.SetOneTimeCommissionConfig(config); err != nil { return nil, errors.Wrap(errors.CodeInternalError, err, "设置一次性佣金配置失败") } } if err := s.packageSeriesStore.Create(ctx, series); err != nil { return nil, errors.Wrap(errors.CodeInternalError, err, "创建套餐系列失败") } return s.toResponse(series), nil } func (s *Service) Get(ctx context.Context, id uint) (*dto.PackageSeriesResponse, error) { series, err := s.packageSeriesStore.GetByID(ctx, id) if err != nil { if err == gorm.ErrRecordNotFound { return nil, errors.New(errors.CodeNotFound, "套餐系列不存在") } return nil, errors.Wrap(errors.CodeInternalError, err, "获取套餐系列失败") } return s.toResponse(series), nil } func (s *Service) Update(ctx context.Context, id uint, req *dto.UpdatePackageSeriesRequest) (*dto.PackageSeriesResponse, error) { currentUserID := middleware.GetUserIDFromContext(ctx) if currentUserID == 0 { return nil, errors.New(errors.CodeUnauthorized, "未授权访问") } series, err := s.packageSeriesStore.GetByID(ctx, id) if err != nil { if err == gorm.ErrRecordNotFound { return nil, errors.New(errors.CodeNotFound, "套餐系列不存在") } return nil, errors.Wrap(errors.CodeInternalError, err, "获取套餐系列失败") } if req.SeriesName != nil { series.SeriesName = *req.SeriesName } if req.Description != nil { series.Description = *req.Description } if req.EnableOneTimeCommission != nil { series.EnableOneTimeCommission = *req.EnableOneTimeCommission } if req.OneTimeCommissionConfig != nil { config := s.dtoToModelConfig(req.OneTimeCommissionConfig) config.Enable = series.EnableOneTimeCommission if err := series.SetOneTimeCommissionConfig(config); err != nil { return nil, errors.Wrap(errors.CodeInternalError, err, "设置一次性佣金配置失败") } } else if req.EnableOneTimeCommission != nil { existingConfig, _ := series.GetOneTimeCommissionConfig() if existingConfig == nil { existingConfig = &model.OneTimeCommissionConfig{} } existingConfig.Enable = series.EnableOneTimeCommission if err := series.SetOneTimeCommissionConfig(existingConfig); err != nil { return nil, errors.Wrap(errors.CodeInternalError, err, "设置一次性佣金配置失败") } } series.Updater = currentUserID if err := s.packageSeriesStore.Update(ctx, series); err != nil { return nil, errors.Wrap(errors.CodeInternalError, err, "更新套餐系列失败") } return s.toResponse(series), nil } func (s *Service) Delete(ctx context.Context, id uint) error { _, err := s.packageSeriesStore.GetByID(ctx, id) if err != nil { if err == gorm.ErrRecordNotFound { return errors.New(errors.CodeNotFound, "套餐系列不存在") } return errors.Wrap(errors.CodeInternalError, err, "获取套餐系列失败") } if err := s.packageSeriesStore.Delete(ctx, id); err != nil { return errors.Wrap(errors.CodeInternalError, err, "删除套餐系列失败") } return nil } func (s *Service) List(ctx context.Context, req *dto.PackageSeriesListRequest) ([]*dto.PackageSeriesResponse, int64, error) { opts := &store.QueryOptions{ Page: req.Page, PageSize: req.PageSize, OrderBy: "id DESC", } if opts.Page == 0 { opts.Page = 1 } if opts.PageSize == 0 { opts.PageSize = constants.DefaultPageSize } filters := make(map[string]interface{}) if req.SeriesName != nil { filters["series_name"] = *req.SeriesName } if req.Status != nil { filters["status"] = *req.Status } if req.EnableOneTimeCommission != nil { filters["enable_one_time_commission"] = *req.EnableOneTimeCommission } // 获取用户类型,代理用户需要过滤只能看到分配给自己店铺的套餐系列 userType := middleware.GetUserTypeFromContext(ctx) if userType == constants.UserTypeAgent { shopID := middleware.GetShopIDFromContext(ctx) if shopID == 0 { // 代理用户没有店铺,返回空结果 return []*dto.PackageSeriesResponse{}, 0, nil } // 查询分配给该店铺的系列 ID allocations, err := s.shopSeriesAllocationStore.GetByShopID(ctx, shopID) if err != nil { return nil, 0, errors.Wrap(errors.CodeInternalError, err, "查询套餐系列分配失败") } if len(allocations) == 0 { // 没有分配任何套餐系列,返回空结果 return []*dto.PackageSeriesResponse{}, 0, nil } // 提取系列 ID 列表 seriesIDs := make([]uint, len(allocations)) for i, a := range allocations { seriesIDs[i] = a.SeriesID } filters["series_ids"] = seriesIDs } seriesList, total, err := s.packageSeriesStore.List(ctx, opts, filters) if err != nil { return nil, 0, errors.Wrap(errors.CodeInternalError, err, "查询套餐系列列表失败") } responses := make([]*dto.PackageSeriesResponse, len(seriesList)) for i, series := range seriesList { responses[i] = s.toResponse(series) } return responses, total, nil } func (s *Service) UpdateStatus(ctx context.Context, id uint, status int) error { currentUserID := middleware.GetUserIDFromContext(ctx) if currentUserID == 0 { return errors.New(errors.CodeUnauthorized, "未授权访问") } series, err := s.packageSeriesStore.GetByID(ctx, id) if err != nil { if err == gorm.ErrRecordNotFound { return errors.New(errors.CodeNotFound, "套餐系列不存在") } return errors.Wrap(errors.CodeInternalError, err, "获取套餐系列失败") } series.Status = status series.Updater = currentUserID if err := s.packageSeriesStore.Update(ctx, series); err != nil { return errors.Wrap(errors.CodeInternalError, err, "更新套餐系列状态失败") } return nil } func (s *Service) toResponse(series *model.PackageSeries) *dto.PackageSeriesResponse { resp := &dto.PackageSeriesResponse{ ID: series.ID, SeriesCode: series.SeriesCode, SeriesName: series.SeriesName, Description: series.Description, EnableOneTimeCommission: series.EnableOneTimeCommission, Status: series.Status, CreatedAt: series.CreatedAt.Format(time.RFC3339), UpdatedAt: series.UpdatedAt.Format(time.RFC3339), } if config, err := series.GetOneTimeCommissionConfig(); err == nil && config != nil { resp.OneTimeCommissionConfig = s.modelToDTO(config) } return resp } func (s *Service) dtoToModelConfig(dtoConfig *dto.SeriesOneTimeCommissionConfigDTO) *model.OneTimeCommissionConfig { if dtoConfig == nil { return nil } var tiers []model.OneTimeCommissionTier if len(dtoConfig.Tiers) > 0 { tiers = make([]model.OneTimeCommissionTier, len(dtoConfig.Tiers)) for i, tier := range dtoConfig.Tiers { tiers[i] = model.OneTimeCommissionTier{ Dimension: tier.Dimension, StatScope: tier.StatScope, Threshold: tier.Threshold, Amount: tier.Amount, } } } return &model.OneTimeCommissionConfig{ Enable: dtoConfig.Enable, TriggerType: dtoConfig.TriggerType, Threshold: dtoConfig.Threshold, CommissionType: dtoConfig.CommissionType, CommissionAmount: dtoConfig.CommissionAmount, Tiers: tiers, ValidityType: dtoConfig.ValidityType, ValidityValue: dtoConfig.ValidityValue, EnableForceRecharge: dtoConfig.EnableForceRecharge, ForceCalcType: dtoConfig.ForceCalcType, ForceAmount: dtoConfig.ForceAmount, } } func (s *Service) modelToDTO(config *model.OneTimeCommissionConfig) *dto.SeriesOneTimeCommissionConfigDTO { if config == nil { return nil } var tiers []dto.OneTimeCommissionTierDTO if len(config.Tiers) > 0 { tiers = make([]dto.OneTimeCommissionTierDTO, len(config.Tiers)) for i, tier := range config.Tiers { tiers[i] = dto.OneTimeCommissionTierDTO{ Dimension: tier.Dimension, StatScope: tier.StatScope, Threshold: tier.Threshold, Amount: tier.Amount, } } } return &dto.SeriesOneTimeCommissionConfigDTO{ Enable: config.Enable, TriggerType: config.TriggerType, Threshold: config.Threshold, CommissionType: config.CommissionType, CommissionAmount: config.CommissionAmount, Tiers: tiers, ValidityType: config.ValidityType, ValidityValue: config.ValidityValue, EnableForceRecharge: config.EnableForceRecharge, ForceCalcType: config.ForceCalcType, ForceAmount: config.ForceAmount, } }