118 lines
4.0 KiB
Go
118 lines
4.0 KiB
Go
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
|
||
} |