bindbox-game/internal/service/user/coupon_transfer.go

100 lines
2.4 KiB
Go
Executable File

package user
import (
"context"
"errors"
"fmt"
"time"
"bindbox-game/internal/repository/mysql/model"
"gorm.io/gorm"
)
// TransferCoupon 转赠优惠券给另一个用户
// fromUserID: 发送方用户ID
// toUserID: 接收方用户ID
// userCouponID: 用户持有的优惠券记录ID
func (s *service) TransferCoupon(ctx context.Context, fromUserID, toUserID, userCouponID int64) error {
if fromUserID <= 0 || toUserID <= 0 || userCouponID <= 0 {
return fmt.Errorf("invalid_params")
}
if fromUserID == toUserID {
return fmt.Errorf("cannot_transfer_to_self")
}
// 1. 校验发送方持有该优惠券
uc, err := s.readDB.UserCoupons.WithContext(ctx).
Where(s.readDB.UserCoupons.ID.Eq(userCouponID)).
Where(s.readDB.UserCoupons.UserID.Eq(fromUserID)).
First()
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return fmt.Errorf("coupon_not_found")
}
return err
}
// 2. 校验优惠券状态为可用
if uc.Status != 1 {
return fmt.Errorf("coupon_not_available")
}
// 3. 校验接收方用户存在
_, err = s.readDB.Users.WithContext(ctx).Where(s.readDB.Users.ID.Eq(toUserID)).First()
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return fmt.Errorf("receiver_not_found")
}
return err
}
// 4. 执行转赠:更新 user_id
db := s.repo.GetDbW()
err = db.Transaction(func(tx *gorm.DB) error {
// 更新优惠券归属
if err := tx.Model(&model.UserCoupons{}).
Where("id = ? AND user_id = ? AND status = 1", userCouponID, fromUserID).
Update("user_id", toUserID).Error; err != nil {
return err
}
// 记录转出日志
transferOutLog := &model.UserCouponLedger{
UserID: fromUserID,
UserCouponID: userCouponID,
ChangeAmount: 0, // 转赠不涉及金额变动
BalanceAfter: uc.BalanceAmount,
OrderID: 0,
Action: "transfer_out",
CreatedAt: time.Now(),
}
if err := tx.Create(transferOutLog).Error; err != nil {
return err
}
// 记录转入日志
transferInLog := &model.UserCouponLedger{
UserID: toUserID,
UserCouponID: userCouponID,
ChangeAmount: 0,
BalanceAfter: uc.BalanceAmount,
OrderID: 0,
Action: "transfer_in",
CreatedAt: time.Now(),
}
if err := tx.Create(transferInLog).Error; err != nil {
return err
}
return nil
})
if err != nil {
return err
}
fmt.Printf("[优惠券转赠] 成功: coupon_id=%d from=%d to=%d\n", userCouponID, fromUserID, toUserID)
return nil
}