package user import ( "context" "time" "bindbox-game/internal/repository/mysql/model" "gorm.io/gorm" ) func (s *service) AddCoupon(ctx context.Context, userID int64, couponID int64) error { tpl, err := s.readDB.SystemCoupons.WithContext(ctx).Where(s.readDB.SystemCoupons.ID.Eq(couponID)).First() if err != nil { return err } if tpl == nil || tpl.Status != 1 { return nil } // 配额检查:若 TotalQuantity > 0 则限制发放总量 if tpl.TotalQuantity > 0 { issued, ierr := s.readDB.UserCoupons.WithContext(ctx).Where(s.readDB.UserCoupons.CouponID.Eq(couponID)).Count() if ierr != nil { return ierr } if issued >= tpl.TotalQuantity { return gorm.ErrInvalidData } } // 用户持有上限:同模板未使用的数量最多1张 exist, eerr := s.readDB.UserCoupons.WithContext(ctx). Where(s.readDB.UserCoupons.UserID.Eq(userID)). Where(s.readDB.UserCoupons.CouponID.Eq(couponID)). Where(s.readDB.UserCoupons.Status.Eq(1)). Count() if eerr != nil { return eerr } if exist > 0 { return gorm.ErrInvalidData } item := &model.UserCoupons{UserID: userID, CouponID: couponID, Status: 1} if !tpl.ValidStart.IsZero() { item.ValidStart = tpl.ValidStart } else { item.ValidStart = time.Now() } if !tpl.ValidEnd.IsZero() { item.ValidEnd = tpl.ValidEnd } do := s.writeDB.UserCoupons.WithContext(ctx).Omit(s.readDB.UserCoupons.UsedAt, s.readDB.UserCoupons.UsedOrderID) if tpl.ValidEnd.IsZero() { do = do.Omit(s.writeDB.UserCoupons.ValidEnd) } return do.Create(item) }