micro-bundle/internal/logic/taskLogic.go

444 lines
15 KiB
Go
Raw Permalink 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 logic
import (
"encoding/json"
"micro-bundle/internal/dao"
"micro-bundle/internal/dto"
"micro-bundle/pb/bundle"
commonErr "micro-bundle/pkg/err"
"strings"
)
// GetValidArtistList 查询套餐状态为有效中的艺人列表
func GetValidArtistList() ([]dto.ValidArtistInfo, error) {
return dao.GetValidArtistList()
}
// GetValidArtistIDs 查询套餐没有过期的艺人ID列表保持向后兼容
func GetValidArtistIDs() ([]string, error) {
artistList, err := GetValidArtistList()
if err != nil {
return nil, err
}
var artistIDs []string
for _, artist := range artistList {
if artist.CustomerNum != "" {
artistIDs = append(artistIDs, artist.CustomerNum)
}
}
return artistIDs, nil
}
// todo 目前暂时不做检验,后续需要做判断
// GetValidEmployeeIDs 查询可以被指派任务的员工ID列表
func GetValidEmployeeIDs() ([]string, error) {
var employeeIDs []string
return employeeIDs, nil
}
// ValidateEmployee 验证员工是否可以被指派任务
func ValidateEmployee(employeeNum string) (bool, error) {
validEmployees, err := GetValidEmployeeIDs()
if err != nil {
return false, err
}
// 如果没有限制(返回空列表),则认为所有员工都可以被指派
if len(validEmployees) == 0 {
return true, nil
}
for _, validEmp := range validEmployees {
if validEmp == employeeNum {
return true, nil
}
}
return false, nil
}
// GetArtistUploadStatsList 查询艺人上传与额度统计列表
func GetArtistUploadStatsList(req *dto.TaskQueryRequest) ([]*dto.ArtistUploadStatsItem, int64, error) {
return dao.GetArtistUploadStatsList(req)
}
// GetPendingAssignBySubNums 查询指定艺人的可指派数量
func GetPendingAssignBySubNums(subNums []string, page int, pageSize int) ([]*dto.ArtistPendingAssignItem, int64, error) {
return dao.GetPendingAssignBySubNums(subNums, page, pageSize)
}
// AssignTask 指派某位员工完成某个艺人的任务
func AssignTask(req *dto.TaskAssignRequest) error {
// 1. 验证员工是否可以被指派任务
isValid, err := ValidateEmployee(req.TaskAssigneeNum)
if err != nil {
return err
}
if !isValid {
return commonErr.ReturnError(nil, "员工不能被指派任务", "该员工不在可指派任务的员工列表中")
}
if req.AssignVideoCount < 0 || req.AssignPostCount < 0 || req.AssignDataCount < 0 || req.AssignVideoScriptCount < 0 {
return commonErr.ReturnError(nil, "指派数量不能小于0", "任一指派数量不得小于0")
}
if req.AssignVideoCount == 0 && req.AssignPostCount == 0 && req.AssignDataCount == 0 && req.AssignVideoScriptCount == 0 {
return commonErr.ReturnError(nil, "指派数量不能全部为0", "至少有一个指派数量需大于0")
}
progressTaskCount, completeTaskCount, err := dao.GetArtistTaskStatsBySubNum(req.SubNum)
if err != nil {
// 查询不到的话,给一个默认值
progressTaskCount, completeTaskCount = 0, 0
}
// 2. 调用DAO层执行指派任务
// 待完成任务数量需要+1因为这个任务暂时还没有指派所以+1
return dao.AssignTask(req, progressTaskCount+1, completeTaskCount)
}
// BatchAssignTask 批量指派
func BatchAssignTask(items []*dto.BatchAssignItem) error {
if len(items) == 0 {
return commonErr.ReturnError(nil, "参数错误", "批量指派项不能为空")
}
// 逐项校验员工是否可被指派(当前实现默认全部有效)
hasPositive := false
for _, it := range items {
if it == nil {
return commonErr.ReturnError(nil, "参数错误", "存在空的指派项")
}
isValid, err := ValidateEmployee(it.TaskAssigneeNum)
if err != nil {
return err
}
if !isValid {
return commonErr.ReturnError(nil, "员工不能被指派任务", "该员工不在可指派任务的员工列表中")
}
if it.AssignVideoCount < 0 || it.AssignPostCount < 0 || it.AssignDataCount < 0 || it.AssignVideoScriptCount < 0 {
return commonErr.ReturnError(nil, "指派数量不能小于0", "任一指派数量不得小于0")
}
if it.AssignVideoCount == 0 && it.AssignPostCount == 0 && it.AssignDataCount == 0 && it.AssignVideoScriptCount == 0 {
return commonErr.ReturnError(nil, "指派数量不能全部为0", "至少有一个指派数量需大于0")
}
if it.AssignVideoCount > 0 || it.AssignPostCount > 0 || it.AssignDataCount > 0 || it.AssignVideoScriptCount > 0 {
hasPositive = true
}
}
if !hasPositive {
return commonErr.ReturnError(nil, "所有指派项数量都为0", "至少有一个指派项的数量需大于0")
}
// 调用DAO层批量写入指派记录
return dao.BatchAssignTasks(items)
}
// GetRecentAssignRecords 查询最近被指派记录
func GetRecentAssignRecords(limit int) ([]*bundle.RecentAssigneeItem, error) {
records, err := dao.GetRecentAssignRecords(limit)
if err != nil {
return nil, err
}
var operatorList []*bundle.RecentAssigneeItem
for _, record := range records {
operatorList = append(operatorList, &bundle.RecentAssigneeItem{
TaskAssignee: record.TaskAssignee,
TaskAssigneeNum: record.TaskAssigneeNum,
})
}
return operatorList, nil
}
// GetEmployeeAssignedTasks 根据登录人信息查询被指派给该员工的艺人任务
func GetEmployeeAssignedTasks(req *dto.EmployeeTaskQueryRequest) ([]*dto.TaskAssignRecordsResponse, int64, error) {
// 1. 调用DAO层查询被指派给该员工的艺人任务
record, total, err := dao.GetEmployeeAssignedTasks(req)
if err != nil {
return nil, 0, err
}
// 如果查询的 status = 2 的话,待发数量就为指派时,指派的数量
if req.Status == 2 {
var recordResponse []*dto.TaskAssignRecordsResponse
for _, record := range record {
recordResponse = append(recordResponse, &dto.TaskAssignRecordsResponse{
AssignRecordsUUID: record.AssignRecordsUUID,
SubNum: record.SubNum,
TelNum: record.TelNum,
ArtistName: record.ArtistName,
Status: record.Status,
ActualStatus: record.ActualStatus,
CompleteTime: record.CompleteTime,
OperatorType: record.OperatorType,
Operator: record.Operator,
OperatorNum: record.OperatorNum,
OperatorTime: record.OperatorTime,
TaskAssignee: record.TaskAssignee,
TaskAssigneeNum: record.TaskAssigneeNum,
PendingVideoCount: record.AssignVideoCount,
PendingPostCount: record.AssignPostCount,
PendingDataCount: record.AssignDataCount,
PendingVideoScriptCount: record.AssignVideoScriptCount,
TaskBatch: record.TaskBatch,
UpdatedAt: record.UpdatedAt,
})
}
return recordResponse, total, nil
}
// 2. 转换为响应结构体
var recordResponse []*dto.TaskAssignRecordsResponse
for _, record := range record {
recordResponse = append(recordResponse, &dto.TaskAssignRecordsResponse{
AssignRecordsUUID: record.AssignRecordsUUID,
SubNum: record.SubNum,
TelNum: record.TelNum,
ArtistName: record.ArtistName,
Status: record.Status,
ActualStatus: record.ActualStatus,
CompleteTime: record.CompleteTime,
OperatorType: record.OperatorType,
Operator: record.Operator,
OperatorNum: record.OperatorNum,
OperatorTime: record.OperatorTime,
TaskAssignee: record.TaskAssignee,
TaskAssigneeNum: record.TaskAssigneeNum,
PendingVideoCount: record.PendingVideoCount,
PendingPostCount: record.PendingPostCount,
PendingDataCount: record.PendingDataCount,
PendingVideoScriptCount: record.PendingVideoScriptCount,
TaskBatch: record.TaskBatch,
UpdatedAt: record.UpdatedAt,
})
}
return recordResponse, total, nil
}
// TerminateTaskByUUID 根据指派记录UUID更新实际完成状态1:未完成 2:完成 3:已中止)
func TerminateTaskByUUID(assignRecordsUUID string) error {
if assignRecordsUUID == "" {
return commonErr.ReturnError(nil, "参数错误", "AssignRecordsUUID 不能为空")
}
return dao.UpdateTaskActualStatusByUUID(assignRecordsUUID, 3)
}
// BatchTerminateTaskByUUIDs 批量根据指派记录UUID终止任务实际状态置为已中止
func BatchTerminateTaskByUUIDs(assignRecordsUUIDs []string) (int, int, []string, error) {
if len(assignRecordsUUIDs) == 0 {
return 0, 0, nil, commonErr.ReturnError(nil, "参数错误", "AssignRecordsUUIDs 不能为空")
}
success := 0
failed := 0
failedUUIDs := make([]string, 0)
for _, uuid := range assignRecordsUUIDs {
if strings.TrimSpace(uuid) == "" {
failed++
failedUUIDs = append(failedUUIDs, uuid)
continue
}
if err := dao.UpdateTaskActualStatusByUUID(uuid, 3); err != nil {
failed++
failedUUIDs = append(failedUUIDs, uuid)
continue
}
success++
}
return success, failed, failedUUIDs, nil
}
func RevertTaskCompletionByUUIDItem(uuid string) error {
if strings.TrimSpace(uuid) == "" {
return commonErr.ReturnError(nil, "参数错误", "UUID不能为空")
}
return dao.RevertTaskCompletionByUUIDItem(uuid)
}
// CompleteTaskManually 员工手动点击完成任务
func CompleteTaskManually(assignRecordsUUID string, taskAssigneeNum string) error {
// 第一步,查询指派记录,获取艺人编号
record, err := dao.GetAssignRecordByUUID(assignRecordsUUID)
if err != nil {
return err
}
if record == nil {
return commonErr.ReturnError(nil, "未找到任务记录", "未找到指派记录: ")
}
// 第二步,校验该艺人是否为有效艺人(套餐未过期且已激活)
validArtistList, err := GetValidArtistList()
if err != nil {
return err
}
isValid := false
for _, a := range validArtistList {
if a.CustomerNum == record.SubNum {
isValid = true
break
}
}
if !isValid {
return commonErr.ReturnError(nil, "该艺人套餐已过期,暂不能完成任务", "艺人套餐已过期,暂不能完成任务: ")
}
// 第三步,执行任务完成更新
return dao.CompleteTaskManually(assignRecordsUUID)
}
// UpdateTaskProgress 员工实际完成任务状态更新
func UpdateTaskProgress(req *dto.CompleteTaskRequest) error {
if req.UUID == "" {
return commonErr.ReturnError(nil, "作品UUID不能为空", "UUID不能为空")
}
return dao.UpdateTaskProgress(req)
}
// GetTaskAssignRecordsList 多条件查询操作记录表
func GetTaskAssignRecordsList(req *dto.TaskAssignRecordsQueryRequest) ([]*dto.TaskAssignRecordsResponse, int64, *dto.TaskAssignRecordsSummary, error) {
record, total, summary, err := dao.GetTaskAssignRecordsList(req)
if err != nil {
return nil, 0, nil, err
}
// 2. 转换为响应结构体
var recordResponse []*dto.TaskAssignRecordsResponse
for _, record := range record {
recordResponse = append(recordResponse, &dto.TaskAssignRecordsResponse{
AssignRecordsUUID: record.AssignRecordsUUID,
SubNum: record.SubNum,
TelNum: record.TelNum,
ArtistName: record.ArtistName,
Status: record.Status,
TaskBatch: record.TaskBatch,
ActualStatus: record.ActualStatus,
CompleteTime: record.CompleteTime,
OperatorType: record.OperatorType,
Operator: record.Operator,
OperatorNum: record.OperatorNum,
OperatorTime: record.OperatorTime,
TaskAssignee: record.TaskAssignee,
TaskAssigneeNum: record.TaskAssigneeNum,
PendingVideoCount: record.AssignVideoCount,
PendingPostCount: record.AssignPostCount,
PendingDataCount: record.AssignDataCount,
PendingVideoScriptCount: record.AssignVideoScriptCount,
CompleteVideoScriptCount: record.CompleteVideoScriptCount,
CompleteVideoCount: record.CompleteVideoCount,
CompletePostCount: record.CompletePostCount,
CompleteDataCount: record.CompleteDataCount,
UpdatedAt: record.UpdatedAt,
})
}
return recordResponse, total, summary, nil
}
// GetTaskActualStatusByUUID 根据指派记录UUID查询实际完成状态
func GetTaskActualStatusByUUID(assignRecordsUUID string) (int, error) {
if strings.TrimSpace(assignRecordsUUID) == "" {
return 0, commonErr.ReturnError(nil, "查询参数错误", "AssignRecordsUUID 不能为空")
}
record, err := dao.GetAssignRecordByUUID(assignRecordsUUID)
if err != nil {
return 0, err
}
if record == nil {
return 0, commonErr.ReturnError(nil, "未找到任务记录", "未找到指派记录: ")
}
return record.ActualStatus, nil
}
func GetPendingTaskLayout() (string, error) {
data, err := dao.GetPendingTaskLayout()
if err != nil {
return buildDefaultPendingLayout(), nil
}
return data, nil
}
func SetPendingTaskLayout(data string) error {
return dao.SetPendingTaskLayout(data)
}
func buildDefaultPendingLayout() string {
var data = []struct {
Title string
Column string
Status int
}{
{"用户编号", "subNum", 1},
{"艺人", "artistName", 1},
{"手机号", "telNum", 1},
{"最近一次指派人", "lastTaskAssignee", 1},
{"可指派视频脚本数", "allowVideoScriptCount", 1},
{"可上传视频脚本数", "pendingVideoScriptCount", 1},
{"已上传视频脚本数", "uploadedVideoScriptCount", 1},
{"可指派视频数", "allowVideoCount", 1},
{"可上传视频数", "pendingVideoCount", 1},
{"已经上传视频数", "uploadedVideoCount", 1},
{"已释放视频额度", "releasedVideoTotal", 1},
{"套餐视频总数", "bundleVideoTotal", 1},
{"增值视频总数", "increaseVideoTotal", 1},
{"可指派图文数", "allowPostCount", 1},
{"可上传图文数", "pendingPostCount", 1},
{"已上传图文数", "uploadedPostCount", 1},
{"已释放图文额度", "releasedPostTotal", 1},
{"套餐图文总数", "bundlePostTotal", 1},
{"增值图文总数", "increasePostTotal", 1},
{"可指派数据数", "allowDataCount", 1},
{"可上传数据数", "pendingDataAnalysisCount", 1},
{"已上传数据数", "uploadedDataAnalysisCount", 1},
{"已释放数据额度", "releasedDataAnalysisTotal", 1},
{"套餐数据总数", "bundleDataAnalysisTotal", 1},
{"增值数据总数", "increaseDataAnalysisTotal", 1},
{"进行中任务数", "progressTaskCount", 1},
{"已完成任务数", "completeTaskCount", 1},
}
jsonMap := []map[string]any{}
for _, v := range data {
jsonMap = append(jsonMap, map[string]any{
"sort": 1,
"fieldKey": v.Column,
"fieldValue": v.Title,
"sortOrNot": true,
"status": v.Status,
"width": 160,
})
}
b, _ := json.Marshal(jsonMap)
return string(b)
}
func AddHiddenTaskAssignee(taskAssignee string, taskAssigneeNum string) error {
if strings.TrimSpace(taskAssignee) == "" || strings.TrimSpace(taskAssigneeNum) == "" {
return commonErr.ReturnError(nil, "参数错误", "任务指派人或账号不能为空")
}
return dao.AddHiddenTaskAssignee(taskAssignee, taskAssigneeNum)
}
// CreateTaskWorkLog 创建任务日志记录
func CreateTaskWorkLog(req *dto.CreateTaskWorkLogRequest) error {
if req.OperationType < 1 || req.OperationType > 4 {
return commonErr.ReturnError(nil, "参数错误", "操作类型必须在1-4之间")
}
if req.TaskType < 1 || req.TaskType > 3 {
return commonErr.ReturnError(nil, "参数错误", "任务类型必须在1-3之间")
}
if req.TaskCount < 0 {
return commonErr.ReturnError(nil, "参数错误", "任务数量不能为负数")
}
// 调用 DAO 层创建日志
return dao.CreateTaskWorkLog(req)
}