package user import ( "context" "time" "bindbox-game/internal/repository/mysql/model" ) // 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, userID int64, orderID int64, paidAt time.Time) error { type row struct { UserCouponID int64 AppliedAmount int64 Status int32 UsedOrderID int64 DiscountType int32 } var rows []row // 若结构表不存在或无数据,不报错(由调用方做降级处理) _ = s.repo.GetDbR().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 } if r.DiscountType == 1 { // 金额券 var bal int64 _ = s.repo.GetDbR().Raw("SELECT COALESCE(balance_amount,0) FROM user_coupons WHERE id=?", r.UserCouponID).Scan(&bal).Error nb := bal - r.AppliedAmount if nb < 0 { nb = 0 } if nb == 0 { _ = s.repo.GetDbW().Exec("UPDATE user_coupons SET balance_amount=?, status=2, used_order_id=?, used_at=? WHERE id=?", nb, orderID, paidAt, r.UserCouponID).Error } else { _ = s.repo.GetDbW().Exec("UPDATE user_coupons SET balance_amount=?, used_order_id=?, used_at=? WHERE id=?", nb, orderID, paidAt, r.UserCouponID).Error } var uid int64 _ = s.repo.GetDbR().Raw("SELECT user_id FROM user_coupons WHERE id=?", r.UserCouponID).Scan(&uid).Error ledger := &model.UserCouponLedger{ UserID: uid, UserCouponID: r.UserCouponID, ChangeAmount: -r.AppliedAmount, BalanceAfter: nb, OrderID: orderID, Action: "apply", CreatedAt: time.Now(), } _ = s.repo.GetDbW().Create(ledger).Error } else { // 满减/折扣券:一次性核销 _ = s.repo.GetDbW().Exec("UPDATE user_coupons SET status=2, used_order_id=?, used_at=? WHERE id=?", orderID, paidAt, r.UserCouponID).Error var uid int64 _ = s.repo.GetDbR().Raw("SELECT user_id FROM user_coupons WHERE id=?", r.UserCouponID).Scan(&uid).Error ledger := &model.UserCouponLedger{ UserID: uid, UserCouponID: r.UserCouponID, ChangeAmount: -r.AppliedAmount, BalanceAfter: 0, OrderID: orderID, Action: "apply", CreatedAt: time.Now(), } _ = s.repo.GetDbW().Create(ledger).Error } } return nil }