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 } func New(packageSeriesStore *postgres.PackageSeriesStore) *Service { return &Service{packageSeriesStore: packageSeriesStore} } 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.OneTimeCommissionConfig != nil { config := s.dtoToModelConfig(req.OneTimeCommissionConfig) 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.OneTimeCommissionConfig != nil { config := s.dtoToModelConfig(req.OneTimeCommissionConfig) if err := series.SetOneTimeCommissionConfig(config); 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 } 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, } }