七月迭代短暂完结,还有很多后端的关键东西没有弄,这是一版赶时间做的东西
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m26s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m26s
This commit is contained in:
@@ -57,6 +57,15 @@ type PurchaseValidationResult struct {
|
||||
}
|
||||
|
||||
func (s *Service) ValidateCardPurchase(ctx context.Context, cardID uint, packageIDs []uint) (*PurchaseValidationResult, error) {
|
||||
return s.validateCardPurchase(ctx, cardID, packageIDs, false)
|
||||
}
|
||||
|
||||
// ValidatePersonalCardPurchase 校验个人客户卡套餐购买,并允许当前世代生效中套餐续费。
|
||||
func (s *Service) ValidatePersonalCardPurchase(ctx context.Context, cardID uint, packageIDs []uint) (*PurchaseValidationResult, error) {
|
||||
return s.validateCardPurchase(ctx, cardID, packageIDs, true)
|
||||
}
|
||||
|
||||
func (s *Service) validateCardPurchase(ctx context.Context, cardID uint, packageIDs []uint, allowRenewal bool) (*PurchaseValidationResult, error) {
|
||||
card, err := s.iotCardStore.GetByID(ctx, cardID)
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
@@ -79,7 +88,11 @@ func (s *Service) ValidateCardPurchase(ctx context.Context, cardID uint, package
|
||||
sellerShopID = *card.ShopID
|
||||
}
|
||||
|
||||
packages, totalPrice, err := s.validatePackages(ctx, packageIDs, *card.SeriesID, sellerShopID)
|
||||
renewablePackageIDs, err := s.loadRenewablePackageIDs(ctx, constants.AssetWalletResourceTypeIotCard, card.ID, card.Generation, packageIDs, allowRenewal)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
packages, totalPrice, err := s.validatePackages(ctx, packageIDs, *card.SeriesID, sellerShopID, renewablePackageIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -96,6 +109,15 @@ func (s *Service) ValidateCardPurchase(ctx context.Context, cardID uint, package
|
||||
}
|
||||
|
||||
func (s *Service) ValidateDevicePurchase(ctx context.Context, deviceID uint, packageIDs []uint) (*PurchaseValidationResult, error) {
|
||||
return s.validateDevicePurchase(ctx, deviceID, packageIDs, false)
|
||||
}
|
||||
|
||||
// ValidatePersonalDevicePurchase 校验个人客户设备套餐购买,并允许当前世代生效中套餐续费。
|
||||
func (s *Service) ValidatePersonalDevicePurchase(ctx context.Context, deviceID uint, packageIDs []uint) (*PurchaseValidationResult, error) {
|
||||
return s.validateDevicePurchase(ctx, deviceID, packageIDs, true)
|
||||
}
|
||||
|
||||
func (s *Service) validateDevicePurchase(ctx context.Context, deviceID uint, packageIDs []uint, allowRenewal bool) (*PurchaseValidationResult, error) {
|
||||
device, err := s.deviceStore.GetByID(ctx, deviceID)
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
@@ -114,7 +136,11 @@ func (s *Service) ValidateDevicePurchase(ctx context.Context, deviceID uint, pac
|
||||
sellerShopID = *device.ShopID
|
||||
}
|
||||
|
||||
packages, totalPrice, err := s.validatePackages(ctx, packageIDs, *device.SeriesID, sellerShopID)
|
||||
renewablePackageIDs, err := s.loadRenewablePackageIDs(ctx, constants.AssetWalletResourceTypeDevice, device.ID, device.Generation, packageIDs, allowRenewal)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
packages, totalPrice, err := s.validatePackages(ctx, packageIDs, *device.SeriesID, sellerShopID, renewablePackageIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -133,7 +159,7 @@ func (s *Service) ValidateDevicePurchase(ctx context.Context, deviceID uint, pac
|
||||
// validatePackages 验证套餐列表是否可购买
|
||||
// sellerShopID > 0 表示代理渠道,校验该代理的 allocation.shelf_status;
|
||||
// sellerShopID == 0 表示平台自营渠道,校验 package.shelf_status
|
||||
func (s *Service) validatePackages(ctx context.Context, packageIDs []uint, seriesID uint, sellerShopID uint) ([]*model.Package, int64, error) {
|
||||
func (s *Service) validatePackages(ctx context.Context, packageIDs []uint, seriesID uint, sellerShopID uint, renewablePackageIDs map[uint]struct{}) ([]*model.Package, int64, error) {
|
||||
if len(packageIDs) == 0 {
|
||||
return nil, 0, errors.New(errors.CodeInvalidParam, "请选择至少一个套餐")
|
||||
}
|
||||
@@ -164,9 +190,10 @@ func (s *Service) validatePackages(ctx context.Context, packageIDs []uint, serie
|
||||
return nil, 0, errors.New(errors.CodeInvalidParam, "套餐已禁用")
|
||||
}
|
||||
|
||||
_, canRenewOffShelf := renewablePackageIDs[pkgID]
|
||||
if sellerShopID > 0 {
|
||||
// 代理渠道:检查上架状态并获取分配记录,使用零售价
|
||||
allocation, allocErr := s.validateAgentAllocation(ctx, sellerShopID, pkgID)
|
||||
allocation, allocErr := s.validateAgentAllocation(ctx, sellerShopID, pkgID, canRenewOffShelf)
|
||||
if allocErr != nil {
|
||||
return nil, 0, allocErr
|
||||
}
|
||||
@@ -177,7 +204,7 @@ func (s *Service) validatePackages(ctx context.Context, packageIDs []uint, serie
|
||||
}
|
||||
totalPrice += effectiveRetailPrice
|
||||
} else {
|
||||
if pkg.ShelfStatus != constants.ShelfStatusOn {
|
||||
if pkg.ShelfStatus != constants.ShelfStatusOn && !canRenewOffShelf {
|
||||
return nil, 0, errors.New(errors.CodeInvalidParam, "套餐已下架")
|
||||
}
|
||||
totalPrice += packageprice.PackageEffectiveRetailPrice(pkg)
|
||||
@@ -230,7 +257,7 @@ func (s *Service) validatePackageUsageRules(ctx context.Context, carrierType str
|
||||
}
|
||||
|
||||
// validateAgentAllocation 校验卖家代理的分配记录上架状态,并返回分配记录
|
||||
func (s *Service) validateAgentAllocation(ctx context.Context, sellerShopID, packageID uint) (*model.ShopPackageAllocation, error) {
|
||||
func (s *Service) validateAgentAllocation(ctx context.Context, sellerShopID, packageID uint, allowOffShelf bool) (*model.ShopPackageAllocation, error) {
|
||||
allocation, err := s.packageAllocationStore.GetByShopAndPackageForSystem(ctx, sellerShopID, packageID)
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
@@ -239,13 +266,44 @@ func (s *Service) validateAgentAllocation(ctx context.Context, sellerShopID, pac
|
||||
return nil, errors.Wrap(errors.CodeInternalError, err, "查询套餐分配记录失败")
|
||||
}
|
||||
|
||||
if allocation.ShelfStatus != constants.ShelfStatusOn {
|
||||
if allocation.Status != constants.StatusEnabled {
|
||||
return nil, errors.New(errors.CodeInvalidParam, "套餐已禁用")
|
||||
}
|
||||
if allocation.ShelfStatus != constants.ShelfStatusOn && !allowOffShelf {
|
||||
return nil, errors.New(errors.CodeInvalidParam, "套餐已下架")
|
||||
}
|
||||
|
||||
return allocation, nil
|
||||
}
|
||||
|
||||
func (s *Service) loadRenewablePackageIDs(ctx context.Context, assetType string, assetID uint, generation int, packageIDs []uint, allowRenewal bool) (map[uint]struct{}, error) {
|
||||
result := make(map[uint]struct{})
|
||||
if !allowRenewal || len(packageIDs) == 0 {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
query := s.db.WithContext(ctx).Model(&model.PackageUsage{}).
|
||||
Distinct("package_id").
|
||||
Where("generation = ? AND status = ? AND refund_id IS NULL AND package_id IN ?", generation, constants.PackageUsageStatusActive, packageIDs)
|
||||
switch assetType {
|
||||
case constants.AssetWalletResourceTypeIotCard:
|
||||
query = query.Where("usage_type = ? AND iot_card_id = ?", constants.PackageUsageTypeSingleCard, assetID)
|
||||
case constants.AssetWalletResourceTypeDevice:
|
||||
query = query.Where("usage_type = ? AND device_id = ?", constants.AssetWalletResourceTypeDevice, assetID)
|
||||
default:
|
||||
return nil, errors.New(errors.CodeInvalidParam)
|
||||
}
|
||||
|
||||
var ids []uint
|
||||
if err := query.Pluck("package_id", &ids).Error; err != nil {
|
||||
return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询套餐续费资格失败")
|
||||
}
|
||||
for _, id := range ids {
|
||||
result[id] = struct{}{}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetPurchasePrice 获取购买价格
|
||||
// 代理渠道(sellerShopID > 0)返回 allocation.RetailPrice,平台渠道返回 Package.SuggestedRetailPrice
|
||||
func (s *Service) GetPurchasePrice(ctx context.Context, pkg *model.Package, sellerShopID uint) (int64, error) {
|
||||
@@ -297,7 +355,7 @@ func (s *Service) ValidateAdminOfflineCardPurchase(ctx context.Context, cardID u
|
||||
return nil, errors.New(errors.CodeInvalidParam, "该卡未关联套餐系列,无法购买套餐")
|
||||
}
|
||||
|
||||
packages, totalPrice, err := s.validatePackages(ctx, packageIDs, *card.SeriesID, 0)
|
||||
packages, totalPrice, err := s.validatePackages(ctx, packageIDs, *card.SeriesID, 0, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -328,7 +386,7 @@ func (s *Service) ValidateAdminOfflineDevicePurchase(ctx context.Context, device
|
||||
return nil, errors.New(errors.CodeInvalidParam, "该设备未关联套餐系列,无法购买套餐")
|
||||
}
|
||||
|
||||
packages, totalPrice, err := s.validatePackages(ctx, packageIDs, *device.SeriesID, 0)
|
||||
packages, totalPrice, err := s.validatePackages(ctx, packageIDs, *device.SeriesID, 0, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user