115 lines
3.5 KiB
Go
115 lines
3.5 KiB
Go
package user
|
|
|
|
import (
|
|
"bindbox-game/internal/repository/mysql/dao"
|
|
"bindbox-game/internal/repository/mysql/model"
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
// RecordOrderCouponUsage 记录订单使用的用户券与本次抵扣金额
|
|
func (s *service) RecordOrderCouponUsage(ctx context.Context, orderID int64, userCouponID int64, appliedAmount int64) error {
|
|
if orderID <= 0 || userCouponID <= 0 || appliedAmount <= 0 {
|
|
return nil
|
|
}
|
|
return s.repo.GetDbW().Exec("INSERT INTO order_coupons (order_id, user_coupon_id, applied_amount, created_at) VALUES (?,?,?,NOW(3))", orderID, userCouponID, appliedAmount).Error
|
|
}
|
|
|
|
// DeductCouponsForPaidOrder 支付成功后扣减金额券余额或核销一次性券
|
|
func (s *service) DeductCouponsForPaidOrder(ctx context.Context, tx *dao.Query, userID int64, orderID int64, paidAt time.Time) error {
|
|
type row struct {
|
|
UserCouponID int64
|
|
AppliedAmount int64
|
|
Status int32
|
|
UsedOrderID int64
|
|
DiscountType int32
|
|
}
|
|
var rows []row
|
|
|
|
// 确定使用的数据库查询对象
|
|
db := s.writeDB
|
|
if tx != nil {
|
|
db = tx
|
|
}
|
|
readDb := s.readDB
|
|
if tx != nil {
|
|
readDb = tx
|
|
}
|
|
|
|
// 1. 获取该订单关联的所有优惠券使用记录
|
|
_ = readDb.OrderCoupons.WithContext(ctx).UnderlyingDB().Raw("SELECT oc.user_coupon_id AS user_coupon_id, oc.applied_amount AS applied_amount, uc.status AS status, uc.used_order_id AS used_order_id, sc.discount_type AS discount_type FROM order_coupons oc JOIN user_coupons uc ON uc.id=oc.user_coupon_id JOIN system_coupons sc ON sc.id=uc.coupon_id WHERE oc.order_id=?", orderID).Scan(&rows).Error
|
|
|
|
for _, r := range rows {
|
|
// 幂等校验:已核销且绑定本订单,则跳过
|
|
if r.Status == 2 && r.UsedOrderID == orderID {
|
|
continue
|
|
}
|
|
|
|
var currentBal int64
|
|
var ucUserID int64
|
|
uc, err := readDb.UserCoupons.WithContext(ctx).Where(readDb.UserCoupons.ID.Eq(r.UserCouponID)).First()
|
|
if err != nil || uc == nil {
|
|
continue // 或记录日志
|
|
}
|
|
currentBal = uc.BalanceAmount
|
|
ucUserID = uc.UserID
|
|
|
|
if r.DiscountType == 1 { // 金额券:按量扣减
|
|
nb := currentBal - r.AppliedAmount
|
|
if nb < 0 {
|
|
nb = 0
|
|
}
|
|
|
|
upd := map[string]any{
|
|
"balance_amount": nb,
|
|
"used_order_id": orderID,
|
|
"used_at": paidAt,
|
|
}
|
|
if nb == 0 {
|
|
upd["status"] = 2 // 余额扣完,标记为已完成
|
|
}
|
|
|
|
_, err = db.UserCoupons.WithContext(ctx).Where(db.UserCoupons.ID.Eq(r.UserCouponID)).Updates(upd)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to update user coupon balance: %w", err)
|
|
}
|
|
|
|
// 记录账变流水
|
|
ledger := &model.UserCouponLedger{
|
|
UserID: ucUserID,
|
|
UserCouponID: r.UserCouponID,
|
|
ChangeAmount: -r.AppliedAmount,
|
|
BalanceAfter: nb,
|
|
OrderID: orderID,
|
|
Action: "apply",
|
|
CreatedAt: time.Now(),
|
|
}
|
|
_ = db.UserCouponLedger.WithContext(ctx).Create(ledger)
|
|
|
|
} else { // 满减/折扣券:一次性核销
|
|
_, err = db.UserCoupons.WithContext(ctx).Where(db.UserCoupons.ID.Eq(r.UserCouponID)).Updates(map[string]any{
|
|
"status": 2,
|
|
"used_order_id": orderID,
|
|
"used_at": paidAt,
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("failed to verify user coupon: %w", err)
|
|
}
|
|
|
|
// 记录账变流水
|
|
ledger := &model.UserCouponLedger{
|
|
UserID: ucUserID,
|
|
UserCouponID: r.UserCouponID,
|
|
ChangeAmount: -r.AppliedAmount,
|
|
BalanceAfter: 0,
|
|
OrderID: orderID,
|
|
Action: "apply",
|
|
CreatedAt: time.Now(),
|
|
}
|
|
_ = db.UserCouponLedger.WithContext(ctx).Create(ledger)
|
|
}
|
|
}
|
|
return nil
|
|
}
|