package packagepkg import ( "context" "fmt" "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 { packageStore *postgres.PackageStore packageSeriesStore *postgres.PackageSeriesStore } func New(packageStore *postgres.PackageStore, packageSeriesStore *postgres.PackageSeriesStore) *Service { return &Service{ packageStore: packageStore, packageSeriesStore: packageSeriesStore, } } func (s *Service) Create(ctx context.Context, req *dto.CreatePackageRequest) (*dto.PackageResponse, error) { currentUserID := middleware.GetUserIDFromContext(ctx) if currentUserID == 0 { return nil, errors.New(errors.CodeUnauthorized, "未授权访问") } existing, _ := s.packageStore.GetByCode(ctx, req.PackageCode) if existing != nil { return nil, errors.New(errors.CodeConflict, "套餐编码已存在") } if req.SeriesID != nil && *req.SeriesID > 0 { _, err := s.packageSeriesStore.GetByID(ctx, *req.SeriesID) if err != nil { if err == gorm.ErrRecordNotFound { return nil, errors.New(errors.CodeNotFound, "套餐系列不存在") } return nil, fmt.Errorf("获取套餐系列失败: %w", err) } } pkg := &model.Package{ PackageCode: req.PackageCode, PackageName: req.PackageName, PackageType: req.PackageType, DurationMonths: req.DurationMonths, Price: req.Price, Status: constants.StatusEnabled, ShelfStatus: 2, } if req.SeriesID != nil { pkg.SeriesID = *req.SeriesID } if req.DataType != nil { pkg.DataType = *req.DataType } if req.RealDataMB != nil { pkg.RealDataMB = *req.RealDataMB } if req.VirtualDataMB != nil { pkg.VirtualDataMB = *req.VirtualDataMB } if req.DataAmountMB != nil { pkg.DataAmountMB = *req.DataAmountMB } if req.SuggestedCostPrice != nil { pkg.SuggestedCostPrice = *req.SuggestedCostPrice } if req.SuggestedRetailPrice != nil { pkg.SuggestedRetailPrice = *req.SuggestedRetailPrice } pkg.Creator = currentUserID if err := s.packageStore.Create(ctx, pkg); err != nil { return nil, fmt.Errorf("创建套餐失败: %w", err) } return s.toResponse(pkg), nil } func (s *Service) Get(ctx context.Context, id uint) (*dto.PackageResponse, error) { pkg, err := s.packageStore.GetByID(ctx, id) if err != nil { if err == gorm.ErrRecordNotFound { return nil, errors.New(errors.CodeNotFound, "套餐不存在") } return nil, fmt.Errorf("获取套餐失败: %w", err) } return s.toResponse(pkg), nil } func (s *Service) Update(ctx context.Context, id uint, req *dto.UpdatePackageRequest) (*dto.PackageResponse, error) { currentUserID := middleware.GetUserIDFromContext(ctx) if currentUserID == 0 { return nil, errors.New(errors.CodeUnauthorized, "未授权访问") } pkg, err := s.packageStore.GetByID(ctx, id) if err != nil { if err == gorm.ErrRecordNotFound { return nil, errors.New(errors.CodeNotFound, "套餐不存在") } return nil, fmt.Errorf("获取套餐失败: %w", err) } if req.SeriesID != nil && *req.SeriesID > 0 { _, err := s.packageSeriesStore.GetByID(ctx, *req.SeriesID) if err != nil { if err == gorm.ErrRecordNotFound { return nil, errors.New(errors.CodeNotFound, "套餐系列不存在") } return nil, fmt.Errorf("获取套餐系列失败: %w", err) } pkg.SeriesID = *req.SeriesID } if req.PackageName != nil { pkg.PackageName = *req.PackageName } if req.PackageType != nil { pkg.PackageType = *req.PackageType } if req.DurationMonths != nil { pkg.DurationMonths = *req.DurationMonths } if req.DataType != nil { pkg.DataType = *req.DataType } if req.RealDataMB != nil { pkg.RealDataMB = *req.RealDataMB } if req.VirtualDataMB != nil { pkg.VirtualDataMB = *req.VirtualDataMB } if req.DataAmountMB != nil { pkg.DataAmountMB = *req.DataAmountMB } if req.Price != nil { pkg.Price = *req.Price } if req.SuggestedCostPrice != nil { pkg.SuggestedCostPrice = *req.SuggestedCostPrice } if req.SuggestedRetailPrice != nil { pkg.SuggestedRetailPrice = *req.SuggestedRetailPrice } pkg.Updater = currentUserID if err := s.packageStore.Update(ctx, pkg); err != nil { return nil, fmt.Errorf("更新套餐失败: %w", err) } return s.toResponse(pkg), nil } func (s *Service) Delete(ctx context.Context, id uint) error { _, err := s.packageStore.GetByID(ctx, id) if err != nil { if err == gorm.ErrRecordNotFound { return errors.New(errors.CodeNotFound, "套餐不存在") } return fmt.Errorf("获取套餐失败: %w", err) } if err := s.packageStore.Delete(ctx, id); err != nil { return fmt.Errorf("删除套餐失败: %w", err) } return nil } func (s *Service) List(ctx context.Context, req *dto.PackageListRequest) ([]*dto.PackageResponse, 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.PackageName != nil { filters["package_name"] = *req.PackageName } if req.SeriesID != nil { filters["series_id"] = *req.SeriesID } if req.Status != nil { filters["status"] = *req.Status } if req.ShelfStatus != nil { filters["shelf_status"] = *req.ShelfStatus } if req.PackageType != nil { filters["package_type"] = *req.PackageType } packages, total, err := s.packageStore.List(ctx, opts, filters) if err != nil { return nil, 0, fmt.Errorf("查询套餐列表失败: %w", err) } responses := make([]*dto.PackageResponse, len(packages)) for i, pkg := range packages { responses[i] = s.toResponse(pkg) } 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, "未授权访问") } pkg, err := s.packageStore.GetByID(ctx, id) if err != nil { if err == gorm.ErrRecordNotFound { return errors.New(errors.CodeNotFound, "套餐不存在") } return fmt.Errorf("获取套餐失败: %w", err) } pkg.Status = status pkg.Updater = currentUserID if status == constants.StatusDisabled { pkg.ShelfStatus = 2 } if err := s.packageStore.Update(ctx, pkg); err != nil { return fmt.Errorf("更新套餐状态失败: %w", err) } return nil } func (s *Service) UpdateShelfStatus(ctx context.Context, id uint, shelfStatus int) error { currentUserID := middleware.GetUserIDFromContext(ctx) if currentUserID == 0 { return errors.New(errors.CodeUnauthorized, "未授权访问") } pkg, err := s.packageStore.GetByID(ctx, id) if err != nil { if err == gorm.ErrRecordNotFound { return errors.New(errors.CodeNotFound, "套餐不存在") } return fmt.Errorf("获取套餐失败: %w", err) } if shelfStatus == 1 && pkg.Status == constants.StatusDisabled { return errors.New(errors.CodeInvalidStatus, "禁用的套餐不能上架,请先启用") } pkg.ShelfStatus = shelfStatus pkg.Updater = currentUserID if err := s.packageStore.Update(ctx, pkg); err != nil { return fmt.Errorf("更新套餐上架状态失败: %w", err) } return nil } func (s *Service) toResponse(pkg *model.Package) *dto.PackageResponse { var seriesID *uint if pkg.SeriesID > 0 { seriesID = &pkg.SeriesID } return &dto.PackageResponse{ ID: pkg.ID, PackageCode: pkg.PackageCode, PackageName: pkg.PackageName, SeriesID: seriesID, PackageType: pkg.PackageType, DurationMonths: pkg.DurationMonths, DataType: pkg.DataType, RealDataMB: pkg.RealDataMB, VirtualDataMB: pkg.VirtualDataMB, DataAmountMB: pkg.DataAmountMB, Price: pkg.Price, SuggestedCostPrice: pkg.SuggestedCostPrice, SuggestedRetailPrice: pkg.SuggestedRetailPrice, Status: pkg.Status, ShelfStatus: pkg.ShelfStatus, CreatedAt: pkg.CreatedAt.Format(time.RFC3339), UpdatedAt: pkg.UpdatedAt.Format(time.RFC3339), } }