diff --git a/internal/api/activity/matching_game_helper.go b/internal/api/activity/matching_game_helper.go index 652ad22..548a2e9 100755 --- a/internal/api/activity/matching_game_helper.go +++ b/internal/api/activity/matching_game_helper.go @@ -40,12 +40,12 @@ func matchingRewardDisplayName(name string, isDoubled bool) string { } type matchingSettlementPlan struct { - reward *model.ActivityRewardSettings - quantity int - productName string - rewardName string - cardToVoid int64 - drawLogID int64 + reward *model.ActivityRewardSettings + quantity int + productName string + rewardName string + cardToVoid int64 + drawLogID int64 } // grantRewardHelper 发放奖励辅助函数 @@ -59,12 +59,13 @@ func (h *handler) grantRewardHelper(ctx context.Context, userID, orderID int64, rid := r.ID _, err := h.user.GrantRewardToOrder(ctx, userID, usersvc.GrantRewardToOrderRequest{ - OrderID: orderID, - ProductID: r.ProductID, - Quantity: quantity, - ActivityID: &actID, - RewardID: &rid, - Remark: remark, + OrderID: orderID, + ProductID: r.ProductID, + Quantity: quantity, + ActivityID: &actID, + RewardID: &rid, + Remark: remark, + SkipRewardInventory: true, }) if err != nil { h.logger.Error("Failed to grant reward to order", zap.Int64("order_id", orderID), zap.Error(err)) diff --git a/internal/service/user/reward_grant.go b/internal/service/user/reward_grant.go index cba8ce9..b9bfbdf 100755 --- a/internal/service/user/reward_grant.go +++ b/internal/service/user/reward_grant.go @@ -280,12 +280,13 @@ func generateOrderNo() string { // GrantRewardToOrderRequest 在现有订单上发放奖励的请求参数 type GrantRewardToOrderRequest struct { - OrderID int64 `json:"order_id" binding:"required"` // 现有订单ID - ProductID int64 `json:"product_id" binding:"required"` // 商品ID - Quantity int `json:"quantity" binding:"min=1"` // 发放数量 - ActivityID *int64 `json:"activity_id,omitempty"` // 活动ID(可选) - RewardID *int64 `json:"reward_id,omitempty"` // 奖励配置ID(可选) - Remark string `json:"remark,omitempty"` // 备注 + OrderID int64 `json:"order_id" binding:"required"` // 现有订单ID + ProductID int64 `json:"product_id" binding:"required"` // 商品ID + Quantity int `json:"quantity" binding:"min=1"` // 发放数量 + ActivityID *int64 `json:"activity_id,omitempty"` // 活动ID(可选) + RewardID *int64 `json:"reward_id,omitempty"` // 奖励配置ID(可选) + Remark string `json:"remark,omitempty"` // 备注 + SkipRewardInventory bool `json:"-"` // 跳过活动奖项库存扣减 } // GrantRewardToOrderResponse 在现有订单上发放奖励的响应 @@ -330,18 +331,21 @@ func (s *service) GrantRewardToOrder(ctx context.Context, userID int64, req Gran if req.RewardID != nil { logger.Info("检查奖励配置", zap.Int64("reward_id", *req.RewardID)) - // 【使用乐观锁扣减库存】直接用 Quantity > 0 作为更新条件,避免竞态 - result, err := tx.ActivityRewardSettings.WithContext(ctx).Where( - tx.ActivityRewardSettings.ID.Eq(*req.RewardID), - tx.ActivityRewardSettings.Quantity.Gt(0), // 乐观锁:只有库存>0才能扣减 - ).UpdateSimple(tx.ActivityRewardSettings.Quantity.Add(-int64(req.Quantity))) - if err != nil { - logger.Error("扣减奖励库存失败", zap.Error(err)) - return fmt.Errorf("扣减奖励库存失败: %w", err) - } - if result.RowsAffected == 0 { - logger.Error("奖励库存不足或不存在") - return fmt.Errorf("奖励库存不足或不存在") + if !req.SkipRewardInventory { + // 【使用乐观锁扣减库存】直接用 Quantity > 0 作为更新条件,避免竞态 + result, err := tx.ActivityRewardSettings.WithContext(ctx).Where( + tx.ActivityRewardSettings.ID.Eq(*req.RewardID), + tx.ActivityRewardSettings.Quantity.Gt(0), // 乐观锁:只有库存>0才能扣减 + ).UpdateSimple(tx.ActivityRewardSettings.Quantity.Add(-int64(req.Quantity))) + if err != nil { + logger.Error("扣减奖励库存失败", zap.Error(err)) + return fmt.Errorf("扣减奖励库存失败: %w", err) + } + if result.RowsAffected == 0 { + logger.Error("奖励库存不足或不存在") + return fmt.Errorf("奖励库存不足或不存在") + } + logger.Info("奖励库存扣减成功(乐观锁)") } rewardSetting, err = tx.ActivityRewardSettings.WithContext(ctx).Where( tx.ActivityRewardSettings.ID.Eq(*req.RewardID), @@ -350,7 +354,6 @@ func (s *service) GrantRewardToOrder(ctx context.Context, userID int64, req Gran logger.Error("查询奖励配置失败", zap.Error(err)) return fmt.Errorf("查询奖励配置失败: %w", err) } - logger.Info("奖励库存扣减成功(乐观锁)") } // 3. 查询商品信息快照