This commit is contained in:
@@ -153,32 +153,18 @@ func (l *PurchaseLogic) Purchase(req *types.PurchaseOrderRequest) (resp *types.P
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SubscribeOutOfStock), "subscribe out of stock")
|
||||
}
|
||||
|
||||
var discount float64 = 1
|
||||
isNewUserForDiscount := time.Since(u.CreatedAt) <= 24*time.Hour
|
||||
if isNewUserForDiscount && sub.Discount != "" {
|
||||
// If the matched tier is new_user_only, check whether the user has already purchased this plan.
|
||||
// If so, they are not eligible for the new-user discount (but the order is still allowed).
|
||||
var dis []types.SubscribeDiscount
|
||||
_ = json.Unmarshal([]byte(sub.Discount), &dis)
|
||||
if isNewUserOnlyForQuantity(dis, req.Quantity) {
|
||||
var historyCount int64
|
||||
if e := l.svcCtx.DB.Model(&order.Order{}).
|
||||
Where("user_id = ? AND subscribe_id = ? AND type = 1 AND status IN ?",
|
||||
u.Id, targetSubscribeID, []int{2, 5}).
|
||||
Count(&historyCount).Error; e != nil {
|
||||
l.Errorw("[Purchase] Database query error checking new user discount eligibility",
|
||||
logger.Field("error", e.Error()), logger.Field("user_id", u.Id))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "check new user discount history error: %v", e.Error())
|
||||
}
|
||||
if historyCount >= 1 {
|
||||
isNewUserForDiscount = false
|
||||
}
|
||||
}
|
||||
newUserDiscount, err := resolveNewUserDiscountEligibility(l.ctx, l.svcCtx.DB, u.Id, targetSubscribeID, req.Quantity, sub.Discount)
|
||||
if err != nil {
|
||||
l.Errorw("[Purchase] Database query error resolving new user eligibility",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("user_id", u.Id),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
if sub.Discount != "" {
|
||||
var dis []types.SubscribeDiscount
|
||||
_ = json.Unmarshal([]byte(sub.Discount), &dis)
|
||||
discount = getDiscount(dis, req.Quantity, isNewUserForDiscount)
|
||||
|
||||
var discount float64 = 1
|
||||
if len(newUserDiscount.Discounts) > 0 {
|
||||
discount = getDiscount(newUserDiscount.Discounts, req.Quantity, newUserDiscount.EligibleForDiscount)
|
||||
}
|
||||
price := sub.UnitPrice * req.Quantity
|
||||
// discount amount
|
||||
@@ -272,23 +258,23 @@ func (l *PurchaseLogic) Purchase(req *types.PurchaseOrderRequest) (resp *types.P
|
||||
UserId: u.Id,
|
||||
SubscriptionUserId: entitlement.EffectiveUserID,
|
||||
ParentId: parentOrderID,
|
||||
OrderNo: tool.GenerateTradeNo(),
|
||||
Type: orderType,
|
||||
Quantity: req.Quantity,
|
||||
Price: price,
|
||||
Amount: amount,
|
||||
Discount: discountAmount,
|
||||
GiftAmount: deductionAmount,
|
||||
Coupon: req.Coupon,
|
||||
CouponDiscount: coupon,
|
||||
PaymentId: payment.Id,
|
||||
Method: canonicalOrderMethod(payment.Platform),
|
||||
FeeAmount: feeAmount,
|
||||
Status: 1,
|
||||
IsNew: isNew,
|
||||
SubscribeId: targetSubscribeID,
|
||||
SubscribeToken: subscribeToken,
|
||||
AppAccountToken: uuid.New().String(),
|
||||
OrderNo: tool.GenerateTradeNo(),
|
||||
Type: orderType,
|
||||
Quantity: req.Quantity,
|
||||
Price: price,
|
||||
Amount: amount,
|
||||
Discount: discountAmount,
|
||||
GiftAmount: deductionAmount,
|
||||
Coupon: req.Coupon,
|
||||
CouponDiscount: coupon,
|
||||
PaymentId: payment.Id,
|
||||
Method: canonicalOrderMethod(payment.Platform),
|
||||
FeeAmount: feeAmount,
|
||||
Status: 1,
|
||||
IsNew: isNew,
|
||||
SubscribeId: targetSubscribeID,
|
||||
SubscribeToken: subscribeToken,
|
||||
AppAccountToken: uuid.New().String(),
|
||||
}
|
||||
if isSingleModeRenewal {
|
||||
l.Infow("[Purchase] single mode purchase order created as renewal",
|
||||
@@ -320,20 +306,21 @@ func (l *PurchaseLogic) Purchase(req *types.PurchaseOrderRequest) (resp *types.P
|
||||
}
|
||||
}
|
||||
|
||||
// check new user only restriction inside transaction to prevent race condition (tier-level only)
|
||||
// Only block users who registered more than 24h ago; users within 24h who already purchased
|
||||
// are allowed to place another order (they just won't receive the new-user discount).
|
||||
if orderInfo.Type == 1 {
|
||||
var txNewUserOnly bool
|
||||
if sub.Discount != "" {
|
||||
var dis []types.SubscribeDiscount
|
||||
_ = json.Unmarshal([]byte(sub.Discount), &dis)
|
||||
txNewUserOnly = isNewUserOnlyForQuantity(dis, orderInfo.Quantity)
|
||||
// Re-check new-user-only restriction inside the transaction to prevent race conditions.
|
||||
if orderInfo.Type == 1 && newUserDiscount.NewUserOnly {
|
||||
txNewUserDiscount, txErr := resolveNewUserDiscountEligibility(
|
||||
l.ctx,
|
||||
db,
|
||||
u.Id,
|
||||
targetSubscribeID,
|
||||
orderInfo.Quantity,
|
||||
sub.Discount,
|
||||
)
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
if txNewUserOnly {
|
||||
if time.Since(u.CreatedAt) > 24*time.Hour {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.SubscribeNewUserOnly), "not a new user")
|
||||
}
|
||||
if !txNewUserDiscount.WithinWindow {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.SubscribeNewUserOnly), "not a new user")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user