package title import ( "context" "time" "bindbox-game/internal/repository/mysql/model" "fmt" ) func (s *service) AssignUserTitle(ctx context.Context, userID int64, titleID int64, expiresAt *time.Time, remark string) error { t, err := s.readDB.SystemTitles.WithContext(ctx). Where(s.readDB.SystemTitles.ID.Eq(titleID)).First() if err != nil || t == nil || t.Status != 1 { return err } ut, err := s.readDB.UserTitles.WithContext(ctx). Where(s.readDB.UserTitles.UserID.Eq(userID)). Where(s.readDB.UserTitles.TitleID.Eq(titleID)).First() if err == nil && ut != nil { now := time.Now() if ut.Active == 1 && (ut.ExpiresAt.IsZero() || ut.ExpiresAt.After(now)) { return fmt.Errorf("already_owned") } ut.Active = 1 ut.Remark = remark if expiresAt != nil && !expiresAt.IsZero() { ut.ExpiresAt = *expiresAt } if err := s.writeDB.UserTitles.WithContext(ctx).Save(ut); err != nil { return err } } else { now := time.Now() row := &model.UserTitles{ UserID: userID, TitleID: titleID, Active: 1, ObtainedAt: now, Source: "admin_assign", Remark: remark, } if expiresAt != nil && !expiresAt.IsZero() { row.ExpiresAt = *expiresAt } if err := s.writeDB.UserTitles.WithContext(ctx).Create(row); err != nil { return err } } others, _ := s.readDB.UserTitles.WithContext(ctx). Where(s.readDB.UserTitles.UserID.Eq(userID)). Where(s.readDB.UserTitles.TitleID.Neq(titleID)). Where(s.readDB.UserTitles.Active.Eq(1)).Find() for _, o := range others { o.Active = 0 _ = s.writeDB.UserTitles.WithContext(ctx).Save(o) } return nil }