topfans/backend/services/taskService/repository/like_bet_repo.go
2026-06-29 14:47:32 +08:00

118 lines
4.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package repository
import (
"time"
"github.com/topfans/backend/pkg/logger"
"github.com/topfans/backend/services/taskService/model"
"go.uber.org/zap"
"gorm.io/gorm"
)
// LikeBetRevenueRepository 点赞押注收益仓库接口
type LikeBetRevenueRepository interface {
// BatchCreate 批量写入点赞押注收益记录(同一次 exhibition 到期,一次性写所有点赞者)
BatchCreate(records []*model.LikeBetRevenueRecord) error
// GetRecord 按 ID 查询单条记录(领取前先 Get 用于 userID 校验与状态校验)
GetRecord(id int64) (*model.LikeBetRevenueRecord, error)
// ListByUser 查询某用户某 star_id 下的收益记录(按 status 可选过滤)
ListByUser(userID, starID int64, status string, page, pageSize int) ([]*model.LikeBetRevenueRecord, int64, error)
// ClaimRecord 乐观锁领取:只有 status='claimable' 且 user_id 匹配时才更新为 claimed
ClaimRecord(id int64, userID int64) (bool, error)
}
type likeBetRevenueRepository struct {
db *gorm.DB
}
// NewLikeBetRevenueRepository 创建 LikeBetRevenueRepository 实例
func NewLikeBetRevenueRepository(db *gorm.DB) LikeBetRevenueRepository {
return &likeBetRevenueRepository{db: db}
}
// BatchCreate 批量创建点赞押注收益记录
// 若 (exhibition_id, like_id) 唯一约束冲突cleanup_worker 重跑场景),返回 error 但不影响主流程
// 调用方应在 CleanupWorker 中降级为 warn 日志
func (r *likeBetRevenueRepository) BatchCreate(records []*model.LikeBetRevenueRecord) error {
if len(records) == 0 {
return nil
}
now := time.Now().UnixMilli()
for _, rec := range records {
if rec.CreatedAt == 0 {
rec.CreatedAt = now
}
if rec.Status == "" {
rec.Status = "claimable"
}
}
if err := r.db.Create(records).Error; err != nil {
logger.Logger.Error("Failed to BatchCreate LikeBetRevenueRecords",
zap.Int("count", len(records)),
zap.Error(err))
return err
}
return nil
}
// GetRecord 按 ID 查询单条记录
func (r *likeBetRevenueRepository) GetRecord(id int64) (*model.LikeBetRevenueRecord, error) {
var record model.LikeBetRevenueRecord
if err := r.db.First(&record, id).Error; err != nil {
return nil, err
}
return &record, nil
}
// ListByUser 查询某用户的点赞押注收益记录
// SQL: WHERE user_id=? AND star_id=? [AND status=?] ORDER BY created_at DESC
func (r *likeBetRevenueRepository) ListByUser(userID, starID int64, status string, page, pageSize int) ([]*model.LikeBetRevenueRecord, int64, error) {
var records []*model.LikeBetRevenueRecord
var total int64
query := r.db.Model(&model.LikeBetRevenueRecord{}).Where("user_id = ? AND star_id = ?", userID, starID)
if status != "" {
query = query.Where("status = ?", status)
}
if err := query.Count(&total).Error; err != nil {
logger.Logger.Error("Failed to count like_bet_revenue_records",
zap.Int64("user_id", userID),
zap.Int64("star_id", starID),
zap.Error(err))
return nil, 0, err
}
offset := (page - 1) * pageSize
if err := query.Order("created_at DESC").Offset(offset).Limit(pageSize).Find(&records).Error; err != nil {
logger.Logger.Error("Failed to ListByUser like_bet_revenue_records",
zap.Int64("user_id", userID),
zap.Int64("star_id", starID),
zap.Error(err))
return nil, 0, err
}
return records, total, nil
}
// ClaimRecord 乐观锁领取:仅当 id/user_id/status='claimable' 同时匹配时才更新为 claimed
// 返回 RowsAffected > 0 表示领取成功
func (r *likeBetRevenueRepository) ClaimRecord(id int64, userID int64) (bool, error) {
now := time.Now().UnixMilli()
result := r.db.Model(&model.LikeBetRevenueRecord{}).
Where("id = ? AND user_id = ? AND status = ?", id, userID, "claimable").
Updates(map[string]interface{}{
"status": "claimed",
"claimed_at": now,
})
if result.Error != nil {
logger.Logger.Error("Failed to ClaimRecord like_bet",
zap.Int64("id", id),
zap.Int64("user_id", userID),
zap.Error(result.Error))
return false, result.Error
}
return result.RowsAffected > 0, nil
}