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) }