Merge branch 'feat-cjy-taskBench' into dev

This commit is contained in:
cjy 2025-10-22 12:46:45 +08:00
commit 947651ea3f
2 changed files with 90 additions and 58 deletions

View File

@ -41,31 +41,34 @@ func RunInitialTaskBalanceSync() error {
return nil return nil
} }
// 直接获取所有BundleBalance记录进行同步不再依赖GetValidArtistList的严格过滤 // 获取当前有效(未过期且已支付)的艺人及其最新订单
var bundleBalances []model.BundleBalance validArtists, err := GetValidArtistList()
if err := app.ModuleClients.BundleDB.Find(&bundleBalances).Error; err != nil { if err != nil {
return err return err
} }
fmt.Println(validArtists)
if len(bundleBalances) == 0 { if len(validArtists) == 0 {
_ = app.ModuleClients.TaskBenchDB.Create(&model.TaskSyncStatus{ // 不写入已执行标记,留待后续有数据时再次执行
SyncKey: model.InitialSyncKey, fmt.Println("无数据更新")
ExecutedAt: time.Now(),
Remark: "skipped: no bundle_balance records found",
}).Error
return nil return nil
} }
// 构造待插入的 TaskBalance 列表 // 构造待插入的 TaskBalance 列表
tasks := make([]model.TaskBalance, 0, len(bundleBalances)) tasks := make([]model.TaskBalance, 0, len(validArtists))
skippedCount := 0 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
}
for _, bb := range bundleBalances {
subNum, telNum, err := fetchIdentityForBundle(&bb) subNum, telNum, err := fetchIdentityForBundle(&bb)
if err != nil { if err != nil {
// 无法获取身份信息则跳过该条,但记录跳过数量 // 无法获取身份信息则跳过该条
fmt.Println("跳过 BundleBalance ID:", bb.ID, "错误:", err)
skippedCount++
continue continue
} }
@ -82,7 +85,7 @@ func RunInitialTaskBalanceSync() error {
tasks = append(tasks, tb) tasks = append(tasks, tb)
} }
// 原子写入:插入 TaskBalance + 插入标记 // 原子写入:插入 TaskBalance + 插入标记(确保有插入才写标记)
tx := app.ModuleClients.TaskBenchDB.Begin() tx := app.ModuleClients.TaskBenchDB.Begin()
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
@ -90,23 +93,20 @@ func RunInitialTaskBalanceSync() error {
} }
}() }()
if len(tasks) > 0 { if len(tasks) == 0 {
// 没有可插入的数据,不写标记,直接返回
tx.Rollback()
return nil
}
if err := tx.Create(&tasks).Error; err != nil { if err := tx.Create(&tasks).Error; err != nil {
tx.Rollback() tx.Rollback()
return err return err
} }
}
// 记录同步结果
remark := "initial sync executed"
if skippedCount > 0 {
remark = fmt.Sprintf("initial sync executed with %d records skipped due to missing identity info", skippedCount)
}
if err := tx.Create(&model.TaskSyncStatus{ if err := tx.Create(&model.TaskSyncStatus{
SyncKey: model.InitialSyncKey, SyncKey: model.InitialSyncKey,
ExecutedAt: time.Now(), ExecutedAt: time.Now(),
Remark: remark, Remark: "initial sync executed",
}).Error; err != nil { }).Error; err != nil {
tx.Rollback() tx.Rollback()
return err return err
@ -159,33 +159,27 @@ func SyncTaskBalanceFromBundleBalance(bb model.BundleBalance) error {
// fetchIdentityForBundle 根据 BundleBalance 拿到 sub_num 与 tel_num // fetchIdentityForBundle 根据 BundleBalance 拿到 sub_num 与 tel_num
func fetchIdentityForBundle(bb *model.BundleBalance) (string, string, error) { func fetchIdentityForBundle(bb *model.BundleBalance) (string, string, error) {
// tel_num 来自 micro-account.user // tel_num 来自 micro-account.user
var telNum string type userRow struct {
Tel string
}
var ur userRow
if err := app.ModuleClients.BundleDB.Table("`micro-account`.`user`").Unscoped(). if err := app.ModuleClients.BundleDB.Table("`micro-account`.`user`").Unscoped().
Select("tel_num").Where("id = ?", bb.UserId).Scan(&telNum).Error; err != nil { Select("tel_num AS tel").Where("id = ?", bb.UserId).Limit(1).Scan(&ur).Error; err != nil {
return "", "", err return "", "", err
} }
// customer_num 来自 bundle_order_records按 order_uuid // customer_num 来自 bundle_order_records按 order_uuid
// 添加容错机制如果order_uuid为空或查询失败使用user_id作为备用方案
var customerNum string
if bb.OrderUUID != "" {
type orderRow struct { type orderRow struct {
Customer string `gorm:"column:customer_num"` Customer string
} }
var or orderRow var or orderRow
if bb.OrderUUID == "" {
return "", "", errors.New("bundle order_uuid missing")
}
if err := app.ModuleClients.BundleDB.Table("bundle_order_records"). if err := app.ModuleClients.BundleDB.Table("bundle_order_records").
Select("customer_num").Where("uuid = ?", bb.OrderUUID).First(&or).Error; err != nil { Select("customer_num AS customer").Where("uuid = ?", bb.OrderUUID).Limit(1).Scan(&or).Error; err != nil {
// 如果查询失败如记录不存在使用user_id作为备用customer_num return "", "", err
customerNum = fmt.Sprintf("user_%d", bb.UserId)
} else {
customerNum = or.Customer
} }
} else { return or.Customer, ur.Tel, nil
// 如果order_uuid为空使用user_id作为备用customer_num
customerNum = fmt.Sprintf("user_%d", bb.UserId)
}
return customerNum, telNum, nil
} }
// UpdateTaskBalance 每月批量更新任务余额 // UpdateTaskBalance 每月批量更新任务余额

View File

@ -1,10 +1,12 @@
package dao package dao
import ( import (
"fmt"
"micro-bundle/internal/model" "micro-bundle/internal/model"
"micro-bundle/pkg/app" "micro-bundle/pkg/app"
commonErr "micro-bundle/pkg/err" commonErr "micro-bundle/pkg/err"
"time" "time"
"strings"
"github.com/google/uuid" "github.com/google/uuid"
"gorm.io/gorm" "gorm.io/gorm"
@ -1071,7 +1073,7 @@ func GetTaskAssignRecordsList(req *TaskAssignRecordsQueryRequest) ([]*model.Task
} }
// GetValidArtistList 查询套餐状态为有效中的艺人数据列表 // GetValidArtistList 查询套餐状态为有效中的艺人数据列表
// 根据BundleOrderRecords表查询过期时间大于当前时间且状态为已支付的艺人详细信息 // 根据BundleOrderRecords表查询过期时间大于当前时间且状态为已支付,同时已激活的艺人详细信息
func GetValidArtistList() ([]ValidArtistInfo, error) { func GetValidArtistList() ([]ValidArtistInfo, error) {
// 构建子查询,获取每个用户的最新订单记录 // 构建子查询,获取每个用户的最新订单记录
subQuery := app.ModuleClients.BundleDB.Table("bundle_order_records as bor1"). subQuery := app.ModuleClients.BundleDB.Table("bundle_order_records as bor1").
@ -1083,7 +1085,7 @@ func GetValidArtistList() ([]ValidArtistInfo, error) {
) bor2 ON bor1.customer_id = bor2.customer_id AND bor1.created_at = bor2.max_created_time`) ) bor2 ON bor1.customer_id = bor2.customer_id AND bor1.created_at = bor2.max_created_time`)
// 主查询,关联用户表和实名信息表 // 主查询,关联用户表和实名信息表
session := app.ModuleClients.BundleDB.Table("`micro-account`.`user` AS u"). session := app.ModuleClients.BundleDB.Table("`micro-account`.`user` AS u").Unscoped().
Select(`u.id as user_id, bor.customer_num, rn.name as user_name, Select(`u.id as user_id, bor.customer_num, rn.name as user_name,
u.tel_num as user_phone_number, bor.bundle_name, bor.expiration_time, u.tel_num as user_phone_number, bor.bundle_name, bor.expiration_time,
bor.status, bor.uuid as order_uuid, bor.status, bor.uuid as order_uuid,
@ -1098,11 +1100,14 @@ func GetValidArtistList() ([]ValidArtistInfo, error) {
bb.expansion_packs_number`). bb.expansion_packs_number`).
Joins("LEFT JOIN `micro-account`.real_name rn ON u.real_name_id = rn.id"). Joins("LEFT JOIN `micro-account`.real_name rn ON u.real_name_id = rn.id").
Joins("LEFT JOIN (?) as bor ON bor.customer_id = u.id", subQuery). Joins("LEFT JOIN (?) as bor ON bor.customer_id = u.id", subQuery).
Joins("LEFT JOIN bundle_balance bb ON u.id = bb.user_id AND bb.order_uuid = bor.uuid"). Joins("LEFT JOIN fiee_bundle.bundle_balance bb ON u.id = bb.user_id AND bb.order_uuid = bor.uuid").
Joins("LEFT JOIN bundle_activate bc ON bc.user_id = u.id").
Where("rn.name IS NOT NULL"). Where("rn.name IS NOT NULL").
Where("u.deleted_at = 0"). Where("u.deleted_at = 0").
Where("bor.expiration_time > ?", time.Now().Format("2006-01-02 15:04:05")). Where("bor.deleted_at IS NULL").
Where("bor.status = ?", 2). // 2:已签已支付 Where("bb.expired_at > ?", time.Now()).
Where("bc.activate = ?", 2).
Where("bb.month = ?", time.Now().Format("2006-01")).
Order("bor.expiration_time desc") Order("bor.expiration_time desc")
var data []ValidArtistInfo var data []ValidArtistInfo
@ -1111,6 +1116,7 @@ func GetValidArtistList() ([]ValidArtistInfo, error) {
return nil, commonErr.ReturnError(err, "查询有效艺人失败", "查询有效艺人失败: ") return nil, commonErr.ReturnError(err, "查询有效艺人失败", "查询有效艺人失败: ")
} }
fmt.Println(data)
return data, nil return data, nil
} }
@ -1182,11 +1188,14 @@ func GetPendingTaskList(req *TaskQueryRequest, validArtist []ValidArtistInfo) ([
return nil, 0, commonErr.ReturnError(err, "查询待指派任务记录失败", "查询待指派任务记录失败: ") return nil, 0, commonErr.ReturnError(err, "查询待指派任务记录失败", "查询待指派任务记录失败: ")
} }
// 统计总数(分页前) // 构建已存在的 sub_num 集合,用于补充缺失的有效艺人
total := int64(len(tmList)) existingSubNums := make(map[string]struct{}, len(tmList))
for _, t := range tmList {
existingSubNums[t.SubNum] = struct{}{}
}
// 映射为响应结构(基础字段) // 映射为响应结构(基础字段)
resp := make([]*TaskQueryResponse, 0, len(tmList)) resp := make([]*TaskQueryResponse, 0, len(tmList)+len(validArtist))
for _, t := range tmList { for _, t := range tmList {
resp = append(resp, &TaskQueryResponse{ resp = append(resp, &TaskQueryResponse{
SubNum: t.SubNum, SubNum: t.SubNum,
@ -1197,5 +1206,34 @@ func GetPendingTaskList(req *TaskQueryRequest, validArtist []ValidArtistInfo) ([
}) })
} }
// 追加:对在 TaskManagement 中不存在的有效艺人构建基础记录
for _, a := range validArtist {
if a.CustomerNum == "" {
continue
}
if _, ok := existingSubNums[a.CustomerNum]; ok {
continue
}
// 关键词过滤(与查询条件保持一致)
if req.Keyword != "" {
kw := strings.ToLower(req.Keyword)
if !(strings.Contains(strings.ToLower(a.CustomerNum), kw) ||
strings.Contains(strings.ToLower(a.UserPhoneNumber), kw) ||
strings.Contains(strings.ToLower(a.UserName), kw)) {
continue
}
}
resp = append(resp, &TaskQueryResponse{
SubNum: a.CustomerNum,
TelNum: a.UserPhoneNumber,
ArtistName: a.UserName,
LastTaskAssignee: "",
TaskAssigneeNum: "",
})
}
// 统计总数(分页前)
total := int64(len(resp))
return resp, total, nil return resp, total, nil
} }