package purchase_validation import ( "context" "github.com/break/junhong_cmp_fiber/internal/model" "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" "gorm.io/gorm" ) type Service struct { db *gorm.DB iotCardStore *postgres.IotCardStore deviceStore *postgres.DeviceStore packageStore *postgres.PackageStore seriesAllocationStore *postgres.ShopSeriesAllocationStore } func New( db *gorm.DB, iotCardStore *postgres.IotCardStore, deviceStore *postgres.DeviceStore, packageStore *postgres.PackageStore, seriesAllocationStore *postgres.ShopSeriesAllocationStore, ) *Service { return &Service{ db: db, iotCardStore: iotCardStore, deviceStore: deviceStore, packageStore: packageStore, seriesAllocationStore: seriesAllocationStore, } } type PurchaseValidationResult struct { Card *model.IotCard Device *model.Device Packages []*model.Package TotalPrice int64 Allocation *model.ShopSeriesAllocation } func (s *Service) ValidateCardPurchase(ctx context.Context, cardID uint, packageIDs []uint) (*PurchaseValidationResult, error) { card, err := s.iotCardStore.GetByID(ctx, cardID) if err != nil { if err == gorm.ErrRecordNotFound { return nil, errors.New(errors.CodeIotCardNotFound, "IoT卡不存在") } return nil, err } if card.SeriesAllocationID == nil || *card.SeriesAllocationID == 0 { return nil, errors.New(errors.CodeInvalidParam, "该卡未关联套餐系列,无法购买套餐") } allocation, err := s.seriesAllocationStore.GetByID(ctx, *card.SeriesAllocationID) if err != nil { if err == gorm.ErrRecordNotFound { return nil, errors.New(errors.CodeInvalidParam, "套餐系列分配不存在") } return nil, err } if allocation.Status != constants.StatusEnabled { return nil, errors.New(errors.CodeInvalidParam, "套餐系列分配已禁用") } packages, totalPrice, err := s.validatePackages(ctx, packageIDs, allocation.SeriesID) if err != nil { return nil, err } return &PurchaseValidationResult{ Card: card, Packages: packages, TotalPrice: totalPrice, Allocation: allocation, }, nil } func (s *Service) ValidateDevicePurchase(ctx context.Context, deviceID uint, packageIDs []uint) (*PurchaseValidationResult, error) { device, err := s.deviceStore.GetByID(ctx, deviceID) if err != nil { if err == gorm.ErrRecordNotFound { return nil, errors.New(errors.CodeNotFound, "设备不存在") } return nil, err } if device.SeriesAllocationID == nil || *device.SeriesAllocationID == 0 { return nil, errors.New(errors.CodeInvalidParam, "该设备未关联套餐系列,无法购买套餐") } allocation, err := s.seriesAllocationStore.GetByID(ctx, *device.SeriesAllocationID) if err != nil { if err == gorm.ErrRecordNotFound { return nil, errors.New(errors.CodeInvalidParam, "套餐系列分配不存在") } return nil, err } if allocation.Status != constants.StatusEnabled { return nil, errors.New(errors.CodeInvalidParam, "套餐系列分配已禁用") } packages, totalPrice, err := s.validatePackages(ctx, packageIDs, allocation.SeriesID) if err != nil { return nil, err } return &PurchaseValidationResult{ Device: device, Packages: packages, TotalPrice: totalPrice, Allocation: allocation, }, nil } func (s *Service) validatePackages(ctx context.Context, packageIDs []uint, seriesID uint) ([]*model.Package, int64, error) { if len(packageIDs) == 0 { return nil, 0, errors.New(errors.CodeInvalidParam, "请选择至少一个套餐") } var packages []*model.Package var totalPrice int64 for _, pkgID := range packageIDs { pkg, err := s.packageStore.GetByID(ctx, pkgID) if err != nil { if err == gorm.ErrRecordNotFound { return nil, 0, errors.New(errors.CodeInvalidParam, "套餐不存在") } return nil, 0, err } if pkg.SeriesID != seriesID { return nil, 0, errors.New(errors.CodeInvalidParam, "套餐不在可购买范围内") } if pkg.Status != constants.StatusEnabled { return nil, 0, errors.New(errors.CodeInvalidParam, "套餐已禁用") } if pkg.ShelfStatus != constants.ShelfStatusOn { return nil, 0, errors.New(errors.CodeInvalidParam, "套餐已下架") } packages = append(packages, pkg) totalPrice += pkg.SuggestedRetailPrice } return packages, totalPrice, nil } func (s *Service) GetPurchasePrice(ctx context.Context, pkg *model.Package, buyerType string) int64 { return pkg.SuggestedRetailPrice }