micro-bundle/internal/logic/taskLogic.go

318 lines
12 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package logic
import (
"fmt"
"micro-bundle/internal/dao"
commonErr "micro-bundle/pkg/err"
)
// GetValidArtistList 查询套餐状态为有效中的艺人列表
// 调用dao层获取艺人详细信息
func GetValidArtistList() ([]dao.ValidArtistInfo, error) {
return dao.GetValidArtistList()
}
// GetValidArtistIDs 查询套餐没有过期的艺人ID列表保持向后兼容
// 根据BundleOrderRecords表查询过期时间大于当前时间且状态为已支付的艺人
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
}
// GetPendingTaskList 查询待指派任务记录
func GetPendingTaskList(req *dao.TaskQueryRequest) ([]*dao.TaskQueryResponse, int64, error) {
// 1. 先查询套餐没有过期的艺人
validArtist, err := GetValidArtistList()
if err != nil {
return nil, 0, err
}
// 2. 调用DAO层查询待指派任务记录
record, total, err := dao.GetPendingTaskList(req, validArtist)
if err != nil {
return nil, 0, err
}
// 3. 转换为响应结构体
var recordResponse []*dao.TaskQueryResponse
for _, record := range record {
// 计算聚合的待发数量:视频、图文、数据分析
videoTotal := record.PendingBundleLimitVideoExpiredCount + record.PendingBundleLimitVideoCount + record.PendingIncreaseLimitVideoExpiredCount + record.PendingIncreaseLimitVideoCount + record.PendingBundleVideoCount + record.PendingIncreaseVideoCount
imageTotal := record.PendingBundleLimitImageExpiredCount + record.PendingBundleLimitImageCount + record.PendingIncreaseLimitImageExpiredCount + record.PendingIncreaseLimitImageCount + record.PendingBundleImageCount + record.PendingIncreaseImageCount
dataTotal := record.PendingBundleLimitDataAnalysisExpiredCount + record.PendingBundleLimitDataAnalysisCount + record.PendingIncreaseLimitDataAnalysisExpiredCount + record.PendingIncreaseLimitDataAnalysisCount + record.PendingBundleDataAnalysisCount + record.PendingIncreaseDataAnalysisCount
// 根据 SubNum 和 TelNum 查询对应的员工正在进行中的任务和已完成任务数量
progressTaskCount, completeTaskCount, err := dao.GetTaskAssigneeInfo(record.TaskAssigneeNum)
if err != nil {
recordResponse = append(recordResponse, &dao.TaskQueryResponse{
SubNum: record.SubNum,
TelNum: record.TelNum,
ArtistName: record.ArtistName,
TaskAssigneeNum: record.TaskAssigneeNum,
PendingPostCount: imageTotal,
PendingVideoCount: videoTotal,
PendingDataCount: dataTotal,
ProgressTaskCount: 0,
CompleteTaskCount: 0,
LastTaskAssignee: record.LastTaskAssignee,
})
} else {
recordResponse = append(recordResponse, &dao.TaskQueryResponse{
SubNum: record.SubNum,
TelNum: record.TelNum,
ArtistName: record.ArtistName,
TaskAssigneeNum: record.TaskAssigneeNum,
PendingPostCount: imageTotal,
PendingVideoCount: videoTotal,
PendingDataCount: dataTotal,
ProgressTaskCount: progressTaskCount,
CompleteTaskCount: completeTaskCount,
LastTaskAssignee: record.LastTaskAssignee,
})
}
}
return recordResponse, total, nil
}
// AssignTask 指派某位员工完成某个艺人的任务
func AssignTask(req *dao.TaskAssignRequest) error {
// 1. 验证员工是否可以被指派任务
isValid, err := ValidateEmployee(req.TaskAssigneeNum)
if err != nil {
return err
}
if !isValid {
return commonErr.ReturnError(nil, "员工不能被指派任务", "该员工不在可指派任务的员工列表中")
}
progressTaskCount, completeTaskCount, err := dao.GetTaskAssigneeInfo(req.TaskAssigneeNum)
if err != nil {
// 查询不到的话,给一个默认值
progressTaskCount, completeTaskCount = 1, 0
}
// 2. 调用DAO层执行指派任务
// 待完成任务数量需要+1因为这个任务暂时还没有指派所以+1
return dao.AssignTask(req, progressTaskCount+1, completeTaskCount)
}
// UpdatePendingCount 修改待发数量
func UpdatePendingCount(req *dao.UpdatePendingCountRequest) error {
// 1. 验证艺人是否有有效套餐
validArtistIDs, err := GetValidArtistIDs()
if err != nil {
return err
}
// 检查艺人是否在有效列表中
isValidArtist := false
for _, artistID := range validArtistIDs {
if artistID == req.SubNum {
isValidArtist = true
break
}
}
if !isValidArtist {
return commonErr.ReturnError(nil, "艺人套餐已过期", "该艺人没有有效的套餐,无法修改待发数量")
}
// 查询艺人当前任务余额与待发汇总,校验待发数量和余额的总和是否足够
resp, err := dao.GetUserPendingAndTaskBalances(&dao.PendingAndBalanceRequest{
SubNum: req.SubNum,
TelNum: req.TelNum,
})
if err != nil {
return commonErr.ReturnError(err, "查询艺人任务余额失败", "查询艺人任务余额失败: ")
}
// 计算当前待发数量(聚合所有类型)
curVideo := resp.PendingBundleVideoCount + resp.PendingIncreaseVideoCount
curImage := resp.PendingBundleImageCount + resp.PendingIncreaseImageCount
curData := resp.PendingBundleDataAnalysisCount + resp.PendingIncreaseDataAnalysisCount
// 计算可用余额(套餐 + 增值)
availVideo := resp.BundleVideoBalance + resp.IncreaseVideoBalance
availImage := resp.BundleImageBalance + resp.IncreaseImageBalance
availData := resp.BundleDataAnalysisBalance + resp.IncreaseDataAnalysisBalance
// 校验:当前待发数量 + 艺人余额 >= 目标数量
// 这确保了可以优先扣减待发数量,不足时再扣减余额
totalAvailVideo := curVideo + availVideo
totalAvailImage := curImage + availImage
totalAvailData := curData + availData
if req.PendingVideoCount > totalAvailVideo {
return commonErr.ReturnError(nil, "视频任务数量不足",
fmt.Sprintf("目标待发视频数量(%d)超出当前待发数量(%d)和可用余额(%d)的总和(%d)",
req.PendingVideoCount, curVideo, availVideo, totalAvailVideo))
}
if req.PendingPostCount > totalAvailImage {
return commonErr.ReturnError(nil, "图文任务数量不足",
fmt.Sprintf("目标待发图文数量(%d)超出当前待发数量(%d)和可用余额(%d)的总和(%d)",
req.PendingPostCount, curImage, availImage, totalAvailImage))
}
if req.PendingDataCount > totalAvailData {
return commonErr.ReturnError(nil, "数据分析任务数量不足",
fmt.Sprintf("目标待发数据分析数量(%d)超出当前待发数量(%d)和可用余额(%d)的总和(%d)",
req.PendingDataCount, curData, availData, totalAvailData))
}
// 2. 调用DAO层更新待发数量
return dao.UpdatePendingCount(req)
}
// GetRecentAssignRecords 查询最近被指派记录
func GetRecentAssignRecords(limit int) ([]string, error) {
records, err := dao.GetRecentAssignRecords(limit)
if err != nil {
return nil, err
}
var recordOperator []string
for _, record := range records {
recordOperator = append(recordOperator, record.TaskAssignee)
}
return recordOperator, nil
}
// GetEmployeeAssignedTasks 根据登录人信息查询被指派给该员工的艺人任务
func GetEmployeeAssignedTasks(req *dao.EmployeeTaskQueryRequest) ([]*dao.TaskAssignRecordsResponse, int64, error) {
// 1. 调用DAO层查询被指派给该员工的艺人任务
record, total, err := dao.GetEmployeeAssignedTasks(req)
if err != nil {
return nil, 0, err
}
// 2. 转换为响应结构体
var recordResponse []*dao.TaskAssignRecordsResponse
for _, record := range record {
recordResponse = append(recordResponse, &dao.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,
// todo: 将更新时间转换成人类可读的格式
UpdatedAt: record.UpdatedAt,
})
}
return recordResponse, total, nil
}
// CompleteTaskManually 员工手动点击完成任务
func CompleteTaskManually(assignRecordsUUID string, taskAssigneeNum string) error {
// // 第一步批量更新记录被指派的员工为taskAssigneeNum的待完成任务数量和已经完成任务的数量
// err := dao.UpdateTaskRecordsByAssigneeNum(taskAssigneeNum)
// if err != nil {
// return err
// }
return dao.CompleteTaskManually(assignRecordsUUID)
}
// UpdateTaskProgress 员工实际完成任务状态更新
func UpdateTaskProgress(req *dao.CompleteTaskRequest) error {
return dao.UpdateTaskProgress(req)
}
// GetTaskAssignRecordsList 多条件查询操作记录表
func GetTaskAssignRecordsList(req *dao.TaskAssignRecordsQueryRequest) ([]*dao.TaskAssignRecordsResponse, int64, error) {
record, total, err := dao.GetTaskAssignRecordsList(req)
if err != nil {
return nil, 0, err
}
// 2. 转换为响应结构体
var recordResponse []*dao.TaskAssignRecordsResponse
for _, record := range record {
recordResponse = append(recordResponse, &dao.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,
UpdatedAt: record.UpdatedAt,
})
}
return recordResponse, total, nil
}
// // GetArtistBundleBalance 查询艺人套餐剩余数量
// func GetArtistBundleBalance(req *dao.ArtistBundleBalanceRequest) (*dao.ArtistBundleBalanceResponse, error) {
// return dao.GetArtistBundleBalance(req)
// }
// GetPendingAndTaskBalances 查询艺人当前的待发数量与任务余额(区分套餐/增值)
// 根据艺人的编号 SubNum 或手机号 TelNum 进行查询,优先使用编号
// 返回的数据会区分为“套餐类型”和“增值类型”两大类,涵盖视频/图文/数据分析三种任务
func GetPendingAndTaskBalances(req *dao.PendingAndBalanceRequest) (*dao.PendingAndBalanceResponse, error) {
return dao.GetUserPendingAndTaskBalances(req)
}