Merge branch 'feat-cjy-taskBench' into dev

# Conflicts:
#	pb/bundle/bundle.pb.go
#	pkg/cron/cron.go
This commit is contained in:
cjy 2025-10-21 20:29:28 +08:00
commit b6d7271420
10 changed files with 2255 additions and 1343 deletions

View File

@ -3,6 +3,7 @@ package main
import (
bundleConfig "micro-bundle/config"
"micro-bundle/internal/controller"
"micro-bundle/internal/dao"
_ "micro-bundle/internal/handler"
"micro-bundle/pkg/app"
"micro-bundle/pkg/cron"
@ -33,6 +34,12 @@ func main() {
if err != nil {
panic(err)
}
// 一次性执行任务余额同步(幂等):若已执行或存在数据则跳过
if syncErr := dao.RunInitialTaskBalanceSync(); syncErr != nil {
app.ModuleClients.Lg.Warn("initial task-balance sync failed", zap.Error(syncErr))
}
//l, err := net.Listen("tcp", ":8883")
//if err != nil {
// fmt.Printf("failed to listen: %v", err)

View File

@ -93,6 +93,8 @@ func (b *BundleProvider) UpdatePendingCount(_ context.Context, req *bundle.Updat
PendingDataCount: int(req.PendingDataCount),
Operator: req.Operator,
OperatorNum: req.OperatorNum,
TaskAssignee: req.TaskAssignee,
TaskAssigneeNum: req.TaskAssigneeNum,
}
// 调用logic层

View File

@ -0,0 +1,459 @@
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
}

View File

@ -43,6 +43,8 @@ type UpdatePendingCountRequest struct {
PendingDataCount int `json:"pendingDataCount"` // 待发数据数量
Operator string `json:"operator"` // 操作人
OperatorNum string `json:"operatorNum"` // 操作人账号
TaskAssignee string `json:"taskAssignee"` // 任务指派人
TaskAssigneeNum string `json:"taskAssigneeNum"` // 任务指派人账号
}
// EmployeeTaskQueryRequest 员工任务查询请求参数
@ -614,6 +616,380 @@ func GetRemainingPendingBySubNum(subNum string) (*ArtistRemainingPendingResponse
}, nil
}
// UpdatePendingCount 扣减任务余额(一次可同时扣减视频/图文/数据),遵循套餐扣减优先级
func UpdatePendingCount(req *UpdatePendingCountRequest) error {
// 参数校验
if req.SubNum == "" {
return commonErr.ReturnError(nil, "参数错误", "艺人编号不能为空")
}
if req.PendingVideoCount < 0 || req.PendingPostCount < 0 || req.PendingDataCount < 0 {
return commonErr.ReturnError(nil, "参数错误", "扣减数量必须为非负")
}
// 开启事务
tx := app.ModuleClients.TaskBenchDB.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
// 查询当前有效期内或最新一条任务余额
now := time.Now()
var tb model.TaskBalance
{
err := tx.Where("sub_num = ? AND start_at <= ? AND expired_at >= ?", req.SubNum, now, now).Order("start_at DESC").First(&tb).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
err = tx.Where("sub_num = ?", req.SubNum).Order("start_at DESC").First(&tb).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
tx.Rollback()
return commonErr.ReturnError(nil, "余额不存在", "未找到任务余额记录")
}
tx.Rollback()
return commonErr.ReturnError(err, "查询任务余额失败", "查询任务余额失败: ")
}
} else {
tx.Rollback()
return commonErr.ReturnError(err, "查询任务余额失败", "查询任务余额失败: ")
}
}
}
// 先检查各类型是否有足够的总体余额(包含套餐、增值、手动)
bundleVideo, bundleImage, bundleData := calculateBundleBalances(&tb)
increaseVideo, increaseImage, increaseData := calculateIncreaseBalances(&tb)
manualVideo := tb.TaskManualVideoNumber - tb.TaskManualVideoConsumptionNumber
manualImage := tb.TaskManualImageNumber - tb.TaskManualImageConsumptionNumber
manualData := tb.TaskManualDataAnalysisNumber - tb.TaskManualDataAnalysisConsumptionNumber
if req.PendingVideoCount > bundleVideo+increaseVideo+manualVideo {
tx.Rollback()
return commonErr.ReturnError(nil, "可用视频数不足", "扣减视频数量超过当前余额")
}
if req.PendingPostCount > bundleImage+increaseImage+manualImage {
tx.Rollback()
return commonErr.ReturnError(nil, "可用图文数不足", "扣减图文数量超过当前余额")
}
if req.PendingDataCount > bundleData+increaseData+manualData {
tx.Rollback()
return commonErr.ReturnError(nil, "可用数据分析数不足", "扣减数据分析数量超过当前余额")
}
// 扣减视频:优先 会过期限制(套餐→增值) → 不过期限制(套餐→增值) → 非限制套餐 → 非限制增值 → 手动
need := req.PendingVideoCount
if need > 0 {
// 限制会过期 - 套餐
if need > 0 {
limitRemain := tb.TaskMonthlyLimitVideoExpireNumber - tb.TaskMonthlyLimitVideoExpireConsumptionNumber
totalRemain := tb.TaskBundleLimitVideoExpiredNumber - tb.TaskBundleLimitVideoExpiredConsumptionNumber
alloc := minInt(need, minInt(limitRemain, totalRemain))
if alloc > 0 {
tb.TaskBundleLimitVideoExpiredConsumptionNumber += alloc
tb.TaskMonthlyLimitVideoExpireConsumptionNumber += alloc
tb.TaskMonthlyBundleVideoConsumptionNumber += alloc
need -= alloc
}
}
// 限制会过期 - 增值
if need > 0 {
limitRemain := tb.TaskMonthlyLimitVideoExpireNumber - tb.TaskMonthlyLimitVideoExpireConsumptionNumber
totalRemain := tb.TaskIncreaseLimitVideoExpiredNumber - tb.TaskIncreaseLimitVideoExpiredConsumptionNumber
alloc := minInt(need, minInt(limitRemain, totalRemain))
if alloc > 0 {
tb.TaskIncreaseLimitVideoExpiredConsumptionNumber += alloc
tb.TaskMonthlyLimitVideoExpireConsumptionNumber += alloc
tb.TaskMonthlyIncreaseVideoConsumptionNumber += alloc
need -= alloc
}
}
// 限制不过期 - 套餐
if need > 0 {
limitRemain := tb.TaskMonthlyLimitVideoNumber - tb.TaskMonthlyLimitVideoConsumptionNumber
totalRemain := tb.TaskBundleLimitVideoNumber - tb.TaskBundleLimitVideoConsumptionNumber
alloc := minInt(need, minInt(limitRemain, totalRemain))
if alloc > 0 {
tb.TaskBundleLimitVideoConsumptionNumber += alloc
tb.TaskMonthlyLimitVideoConsumptionNumber += alloc
tb.TaskMonthlyBundleVideoConsumptionNumber += alloc
need -= alloc
}
}
// 限制不过期 - 增值
if need > 0 {
limitRemain := tb.TaskMonthlyLimitVideoNumber - tb.TaskMonthlyLimitVideoConsumptionNumber
totalRemain := tb.TaskIncreaseLimitVideoNumber - tb.TaskIncreaseLimitVideoConsumptionNumber
alloc := minInt(need, minInt(limitRemain, totalRemain))
if alloc > 0 {
tb.TaskIncreaseLimitVideoConsumptionNumber += alloc
tb.TaskMonthlyLimitVideoConsumptionNumber += alloc
tb.TaskMonthlyIncreaseVideoConsumptionNumber += alloc
need -= alloc
}
}
// 非限制 - 套餐
if need > 0 {
totalRemain := tb.TaskBundleVideoNumber - tb.TaskBundleVideoConsumptionNumber
alloc := minInt(need, totalRemain)
if alloc > 0 {
tb.TaskBundleVideoConsumptionNumber += alloc
tb.TaskMonthlyBundleVideoConsumptionNumber += alloc
need -= alloc
}
}
// 非限制 - 增值
if need > 0 {
totalRemain := tb.TaskIncreaseVideoNumber - tb.TaskIncreaseVideoConsumptionNumber
alloc := minInt(need, totalRemain)
if alloc > 0 {
tb.TaskIncreaseVideoConsumptionNumber += alloc
tb.TaskMonthlyIncreaseVideoConsumptionNumber += alloc
need -= alloc
}
}
// 手动扩展
if need > 0 {
totalRemain := tb.TaskManualVideoNumber - tb.TaskManualVideoConsumptionNumber
alloc := minInt(need, totalRemain)
if alloc > 0 {
tb.TaskManualVideoConsumptionNumber += alloc
tb.TaskMonthlyManualVideoConsumptionNumber += alloc
need -= alloc
}
}
if need > 0 {
tx.Rollback()
return commonErr.ReturnError(nil, "可用视频数不足", "扣减视频数量超过当前余额或当月限额")
}
}
// 扣减图文
need = req.PendingPostCount
if need > 0 {
// 限制会过期 - 套餐
if need > 0 {
limitRemain := tb.TaskMonthlyLimitImageExpireNumber - tb.TaskMonthlyLimitImageExpireConsumptionNumber
totalRemain := tb.TaskBundleLimitImageExpiredNumber - tb.TaskBundleLimitImageExpiredConsumptionNumber
alloc := minInt(need, minInt(limitRemain, totalRemain))
if alloc > 0 {
tb.TaskBundleLimitImageExpiredConsumptionNumber += alloc
tb.TaskMonthlyLimitImageExpireConsumptionNumber += alloc
tb.TaskMonthlyBundleImageConsumptionNumber += alloc
need -= alloc
}
}
// 限制会过期 - 增值
if need > 0 {
limitRemain := tb.TaskMonthlyLimitImageExpireNumber - tb.TaskMonthlyLimitImageExpireConsumptionNumber
totalRemain := tb.TaskIncreaseLimitImageExpiredNumber - tb.TaskIncreaseLimitImageExpiredConsumptionNumber
alloc := minInt(need, minInt(limitRemain, totalRemain))
if alloc > 0 {
tb.TaskIncreaseLimitImageExpiredConsumptionNumber += alloc
tb.TaskMonthlyLimitImageExpireConsumptionNumber += alloc
tb.TaskMonthlyIncreaseImageConsumptionNumber += alloc
need -= alloc
}
}
// 限制不过期 - 套餐
if need > 0 {
limitRemain := tb.TaskMonthlyLimitImageNumber - tb.TaskMonthlyLimitImageConsumptionNumber
totalRemain := tb.TaskBundleLimitImageNumber - tb.TaskBundleLimitImageConsumptionNumber
alloc := minInt(need, minInt(limitRemain, totalRemain))
if alloc > 0 {
tb.TaskBundleLimitImageConsumptionNumber += alloc
tb.TaskMonthlyLimitImageConsumptionNumber += alloc
tb.TaskMonthlyBundleImageConsumptionNumber += alloc
need -= alloc
}
}
// 限制不过期 - 增值
if need > 0 {
limitRemain := tb.TaskMonthlyLimitImageNumber - tb.TaskMonthlyLimitImageConsumptionNumber
totalRemain := tb.TaskIncreaseLimitImageNumber - tb.TaskIncreaseLimitImageConsumptionNumber
alloc := minInt(need, minInt(limitRemain, totalRemain))
if alloc > 0 {
tb.TaskIncreaseLimitImageConsumptionNumber += alloc
tb.TaskMonthlyLimitImageConsumptionNumber += alloc
tb.TaskMonthlyIncreaseImageConsumptionNumber += alloc
need -= alloc
}
}
// 非限制 - 套餐
if need > 0 {
totalRemain := tb.TaskBundleImageNumber - tb.TaskBundleImageConsumptionNumber
alloc := minInt(need, totalRemain)
if alloc > 0 {
tb.TaskBundleImageConsumptionNumber += alloc
tb.TaskMonthlyBundleImageConsumptionNumber += alloc
need -= alloc
}
}
// 非限制 - 增值
if need > 0 {
totalRemain := tb.TaskIncreaseImageNumber - tb.TaskIncreaseImageConsumptionNumber
alloc := minInt(need, totalRemain)
if alloc > 0 {
tb.TaskIncreaseImageConsumptionNumber += alloc
tb.TaskMonthlyIncreaseImageConsumptionNumber += alloc
need -= alloc
}
}
// 手动扩展
if need > 0 {
totalRemain := tb.TaskManualImageNumber - tb.TaskManualImageConsumptionNumber
alloc := minInt(need, totalRemain)
if alloc > 0 {
tb.TaskManualImageConsumptionNumber += alloc
tb.TaskMonthlyManualImageConsumptionNumber += alloc
need -= alloc
}
}
if need > 0 {
tx.Rollback()
return commonErr.ReturnError(nil, "可用图文数不足", "扣减图文数量超过当前余额或当月限额")
}
}
// 扣减数据分析
need = req.PendingDataCount
if need > 0 {
// 限制会过期 - 套餐
if need > 0 {
limitRemain := tb.TaskMonthlyLimitDataAnalysisExpireNumber - tb.TaskMonthlyLimitDataAnalysisExpireConsumptionNumber
totalRemain := tb.TaskBundleLimitDataAnalysisExpiredNumber - tb.TaskBundleLimitDataAnalysisExpiredConsumptionNumber
alloc := minInt(need, minInt(limitRemain, totalRemain))
if alloc > 0 {
tb.TaskBundleLimitDataAnalysisExpiredConsumptionNumber += alloc
tb.TaskMonthlyLimitDataAnalysisExpireConsumptionNumber += alloc
tb.TaskMonthlyBundleDataAnalysisConsumptionNumber += alloc
need -= alloc
}
}
// 限制会过期 - 增值
if need > 0 {
limitRemain := tb.TaskMonthlyLimitDataAnalysisExpireNumber - tb.TaskMonthlyLimitDataAnalysisExpireConsumptionNumber
totalRemain := tb.TaskIncreaseLimitDataAnalysisExpiredNumber - tb.TaskIncreaseLimitDataAnalysisExpiredConsumptionNumber
alloc := minInt(need, minInt(limitRemain, totalRemain))
if alloc > 0 {
tb.TaskIncreaseLimitDataAnalysisExpiredConsumptionNumber += alloc
tb.TaskMonthlyLimitDataAnalysisExpireConsumptionNumber += alloc
tb.TaskMonthlyIncreaseDataAnalysisConsumptionNumber += alloc
need -= alloc
}
}
// 限制不过期 - 套餐
if need > 0 {
limitRemain := tb.TaskMonthlyLimitDataAnalysisNumber - tb.TaskMonthlyLimitDataAnalysisConsumptionNumber
totalRemain := tb.TaskBundleLimitDataAnalysisNumber - tb.TaskBundleLimitDataAnalysisConsumptionNumber
alloc := minInt(need, minInt(limitRemain, totalRemain))
if alloc > 0 {
tb.TaskBundleLimitDataAnalysisConsumptionNumber += alloc
tb.TaskMonthlyLimitDataAnalysisConsumptionNumber += alloc
tb.TaskMonthlyBundleDataAnalysisConsumptionNumber += alloc
need -= alloc
}
}
// 限制不过期 - 增值
if need > 0 {
limitRemain := tb.TaskMonthlyLimitDataAnalysisNumber - tb.TaskMonthlyLimitDataAnalysisConsumptionNumber
totalRemain := tb.TaskIncreaseLimitDataAnalysisNumber - tb.TaskIncreaseLimitDataAnalysisConsumptionNumber
alloc := minInt(need, minInt(limitRemain, totalRemain))
if alloc > 0 {
tb.TaskIncreaseLimitDataAnalysisConsumptionNumber += alloc
tb.TaskMonthlyLimitDataAnalysisConsumptionNumber += alloc
tb.TaskMonthlyIncreaseDataAnalysisConsumptionNumber += alloc
need -= alloc
}
}
// 非限制 - 套餐
if need > 0 {
totalRemain := tb.TaskBundleDataAnalysisNumber - tb.TaskBundleDataAnalysisConsumptionNumber
alloc := minInt(need, totalRemain)
if alloc > 0 {
tb.TaskBundleDataAnalysisConsumptionNumber += alloc
tb.TaskMonthlyBundleDataAnalysisConsumptionNumber += alloc
need -= alloc
}
}
// 非限制 - 增值
if need > 0 {
totalRemain := tb.TaskIncreaseDataAnalysisNumber - tb.TaskIncreaseDataAnalysisConsumptionNumber
alloc := minInt(need, totalRemain)
if alloc > 0 {
tb.TaskIncreaseDataAnalysisConsumptionNumber += alloc
tb.TaskMonthlyIncreaseDataAnalysisConsumptionNumber += alloc
need -= alloc
}
}
// 手动扩展
if need > 0 {
totalRemain := tb.TaskManualDataAnalysisNumber - tb.TaskManualDataAnalysisConsumptionNumber
alloc := minInt(need, totalRemain)
if alloc > 0 {
tb.TaskManualDataAnalysisConsumptionNumber += alloc
tb.TaskMonthlyManualDataAnalysisConsumptionNumber += alloc
need -= alloc
}
}
if need > 0 {
tx.Rollback()
return commonErr.ReturnError(nil, "可用数据分析数不足", "扣减数据分析数量超过当前余额或当月限额")
}
}
// 保存余额
if err := tx.Model(&model.TaskBalance{}).Where("id = ?", tb.ID).Save(&tb).Error; err != nil {
tx.Rollback()
return commonErr.ReturnError(err, "更新任务余额失败", "更新任务余额失败: ")
}
// 写入操作日志(修改待发数量)
assignRecord := &model.TaskAssignRecords{
AssignRecordsUUID: uuid.New().String(),
SubNum: req.SubNum,
TelNum: req.TelNum,
ArtistName: req.ArtistName,
Status: 1,
ActualStatus: 1,
OperatorType: 2, // 2 是指派,现在把修改待发数量接口改成指派
Operator: req.Operator,
OperatorNum: req.OperatorNum,
OperatorTime: time.Now(),
TaskAssignee: req.TaskAssignee,
TaskAssigneeNum: req.TaskAssigneeNum,
PendingVideoCount: req.PendingVideoCount,
PendingPostCount: req.PendingPostCount,
PendingDataCount: req.PendingDataCount,
AssignVideoCount: 0,
AssignPostCount: 0,
AssignDataCount: 0,
CompleteVideoCount: 0,
CompletePostCount: 0,
CompleteDataCount: 0,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
if err := tx.Create(assignRecord).Error; err != nil {
tx.Rollback()
return commonErr.ReturnError(err, "记录任务操作日志失败", "创建修改待发数量记录失败: ")
}
// 提交事务
if err := tx.Commit().Error; err != nil {
return commonErr.ReturnError(err, "提交事务失败", "提交事务失败: ")
}
return nil
}
// minInt 返回两个整数的最小值
func minInt(a, b int) int {
if a < b {
return a
}
return b
}
// GetAssignRecordByUUID 根据UUID查询指派记录
func GetAssignRecordByUUID(uuid string) (*model.TaskAssignRecords, error) {
var record model.TaskAssignRecords

View File

@ -1,7 +1,6 @@
package logic
import (
"fmt"
"micro-bundle/internal/dao"
commonErr "micro-bundle/pkg/err"
"sort"
@ -221,17 +220,14 @@ func UpdatePendingCount(req *dao.UpdatePendingCountRequest) error {
return commonErr.ReturnError(nil, "艺人套餐已过期", "该艺人没有有效的套餐,无法修改待发数量")
}
// 查询艺人当前任务余额,校验余额的总和是否足够
resp, err := dao.GetRemainingPendingBySubNum(req.SubNum)
// 查询艺人当前任务余额,校验是否存在记录(不做数量比较,避免排除手动余额)
_, err = dao.GetRemainingPendingBySubNum(req.SubNum)
if err != nil {
return commonErr.ReturnError(err, "查询艺人任务余额失败", "查询艺人任务余额失败: ")
}
fmt.Println(resp)
// 2. 调用DAO层更新待发数量
// return dao.UpdatePendingCount(req)
return nil
// 2. 调用DAO层更新待发数量DAO 内部已做充足的额度与当月限额校验)
return dao.UpdatePendingCount(req)
}
// GetRecentAssignRecords 查询最近被指派记录
@ -384,3 +380,7 @@ func calculatePendingFromTaskBalance(subNum string) (videoTotal, imageTotal, dat
return videoTotal, imageTotal, dataTotal
}
func UpdateTaskBalanceEveryMonLogic() {
dao.UpdateTaskBalanceEveryMon()
}

View File

@ -93,6 +93,11 @@ type TaskBalance struct {
TaskMonthlyIncreaseVideoConsumptionNumber int `gorm:"column:task_monthly_increase_video_consumption_number;not null;comment:任务当月增值类型总使用数" json:"taskMonthlyIncreaseVideoConsumptionNumber"`
TaskMonthlyLimitVideoQuotaNumber int `gorm:"column:task_monthly_limit_video_quota_number;not null;comment:任务当月限制类型视频额度" json:"taskMonthlyLimitVideoQuotaNumber"`
TaskManualVideoNumber int `gorm:"column:task_manual_video_number;comment:手动扩展视频总数"`
TaskManualVideoConsumptionNumber int `gorm:"column:task_manual_video_consumption_number;comment:手动扩展视频使用数"`
TaskMonthlyNewManualVideoNumber int `gorm:"column:task_monthly_new_manual_video_number;comment:当月手动扩展视频新增数"`
TaskMonthlyManualVideoConsumptionNumber int `gorm:"column:task_monthly_manual_video_consumption_number;comment:当月手动扩展视频使用数"`
// ===== 任务图片类 =====
TaskBundleImageNumber int `gorm:"column:task_bundle_image_number;not null;comment:任务非限制类型套餐权益图片总数" json:"taskBundleImageNumber"`
TaskIncreaseImageNumber int `gorm:"column:task_increase_image_number;not null;comment:任务非限制类型增值权益图片总数" json:"taskIncreaseImageNumber"`
@ -118,6 +123,11 @@ type TaskBalance struct {
TaskMonthlyIncreaseImageConsumptionNumber int `gorm:"column:task_monthly_increase_image_consumption_number;not null;comment:任务当月增值类型总使用数" json:"taskMonthlyIncreaseImageConsumptionNumber"`
TaskMonthlyLimitImageQuotaNumber int `gorm:"column:task_monthly_limit_image_quota_number;not null;comment:任务当月限制类型图片额度" json:"taskMonthlyLimitImageQuotaNumber"`
TaskManualImageNumber int `gorm:"column:task_manual_image_number;comment:手动扩展图片总数"`
TaskManualImageConsumptionNumber int `gorm:"column:task_manual_image_consumption_number;comment:手动扩展图片使用数"`
TaskMonthlyNewManualImageNumber int `gorm:"column:task_monthly_new_manual_image_number;comment:当月手动扩展图片新增数"`
TaskMonthlyManualImageConsumptionNumber int `gorm:"column:task_monthly_manual_image_consumption_number;comment:当月手动扩展图片使用数"`
// ===== 任务数据分析类 =====
TaskBundleDataAnalysisNumber int `gorm:"column:task_bundle_data_analysis_number;not null;comment:任务非限制类型套餐权益数据分析总数" json:"taskBundleDataAnalysisNumber"`
TaskIncreaseDataAnalysisNumber int `gorm:"column:task_increase_data_analysis_number;not null;comment:任务非限制类型增值权益数据分析总数" json:"taskIncreaseDataAnalysisNumber"`
@ -143,6 +153,14 @@ type TaskBalance struct {
TaskMonthlyIncreaseDataAnalysisConsumptionNumber int `gorm:"column:task_monthly_increase_data_analysis_consumption_number;not null;comment:任务当月增值类型总使用数" json:"taskMonthlyIncreaseDataAnalysisConsumptionNumber"`
TaskMonthlyLimitDataAnalysisQuotaNumber int `gorm:"column:task_monthly_limit_data_analysis_quota_number;not null;comment:任务当月限制类型数据分析额度" json:"taskMonthlyLimitDataAnalysisQuotaNumber"`
TaskManualDataAnalysisNumber int `gorm:"column:task_manual_data_analysis_number;comment:手动扩展数据分析总数"`
TaskManualDataAnalysisConsumptionNumber int `gorm:"column:task_manual_data_analysis_consumption_number;comment:手动扩展数据分析使用数"`
TaskMonthlyNewManualDataAnalysisNumber int `gorm:"column:task_monthly_new_manual_data_analysis_number;comment:当月手动扩展数据分析新增数"`
TaskMonthlyManualDataAnalysisConsumptionNumber int `gorm:"column:task_monthly_manual_data_analysis_consumption_number;comment:当月手动扩展数据分析使用数"`
TaskMonthlyNewDurationNumber int `gorm:"column:task_monthly_new_duration_number;comment:当月新增手动扩展时长(天)"`
TaskExpansionPacksNumber int `gorm:"column:task_expansion_packs_number;not null;comment:扩展包数量"`
CreatedAt time.Time `gorm:"column:created_at;comment:创建时间" json:"createdAt"`
UpdatedAt time.Time `gorm:"column:updated_at;comment:更新时间" json:"updatedAt"`
DeletedAt soft_delete.DeletedAt `gorm:"column:deleted_at;type:int(11);index:idx_task_balance_deleted_at" json:"deletedAt"`
@ -152,6 +170,20 @@ func (t *TaskBalance) TableName() string {
return "task_balance"
}
// TaskSyncStatus 用于标记一次性任务余额同步是否已经执行
// 记录键唯一,避免重复执行
type TaskSyncStatus struct {
ID int64 `gorm:"primarykey"`
SyncKey string `gorm:"column:sync_key;type:varchar(100);uniqueIndex;not null"`
ExecutedAt time.Time `gorm:"column:executed_at;type:datetime;not null"`
Remark string `gorm:"column:remark;type:varchar(255)"`
}
func (TaskSyncStatus) TableName() string { return "task_sync_status" }
// InitialSyncKey 一次性同步的唯一标识键
const InitialSyncKey = "bundle_to_task_balance_initial_sync"
// 任务日志表
type TaskLog struct {
LogUUID string `gorm:"column:log_uuid;type:varchar(50);comment:任务日志UUID;not null" json:"taskLogUUID"`

View File

@ -1146,6 +1146,8 @@ message UpdatePendingCountRequest {
int32 pendingDataCount = 6 [json_name = "pendingDataCount"]; //
string operator = 7 [json_name = "operator"]; //
string operatorNum = 8 [json_name = "operatorNum"]; //
string taskAssignee = 9 [json_name = "taskAssignee"]; //
string taskAssigneeNum = 10 [json_name = "taskAssigneeNum"]; //
}
//

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
package cron
import (
"fmt"
"log"
"micro-bundle/internal/logic"
@ -20,6 +21,17 @@ func InitCronJob() {
panic(err)
}
// 避免冲突,任务余额每月更新定时任务 - 每月1号1点执行
taskBalanceSpec := "0 0 1 1 * *"
_, err = c.AddFunc(taskBalanceSpec, func() {
log.Printf("执行任务余额每月数据更新")
logic.UpdateTaskBalanceEveryMonLogic()
})
if err != nil {
fmt.Println("添加任务余额每月数据更新定时任务失败", err)
panic(err)
}
c.Start()
}

View File

@ -107,6 +107,7 @@ func loadTaskBenchMysqlConn(conn string) *gorm.DB {
&model.TaskAssignRecords{},
&model.TaskBalance{},
&model.TaskLog{},
&model.TaskSyncStatus{},
)
if err != nil {