Update:任务管理台统计接入先用后付维度
- proto/dto: TaskQueryRequest、BatchAssignTaskItem、PendingAssignRequest 新增 bundle_task_type 字段;dto 拆出 PendingAssignQueryRequest - 艺人上传统计/可指派数量查询:抽出 target_orders + active_order_balances 作为共享 CTE,普通套餐仍按"每用户最新一单"过滤,先用后付按 pay_later_status IN (1,2) 取全部有效单,并在 active_windows 里 按 user_id 聚合多条先用后付订单的配额 - cast_work(视频)和 cast_video_script 统计按 billing_type 过滤, task_assign_records / task_management 按 bundle_task_type 过滤, AssignTask / BatchAssignTasks / CompleteTaskManually / GetArtistTaskStatsBySubNum 全部加入 bundle_task_type 维度 - 顺手修 pkg/db/mysql.go 里 fmt.Println 用了 %s 占位符不生效的问题
This commit is contained in:
parent
0a1878e5ae
commit
06fb278dcc
@ -197,19 +197,19 @@ func (b *BundleProvider) GetTaskAssignRecordsList(_ context.Context, req *bundle
|
||||
req.SortBy = sortBy
|
||||
}
|
||||
daoReq := &dto.TaskAssignRecordsQueryRequest{
|
||||
Keyword: req.Keyword,
|
||||
TaskAssignee: req.TaskAssignee,
|
||||
Operator: req.Operator,
|
||||
OperatorNum: req.OperatorNum,
|
||||
StartTime: req.StartTime,
|
||||
EndTime: req.EndTime,
|
||||
Status: int(req.Status),
|
||||
ActualStatus: int(req.ActualStatus),
|
||||
Page: int(req.Page),
|
||||
PageSize: int(req.PageSize),
|
||||
TaskBatch: req.TaskBatch,
|
||||
SortBy: req.SortBy,
|
||||
SortType: req.SortType,
|
||||
Keyword: req.Keyword,
|
||||
TaskAssignee: req.TaskAssignee,
|
||||
Operator: req.Operator,
|
||||
OperatorNum: req.OperatorNum,
|
||||
StartTime: req.StartTime,
|
||||
EndTime: req.EndTime,
|
||||
Status: int(req.Status),
|
||||
ActualStatus: int(req.ActualStatus),
|
||||
Page: int(req.Page),
|
||||
PageSize: int(req.PageSize),
|
||||
TaskBatch: req.TaskBatch,
|
||||
SortBy: req.SortBy,
|
||||
SortType: req.SortType,
|
||||
BundleTaskType: int(req.BundleTaskType),
|
||||
}
|
||||
|
||||
@ -318,6 +318,7 @@ func (b *BundleProvider) BatchAssignTask(_ context.Context, req *bundle.BatchAss
|
||||
AssignReportCount: int(it.AssignReportCount),
|
||||
TaskBatch: it.TaskBatch,
|
||||
UserID: int(it.UserID),
|
||||
BundleTaskType: int(it.BundleTaskType),
|
||||
})
|
||||
}
|
||||
|
||||
@ -343,6 +344,7 @@ func (b *BundleProvider) GetArtistUploadStatsList(_ context.Context, req *bundle
|
||||
SortType: req.SortType,
|
||||
LastTaskAssignee: req.LastTaskAssignee,
|
||||
SubNums: req.SubNums,
|
||||
BundleTaskType: int(req.BundleTaskType),
|
||||
}
|
||||
|
||||
items, total, err := logic.GetArtistUploadStatsList(daoReq)
|
||||
@ -414,7 +416,12 @@ func (b *BundleProvider) GetArtistUploadStatsList(_ context.Context, req *bundle
|
||||
|
||||
// GetPendingAssign 查询艺人可指派数量
|
||||
func (b *BundleProvider) GetPendingAssign(_ context.Context, req *bundle.PendingAssignRequest) (*bundle.PendingAssignResponse, error) {
|
||||
items, total, err := logic.GetPendingAssignBySubNums(req.SubNums, int(req.Page), int(req.PageSize))
|
||||
items, total, err := logic.GetPendingAssignBySubNums(&dto.PendingAssignQueryRequest{
|
||||
SubNums: req.SubNums,
|
||||
Page: int(req.Page),
|
||||
PageSize: int(req.PageSize),
|
||||
BundleTaskType: int(req.BundleTaskType),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -57,36 +57,63 @@ func AddHiddenTaskAssignee(taskAssignee string, taskAssigneeNum string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func normalizeBundleTaskType(bundleTaskType int) int {
|
||||
if bundleTaskType == model.BundleTaskTypePayLater {
|
||||
return model.BundleTaskTypePayLater
|
||||
}
|
||||
return model.BundleTaskTypeNormal
|
||||
}
|
||||
|
||||
func taskStatsQueryOptions(bundleTaskType int) (int, int, string, string) {
|
||||
taskType := normalizeBundleTaskType(bundleTaskType)
|
||||
if taskType == model.BundleTaskTypePayLater {
|
||||
return taskType, model.BillingTypeBNPL, "bor.order_mode = 2 AND bor.pay_later_status IN (1, 2)", ""
|
||||
}
|
||||
|
||||
return taskType, model.BillingTypeNormal, "bor.status = 2 AND IFNULL(bor.order_mode, 1) = 1", `
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM bundle_order_records bor2
|
||||
WHERE bor2.customer_id = bor.customer_id
|
||||
AND bor2.deleted_at IS NULL
|
||||
AND bor2.customer_id IS NOT NULL
|
||||
AND bor2.status = 2
|
||||
AND IFNULL(bor2.order_mode, 1) = 1
|
||||
AND (bor2.created_at > bor.created_at OR (bor2.created_at = bor.created_at AND bor2.id > bor.id))
|
||||
)`
|
||||
}
|
||||
|
||||
// GetArtistUploadStatsList 查询所有艺人的上传统计与额度信息(通过 BundleBalance 关联 CastWork/CastWorkAnalysis,及 subNum 关联 TaskManagement)
|
||||
func GetArtistUploadStatsList(req *dto.TaskQueryRequest) ([]*dto.ArtistUploadStatsItem, int64, error) {
|
||||
taskSchema := bundleConfig.Data.TaskBenchDB.DbName
|
||||
nowMonth := time.Now().Format("2006-01")
|
||||
bundleTaskType := 0
|
||||
if req != nil {
|
||||
bundleTaskType = req.BundleTaskType
|
||||
}
|
||||
taskType, billingType, orderFilter, latestOrderFilter := taskStatsQueryOptions(bundleTaskType)
|
||||
|
||||
cte := `WITH
|
||||
-- 1. 获取每个用户最新的订单记录(使用NOT EXISTS避免窗口函数重复物化)
|
||||
latest_bor AS (
|
||||
cte := fmt.Sprintf(`WITH
|
||||
-- 1. 获取当前套餐类型下参与统计的订单。基础套餐取每个用户最新普通订单,先用后付取所有待付款/已付款订单
|
||||
target_orders AS (
|
||||
SELECT bor.id, bor.uuid, bor.customer_id, bor.customer_num, bor.created_at
|
||||
FROM bundle_order_records bor
|
||||
WHERE bor.deleted_at IS NULL
|
||||
AND bor.customer_id IS NOT NULL
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM bundle_order_records bor2
|
||||
WHERE bor2.customer_id = bor.customer_id
|
||||
AND bor2.deleted_at IS NULL
|
||||
AND (bor2.created_at > bor.created_at OR (bor2.created_at = bor.created_at AND bor2.id > bor.id))
|
||||
)
|
||||
AND %s%s
|
||||
),
|
||||
|
||||
-- 2. 获取每个用户的最新月份
|
||||
newest_month AS (
|
||||
SELECT user_id, MAX(month) AS month
|
||||
FROM bundle_balance
|
||||
WHERE deleted_at IS NULL
|
||||
GROUP BY user_id
|
||||
-- 2. 每个目标订单的最新月份余额
|
||||
newest_order_month AS (
|
||||
SELECT bb.user_id, bb.order_uuid, MAX(bb.month) AS month
|
||||
FROM bundle_balance bb
|
||||
INNER JOIN target_orders bor ON bor.uuid = bb.order_uuid
|
||||
WHERE bb.deleted_at IS NULL
|
||||
AND bb.month <= ?
|
||||
GROUP BY bb.user_id, bb.order_uuid
|
||||
),
|
||||
|
||||
-- 3. 活跃窗口:包含所有必要字段,作为核心CTE
|
||||
active_windows AS (
|
||||
-- 3. 目标订单的活跃余额明细
|
||||
active_order_balances AS (
|
||||
SELECT
|
||||
u.id AS user_id,
|
||||
u.tel_num COLLATE utf8mb4_0900_ai_ci AS phone,
|
||||
@ -95,38 +122,103 @@ active_windows AS (
|
||||
bb.start_at,
|
||||
bb.expired_at,
|
||||
bb.bundle_video_number, bb.bundle_limit_video_number, bb.bundle_limit_video_expired_number,
|
||||
bb.monthly_bundle_limit_video_number, bb.monthly_bundle_limit_expired_video_number,
|
||||
bb.invalid_bundle_video_number, bb.bundle_limit_video_consumption_number,
|
||||
bb.bundle_limit_video_expired_consumption_number, bb.monthly_bundle_limit_expired_video_consumption_number,
|
||||
bb.monthly_bundle_limit_video_consumption_number,
|
||||
bb.increase_video_number, bb.increase_limit_video_number, bb.increase_limit_video_expired_number,
|
||||
bb.monthly_increase_limit_video_number, bb.monthly_increase_limit_expired_video_number,
|
||||
bb.invalid_increase_video_number, bb.increase_limit_video_consumption_number,
|
||||
bb.increase_limit_video_expired_consumption_number, bb.monthly_increase_limit_expired_video_consumption_number,
|
||||
bb.monthly_increase_limit_video_consumption_number,
|
||||
bb.manual_video_number, bb.manual_video_consumption_number,
|
||||
bb.bundle_image_number, bb.bundle_limit_image_number, bb.bundle_limit_image_expired_number,
|
||||
bb.monthly_bundle_limit_image_number, bb.monthly_bundle_limit_expired_image_number,
|
||||
bb.invalid_bundle_image_number, bb.bundle_limit_image_consumption_number,
|
||||
bb.bundle_limit_image_expired_consumption_number, bb.monthly_bundle_limit_expired_image_consumption_number,
|
||||
bb.monthly_bundle_limit_image_consumption_number,
|
||||
bb.increase_image_number, bb.increase_limit_image_number, bb.increase_limit_image_expired_number,
|
||||
bb.monthly_increase_limit_image_number, bb.monthly_increase_limit_expired_image_number,
|
||||
bb.invalid_increase_image_number, bb.increase_limit_image_consumption_number,
|
||||
bb.increase_limit_image_expired_consumption_number, bb.monthly_increase_limit_expired_image_consumption_number,
|
||||
bb.monthly_increase_limit_image_consumption_number,
|
||||
bb.manual_image_number, bb.manual_image_consumption_number,
|
||||
bb.bundle_data_analysis_number, bb.bundle_limit_data_analysis_number, bb.bundle_limit_data_analysis_expired_number,
|
||||
bb.monthly_bundle_limit_data_analysis_number, bb.monthly_bundle_limit_data_analysis_expired_number,
|
||||
bb.invalid_bundle_data_analysis_number, bb.bundle_limit_data_analysis_consumption_number,
|
||||
bb.bundle_limit_data_analysis_expired_consumption_number, bb.monthly_bundle_limit_expired_data_analysis_consumption_number,
|
||||
bb.monthly_bundle_limit_data_analysis_consumption_number,
|
||||
bb.increase_data_analysis_number, bb.increase_limit_data_analysis_number, bb.increase_limit_data_analysis_expired_number,
|
||||
bb.monthly_increase_limit_data_analysis_number, bb.monthly_increase_limit_expired_data_analysis_number,
|
||||
bb.invalid_increase_data_analysis_number, bb.increase_limit_data_analysis_consumption_number,
|
||||
bb.increase_limit_data_analysis_expired_consumption_number, bb.monthly_increase_limit_expired_data_analysis_consumption_number,
|
||||
bb.monthly_increase_limit_data_analysis_consumption_number,
|
||||
bb.manual_data_analysis_number, bb.manual_data_analysis_consumption_number,
|
||||
bb.bundle_competitive_number, bb.bundle_limit_competitive_number, bb.bundle_limit_competitive_expired_number,
|
||||
bb.monthly_bundle_limit_competitive_number, bb.monthly_bundle_limit_expired_competitive_number,
|
||||
bb.invalid_bundle_competitive_number, bb.bundle_limit_competitive_consumption_number,
|
||||
bb.bundle_limit_competitive_expired_consumption_number, bb.monthly_bundle_limit_expired_competitive_consumption_number,
|
||||
bb.monthly_bundle_limit_competitive_consumption_number,
|
||||
bb.increase_competitive_number, bb.increase_limit_competitive_number, bb.increase_limit_competitive_expired_number,
|
||||
bb.monthly_increase_limit_competitive_number, bb.monthly_increase_limit_expired_competitive_number,
|
||||
bb.invalid_increase_competitive_number, bb.increase_limit_competitive_consumption_number,
|
||||
bb.increase_limit_competitive_expired_consumption_number, bb.monthly_increase_limit_expired_competitive_consumption_number,
|
||||
bb.monthly_increase_limit_competitive_consumption_number,
|
||||
bb.manual_competitive_number, bb.manual_competitive_consumption_number,
|
||||
rn.name COLLATE utf8mb4_0900_ai_ci AS user_name
|
||||
FROM ` + "`micro-account`.`user`" + ` u
|
||||
INNER JOIN ` + "`micro-account`.real_name" + ` rn ON rn.id = u.real_name_id AND rn.name IS NOT NULL AND rn.deleted_at = 0
|
||||
FROM `+"`micro-account`.`user`"+` u
|
||||
INNER JOIN `+"`micro-account`.real_name"+` rn ON rn.id = u.real_name_id AND rn.name IS NOT NULL AND rn.deleted_at = 0
|
||||
INNER JOIN bundle_activate bc ON bc.user_id = u.id AND bc.activate = 2
|
||||
INNER JOIN latest_bor bor ON bor.customer_id = u.id AND u.deleted_at = 0
|
||||
INNER JOIN newest_month nm ON nm.user_id = u.id
|
||||
INNER JOIN target_orders bor ON bor.customer_id = u.id AND u.deleted_at = 0
|
||||
INNER JOIN newest_order_month nm ON nm.user_id = u.id AND nm.order_uuid = bor.uuid
|
||||
INNER JOIN bundle_balance bb ON bb.user_id = u.id AND bb.order_uuid = bor.uuid AND bb.month = nm.month AND bb.deleted_at IS NULL
|
||||
WHERE u.deleted_at = 0
|
||||
AND DATE_ADD(UTC_TIMESTAMP(), INTERVAL 8 HOUR) BETWEEN bb.start_at AND bb.expired_at
|
||||
),
|
||||
|
||||
-- 4. 每个订单的最新月份余额
|
||||
latest_per_order AS (
|
||||
SELECT bb_inner.user_id, bb_inner.order_uuid, MAX(bb_inner.month) AS max_month
|
||||
FROM bundle_balance bb_inner
|
||||
INNER JOIN bundle_order_records bor_inner ON bor_inner.uuid = bb_inner.order_uuid
|
||||
AND bor_inner.deleted_at IS NULL
|
||||
AND bor_inner.status = 2
|
||||
WHERE bb_inner.deleted_at IS NULL
|
||||
AND bb_inner.month <= ?
|
||||
GROUP BY bb_inner.user_id, bb_inner.order_uuid
|
||||
-- 4. 活跃窗口:同一用户多条先用后付订单合并为一行
|
||||
active_windows AS (
|
||||
SELECT
|
||||
user_id,
|
||||
phone,
|
||||
customer_num,
|
||||
MIN(start_at) AS start_at,
|
||||
MAX(expired_at) AS expired_at,
|
||||
SUM(bundle_video_number) AS bundle_video_number,
|
||||
SUM(bundle_limit_video_number) AS bundle_limit_video_number,
|
||||
SUM(bundle_limit_video_expired_number) AS bundle_limit_video_expired_number,
|
||||
SUM(increase_video_number) AS increase_video_number,
|
||||
SUM(increase_limit_video_number) AS increase_limit_video_number,
|
||||
SUM(increase_limit_video_expired_number) AS increase_limit_video_expired_number,
|
||||
SUM(manual_video_number) AS manual_video_number,
|
||||
SUM(manual_video_consumption_number) AS manual_video_consumption_number,
|
||||
SUM(bundle_image_number) AS bundle_image_number,
|
||||
SUM(bundle_limit_image_number) AS bundle_limit_image_number,
|
||||
SUM(bundle_limit_image_expired_number) AS bundle_limit_image_expired_number,
|
||||
SUM(increase_image_number) AS increase_image_number,
|
||||
SUM(increase_limit_image_number) AS increase_limit_image_number,
|
||||
SUM(increase_limit_image_expired_number) AS increase_limit_image_expired_number,
|
||||
SUM(manual_image_number) AS manual_image_number,
|
||||
SUM(manual_image_consumption_number) AS manual_image_consumption_number,
|
||||
SUM(bundle_data_analysis_number) AS bundle_data_analysis_number,
|
||||
SUM(bundle_limit_data_analysis_number) AS bundle_limit_data_analysis_number,
|
||||
SUM(bundle_limit_data_analysis_expired_number) AS bundle_limit_data_analysis_expired_number,
|
||||
SUM(increase_data_analysis_number) AS increase_data_analysis_number,
|
||||
SUM(increase_limit_data_analysis_number) AS increase_limit_data_analysis_number,
|
||||
SUM(increase_limit_data_analysis_expired_number) AS increase_limit_data_analysis_expired_number,
|
||||
SUM(manual_data_analysis_number) AS manual_data_analysis_number,
|
||||
SUM(manual_data_analysis_consumption_number) AS manual_data_analysis_consumption_number,
|
||||
SUM(bundle_competitive_number) AS bundle_competitive_number,
|
||||
SUM(bundle_limit_competitive_number) AS bundle_limit_competitive_number,
|
||||
SUM(bundle_limit_competitive_expired_number) AS bundle_limit_competitive_expired_number,
|
||||
SUM(increase_competitive_number) AS increase_competitive_number,
|
||||
SUM(increase_limit_competitive_number) AS increase_limit_competitive_number,
|
||||
SUM(increase_limit_competitive_expired_number) AS increase_limit_competitive_expired_number,
|
||||
SUM(manual_competitive_number) AS manual_competitive_number,
|
||||
SUM(manual_competitive_consumption_number) AS manual_competitive_consumption_number,
|
||||
MAX(user_name) AS user_name
|
||||
FROM active_order_balances
|
||||
GROUP BY user_id, phone, customer_num
|
||||
),
|
||||
|
||||
-- 5. 余额汇总
|
||||
@ -167,15 +259,7 @@ balance_sum AS (
|
||||
+ bb2.invalid_increase_competitive_number + bb2.increase_limit_competitive_consumption_number
|
||||
+ bb2.increase_limit_competitive_expired_consumption_number - bb2.monthly_increase_limit_expired_competitive_consumption_number
|
||||
- bb2.monthly_increase_limit_competitive_consumption_number) AS increase_competitive_sum
|
||||
FROM bundle_balance bb2
|
||||
INNER JOIN latest_per_order lpo ON bb2.user_id = lpo.user_id
|
||||
AND bb2.order_uuid = lpo.order_uuid
|
||||
AND bb2.month = lpo.max_month
|
||||
INNER JOIN bundle_order_records bor2 ON bor2.uuid = bb2.order_uuid
|
||||
AND bor2.deleted_at IS NULL
|
||||
AND bor2.status = 2
|
||||
WHERE bb2.deleted_at IS NULL
|
||||
AND DATE_ADD(UTC_TIMESTAMP(), INTERVAL 8 HOUR) BETWEEN bb2.start_at AND bb2.expired_at
|
||||
FROM active_order_balances bb2
|
||||
GROUP BY bb2.user_id
|
||||
),
|
||||
|
||||
@ -189,6 +273,8 @@ cw_agg AS (
|
||||
COUNT(CASE WHEN cw.work_category = 1 AND cw.cost = 1 AND cw.deleted_at = 0 AND (cw.origin_uuid = '' OR cw.origin_uuid IS NULL) AND cw.submit_time BETWEEN aw.start_at AND aw.expired_at THEN 1 END) AS released_post_consumed
|
||||
FROM active_windows aw
|
||||
LEFT JOIN cast_work cw ON cw.artist_phone = aw.phone
|
||||
LEFT JOIN cast_work_extra cwe ON cwe.work_uuid = cw.uuid AND cwe.deleted_at = 0
|
||||
WHERE (cw.uuid IS NULL OR cw.work_category != 2 OR IFNULL(cwe.billing_type, 0) = ?)
|
||||
GROUP BY aw.user_id
|
||||
),
|
||||
|
||||
@ -222,6 +308,7 @@ cvs_agg AS (
|
||||
FROM active_windows aw
|
||||
LEFT JOIN cast_video_script cvs ON CAST(aw.user_id AS CHAR) = cvs.artist_uuid
|
||||
AND cvs.deleted_at = 0
|
||||
AND cvs.billing_type = ?
|
||||
AND cvs.created_at BETWEEN UNIX_TIMESTAMP(CONVERT_TZ(aw.start_at, '+00:00', '+00:00'))
|
||||
AND UNIX_TIMESTAMP(CONVERT_TZ(aw.expired_at, '+00:00', '+00:00'))
|
||||
GROUP BY aw.user_id
|
||||
@ -234,7 +321,8 @@ tar_agg AS (
|
||||
COUNT(CASE WHEN tar.status = 1 AND tar.deleted_at = 0 AND tar.created_at BETWEEN aw.start_at AND aw.expired_at THEN 1 END) AS progress_task_count,
|
||||
COUNT(CASE WHEN tar.status = 2 AND tar.deleted_at = 0 AND tar.created_at BETWEEN aw.start_at AND aw.expired_at THEN 1 END) AS complete_task_count
|
||||
FROM active_windows aw
|
||||
LEFT JOIN ` + "`" + taskSchema + "`" + `.task_assign_records tar ON tar.sub_num = aw.customer_num
|
||||
LEFT JOIN `+"`"+taskSchema+"`"+`.task_assign_records tar ON tar.sub_num = aw.customer_num
|
||||
AND tar.bundle_task_type = ?
|
||||
GROUP BY aw.user_id
|
||||
),
|
||||
|
||||
@ -273,9 +361,10 @@ assigned_pending_agg AS (
|
||||
END
|
||||
), 0) AS assigned_report_count
|
||||
FROM active_windows aw
|
||||
LEFT JOIN ` + "`" + taskSchema + "`" + `.task_assign_records tar ON tar.sub_num = aw.customer_num
|
||||
LEFT JOIN `+"`"+taskSchema+"`"+`.task_assign_records tar ON tar.sub_num = aw.customer_num
|
||||
AND tar.actual_status IN (1, 3)
|
||||
AND tar.deleted_at = 0
|
||||
AND tar.bundle_task_type = ?
|
||||
AND tar.created_at BETWEEN aw.start_at AND aw.expired_at
|
||||
GROUP BY aw.user_id
|
||||
),
|
||||
@ -283,15 +372,15 @@ assigned_pending_agg AS (
|
||||
-- 11. 任务管理信息
|
||||
task_mgmt AS (
|
||||
SELECT t.user_id, t.last_task_assignee, t.task_assignee_num
|
||||
FROM ` + "`" + taskSchema + "`" + `.task_management t
|
||||
FROM `+"`"+taskSchema+"`"+`.task_management t
|
||||
INNER JOIN (
|
||||
SELECT user_id, MAX(updated_at) AS max_updated_at
|
||||
FROM ` + "`" + taskSchema + "`" + `.task_management
|
||||
WHERE deleted_at = 0
|
||||
FROM `+"`"+taskSchema+"`"+`.task_management
|
||||
WHERE deleted_at = 0 AND bundle_task_type = ?
|
||||
GROUP BY user_id
|
||||
) x ON x.user_id = t.user_id AND x.max_updated_at = t.updated_at
|
||||
WHERE t.deleted_at = 0
|
||||
)`
|
||||
WHERE t.deleted_at = 0 AND t.bundle_task_type = ?
|
||||
)`, orderFilter, latestOrderFilter)
|
||||
|
||||
fromClause := `FROM active_windows aw
|
||||
LEFT JOIN balance_sum bs ON bs.user_id = aw.user_id
|
||||
@ -305,7 +394,7 @@ LEFT JOIN assigned_pending_agg apa ON apa.user_id = aw.user_id`
|
||||
|
||||
whereParts := make([]string, 0, 4)
|
||||
args := make([]interface{}, 0, 8)
|
||||
args = append(args, nowMonth)
|
||||
args = append(args, nowMonth, billingType, billingType, taskType, taskType, taskType, taskType)
|
||||
if req != nil && req.Keyword != "" {
|
||||
like := "%" + req.Keyword + "%"
|
||||
whereParts = append(whereParts, "(aw.customer_num LIKE ? OR aw.phone LIKE ? OR aw.user_name LIKE ?)")
|
||||
@ -445,40 +534,38 @@ LEFT JOIN assigned_pending_agg apa ON apa.user_id = aw.user_id`
|
||||
}
|
||||
|
||||
// GetPendingAssignBySubNums 查询指定艺人的可指派数量(可上传数 - 已指派且未完成的数量)
|
||||
func GetPendingAssignBySubNums(subNums []string, page int, pageSize int) ([]*dto.ArtistPendingAssignItem, int64, error) {
|
||||
if len(subNums) == 0 {
|
||||
func GetPendingAssignBySubNums(req *dto.PendingAssignQueryRequest) ([]*dto.ArtistPendingAssignItem, int64, error) {
|
||||
if req == nil || len(req.SubNums) == 0 {
|
||||
return []*dto.ArtistPendingAssignItem{}, 0, nil
|
||||
}
|
||||
|
||||
taskSchema := bundleConfig.Data.TaskBenchDB.DbName
|
||||
nowMonth := time.Now().Format("2006-01")
|
||||
taskType, billingType, orderFilter, latestOrderFilter := taskStatsQueryOptions(req.BundleTaskType)
|
||||
|
||||
cte := `WITH
|
||||
-- 1. 获取每个用户最新的订单记录(使用NOT EXISTS避免窗口函数重复物化)
|
||||
latest_bor AS (
|
||||
cte := fmt.Sprintf(`WITH
|
||||
-- 1. 获取当前套餐类型下参与统计的订单。基础套餐取每个用户最新普通订单,先用后付取所有待付款/已付款订单
|
||||
target_orders AS (
|
||||
SELECT bor.id, bor.uuid, bor.customer_id, bor.customer_num, bor.created_at
|
||||
FROM bundle_order_records bor
|
||||
WHERE bor.deleted_at IS NULL
|
||||
AND bor.customer_id IS NOT NULL
|
||||
AND bor.customer_num IN ?
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM bundle_order_records bor2
|
||||
WHERE bor2.customer_id = bor.customer_id
|
||||
AND bor2.deleted_at IS NULL
|
||||
AND (bor2.created_at > bor.created_at OR (bor2.created_at = bor.created_at AND bor2.id > bor.id))
|
||||
)
|
||||
AND %s%s
|
||||
),
|
||||
|
||||
-- 2. 获取每个用户的最新月份
|
||||
newest_month AS (
|
||||
SELECT user_id, MAX(month) AS month
|
||||
FROM bundle_balance
|
||||
WHERE deleted_at IS NULL
|
||||
GROUP BY user_id
|
||||
-- 2. 每个目标订单的最新月份余额
|
||||
newest_order_month AS (
|
||||
SELECT bb.user_id, bb.order_uuid, MAX(bb.month) AS month
|
||||
FROM bundle_balance bb
|
||||
INNER JOIN target_orders bor ON bor.uuid = bb.order_uuid
|
||||
WHERE bb.deleted_at IS NULL
|
||||
AND bb.month <= ?
|
||||
GROUP BY bb.user_id, bb.order_uuid
|
||||
),
|
||||
|
||||
-- 3. 活跃窗口:包含所有必要字段,作为核心CTE
|
||||
active_windows AS (
|
||||
-- 3. 目标订单的活跃余额明细
|
||||
active_order_balances AS (
|
||||
SELECT
|
||||
u.id AS user_id,
|
||||
u.tel_num COLLATE utf8mb4_0900_ai_ci AS phone,
|
||||
@ -486,31 +573,74 @@ active_windows AS (
|
||||
bor.customer_num COLLATE utf8mb4_0900_ai_ci AS customer_num,
|
||||
bb.start_at,
|
||||
bb.expired_at,
|
||||
bb.bundle_video_number, bb.monthly_bundle_limit_video_number, bb.monthly_bundle_limit_expired_video_number,
|
||||
bb.invalid_bundle_video_number, bb.bundle_limit_video_consumption_number,
|
||||
bb.bundle_limit_video_expired_consumption_number, bb.monthly_bundle_limit_expired_video_consumption_number,
|
||||
bb.monthly_bundle_limit_video_consumption_number,
|
||||
bb.increase_video_number, bb.monthly_increase_limit_video_number, bb.monthly_increase_limit_expired_video_number,
|
||||
bb.invalid_increase_video_number, bb.increase_limit_video_consumption_number,
|
||||
bb.increase_limit_video_expired_consumption_number, bb.monthly_increase_limit_expired_video_consumption_number,
|
||||
bb.monthly_increase_limit_video_consumption_number,
|
||||
bb.manual_video_number, bb.manual_video_consumption_number,
|
||||
bb.bundle_image_number, bb.monthly_bundle_limit_image_number, bb.monthly_bundle_limit_expired_image_number,
|
||||
bb.invalid_bundle_image_number, bb.bundle_limit_image_consumption_number,
|
||||
bb.bundle_limit_image_expired_consumption_number, bb.monthly_bundle_limit_expired_image_consumption_number,
|
||||
bb.monthly_bundle_limit_image_consumption_number,
|
||||
bb.increase_image_number, bb.monthly_increase_limit_image_number, bb.monthly_increase_limit_expired_image_number,
|
||||
bb.invalid_increase_image_number, bb.increase_limit_image_consumption_number,
|
||||
bb.increase_limit_image_expired_consumption_number, bb.monthly_increase_limit_expired_image_consumption_number,
|
||||
bb.monthly_increase_limit_image_consumption_number,
|
||||
bb.manual_image_number, bb.manual_image_consumption_number,
|
||||
bb.bundle_data_analysis_number, bb.monthly_bundle_limit_data_analysis_number,
|
||||
bb.monthly_bundle_limit_expired_data_analysis_number, bb.invalid_bundle_data_analysis_number,
|
||||
bb.bundle_limit_data_analysis_consumption_number, bb.bundle_limit_data_analysis_expired_consumption_number,
|
||||
bb.monthly_bundle_limit_expired_data_analysis_consumption_number,
|
||||
bb.monthly_bundle_limit_data_analysis_consumption_number,
|
||||
bb.increase_data_analysis_number, bb.monthly_increase_limit_data_analysis_number,
|
||||
bb.monthly_increase_limit_expired_data_analysis_number, bb.invalid_increase_data_analysis_number,
|
||||
bb.increase_limit_data_analysis_consumption_number, bb.increase_limit_data_analysis_expired_consumption_number,
|
||||
bb.monthly_increase_limit_expired_data_analysis_consumption_number,
|
||||
bb.monthly_increase_limit_data_analysis_consumption_number,
|
||||
bb.manual_data_analysis_number, bb.manual_data_analysis_consumption_number,
|
||||
bb.bundle_competitive_number, bb.monthly_bundle_limit_competitive_number, bb.monthly_bundle_limit_expired_competitive_number,
|
||||
bb.invalid_bundle_competitive_number, bb.bundle_limit_competitive_consumption_number,
|
||||
bb.bundle_limit_competitive_expired_consumption_number, bb.monthly_bundle_limit_expired_competitive_consumption_number,
|
||||
bb.monthly_bundle_limit_competitive_consumption_number,
|
||||
bb.increase_competitive_number, bb.monthly_increase_limit_competitive_number, bb.monthly_increase_limit_expired_competitive_number,
|
||||
bb.invalid_increase_competitive_number, bb.increase_limit_competitive_consumption_number,
|
||||
bb.increase_limit_competitive_expired_consumption_number, bb.monthly_increase_limit_expired_competitive_consumption_number,
|
||||
bb.monthly_increase_limit_competitive_consumption_number,
|
||||
bb.manual_competitive_number, bb.manual_competitive_consumption_number,
|
||||
rn.name COLLATE utf8mb4_0900_ai_ci AS user_name
|
||||
FROM ` + "`micro-account`.`user`" + ` u
|
||||
INNER JOIN ` + "`micro-account`.real_name" + ` rn ON rn.id = u.real_name_id AND rn.name IS NOT NULL AND rn.deleted_at = 0
|
||||
FROM `+"`micro-account`.`user`"+` u
|
||||
INNER JOIN `+"`micro-account`.real_name"+` rn ON rn.id = u.real_name_id AND rn.name IS NOT NULL AND rn.deleted_at = 0
|
||||
INNER JOIN bundle_activate bc ON bc.user_id = u.id AND bc.activate = 2
|
||||
INNER JOIN latest_bor bor ON bor.customer_id = u.id AND u.deleted_at = 0
|
||||
INNER JOIN newest_month nm ON nm.user_id = u.id
|
||||
INNER JOIN target_orders bor ON bor.customer_id = u.id AND u.deleted_at = 0
|
||||
INNER JOIN newest_order_month nm ON nm.user_id = u.id AND nm.order_uuid = bor.uuid
|
||||
INNER JOIN bundle_balance bb ON bb.user_id = u.id AND bb.order_uuid = bor.uuid AND bb.month = nm.month AND bb.deleted_at IS NULL
|
||||
WHERE u.deleted_at = 0
|
||||
AND DATE_ADD(UTC_TIMESTAMP(), INTERVAL 8 HOUR) BETWEEN bb.start_at AND bb.expired_at
|
||||
),
|
||||
|
||||
-- 4. 每个订单的最新月份余额
|
||||
latest_per_order AS (
|
||||
SELECT bb_inner.user_id, bb_inner.order_uuid, MAX(bb_inner.month) AS max_month
|
||||
FROM bundle_balance bb_inner
|
||||
INNER JOIN bundle_order_records bor_inner ON bor_inner.uuid = bb_inner.order_uuid
|
||||
AND bor_inner.deleted_at IS NULL
|
||||
AND bor_inner.status = 2
|
||||
WHERE bb_inner.deleted_at IS NULL
|
||||
AND bb_inner.month <= ?
|
||||
GROUP BY bb_inner.user_id, bb_inner.order_uuid
|
||||
-- 4. 活跃窗口:同一用户多条先用后付订单合并为一行
|
||||
active_windows AS (
|
||||
SELECT
|
||||
user_id,
|
||||
phone,
|
||||
customer_num,
|
||||
MIN(start_at) AS start_at,
|
||||
MAX(expired_at) AS expired_at,
|
||||
SUM(manual_video_number) AS manual_video_number,
|
||||
SUM(manual_video_consumption_number) AS manual_video_consumption_number,
|
||||
SUM(manual_image_number) AS manual_image_number,
|
||||
SUM(manual_image_consumption_number) AS manual_image_consumption_number,
|
||||
SUM(manual_data_analysis_number) AS manual_data_analysis_number,
|
||||
SUM(manual_data_analysis_consumption_number) AS manual_data_analysis_consumption_number,
|
||||
SUM(manual_competitive_number) AS manual_competitive_number,
|
||||
SUM(manual_competitive_consumption_number) AS manual_competitive_consumption_number,
|
||||
MAX(user_name) AS user_name
|
||||
FROM active_order_balances
|
||||
GROUP BY user_id, phone, customer_num
|
||||
),
|
||||
|
||||
-- 5. 余额汇总
|
||||
@ -551,15 +681,7 @@ balance_sum AS (
|
||||
+ bb2.invalid_increase_competitive_number + bb2.increase_limit_competitive_consumption_number
|
||||
+ bb2.increase_limit_competitive_expired_consumption_number - bb2.monthly_increase_limit_expired_competitive_consumption_number
|
||||
- bb2.monthly_increase_limit_competitive_consumption_number) AS increase_competitive_sum
|
||||
FROM bundle_balance bb2
|
||||
INNER JOIN latest_per_order lpo ON bb2.user_id = lpo.user_id
|
||||
AND bb2.order_uuid = lpo.order_uuid
|
||||
AND bb2.month = lpo.max_month
|
||||
INNER JOIN bundle_order_records bor2 ON bor2.uuid = bb2.order_uuid
|
||||
AND bor2.deleted_at IS NULL
|
||||
AND bor2.status = 2
|
||||
WHERE bb2.deleted_at IS NULL
|
||||
AND DATE_ADD(UTC_TIMESTAMP(), INTERVAL 8 HOUR) BETWEEN bb2.start_at AND bb2.expired_at
|
||||
FROM active_order_balances bb2
|
||||
GROUP BY bb2.user_id
|
||||
),
|
||||
|
||||
@ -571,6 +693,8 @@ cw_agg AS (
|
||||
COUNT(CASE WHEN cw.work_category = 1 AND cw.deleted_at = 0 AND (cw.origin_uuid = '' OR cw.origin_uuid IS NULL) AND cw.submit_time BETWEEN aw.start_at AND aw.expired_at THEN 1 END) AS uploaded_post_count
|
||||
FROM active_windows aw
|
||||
LEFT JOIN cast_work cw ON cw.artist_phone = aw.phone
|
||||
LEFT JOIN cast_work_extra cwe ON cwe.work_uuid = cw.uuid AND cwe.deleted_at = 0
|
||||
WHERE (cw.uuid IS NULL OR cw.work_category != 2 OR IFNULL(cwe.billing_type, 0) = ?)
|
||||
GROUP BY aw.user_id
|
||||
),
|
||||
|
||||
@ -602,6 +726,7 @@ cvs_agg AS (
|
||||
FROM active_windows aw
|
||||
LEFT JOIN cast_video_script cvs ON CAST(aw.user_id AS CHAR) = cvs.artist_uuid
|
||||
AND cvs.deleted_at = 0
|
||||
AND cvs.billing_type = ?
|
||||
AND cvs.created_at BETWEEN UNIX_TIMESTAMP(CONVERT_TZ(aw.start_at, '+00:00', '+00:00'))
|
||||
AND UNIX_TIMESTAMP(CONVERT_TZ(aw.expired_at, '+00:00', '+00:00'))
|
||||
GROUP BY aw.user_id
|
||||
@ -642,12 +767,13 @@ assigned_pending_agg AS (
|
||||
END
|
||||
), 0) AS assigned_report_count
|
||||
FROM active_windows aw
|
||||
LEFT JOIN ` + "`" + taskSchema + "`" + `.task_assign_records tar ON tar.sub_num = aw.customer_num
|
||||
LEFT JOIN `+"`"+taskSchema+"`"+`.task_assign_records tar ON tar.sub_num = aw.customer_num
|
||||
AND tar.actual_status IN (1, 3)
|
||||
AND tar.deleted_at = 0
|
||||
AND tar.bundle_task_type = ?
|
||||
AND tar.created_at BETWEEN aw.start_at AND aw.expired_at
|
||||
GROUP BY aw.user_id
|
||||
)`
|
||||
)`, orderFilter, latestOrderFilter)
|
||||
|
||||
fromClause := `FROM active_windows aw
|
||||
LEFT JOIN balance_sum bs ON bs.user_id = aw.user_id
|
||||
@ -657,9 +783,8 @@ LEFT JOIN ccr_agg ccr ON ccr.user_id = aw.user_id
|
||||
LEFT JOIN cvs_agg cvs ON cvs.user_id = aw.user_id
|
||||
LEFT JOIN assigned_pending_agg apa ON apa.user_id = aw.user_id`
|
||||
|
||||
args := make([]interface{}, 0, 4)
|
||||
args = append(args, subNums)
|
||||
args = append(args, nowMonth)
|
||||
args := make([]interface{}, 0, 5)
|
||||
args = append(args, req.SubNums, nowMonth, billingType, billingType, taskType)
|
||||
|
||||
// 使用事务固定同一连接,仅对本次查询的 session 设置 collation,不影响其他接口
|
||||
tx2 := app.ModuleClients.BundleDB.Begin()
|
||||
@ -687,10 +812,10 @@ LEFT JOIN assigned_pending_agg apa ON apa.user_id = aw.user_id`
|
||||
|
||||
listArgs := make([]interface{}, 0, len(args)+2)
|
||||
listArgs = append(listArgs, args...)
|
||||
if page > 0 && pageSize > 0 {
|
||||
offset := (page - 1) * pageSize
|
||||
if req.Page > 0 && req.PageSize > 0 {
|
||||
offset := (req.Page - 1) * req.PageSize
|
||||
selectSQL = selectSQL + " LIMIT ? OFFSET ?"
|
||||
listArgs = append(listArgs, pageSize, offset)
|
||||
listArgs = append(listArgs, req.PageSize, offset)
|
||||
}
|
||||
|
||||
items := make([]dto.ArtistPendingAssignItem, 0)
|
||||
@ -707,6 +832,7 @@ LEFT JOIN assigned_pending_agg apa ON apa.user_id = aw.user_id`
|
||||
|
||||
// AssignTask 指派某位员工完成某个艺人的任务
|
||||
func AssignTask(req *dto.TaskAssignRequest, progressTaskCount int, completeTaskCount int) error {
|
||||
req.BundleTaskType = normalizeBundleTaskType(req.BundleTaskType)
|
||||
// 开启事务
|
||||
tx := app.ModuleClients.TaskBenchDB.Begin()
|
||||
defer func() {
|
||||
@ -717,19 +843,19 @@ func AssignTask(req *dto.TaskAssignRequest, progressTaskCount int, completeTaskC
|
||||
|
||||
// 1. 查询当前艺人的任务记录
|
||||
var taskManagement model.TaskManagement
|
||||
err := tx.Where("user_id = ? AND deleted_at = 0", req.UserID).First(&taskManagement).Error
|
||||
err := tx.Where("user_id = ? AND bundle_task_type = ? AND deleted_at = 0", req.UserID, req.BundleTaskType).First(&taskManagement).Error
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
taskManagement = model.TaskManagement{
|
||||
UserId: req.UserID,
|
||||
SubNum: req.SubNum,
|
||||
TelNum: req.TelNum,
|
||||
ArtistName: req.ArtistName,
|
||||
ProgressCount: 0,
|
||||
CompleteCount: 0,
|
||||
BundleTaskType: req.BundleTaskType,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
UserId: req.UserID,
|
||||
SubNum: req.SubNum,
|
||||
TelNum: req.TelNum,
|
||||
ArtistName: req.ArtistName,
|
||||
ProgressCount: 0,
|
||||
CompleteCount: 0,
|
||||
BundleTaskType: req.BundleTaskType,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
if err = tx.Create(&taskManagement).Error; err != nil {
|
||||
tx.Rollback()
|
||||
@ -911,6 +1037,7 @@ func BatchAssignTasks(items []*dto.BatchAssignItem) error {
|
||||
if it == nil {
|
||||
return commonErr.ReturnError(nil, "参数错误", "存在空的指派项")
|
||||
}
|
||||
it.BundleTaskType = normalizeBundleTaskType(it.BundleTaskType)
|
||||
// 校验:数量不可为负,且不可全部为0
|
||||
if it.AssignVideoCount < 0 || it.AssignPostCount < 0 || it.AssignDataCount < 0 || it.AssignVideoScriptCount < 0 || it.AssignReportCount < 0 ||
|
||||
(it.AssignVideoCount == 0 && it.AssignPostCount == 0 && it.AssignDataCount == 0 && it.AssignVideoScriptCount == 0 && it.AssignReportCount == 0) {
|
||||
@ -926,7 +1053,7 @@ func BatchAssignTasks(items []*dto.BatchAssignItem) error {
|
||||
if it.UserID > 0 {
|
||||
userIDSet[it.UserID] = struct{}{}
|
||||
}
|
||||
key := it.SubNum + "|" + it.TelNum
|
||||
key := fmt.Sprintf("%s|%s|%d", it.SubNum, it.TelNum, it.BundleTaskType)
|
||||
subTelKeys[key] = it
|
||||
}
|
||||
|
||||
@ -936,7 +1063,7 @@ func BatchAssignTasks(items []*dto.BatchAssignItem) error {
|
||||
subNums = append(subNums, sn)
|
||||
}
|
||||
// 2.1 批量查询已存在的 task_management 记录
|
||||
existingTMMap := make(map[string]*model.TaskManagement) // key: sub_num|tel_num
|
||||
existingTMMap := make(map[string]*model.TaskManagement) // key: sub_num|tel_num|bundle_task_type
|
||||
if len(userIDSet) > 0 {
|
||||
userIDs := make([]int, 0, len(userIDSet))
|
||||
for id := range userIDSet {
|
||||
@ -948,7 +1075,7 @@ func BatchAssignTasks(items []*dto.BatchAssignItem) error {
|
||||
}
|
||||
for i := range existingTMs {
|
||||
tm := &existingTMs[i]
|
||||
key := tm.SubNum + "|" + tm.TelNum
|
||||
key := fmt.Sprintf("%s|%s|%d", tm.SubNum, tm.TelNum, normalizeBundleTaskType(tm.BundleTaskType))
|
||||
existingTMMap[key] = tm
|
||||
}
|
||||
}
|
||||
@ -961,18 +1088,19 @@ func BatchAssignTasks(items []*dto.BatchAssignItem) error {
|
||||
if len(subNums) > 0 {
|
||||
var statRows []struct {
|
||||
SubNum string `gorm:"column:sub_num"`
|
||||
BundleTaskType int `gorm:"column:bundle_task_type"`
|
||||
ProgressTaskCount int `gorm:"column:progress_task_count"`
|
||||
CompleteTaskCount int `gorm:"column:complete_task_count"`
|
||||
}
|
||||
if err := app.ModuleClients.TaskBenchDB.Table("task_assign_records").
|
||||
Select("sub_num, COUNT(CASE WHEN status = 1 THEN 1 END) as progress_task_count, COUNT(CASE WHEN status = 2 THEN 1 END) as complete_task_count").
|
||||
Select("sub_num, bundle_task_type, COUNT(CASE WHEN status = 1 THEN 1 END) as progress_task_count, COUNT(CASE WHEN status = 2 THEN 1 END) as complete_task_count").
|
||||
Where("sub_num IN ? AND deleted_at = 0", subNums).
|
||||
Group("sub_num").
|
||||
Group("sub_num, bundle_task_type").
|
||||
Scan(&statRows).Error; err != nil {
|
||||
return commonErr.ReturnError(err, "批量查询艺人任务指派记录失败", "批量查询艺人任务指派记录失败: ")
|
||||
}
|
||||
for _, row := range statRows {
|
||||
statsMap[row.SubNum] = struct {
|
||||
statsMap[fmt.Sprintf("%s|%d", row.SubNum, normalizeBundleTaskType(row.BundleTaskType))] = struct {
|
||||
ProgressTaskCount int
|
||||
CompleteTaskCount int
|
||||
}{
|
||||
@ -991,21 +1119,22 @@ func BatchAssignTasks(items []*dto.BatchAssignItem) error {
|
||||
|
||||
// 3.1 准备需要创建的 task_management 记录
|
||||
var newTMs []model.TaskManagement
|
||||
newTMMap := make(map[string]*model.TaskManagement) // key: sub_num|tel_num,用于后续更新时引用
|
||||
newTMMap := make(map[string]*model.TaskManagement) // key: sub_num|tel_num|bundle_task_type,用于后续更新时引用
|
||||
for _, it := range items {
|
||||
key := it.SubNum + "|" + it.TelNum
|
||||
key := fmt.Sprintf("%s|%s|%d", it.SubNum, it.TelNum, it.BundleTaskType)
|
||||
if _, exists := existingTMMap[key]; !exists {
|
||||
// 检查是否已经在 newTMs 中(同一批次可能有重复的 sub_num|tel_num)
|
||||
// 检查是否已经在 newTMs 中(同一批次可能有重复的 sub_num|tel_num|bundle_task_type)
|
||||
if _, inNew := newTMMap[key]; !inNew {
|
||||
tm := model.TaskManagement{
|
||||
UserId: it.UserID,
|
||||
SubNum: it.SubNum,
|
||||
TelNum: it.TelNum,
|
||||
ArtistName: it.ArtistName,
|
||||
ProgressCount: 0,
|
||||
CompleteCount: 0,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
UserId: it.UserID,
|
||||
SubNum: it.SubNum,
|
||||
TelNum: it.TelNum,
|
||||
ArtistName: it.ArtistName,
|
||||
ProgressCount: 0,
|
||||
CompleteCount: 0,
|
||||
BundleTaskType: it.BundleTaskType,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
newTMs = append(newTMs, tm)
|
||||
newTMMap[key] = &newTMs[len(newTMs)-1]
|
||||
@ -1021,7 +1150,7 @@ func BatchAssignTasks(items []*dto.BatchAssignItem) error {
|
||||
}
|
||||
// 更新 newTMMap 中的 ID(CreateInBatches 会填充 ID)
|
||||
for i := range newTMs {
|
||||
key := newTMs[i].SubNum + "|" + newTMs[i].TelNum
|
||||
key := fmt.Sprintf("%s|%s|%d", newTMs[i].SubNum, newTMs[i].TelNum, normalizeBundleTaskType(newTMs[i].BundleTaskType))
|
||||
newTMMap[key] = &newTMs[i]
|
||||
}
|
||||
}
|
||||
@ -1030,7 +1159,7 @@ func BatchAssignTasks(items []*dto.BatchAssignItem) error {
|
||||
// 统计每个 sub_num 在本批次中新增的指派数量(用于计算 progress_count)
|
||||
subNumAssignCount := make(map[string]int)
|
||||
for _, it := range items {
|
||||
subNumAssignCount[it.SubNum]++
|
||||
subNumAssignCount[fmt.Sprintf("%s|%d", it.SubNum, it.BundleTaskType)]++
|
||||
}
|
||||
|
||||
// 准备批量插入的指派记录
|
||||
@ -1065,6 +1194,7 @@ func BatchAssignTasks(items []*dto.BatchAssignItem) error {
|
||||
CompletePostCount: 0,
|
||||
CompleteDataCount: 0,
|
||||
CompleteReportCount: 0,
|
||||
BundleTaskType: it.BundleTaskType,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
@ -1098,13 +1228,14 @@ func BatchAssignTasks(items []*dto.BatchAssignItem) error {
|
||||
// 3.5 批量更新 task_management 表
|
||||
updateGroups := make(map[string]*dto.BatchAssignItem)
|
||||
for _, it := range items {
|
||||
key := it.SubNum + "|" + it.TelNum
|
||||
key := fmt.Sprintf("%s|%s|%d", it.SubNum, it.TelNum, it.BundleTaskType)
|
||||
updateGroups[key] = it
|
||||
}
|
||||
|
||||
for key, it := range updateGroups {
|
||||
stats := statsMap[it.SubNum]
|
||||
newProgressCount := stats.ProgressTaskCount + subNumAssignCount[it.SubNum]
|
||||
statsKey := fmt.Sprintf("%s|%d", it.SubNum, it.BundleTaskType)
|
||||
stats := statsMap[statsKey]
|
||||
newProgressCount := stats.ProgressTaskCount + subNumAssignCount[statsKey]
|
||||
|
||||
// 获取对应的 task_management 记录 ID
|
||||
var tmID int64
|
||||
@ -1120,6 +1251,7 @@ func BatchAssignTasks(items []*dto.BatchAssignItem) error {
|
||||
"complete_count": stats.CompleteTaskCount,
|
||||
"last_task_assignee": it.TaskAssignee,
|
||||
"task_assignee_num": it.TaskAssigneeNum,
|
||||
"bundle_task_type": it.BundleTaskType,
|
||||
"updated_at": now,
|
||||
}
|
||||
if err := tx.Model(&model.TaskManagement{}).Where("id = ?", tmID).Updates(updateData).Error; err != nil {
|
||||
@ -1295,7 +1427,7 @@ func CompleteTaskManually(assignRecordsUUID string) error {
|
||||
|
||||
// 4) 同步任务管理表的进行中与已完成数量(若不存在则创建)
|
||||
var taskManagement model.TaskManagement
|
||||
if err := tx.Where("sub_num = ? AND tel_num = ?", assignRecord.SubNum, assignRecord.TelNum).First(&taskManagement).Error; err != nil {
|
||||
if err := tx.Where("sub_num = ? AND tel_num = ? AND bundle_task_type = ?", assignRecord.SubNum, assignRecord.TelNum, normalizeBundleTaskType(assignRecord.BundleTaskType)).First(&taskManagement).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
// 创建新记录
|
||||
taskManagement = model.TaskManagement{
|
||||
@ -1943,11 +2075,12 @@ func GetValidArtistList() ([]dto.ValidArtistInfo, error) {
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// 根据艺人编号统计进行中的与已完成任务数量
|
||||
func GetArtistTaskStatsBySubNum(SubNum string) (int, int, error) {
|
||||
// 根据艺人编号和套餐类型统计进行中的与已完成任务数量
|
||||
func GetArtistTaskStatsBySubNum(SubNum string, bundleTaskType int) (int, int, error) {
|
||||
if SubNum == "" {
|
||||
return 0, 0, nil
|
||||
}
|
||||
bundleTaskType = normalizeBundleTaskType(bundleTaskType)
|
||||
|
||||
var res struct {
|
||||
ProgressTaskCount int
|
||||
@ -1956,7 +2089,7 @@ func GetArtistTaskStatsBySubNum(SubNum string) (int, int, error) {
|
||||
|
||||
err := app.ModuleClients.TaskBenchDB.Table("task_assign_records").
|
||||
Select("COUNT(CASE WHEN status = 1 THEN 1 END) as progress_task_count, COUNT(CASE WHEN status = 2 THEN 1 END) as complete_task_count").
|
||||
Where("sub_num = ? AND deleted_at = 0", SubNum).
|
||||
Where("sub_num = ? AND bundle_task_type = ? AND deleted_at = 0", SubNum, bundleTaskType).
|
||||
Scan(&res).Error
|
||||
|
||||
if err != nil {
|
||||
|
||||
@ -11,6 +11,15 @@ type TaskQueryRequest struct {
|
||||
SortBy string `json:"sortBy"` // 排序字段(支持白名单字段)
|
||||
SortType string `json:"sortType"` // 排序类型 asc/desc
|
||||
SubNums []string `json:"subNums"` // 选中导出的艺人编号集合(可选)
|
||||
BundleTaskType int `json:"bundleTaskType"` // 任务所属套餐类型 0/1:基础套餐 2:先用后付套餐
|
||||
}
|
||||
|
||||
// PendingAssignQueryRequest 查询艺人可指派数量请求参数
|
||||
type PendingAssignQueryRequest struct {
|
||||
SubNums []string `json:"subNums"`
|
||||
Page int `json:"page"`
|
||||
PageSize int `json:"pageSize"`
|
||||
BundleTaskType int `json:"bundleTaskType"` // 任务所属套餐类型 0/1:基础套餐 2:先用后付套餐
|
||||
}
|
||||
|
||||
// TaskAssignRequest 指派任务请求参数
|
||||
@ -48,6 +57,7 @@ type BatchAssignItem struct {
|
||||
AssignReportCount int `json:"assignReportCount"` // 指派竞品报告数
|
||||
TaskBatch string `json:"taskBatch"` // 任务批次
|
||||
UserID int `json:"userID"` // 用户ID
|
||||
BundleTaskType int `json:"bundleTaskType"` // 任务所属套餐类型 0/1:基础套餐 2:先用后付套餐
|
||||
}
|
||||
|
||||
// EmployeeTaskQueryRequest 员工任务查询请求参数
|
||||
|
||||
@ -67,8 +67,8 @@ func GetArtistUploadStatsList(req *dto.TaskQueryRequest) ([]*dto.ArtistUploadSta
|
||||
}
|
||||
|
||||
// GetPendingAssignBySubNums 查询指定艺人的可指派数量
|
||||
func GetPendingAssignBySubNums(subNums []string, page int, pageSize int) ([]*dto.ArtistPendingAssignItem, int64, error) {
|
||||
return dao.GetPendingAssignBySubNums(subNums, page, pageSize)
|
||||
func GetPendingAssignBySubNums(req *dto.PendingAssignQueryRequest) ([]*dto.ArtistPendingAssignItem, int64, error) {
|
||||
return dao.GetPendingAssignBySubNums(req)
|
||||
}
|
||||
|
||||
// AssignTask 指派某位员工完成某个艺人的任务
|
||||
@ -88,7 +88,10 @@ func AssignTask(req *dto.TaskAssignRequest) error {
|
||||
return commonErr.ReturnError(nil, "指派数量不能全部为0", "至少有一个指派数量需大于0")
|
||||
}
|
||||
|
||||
progressTaskCount, completeTaskCount, err := dao.GetArtistTaskStatsBySubNum(req.SubNum)
|
||||
if req.BundleTaskType != model.BundleTaskTypePayLater {
|
||||
req.BundleTaskType = model.BundleTaskTypeNormal
|
||||
}
|
||||
progressTaskCount, completeTaskCount, err := dao.GetArtistTaskStatsBySubNum(req.SubNum, req.BundleTaskType)
|
||||
if err != nil {
|
||||
// 查询不到的话,给一个默认值
|
||||
progressTaskCount, completeTaskCount = 0, 0
|
||||
|
||||
@ -1394,6 +1394,7 @@ message TaskQueryRequest {
|
||||
string sortType = 5 [json_name = "sortType"]; // 排序类型 asc/desc
|
||||
string lastTaskAssignee = 6 [json_name = "lastTaskAssignee"]; // 最近一次指派人筛选(模糊匹配)
|
||||
repeated string subNums = 7 [json_name = "subNums"]; // 选中导出时的艺人编号集合(可选)
|
||||
BundleTaskType bundle_task_type = 8 [json_name = "bundleTaskType"]; // 任务所属套餐类型 0/1:基础套餐 2:先用后付套餐
|
||||
}
|
||||
|
||||
message TaskQueryResponse {
|
||||
@ -1539,6 +1540,7 @@ message BatchAssignTaskItem {
|
||||
int32 assignVideoScriptCount = 12 [json_name = "assignVideoScriptCount"]; // 指派视频脚本数
|
||||
int32 assignReportCount = 13 [json_name = "assignReportCount"]; // 指派竞品报告数
|
||||
int32 userID = 14 [json_name = "userID"]; // 用户ID
|
||||
BundleTaskType bundle_task_type = 15 [json_name = "bundleTaskType"]; // 任务所属套餐类型
|
||||
}
|
||||
|
||||
message BatchAssignTaskRequest {
|
||||
@ -1726,6 +1728,7 @@ message PendingAssignRequest {
|
||||
repeated string subNums = 1 [json_name = "subNums"];
|
||||
int32 page = 2 [json_name = "page"];
|
||||
int32 pageSize = 3 [json_name = "pageSize"];
|
||||
BundleTaskType bundle_task_type = 4 [json_name = "bundleTaskType"]; // 任务所属套餐类型 0/1:基础套餐 2:先用后付套餐
|
||||
}
|
||||
|
||||
// 艺人可指派数量项
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -38,7 +38,7 @@ func loadMysqlConn(conn string) *gorm.DB {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println("[BundleDB] 数据库连接成功, 连接字符串: %s", conn)
|
||||
fmt.Printf("[BundleDB] 数据库连接成功, 连接字符串: %s\n", conn)
|
||||
sqlDB, _ := db.DB()
|
||||
sqlDB.SetMaxIdleConns(20) //设置连接池,空闲
|
||||
sqlDB.SetMaxOpenConns(100) //打开
|
||||
|
||||
Loading…
Reference in New Issue
Block a user