micro-bundle/internal/dao/taskBalanceSync.go

482 lines
20 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 dao
import (
"errors"
"fmt"
"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
}
fmt.Println(validArtists)
if len(validArtists) == 0 {
// 不写入已执行标记,留待后续有数据时再次执行
fmt.Println("无数据更新")
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 {
// 没有可插入的数据,不写标记,直接返回
tx.Rollback()
return nil
}
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
}
var ur userRow
if err := app.ModuleClients.BundleDB.Table("`micro-account`.`user`").Unscoped().
Select("tel_num AS tel").Where("id = ?", bb.UserId).Limit(1).Scan(&ur).Error; err != nil {
return "", "", err
}
// customer_num 来自 bundle_order_records按 order_uuid
type orderRow struct {
Customer string
}
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 AS customer").Where("uuid = ?", bb.OrderUUID).Limit(1).Scan(&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.TaskManualVideoNumber = bb.ManualVideoNumber
tb.TaskManualVideoConsumptionNumber = bb.ManualVideoConsumptionNumber
tb.TaskMonthlyNewManualVideoNumber = bb.MonthlyNewManualVideoNumber
tb.TaskMonthlyManualVideoConsumptionNumber = bb.MonthlyManualVideoConsumptionNumber
// ===== 图片类 =====
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.TaskManualImageNumber = bb.ManualImageNumber
tb.TaskManualImageConsumptionNumber = bb.ManualImageConsumptionNumber
tb.TaskMonthlyNewManualImageNumber = bb.MonthlyNewManualImageNumber
tb.TaskMonthlyManualImageConsumptionNumber = bb.MonthlyManualImageConsumptionNumber
// ===== 数据分析类 =====
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
// 手动扩展(数据分析)
tb.TaskManualDataAnalysisNumber = bb.ManualDataAnalysisNumber
tb.TaskManualDataAnalysisConsumptionNumber = bb.ManualDataAnalysisConsumptionNumber
tb.TaskMonthlyNewManualDataAnalysisNumber = bb.MonthlyNewManualDataAnalysisNumber
tb.TaskMonthlyManualDataAnalysisConsumptionNumber = bb.MonthlyManualDataAnalysisConsumptionNumber
// 其他字段
tb.TaskMonthlyNewDurationNumber = bb.MonthlyNewDurationNumber
tb.TaskExpansionPacksNumber = bb.ExpansionPacksNumber
}
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
}