fix: scope coupons by tenant
This commit is contained in:
@@ -2,11 +2,14 @@ package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"quyun/v2/app/errorx"
|
||||
coupon_dto "quyun/v2/app/http/v1/dto"
|
||||
"quyun/v2/database/models"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// @provider
|
||||
@@ -14,6 +17,7 @@ type coupon struct{}
|
||||
|
||||
func (s *coupon) ListUserCoupons(
|
||||
ctx context.Context,
|
||||
tenantID int64,
|
||||
userID int64,
|
||||
status string,
|
||||
) ([]coupon_dto.UserCouponItem, error) {
|
||||
@@ -32,11 +36,41 @@ func (s *coupon) ListUserCoupons(
|
||||
if err != nil {
|
||||
return nil, errorx.ErrDatabaseError.WithCause(err)
|
||||
}
|
||||
if len(list) == 0 {
|
||||
return []coupon_dto.UserCouponItem{}, nil
|
||||
}
|
||||
|
||||
var res []coupon_dto.UserCouponItem
|
||||
couponIDSet := make(map[int64]struct{}, len(list))
|
||||
couponIDs := make([]int64, 0, len(list))
|
||||
for _, v := range list {
|
||||
c, _ := models.CouponQuery.WithContext(ctx).Where(models.CouponQuery.ID.Eq(v.CouponID)).First()
|
||||
if _, ok := couponIDSet[v.CouponID]; ok {
|
||||
continue
|
||||
}
|
||||
couponIDs = append(couponIDs, v.CouponID)
|
||||
couponIDSet[v.CouponID] = struct{}{}
|
||||
}
|
||||
|
||||
cTbl, cQ := models.CouponQuery.QueryContext(ctx)
|
||||
cQ = cQ.Where(cTbl.ID.In(couponIDs...))
|
||||
if tenantID > 0 {
|
||||
cQ = cQ.Where(cTbl.TenantID.Eq(tenantID))
|
||||
}
|
||||
coupons, err := cQ.Find()
|
||||
if err != nil {
|
||||
return nil, errorx.ErrDatabaseError.WithCause(err)
|
||||
}
|
||||
|
||||
couponMap := make(map[int64]*models.Coupon, len(coupons))
|
||||
for _, c := range coupons {
|
||||
couponMap[c.ID] = c
|
||||
}
|
||||
|
||||
res := make([]coupon_dto.UserCouponItem, 0, len(list))
|
||||
for _, v := range list {
|
||||
c, ok := couponMap[v.CouponID]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
item := coupon_dto.UserCouponItem{
|
||||
ID: v.ID,
|
||||
CouponID: v.CouponID,
|
||||
@@ -61,7 +95,7 @@ func (s *coupon) ListUserCoupons(
|
||||
}
|
||||
|
||||
// Validate checks if a coupon can be used for an order and returns the discount amount
|
||||
func (s *coupon) Validate(ctx context.Context, userID, userCouponID, amount int64) (int64, error) {
|
||||
func (s *coupon) Validate(ctx context.Context, tenantID, userID, userCouponID, amount int64) (int64, error) {
|
||||
uc, err := models.UserCouponQuery.WithContext(ctx).Where(models.UserCouponQuery.ID.Eq(userCouponID)).First()
|
||||
if err != nil {
|
||||
return 0, errorx.ErrRecordNotFound.WithMsg("优惠券不存在")
|
||||
@@ -77,6 +111,9 @@ func (s *coupon) Validate(ctx context.Context, userID, userCouponID, amount int6
|
||||
if err != nil {
|
||||
return 0, errorx.ErrRecordNotFound.WithMsg("优惠券信息缺失")
|
||||
}
|
||||
if tenantID > 0 && c.TenantID != tenantID {
|
||||
return 0, errorx.ErrForbidden.WithMsg("优惠券租户不匹配")
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
if !c.StartAt.IsZero() && now.Before(c.StartAt) {
|
||||
@@ -109,7 +146,29 @@ func (s *coupon) Validate(ctx context.Context, userID, userCouponID, amount int6
|
||||
}
|
||||
|
||||
// MarkUsed marks a user coupon as used (intended to be called inside a transaction)
|
||||
func (s *coupon) MarkUsed(ctx context.Context, tx *models.Query, userCouponID, orderID int64) error {
|
||||
func (s *coupon) MarkUsed(ctx context.Context, tx *models.Query, tenantID, userCouponID, orderID int64) error {
|
||||
uc, err := tx.UserCoupon.WithContext(ctx).Where(tx.UserCoupon.ID.Eq(userCouponID)).First()
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errorx.ErrRecordNotFound.WithMsg("优惠券不存在")
|
||||
}
|
||||
return errorx.ErrDatabaseError.WithCause(err)
|
||||
}
|
||||
if uc.Status != "unused" {
|
||||
return errorx.ErrBusinessLogic.WithMsg("优惠券核销失败")
|
||||
}
|
||||
|
||||
c, err := tx.Coupon.WithContext(ctx).Where(tx.Coupon.ID.Eq(uc.CouponID)).First()
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errorx.ErrRecordNotFound.WithMsg("优惠券信息缺失")
|
||||
}
|
||||
return errorx.ErrDatabaseError.WithCause(err)
|
||||
}
|
||||
if tenantID > 0 && c.TenantID != tenantID {
|
||||
return errorx.ErrForbidden.WithMsg("优惠券租户不匹配")
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
// Update User Coupon
|
||||
info, err := tx.UserCoupon.WithContext(ctx).
|
||||
@@ -127,8 +186,6 @@ func (s *coupon) MarkUsed(ctx context.Context, tx *models.Query, userCouponID, o
|
||||
}
|
||||
|
||||
// Update Coupon used quantity (Optional, but good for stats)
|
||||
// We need CouponID from uc
|
||||
uc, _ := tx.UserCoupon.WithContext(ctx).Where(tx.UserCoupon.ID.Eq(userCouponID)).First()
|
||||
_, _ = tx.Coupon.WithContext(ctx).Where(tx.Coupon.ID.Eq(uc.CouponID)).UpdateSimple(tx.Coupon.UsedQuantity.Add(1))
|
||||
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user