460 lines
18 KiB
Go
460 lines
18 KiB
Go
package dao
|
||
|
||
import (
|
||
"errors"
|
||
"time"
|
||
|
||
"gorm.io/gorm"
|
||
|
||
"micro-bundle/internal/model"
|
||
"micro-bundle/pkg/app"
|
||
)
|
||
|
||
// RunInitialTaskBalanceSync 一次性将 BundleBalance 同步到 TaskBalance
|
||
// 仅在未执行过且任务余额表为空时运行;执行成功后写入标记,避免再次执行
|
||
func RunInitialTaskBalanceSync() error {
|
||
// 确保标记表存在
|
||
_ = app.ModuleClients.TaskBenchDB.AutoMigrate(&model.TaskSyncStatus{})
|
||
|
||
// 已执行标记检查
|
||
var markerCount int64
|
||
if err := app.ModuleClients.TaskBenchDB.Model(&model.TaskSyncStatus{}).
|
||
Where("sync_key = ?", model.InitialSyncKey).Count(&markerCount).Error; err != nil {
|
||
return err
|
||
}
|
||
if markerCount > 0 {
|
||
return nil
|
||
}
|
||
|
||
// 安全检查:如果任务余额表已存在数据,则不再执行,同样写入标记
|
||
var existing int64
|
||
if err := app.ModuleClients.TaskBenchDB.Model(&model.TaskBalance{}).Count(&existing).Error; err != nil {
|
||
return err
|
||
}
|
||
if existing > 0 {
|
||
_ = app.ModuleClients.TaskBenchDB.Create(&model.TaskSyncStatus{
|
||
SyncKey: model.InitialSyncKey,
|
||
ExecutedAt: time.Now(),
|
||
Remark: "skipped: task_balance already has data",
|
||
}).Error
|
||
return nil
|
||
}
|
||
|
||
// 获取当前有效(未过期且已支付)的艺人及其最新订单
|
||
validArtists, err := GetValidArtistList()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if len(validArtists) == 0 {
|
||
_ = app.ModuleClients.TaskBenchDB.Create(&model.TaskSyncStatus{
|
||
SyncKey: model.InitialSyncKey,
|
||
ExecutedAt: time.Now(),
|
||
Remark: "skipped: no valid artists",
|
||
}).Error
|
||
return nil
|
||
}
|
||
|
||
// 构造待插入的 TaskBalance 列表
|
||
tasks := make([]model.TaskBalance, 0, len(validArtists))
|
||
for _, a := range validArtists {
|
||
// 根据 user_id + order_uuid 获取 BundleBalance 明细
|
||
var bb model.BundleBalance
|
||
if err := app.ModuleClients.BundleDB.Where("user_id = ? AND order_uuid = ?", a.UserID, a.OrderUUID).First(&bb).Error; err != nil {
|
||
// 若未查到则跳过该条
|
||
if err == gorm.ErrRecordNotFound {
|
||
continue
|
||
}
|
||
return err
|
||
}
|
||
|
||
subNum, telNum, err := fetchIdentityForBundle(&bb)
|
||
if err != nil {
|
||
// 无法获取身份信息则跳过该条
|
||
continue
|
||
}
|
||
|
||
tb := model.TaskBalance{
|
||
SubNum: subNum,
|
||
TelNum: telNum,
|
||
Month: bb.Month,
|
||
StartAt: bb.StartAt,
|
||
ExpiredAt: bb.ExpiredAt,
|
||
CreatedAt: time.Now(),
|
||
UpdatedAt: time.Now(),
|
||
}
|
||
copyBundleToTaskBalance(&tb, &bb)
|
||
tasks = append(tasks, tb)
|
||
}
|
||
|
||
// 原子写入:插入 TaskBalance + 插入标记
|
||
tx := app.ModuleClients.TaskBenchDB.Begin()
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
tx.Rollback()
|
||
}
|
||
}()
|
||
|
||
if len(tasks) > 0 {
|
||
if err := tx.Create(&tasks).Error; err != nil {
|
||
tx.Rollback()
|
||
return err
|
||
}
|
||
}
|
||
if err := tx.Create(&model.TaskSyncStatus{
|
||
SyncKey: model.InitialSyncKey,
|
||
ExecutedAt: time.Now(),
|
||
Remark: "initial sync executed",
|
||
}).Error; err != nil {
|
||
tx.Rollback()
|
||
return err
|
||
}
|
||
if err := tx.Commit().Error; err != nil {
|
||
return err
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// 用户新买套餐时使用
|
||
// SyncTaskBalanceFromBundleBalance 增量/每月:根据单条 BundleBalance 同步或更新 TaskBalance(按 sub_num + tel_num + month 唯一)
|
||
func SyncTaskBalanceFromBundleBalance(bb model.BundleBalance) error {
|
||
// 获取身份信息(sub_num, tel_num)
|
||
subNum, telNum, err := fetchIdentityForBundle(&bb)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 组装 TaskBalance
|
||
tb := model.TaskBalance{
|
||
SubNum: subNum,
|
||
TelNum: telNum,
|
||
Month: bb.Month,
|
||
ExpiredAt: bb.ExpiredAt,
|
||
StartAt: bb.StartAt,
|
||
UpdatedAt: time.Now(),
|
||
CreatedAt: time.Now(),
|
||
}
|
||
copyBundleToTaskBalance(&tb, &bb)
|
||
|
||
// 查询是否已存在(唯一:sub_num + tel_num + month)
|
||
var existing model.TaskBalance
|
||
err = app.ModuleClients.TaskBenchDB.
|
||
Where("sub_num = ? AND tel_num = ? AND month = ?", subNum, telNum, bb.Month).
|
||
First(&existing).Error
|
||
if err != nil {
|
||
if err == gorm.ErrRecordNotFound {
|
||
// 不存在则创建
|
||
return app.ModuleClients.TaskBenchDB.Create(&tb).Error
|
||
}
|
||
return err
|
||
}
|
||
|
||
// 已存在则更新所有映射字段与时间
|
||
tb.ID = existing.ID
|
||
return app.ModuleClients.TaskBenchDB.Save(&tb).Error
|
||
}
|
||
|
||
// fetchIdentityForBundle 根据 BundleBalance 拿到 sub_num 与 tel_num
|
||
func fetchIdentityForBundle(bb *model.BundleBalance) (string, string, error) {
|
||
// tel_num 来自 micro-account.user
|
||
type userRow struct {
|
||
Tel string `gorm:"column:tel_num"`
|
||
}
|
||
var ur userRow
|
||
if err := app.ModuleClients.BundleDB.Table("`micro-account`.`user`").Unscoped().
|
||
Select("tel_num").Where("id = ?", bb.UserId).First(&ur).Error; err != nil {
|
||
return "", "", err
|
||
}
|
||
// customer_num 来自 bundle_order_records(按 order_uuid)
|
||
type orderRow struct {
|
||
Customer string `gorm:"column:customer_num"`
|
||
}
|
||
var or orderRow
|
||
if bb.OrderUUID == "" {
|
||
return "", "", errors.New("bundle order_uuid missing")
|
||
}
|
||
if err := app.ModuleClients.BundleDB.Table("bundle_order_records").
|
||
Select("customer_num").Where("uuid = ?", bb.OrderUUID).First(&or).Error; err != nil {
|
||
return "", "", err
|
||
}
|
||
return or.Customer, ur.Tel, nil
|
||
}
|
||
|
||
// UpdateTaskBalance 每月批量更新任务余额
|
||
// 类似于 UpdateBundleBalance 的逻辑,但针对任务余额表
|
||
func UpdateTaskBalanceEveryMon() error {
|
||
// 查询需要更新的任务余额记录(最新月份且未过期的记录)
|
||
tl := []model.TaskBalance{}
|
||
if err := app.ModuleClients.TaskBenchDB.Raw(`select
|
||
*
|
||
from
|
||
task_balance tb
|
||
inner join (
|
||
select
|
||
max(tb.month) as month ,
|
||
sub_num,
|
||
tel_num
|
||
from
|
||
task_balance tb
|
||
group by
|
||
tb.sub_num, tb.tel_num
|
||
) newest on
|
||
newest.month = tb.month
|
||
and (tb.sub_num = newest.sub_num OR tb.tel_num = newest.tel_num)
|
||
and tb.expired_at > now()`).Find(&tl).Error; err != nil {
|
||
return err
|
||
}
|
||
|
||
now := time.Now()
|
||
month := time.Now().Format("2006-01")
|
||
|
||
for _, v := range tl {
|
||
if v.Month == month {
|
||
continue
|
||
}
|
||
|
||
// 计算本月发放的限制类型数量(与套餐余额一致)
|
||
cal := func(total, limit int) int {
|
||
var released int // 已释放的次数
|
||
if v.StartAt.Month() == now.Month() && v.StartAt.Year() == now.Year() {
|
||
// 本月为第一个月,不计算之前的释放
|
||
} else if v.StartAt.Day() >= 16 { // 第一个月释放的(向上取整一半)
|
||
released += (limit + 1) / 2
|
||
} else {
|
||
released += limit
|
||
}
|
||
interval := now.Year()*12 + int(now.Month()) - (v.StartAt.Year()*12 + int(v.StartAt.Month())) // 后续月份释放的
|
||
released += interval * limit
|
||
remaining := max(total-released, 0) // 还剩余多少次没有发放
|
||
|
||
if v.StartAt.Month() == now.Month() && v.StartAt.Year() == now.Year() && v.StartAt.Day() >= 16 { // 本月为第一个月并且16号后购买只给一半(向上取整)
|
||
return min((limit+1)/2, remaining)
|
||
}
|
||
if v.ExpiredAt.Month() == now.Month() && v.ExpiredAt.Year() == now.Year() && v.ExpiredAt.Day() < 16 { // 本月为最后一个月并且16号前到期只给一半(向下取整)
|
||
return min(limit/2, remaining)
|
||
}
|
||
return min(limit, remaining)
|
||
}
|
||
|
||
// ===== 处理视频类过期数据 =====
|
||
v.TaskMonthlyInvalidBundleVideoNumber = v.TaskMonthlyLimitVideoExpireNumber - v.TaskMonthlyLimitVideoExpireConsumptionNumber
|
||
v.TaskInvalidBundleVideoNumber += v.TaskMonthlyInvalidBundleVideoNumber
|
||
|
||
// ===== 处理图片类过期数据 =====
|
||
v.TaskMonthlyInvalidBundleImageNumber = v.TaskMonthlyLimitImageExpireNumber - v.TaskMonthlyLimitImageExpireConsumptionNumber
|
||
v.TaskInvalidBundleImageNumber += v.TaskMonthlyInvalidBundleImageNumber
|
||
|
||
// ===== 处理数据分析类过期数据 =====
|
||
v.TaskMonthlyInvalidBundleDataAnalysisNumber = v.TaskMonthlyLimitDataAnalysisExpireNumber - v.TaskMonthlyLimitDataAnalysisExpireConsumptionNumber
|
||
v.TaskInvalidBundleDataAnalysisNumber += v.TaskMonthlyInvalidBundleDataAnalysisNumber
|
||
|
||
// ===== 计算新月份的可用数量 =====
|
||
// 视频类
|
||
v.TaskMonthlyLimitVideoExpireNumber = cal(v.TaskBundleLimitVideoExpiredNumber, v.TaskMonthlyLimitVideoQuotaNumber) + cal(v.TaskIncreaseLimitVideoExpiredNumber, v.TaskMonthlyLimitVideoQuotaNumber)
|
||
v.TaskMonthlyLimitVideoNumber = v.TaskMonthlyLimitVideoNumber - v.TaskMonthlyLimitVideoConsumptionNumber + cal(v.TaskBundleLimitVideoNumber, v.TaskMonthlyLimitVideoQuotaNumber) + cal(v.TaskIncreaseLimitVideoNumber, v.TaskMonthlyLimitVideoQuotaNumber)
|
||
|
||
// 图片类
|
||
v.TaskMonthlyLimitImageExpireNumber = cal(v.TaskBundleLimitImageExpiredNumber, v.TaskMonthlyLimitImageQuotaNumber) + cal(v.TaskIncreaseLimitImageExpiredNumber, v.TaskMonthlyLimitImageQuotaNumber)
|
||
v.TaskMonthlyLimitImageNumber = v.TaskMonthlyLimitImageNumber - v.TaskMonthlyLimitImageConsumptionNumber + cal(v.TaskBundleLimitImageNumber, v.TaskMonthlyLimitImageQuotaNumber) + cal(v.TaskIncreaseLimitImageNumber, v.TaskMonthlyLimitImageQuotaNumber)
|
||
|
||
// 数据分析类
|
||
v.TaskMonthlyLimitDataAnalysisExpireNumber = cal(v.TaskBundleLimitDataAnalysisExpiredNumber, v.TaskMonthlyLimitDataAnalysisQuotaNumber) + cal(v.TaskIncreaseLimitDataAnalysisExpiredNumber, v.TaskMonthlyLimitDataAnalysisQuotaNumber)
|
||
v.TaskMonthlyLimitDataAnalysisNumber = v.TaskMonthlyLimitDataAnalysisNumber - v.TaskMonthlyLimitDataAnalysisConsumptionNumber + cal(v.TaskBundleLimitDataAnalysisNumber, v.TaskMonthlyLimitDataAnalysisQuotaNumber) + cal(v.TaskIncreaseLimitDataAnalysisNumber, v.TaskMonthlyLimitDataAnalysisQuotaNumber)
|
||
|
||
// ===== 重置月度消耗数量 =====
|
||
// 视频类月度消耗重置
|
||
v.TaskMonthlyLimitVideoConsumptionNumber = 0
|
||
v.TaskMonthlyLimitVideoExpireConsumptionNumber = 0
|
||
v.TaskMonthlyManualVideoConsumptionNumber = 0
|
||
v.TaskMonthlyBundleVideoConsumptionNumber = 0
|
||
v.TaskMonthlyIncreaseVideoConsumptionNumber = 0
|
||
|
||
// 图片类月度消耗重置
|
||
v.TaskMonthlyLimitImageConsumptionNumber = 0
|
||
v.TaskMonthlyLimitImageExpireConsumptionNumber = 0
|
||
v.TaskMonthlyManualImageConsumptionNumber = 0
|
||
v.TaskMonthlyBundleImageConsumptionNumber = 0
|
||
v.TaskMonthlyIncreaseImageConsumptionNumber = 0
|
||
|
||
// 数据分析类月度消耗重置
|
||
v.TaskMonthlyLimitDataAnalysisConsumptionNumber = 0
|
||
v.TaskMonthlyLimitDataAnalysisExpireConsumptionNumber = 0
|
||
v.TaskMonthlyManualDataAnalysisConsumptionNumber = 0
|
||
v.TaskMonthlyBundleDataAnalysisConsumptionNumber = 0
|
||
v.TaskMonthlyIncreaseDataAnalysisConsumptionNumber = 0
|
||
|
||
// 设置新月份和重置ID
|
||
v.Month = month
|
||
v.ID = 0
|
||
|
||
// 创建新的任务余额记录
|
||
if err := app.ModuleClients.TaskBenchDB.Create(&v).Error; err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// updateTaskBalanceExpiredAt 更新任务余额表的ExpiredAt字段
|
||
func updateTaskBalanceExpiredAt(subNum, telNum string, durationNumber int) error {
|
||
return app.ModuleClients.TaskBenchDB.Transaction(func(tx *gorm.DB) error {
|
||
var taskBalance model.TaskBalance
|
||
query := tx.Model(&model.TaskBalance{})
|
||
|
||
// 构建查询条件,优先使用 subNum
|
||
if subNum != "" {
|
||
query = query.Where("sub_num = ?", subNum)
|
||
} else {
|
||
query = query.Where("tel_num = ?", telNum)
|
||
}
|
||
|
||
// 查询当前有效的任务余额记录,按最新的开始时间排序
|
||
now := time.Now()
|
||
err := query.Where("start_at <= ? AND expired_at >= ?", now, now).Order("start_at DESC").First(&taskBalance).Error
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 增加过期时间
|
||
taskBalance.ExpiredAt = taskBalance.ExpiredAt.Add(time.Hour * 24 * time.Duration(durationNumber))
|
||
|
||
return tx.Save(&taskBalance).Error
|
||
})
|
||
}
|
||
|
||
// copyBundleToTaskBalance 将 BundleBalance 的图片、视频、数据分析相关字段映射到 TaskBalance
|
||
func copyBundleToTaskBalance(tb *model.TaskBalance, bb *model.BundleBalance) {
|
||
// ===== 视频类 =====
|
||
tb.TaskBundleVideoNumber = bb.BundleVideoNumber
|
||
tb.TaskIncreaseVideoNumber = bb.IncreaseVideoNumber
|
||
tb.TaskBundleLimitVideoNumber = bb.BundleLimitVideoNumber
|
||
tb.TaskIncreaseLimitVideoNumber = bb.IncreaseLimitVideoNumber
|
||
tb.TaskBundleLimitVideoExpiredNumber = bb.BundleLimitVideoExpiredNumber
|
||
tb.TaskIncreaseLimitVideoExpiredNumber = bb.IncreaseLimitVideoExpiredNumber
|
||
tb.TaskMonthlyInvalidBundleVideoNumber = bb.MonthlyInvalidBundleVideoNumber
|
||
tb.TaskInvalidBundleVideoNumber = bb.InvalidBundleVideoNumber
|
||
tb.TaskMonthlyInvalidIncreaseVideoNumber = bb.MonthlyInvalidIncreaseVideoNumber
|
||
tb.TaskInvalidIncreaseVideoNumber = bb.InvalidIncreaseVideoNumber
|
||
tb.TaskBundleVideoConsumptionNumber = bb.BundleVideoConsumptionNumber
|
||
tb.TaskIncreaseVideoConsumptionNumber = bb.IncreaseVideoConsumptionNumber
|
||
tb.TaskBundleLimitVideoConsumptionNumber = bb.BundleLimitVideoConsumptionNumber
|
||
tb.TaskIncreaseLimitVideoConsumptionNumber = bb.IncreaseLimitVideoConsumptionNumber
|
||
tb.TaskBundleLimitVideoExpiredConsumptionNumber = bb.BundleLimitVideoExpiredConsumptionNumber
|
||
tb.TaskIncreaseLimitVideoExpiredConsumptionNumber = bb.IncreaseLimitVideoExpiredConsumptionNumber
|
||
tb.TaskMonthlyLimitVideoNumber = bb.MonthlyLimitVideoNumber
|
||
tb.TaskMonthlyLimitVideoConsumptionNumber = bb.MonthlyLimitVideoConsumptionNumber
|
||
tb.TaskMonthlyLimitVideoExpireNumber = bb.MonthlyLimitVideoExpireNumber
|
||
tb.TaskMonthlyLimitVideoExpireConsumptionNumber = bb.MonthlyLimitVideoExpireConsumptionNumber
|
||
tb.TaskMonthlyBundleVideoConsumptionNumber = bb.MonthlyBundleVideoConsumptionNumber
|
||
tb.TaskMonthlyIncreaseVideoConsumptionNumber = bb.MonthlyIncreaseVideoConsumptionNumber
|
||
tb.TaskMonthlyLimitVideoQuotaNumber = bb.MonthlyLimitVideoQuotaNumber
|
||
|
||
// ===== 图片类 =====
|
||
tb.TaskBundleImageNumber = bb.BundleImageNumber
|
||
tb.TaskIncreaseImageNumber = bb.IncreaseImageNumber
|
||
tb.TaskBundleLimitImageNumber = bb.BundleLimitImageNumber
|
||
tb.TaskIncreaseLimitImageNumber = bb.IncreaseLimitImageNumber
|
||
tb.TaskBundleLimitImageExpiredNumber = bb.BundleLimitImageExpiredNumber
|
||
tb.TaskIncreaseLimitImageExpiredNumber = bb.IncreaseLimitImageExpiredNumber
|
||
tb.TaskMonthlyInvalidBundleImageNumber = bb.MonthlyInvalidBundleImageNumber
|
||
tb.TaskInvalidBundleImageNumber = bb.InvalidBundleImageNumber
|
||
tb.TaskMonthlyInvalidIncreaseImageNumber = bb.MonthlyInvalidIncreaseImageNumber
|
||
tb.TaskInvalidIncreaseImageNumber = bb.InvalidIncreaseImageNumber
|
||
tb.TaskBundleImageConsumptionNumber = bb.BundleImageConsumptionNumber
|
||
tb.TaskIncreaseImageConsumptionNumber = bb.IncreaseImageConsumptionNumber
|
||
tb.TaskBundleLimitImageConsumptionNumber = bb.BundleLimitImageConsumptionNumber
|
||
tb.TaskIncreaseLimitImageConsumptionNumber = bb.IncreaseLimitImageConsumptionNumber
|
||
tb.TaskBundleLimitImageExpiredConsumptionNumber = bb.BundleLimitImageExpiredConsumptionNumber
|
||
tb.TaskIncreaseLimitImageExpiredConsumptionNumber = bb.IncreaseLimitImageExpiredConsumptionNumber
|
||
tb.TaskMonthlyLimitImageNumber = bb.MonthlyLimitImageNumber
|
||
tb.TaskMonthlyLimitImageConsumptionNumber = bb.MonthlyLimitImageConsumptionNumber
|
||
tb.TaskMonthlyLimitImageExpireNumber = bb.MonthlyLimitImageExpireNumber
|
||
tb.TaskMonthlyLimitImageExpireConsumptionNumber = bb.MonthlyLimitImageExpireConsumptionNumber
|
||
tb.TaskMonthlyBundleImageConsumptionNumber = bb.MonthlyBundleImageConsumptionNumber
|
||
tb.TaskMonthlyIncreaseImageConsumptionNumber = bb.MonthlyIncreaseImageConsumptionNumber
|
||
tb.TaskMonthlyLimitImageQuotaNumber = bb.MonthlyLimitImageQuotaNumber
|
||
|
||
// ===== 数据分析类 =====
|
||
tb.TaskBundleDataAnalysisNumber = bb.BundleDataAnalysisNumber
|
||
tb.TaskIncreaseDataAnalysisNumber = bb.IncreaseDataAnalysisNumber
|
||
tb.TaskBundleLimitDataAnalysisNumber = bb.BundleLimitDataAnalysisNumber
|
||
tb.TaskIncreaseLimitDataAnalysisNumber = bb.IncreaseLimitDataAnalysisNumber
|
||
tb.TaskBundleLimitDataAnalysisExpiredNumber = bb.BundleLimitDataAnalysisExpiredNumber
|
||
tb.TaskIncreaseLimitDataAnalysisExpiredNumber = bb.IncreaseLimitDataAnalysisExpiredNumber
|
||
tb.TaskMonthlyInvalidBundleDataAnalysisNumber = bb.MonthlyInvalidBundleDataAnalysisNumber
|
||
tb.TaskInvalidBundleDataAnalysisNumber = bb.InvalidBundleDataAnalysisNumber
|
||
tb.TaskMonthlyInvalidIncreaseDataAnalysisNumber = bb.MonthlyInvalidIncreaseDataAnalysisNumber
|
||
tb.TaskInvalidIncreaseDataAnalysisNumber = bb.InvalidIncreaseDataAnalysisNumber
|
||
tb.TaskBundleDataAnalysisConsumptionNumber = bb.BundleDataAnalysisConsumptionNumber
|
||
tb.TaskIncreaseDataAnalysisConsumptionNumber = bb.IncreaseDataAnalysisConsumptionNumber
|
||
tb.TaskBundleLimitDataAnalysisConsumptionNumber = bb.BundleLimitDataAnalysisConsumptionNumber
|
||
tb.TaskIncreaseLimitDataAnalysisConsumptionNumber = bb.IncreaseLimitDataAnalysisConsumptionNumber
|
||
tb.TaskBundleLimitDataAnalysisExpiredConsumptionNumber = bb.BundleLimitDataAnalysisExpiredConsumptionNumber
|
||
tb.TaskIncreaseLimitDataAnalysisExpiredConsumptionNumber = bb.IncreaseLimitDataAnalysisExpiredConsumptionNumber
|
||
tb.TaskMonthlyLimitDataAnalysisNumber = bb.MonthlyLimitDataAnalysisNumber
|
||
tb.TaskMonthlyLimitDataAnalysisConsumptionNumber = bb.MonthlyLimitDataAnalysisConsumptionNumber
|
||
tb.TaskMonthlyLimitDataAnalysisExpireNumber = bb.MonthlyLimitDataAnalysisExpireNumber
|
||
tb.TaskMonthlyLimitDataAnalysisExpireConsumptionNumber = bb.MonthlyLimitDataAnalysisExpireConsumptionNumber
|
||
tb.TaskMonthlyBundleDataAnalysisConsumptionNumber = bb.MonthlyBundleDataAnalysisConsumptionNumber
|
||
tb.TaskMonthlyIncreaseDataAnalysisConsumptionNumber = bb.MonthlyIncreaseDataAnalysisConsumptionNumber
|
||
tb.TaskMonthlyLimitDataAnalysisQuotaNumber = bb.MonthlyLimitDataAnalysisQuotaNumber
|
||
}
|
||
|
||
func ExtendTaskBalanceByUserId(userId int, imageNumber int, dataAnalysisNumber int, videoNumber int, durationNumber int) error {
|
||
// 根据用户ID获取其最新套餐记录,进而获取 sub_num、tel_num
|
||
oldBundle := model.BundleBalance{}
|
||
if err := app.ModuleClients.BundleDB.Model(&model.BundleBalance{}).
|
||
Where("user_id = ?", userId).
|
||
Order("created_at desc").
|
||
First(&oldBundle).Error; err != nil {
|
||
return errors.New("用户还没有套餐信息")
|
||
}
|
||
|
||
subNum, telNum, err := fetchIdentityForBundle(&oldBundle)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 事务更新当前有效的任务余额记录(按 start_at 最近的一条)
|
||
err = app.ModuleClients.TaskBenchDB.Transaction(func(tx *gorm.DB) error {
|
||
var tb model.TaskBalance
|
||
now := time.Now()
|
||
query := tx.Model(&model.TaskBalance{}).
|
||
Where("sub_num = ? AND tel_num = ? AND start_at <= ? AND expired_at >= ?", subNum, telNum, now, now).
|
||
Order("start_at DESC")
|
||
|
||
if err := query.First(&tb).Error; err != nil {
|
||
if err == gorm.ErrRecordNotFound {
|
||
return errors.New("用户还没有任务余额信息")
|
||
}
|
||
return err
|
||
}
|
||
|
||
// 手动扩展额度与当月新增记录
|
||
tb.TaskManualImageNumber += imageNumber
|
||
tb.TaskMonthlyNewManualImageNumber += imageNumber
|
||
|
||
tb.TaskManualDataAnalysisNumber += dataAnalysisNumber
|
||
tb.TaskMonthlyNewManualDataAnalysisNumber += dataAnalysisNumber
|
||
|
||
tb.TaskManualVideoNumber += videoNumber
|
||
tb.TaskMonthlyNewManualVideoNumber += videoNumber
|
||
|
||
tb.TaskMonthlyNewDurationNumber += durationNumber
|
||
|
||
return tx.Model(&model.TaskBalance{}).Where("id = ?", tb.ID).Save(&tb).Error
|
||
})
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 增加过期时间(按天)
|
||
if durationNumber > 0 {
|
||
if err := updateTaskBalanceExpiredAt(subNum, telNum, durationNumber); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|