92 lines
2.1 KiB
Go
92 lines
2.1 KiB
Go
package user
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
|
|
"bindbox-game/internal/repository/mysql/dao"
|
|
"bindbox-game/internal/repository/mysql/model"
|
|
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/clause"
|
|
)
|
|
|
|
// BindInviterInput 绑定邀请人输入
|
|
type BindInviterInput struct {
|
|
InviteCode string // 邀请人的邀请码
|
|
}
|
|
|
|
// BindInviterOutput 绑定邀请人输出
|
|
type BindInviterOutput struct {
|
|
InviterID int64 `json:"inviter_id"`
|
|
InviterNickname string `json:"inviter_nickname"`
|
|
}
|
|
|
|
var (
|
|
ErrAlreadyBound = errors.New("already_bound")
|
|
ErrInvalidCode = errors.New("invalid_code")
|
|
ErrCannotInviteSelf = errors.New("cannot_invite_self")
|
|
)
|
|
|
|
// BindInviter 用户主动绑定邀请人(仅限未绑定过的用户)
|
|
func (s *service) BindInviter(ctx context.Context, userID int64, in BindInviterInput) (*BindInviterOutput, error) {
|
|
var result *BindInviterOutput
|
|
|
|
err := s.writeDB.Transaction(func(tx *dao.Query) error {
|
|
// 1. 获取当前用户,加行锁
|
|
user, err := tx.Users.WithContext(ctx).Clauses(clause.Locking{Strength: "UPDATE"}).
|
|
Where(tx.Users.ID.Eq(userID)).First()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// 2. 检查是否已绑定邀请人
|
|
if user.InviterID != 0 {
|
|
return ErrAlreadyBound
|
|
}
|
|
|
|
// 3. 查找邀请人
|
|
inviter, err := tx.Users.WithContext(ctx).Where(tx.Users.InviteCode.Eq(in.InviteCode)).First()
|
|
if err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return ErrInvalidCode
|
|
}
|
|
return err
|
|
}
|
|
|
|
// 4. 不能邀请自己
|
|
if inviter.ID == userID {
|
|
return ErrCannotInviteSelf
|
|
}
|
|
|
|
// 5. 创建邀请记录
|
|
invite := &model.UserInvites{
|
|
InviterID: inviter.ID,
|
|
InviteeID: userID,
|
|
InviteCode: in.InviteCode,
|
|
}
|
|
if err := tx.UserInvites.WithContext(ctx).Create(invite); err != nil {
|
|
return err
|
|
}
|
|
|
|
// 6. 更新用户的邀请人ID
|
|
if _, err := tx.Users.WithContext(ctx).Where(tx.Users.ID.Eq(userID)).
|
|
UpdateColumn(tx.Users.InviterID, inviter.ID); err != nil {
|
|
return err
|
|
}
|
|
|
|
result = &BindInviterOutput{
|
|
InviterID: inviter.ID,
|
|
InviterNickname: inviter.Nickname,
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return result, nil
|
|
}
|