660 lines
26 KiB
Java
660 lines
26 KiB
Java
package com.designhub.service;
|
||
|
||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||
import com.designhub.common.ResultCode;
|
||
import com.designhub.entity.Department;
|
||
import com.designhub.entity.Task;
|
||
import com.designhub.entity.TaskTransferLog;
|
||
import com.designhub.entity.User;
|
||
import com.designhub.exception.BusinessException;
|
||
import com.designhub.mapper.TaskTransferLogMapper;
|
||
import com.designhub.mapper.TaskMapper;
|
||
import lombok.RequiredArgsConstructor;
|
||
import lombok.extern.slf4j.Slf4j;
|
||
import org.springframework.stereotype.Service;
|
||
import org.springframework.transaction.annotation.Transactional;
|
||
import org.springframework.util.StringUtils;
|
||
|
||
import java.math.BigDecimal;
|
||
import java.time.LocalDateTime;
|
||
import java.time.temporal.ChronoUnit;
|
||
import java.util.HashMap;
|
||
import java.util.List;
|
||
import java.util.Map;
|
||
import com.designhub.entity.TaskItem;
|
||
import com.designhub.mapper.TaskItemMapper;
|
||
import com.designhub.util.WorkHoursCalculator;
|
||
|
||
/**
|
||
* 管理员任务调配Service
|
||
*/
|
||
@Slf4j
|
||
@Service
|
||
@RequiredArgsConstructor
|
||
public class AdminTaskService {
|
||
|
||
private final TaskMapper taskMapper;
|
||
private final TaskItemMapper taskItemMapper;
|
||
private final NotificationService notificationService;
|
||
private final UserService userService;
|
||
private final DepartmentService departmentService;
|
||
private final RoleService roleService;
|
||
private final WorkHoursCalculator workHoursCalculator;
|
||
private final TaskTransferLogMapper taskTransferLogMapper;
|
||
private final TaskUnlockService taskUnlockService;
|
||
|
||
/**
|
||
* 应急解锁排队任务到大厅(支持主任务编号/子任务编号)
|
||
*/
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public Map<String, Object> emergencyUnlockQueuedTaskToHall(String taskNoOrItemNo, Long adminId, String reason) {
|
||
if (!isAdminUser(adminId)) {
|
||
throw new BusinessException(ResultCode.FORBIDDEN, "只有管理员可以解锁排队任务");
|
||
}
|
||
if (!StringUtils.hasText(taskNoOrItemNo)) {
|
||
throw new BusinessException(ResultCode.PARAM_ERROR, "任务编号不能为空");
|
||
}
|
||
|
||
Map<String, Object> unlockResult = taskUnlockService.emergencyUnlockToHall(taskNoOrItemNo.trim());
|
||
log.info("管理员应急解锁到大厅: adminId={}, key={}, reason={}, result={}",
|
||
adminId,
|
||
taskNoOrItemNo,
|
||
StringUtils.hasText(reason) ? reason.trim() : "",
|
||
unlockResult
|
||
);
|
||
return unlockResult;
|
||
}
|
||
|
||
/**
|
||
* 管理员分配任务
|
||
*/
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public Task assignTask(Long taskId, Long designerId, Long adminId) {
|
||
// 验证管理员权限
|
||
if (!isAdminUser(adminId)) {
|
||
throw new BusinessException(ResultCode.FORBIDDEN, "只有管理员可以分配任务");
|
||
}
|
||
|
||
// 验证设计师
|
||
User designer = userService.getUserById(designerId);
|
||
if (designer == null) {
|
||
throw new BusinessException(ResultCode.PARAM_ERROR, "设计师不存在");
|
||
}
|
||
|
||
// 验证设计师部门类型(必须是接单部门)
|
||
if (designer.getDeptId() != null) {
|
||
Department dept = departmentService.getDepartmentById(designer.getDeptId());
|
||
if (dept == null || !"receiving".equals(dept.getDeptType())) {
|
||
throw new BusinessException(ResultCode.FORBIDDEN, "只能分配给接单部门的设计师");
|
||
}
|
||
}
|
||
|
||
Task task = taskMapper.selectById(taskId);
|
||
if (task == null) {
|
||
throw new BusinessException(ResultCode.TASK_NOT_EXIST);
|
||
}
|
||
|
||
if (!"pending".equals(task.getStatus()) && !"recruitment".equals(task.getReleaseType())) {
|
||
throw new BusinessException(ResultCode.TASK_STATUS_ERROR, "只能分配待接单的任务");
|
||
}
|
||
|
||
// 验证任务需求类型是否允许该部门接单
|
||
if (task.getDemandTypeId() != null && designer.getDeptId() != null) {
|
||
Department dept = departmentService.getDepartmentById(designer.getDeptId());
|
||
if (dept != null && dept.getAllowedDemandTypes() != null && !dept.getAllowedDemandTypes().isEmpty()) {
|
||
String[] allowedTypes = dept.getAllowedDemandTypes().split(",");
|
||
boolean allowed = false;
|
||
for (String typeId : allowedTypes) {
|
||
if (task.getDemandTypeId().toString().equals(typeId.trim())) {
|
||
allowed = true;
|
||
break;
|
||
}
|
||
}
|
||
if (!allowed) {
|
||
throw new BusinessException(ResultCode.FORBIDDEN, "该设计师所在部门不支持此需求类型");
|
||
}
|
||
}
|
||
}
|
||
|
||
// 记录原接收人(如果有)
|
||
Long originalReceiverId = task.getReceiverId();
|
||
|
||
// 分配任务
|
||
task.setReceiverId(designerId);
|
||
task.setReceiverDeptId(designer.getDeptId());
|
||
task.setStatus("in_progress");
|
||
task.setStartTime(LocalDateTime.now());
|
||
task.setActualStartTime(LocalDateTime.now());
|
||
|
||
// 重新计算截止时间
|
||
if (task.getEstimatedHours() != null) {
|
||
int hours = task.getEstimatedHours().intValue();
|
||
if (hours > 0) {
|
||
task.setDeadline(LocalDateTime.now().plusHours(hours));
|
||
}
|
||
} else if (task.getEstimatedDuration() != null) {
|
||
task.setDeadline(LocalDateTime.now().plusHours(task.getEstimatedDuration()));
|
||
}
|
||
|
||
task.setUpdateTime(LocalDateTime.now());
|
||
taskMapper.updateById(task);
|
||
|
||
// 记录操作日志
|
||
log.info("管理员分配任务: taskId={}, designerId={}, adminId={}", taskId, designerId, adminId);
|
||
|
||
// 发送通知给设计师
|
||
notificationService.sendTaskNotification(
|
||
designerId,
|
||
taskId,
|
||
"📋 新任务分配",
|
||
"管理员为您分配了新任务:" + task.getTitle()
|
||
);
|
||
|
||
// 如果有原接收人,通知他任务已被重新分配
|
||
if (originalReceiverId != null && !originalReceiverId.equals(designerId)) {
|
||
notificationService.sendTaskNotification(
|
||
originalReceiverId,
|
||
taskId,
|
||
"⚠️ 任务重新分配",
|
||
"您的任务已被管理员重新分配"
|
||
);
|
||
}
|
||
|
||
return task;
|
||
}
|
||
|
||
/**
|
||
* 管理员转移任务
|
||
*/
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public Task transferTask(Long taskId, Long newDesignerId, Long adminId, String reason) {
|
||
// 验证管理员权限
|
||
if (!isAdminUser(adminId)) {
|
||
throw new BusinessException(ResultCode.FORBIDDEN, "只有管理员可以转移任务");
|
||
}
|
||
|
||
// 验证新设计师
|
||
User newDesigner = userService.getUserById(newDesignerId);
|
||
if (newDesigner == null) {
|
||
throw new BusinessException(ResultCode.PARAM_ERROR, "新设计师不存在");
|
||
}
|
||
|
||
// 验证新设计师部门类型
|
||
if (newDesigner.getDeptId() != null) {
|
||
Department dept = departmentService.getDepartmentById(newDesigner.getDeptId());
|
||
if (dept == null || !"receiving".equals(dept.getDeptType())) {
|
||
throw new BusinessException(ResultCode.FORBIDDEN, "只能转移给接单部门的设计师");
|
||
}
|
||
}
|
||
|
||
Task task = taskMapper.selectById(taskId);
|
||
if (task == null) {
|
||
throw new BusinessException(ResultCode.TASK_NOT_EXIST);
|
||
}
|
||
|
||
if (!"in_progress".equals(task.getStatus()) && !"review".equals(task.getStatus())) {
|
||
throw new BusinessException(ResultCode.TASK_STATUS_ERROR, "只能转移进行中或待审核的任务");
|
||
}
|
||
|
||
Long originalDesignerId = task.getReceiverId();
|
||
if (originalDesignerId == null) {
|
||
throw new BusinessException("任务没有接收人");
|
||
}
|
||
|
||
if (originalDesignerId.equals(newDesignerId)) {
|
||
throw new BusinessException("新接收人与原接收人相同");
|
||
}
|
||
|
||
// 计算已用时长
|
||
LocalDateTime startTime = task.getActualStartTime();
|
||
if (startTime != null) {
|
||
long hoursUsed = ChronoUnit.HOURS.between(startTime, LocalDateTime.now());
|
||
|
||
// 检查是否已延误
|
||
LocalDateTime originalDeadline = task.getDeadline();
|
||
if (originalDeadline != null && LocalDateTime.now().isAfter(originalDeadline)) {
|
||
// 原设计师已延误,记录延误信息
|
||
long delayHours = ChronoUnit.HOURS.between(originalDeadline, LocalDateTime.now());
|
||
log.warn("任务转移时发现延误: taskId={}, originalDesignerId={}, delayHours={}",
|
||
taskId, originalDesignerId, delayHours);
|
||
|
||
// TODO: 记录延误扣分信息
|
||
// TODO: 更新原设计师的延误统计
|
||
}
|
||
}
|
||
|
||
// 转移任务
|
||
task.setReceiverId(newDesignerId);
|
||
task.setReceiverDeptId(newDesigner.getDeptId());
|
||
task.setActualStartTime(LocalDateTime.now()); // 重新开始计时
|
||
|
||
// 如果任务状态是 review,转回 in_progress
|
||
if ("review".equals(task.getStatus())) {
|
||
task.setStatus("in_progress");
|
||
}
|
||
|
||
// 重新计算截止时间
|
||
if (task.getEstimatedHours() != null) {
|
||
int hours = task.getEstimatedHours().intValue();
|
||
if (hours > 0) {
|
||
task.setDeadline(LocalDateTime.now().plusHours(hours));
|
||
}
|
||
} else if (task.getEstimatedDuration() != null) {
|
||
task.setDeadline(LocalDateTime.now().plusHours(task.getEstimatedDuration()));
|
||
}
|
||
|
||
task.setUpdateTime(LocalDateTime.now());
|
||
|
||
// 在备注中记录转移信息
|
||
String transferNote = String.format("[%s] 管理员转移任务:从设计师%d转移到设计师%d,原因:%s",
|
||
LocalDateTime.now().toString(), originalDesignerId, newDesignerId, reason);
|
||
String existingRemark = task.getRemark();
|
||
task.setRemark(existingRemark != null ? existingRemark + "\n" + transferNote : transferNote);
|
||
|
||
taskMapper.updateById(task);
|
||
|
||
log.info("管理员转移任务: taskId={}, from={}, to={}, adminId={}, reason={}",
|
||
taskId, originalDesignerId, newDesignerId, adminId, reason);
|
||
|
||
// 通知新设计师
|
||
notificationService.sendTaskNotification(
|
||
newDesignerId,
|
||
taskId,
|
||
"📋 新任务转移",
|
||
"管理员为您转移了任务:" + task.getTitle() + ",原因:" + reason
|
||
);
|
||
|
||
// 通知原设计师
|
||
notificationService.sendTaskNotification(
|
||
originalDesignerId,
|
||
taskId,
|
||
"⚠️ 任务已转移",
|
||
"您的任务已被管理员转移,原因:" + reason
|
||
);
|
||
|
||
return task;
|
||
}
|
||
|
||
/**
|
||
* 批量分配任务
|
||
*/
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public int batchAssignTasks(List<Long> taskIds, Long designerId, Long adminId) {
|
||
int successCount = 0;
|
||
for (Long taskId : taskIds) {
|
||
try {
|
||
assignTask(taskId, designerId, adminId);
|
||
successCount++;
|
||
} catch (Exception e) {
|
||
log.error("批量分配任务失败: taskId={}, error={}", taskId, e.getMessage());
|
||
}
|
||
}
|
||
log.info("批量分配任务完成: total={}, success={}, adminId={}", taskIds.size(), successCount, adminId);
|
||
return successCount;
|
||
}
|
||
|
||
/**
|
||
* 调整任务优先级
|
||
*/
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public Task adjustTaskPriority(Long taskId, Integer newPriority, Long adminId) {
|
||
Task task = taskMapper.selectById(taskId);
|
||
if (task == null) {
|
||
throw new BusinessException("任务不存在");
|
||
}
|
||
|
||
Integer oldPriority = task.getPriority();
|
||
task.setPriority(newPriority);
|
||
task.setUpdateTime(LocalDateTime.now());
|
||
taskMapper.updateById(task);
|
||
|
||
log.info("管理员调整任务优先级: taskId={}, old={}, new={}, adminId={}",
|
||
taskId, oldPriority, newPriority, adminId);
|
||
|
||
// 如果任务有接收人,发送通知
|
||
if (task.getReceiverId() != null) {
|
||
String priorityText = getPriorityText(newPriority);
|
||
notificationService.sendTaskNotification(
|
||
task.getReceiverId(),
|
||
taskId,
|
||
"⚡ 任务优先级调整",
|
||
"任务优先级已调整为:" + priorityText
|
||
);
|
||
}
|
||
|
||
return task;
|
||
}
|
||
|
||
/**
|
||
* 获取任务池列表(待分配的任务)
|
||
*/
|
||
public List<Task> getTaskPool() {
|
||
return taskMapper.selectList(
|
||
new LambdaQueryWrapper<Task>()
|
||
.in(Task::getStatus, "pending", "pool")
|
||
.orderByDesc(Task::getCreateTime)
|
||
);
|
||
}
|
||
|
||
/**
|
||
* 获取所有进行中的任务
|
||
*/
|
||
public List<Task> getInProgressTasks() {
|
||
return taskMapper.selectList(
|
||
new LambdaQueryWrapper<Task>()
|
||
.eq(Task::getStatus, "in_progress")
|
||
.orderByAsc(Task::getDeadline)
|
||
);
|
||
}
|
||
|
||
/**
|
||
* 强制完成任务(管理员操作)
|
||
*/
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public Task forceCompleteTask(Long taskId, Long adminId, String reason) {
|
||
Task task = taskMapper.selectById(taskId);
|
||
if (task == null) {
|
||
throw new BusinessException("任务不存在");
|
||
}
|
||
|
||
task.setStatus("completed");
|
||
task.setActualEndTime(LocalDateTime.now());
|
||
task.setUpdateTime(LocalDateTime.now());
|
||
|
||
String completeNote = String.format("[%s] 管理员强制完成,原因:%s",
|
||
LocalDateTime.now().toString(), reason);
|
||
String existingRemark = task.getRemark();
|
||
task.setRemark(existingRemark != null ? existingRemark + "\n" + completeNote : completeNote);
|
||
|
||
taskMapper.updateById(task);
|
||
|
||
log.info("管理员强制完成任务: taskId={}, adminId={}, reason={}", taskId, adminId, reason);
|
||
|
||
// 通知相关人员
|
||
if (task.getReceiverId() != null) {
|
||
notificationService.sendTaskNotification(
|
||
task.getReceiverId(),
|
||
taskId,
|
||
"✅ 任务已完成",
|
||
"管理员已将您的任务标记为完成,原因:" + reason
|
||
);
|
||
}
|
||
|
||
return task;
|
||
}
|
||
|
||
/**
|
||
* 取消任务(管理员操作)
|
||
*/
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public Task cancelTask(Long taskId, Long adminId, String reason) {
|
||
Task task = taskMapper.selectById(taskId);
|
||
if (task == null) {
|
||
throw new BusinessException("任务不存在");
|
||
}
|
||
|
||
task.setStatus("cancelled");
|
||
task.setUpdateTime(LocalDateTime.now());
|
||
|
||
String cancelNote = String.format("[%s] 管理员取消任务,原因:%s",
|
||
LocalDateTime.now().toString(), reason);
|
||
String existingRemark = task.getRemark();
|
||
task.setRemark(existingRemark != null ? existingRemark + "\n" + cancelNote : cancelNote);
|
||
|
||
taskMapper.updateById(task);
|
||
|
||
log.info("管理员取消任务: taskId={}, adminId={}, reason={}", taskId, adminId, reason);
|
||
|
||
// 通知相关人员
|
||
if (task.getReceiverId() != null) {
|
||
notificationService.sendTaskNotification(
|
||
task.getReceiverId(),
|
||
taskId,
|
||
"❌ 任务已取消",
|
||
"管理员已取消该任务,原因:" + reason
|
||
);
|
||
}
|
||
|
||
if (task.getPublisherId() != null) {
|
||
notificationService.sendTaskNotification(
|
||
task.getPublisherId(),
|
||
taskId,
|
||
"❌ 任务已取消",
|
||
"您发布的任务已被取消,原因:" + reason
|
||
);
|
||
}
|
||
|
||
return task;
|
||
}
|
||
|
||
/**
|
||
* 管理员将子任务直接切换到指定接单部门可接单
|
||
*/
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public Map<String, Object> redirectTaskItemToDept(String itemNo, Long targetDeptId, Long adminId, String reason) {
|
||
if (!isAdminUser(adminId)) {
|
||
throw new BusinessException(ResultCode.FORBIDDEN, "只有管理员可以操作任务节点调拨");
|
||
}
|
||
if (!StringUtils.hasText(itemNo)) {
|
||
throw new BusinessException(ResultCode.PARAM_ERROR, "子任务编号不能为空");
|
||
}
|
||
if (targetDeptId == null) {
|
||
throw new BusinessException(ResultCode.PARAM_ERROR, "目标部门不能为空");
|
||
}
|
||
|
||
TaskItem item = taskItemMapper.selectOne(
|
||
new LambdaQueryWrapper<TaskItem>()
|
||
.eq(TaskItem::getItemNo, itemNo.trim())
|
||
.last("LIMIT 1")
|
||
);
|
||
if (item == null) {
|
||
throw new BusinessException(ResultCode.NOT_FOUND, "子任务不存在");
|
||
}
|
||
|
||
Task task = taskMapper.selectById(item.getTaskId());
|
||
if (task == null || task.getDeleted() != null && task.getDeleted() == 1) {
|
||
throw new BusinessException(ResultCode.NOT_FOUND, "主任务不存在");
|
||
}
|
||
|
||
Department targetDept = departmentService.getDepartmentById(targetDeptId);
|
||
if (targetDept == null) {
|
||
throw new BusinessException(ResultCode.PARAM_ERROR, "目标部门不存在");
|
||
}
|
||
if (targetDept.getStatus() == null || targetDept.getStatus() != 1) {
|
||
throw new BusinessException(ResultCode.PARAM_ERROR, "目标部门已禁用");
|
||
}
|
||
if (!"receiving".equals(targetDept.getDeptType())) {
|
||
throw new BusinessException(ResultCode.PARAM_ERROR, "目标部门必须是接单部门");
|
||
}
|
||
|
||
if ("completed".equals(item.getStatus())) {
|
||
throw new BusinessException(ResultCode.TASK_STATUS_ERROR, "已完成子任务不允许调拨");
|
||
}
|
||
if ("in_progress".equals(item.getStatus())) {
|
||
throw new BusinessException(ResultCode.TASK_STATUS_ERROR, "进行中子任务请先转移接单人");
|
||
}
|
||
|
||
Long oldDeptId = item.getReceiverDeptId();
|
||
Long oldReceiverId = item.getReceiverId();
|
||
LocalDateTime oldDeadline = item.getDeadline();
|
||
String oldStatus = item.getStatus();
|
||
|
||
item.setStatus("pending");
|
||
item.setReceiverDeptId(targetDeptId);
|
||
item.setReceiverId(null);
|
||
item.setReceiverName(null);
|
||
item.setClaimTime(null);
|
||
item.setDeadline(null);
|
||
item.setIsLocked(0);
|
||
item.setUpdateTime(LocalDateTime.now());
|
||
taskItemMapper.updateById(item);
|
||
|
||
// 排队记录重建到新部门,确保可见且可抢
|
||
taskUnlockService.deleteUnlockStatus(item.getId());
|
||
if (taskUnlockService.isUnlockEnabled() && !"assigned".equals(task.getReleaseType())) {
|
||
taskUnlockService.onPipelineUnlock(item, targetDeptId);
|
||
}
|
||
|
||
String transferReason = StringUtils.hasText(reason) ? reason.trim() : "管理员手动调拨子任务到指定接单部门";
|
||
TaskTransferLog transferLog = new TaskTransferLog();
|
||
transferLog.setTaskId(task.getId());
|
||
transferLog.setTransferType("transfer");
|
||
transferLog.setFromUserId(oldReceiverId);
|
||
transferLog.setToUserId(null);
|
||
transferLog.setOperatorId(adminId);
|
||
transferLog.setOldDeadline(oldDeadline);
|
||
transferLog.setNewDeadline(null);
|
||
transferLog.setOldPriority(task.getPriority());
|
||
transferLog.setNewPriority(task.getPriority());
|
||
transferLog.setReason(transferReason);
|
||
transferLog.setRemark(String.format("节点调拨:%s(%s)->%s(%s), itemNo=%s, oldStatus=%s",
|
||
oldDeptId == null ? "-" : oldDeptId,
|
||
resolveDeptName(oldDeptId),
|
||
targetDeptId,
|
||
targetDept.getDeptName(),
|
||
item.getItemNo(),
|
||
oldStatus
|
||
));
|
||
transferLog.setCreateTime(LocalDateTime.now());
|
||
taskTransferLogMapper.insert(transferLog);
|
||
|
||
Map<String, Object> result = new HashMap<>();
|
||
result.put("taskId", task.getId());
|
||
result.put("taskNo", task.getTaskNo());
|
||
result.put("itemId", item.getId());
|
||
result.put("itemNo", item.getItemNo());
|
||
result.put("oldStatus", oldStatus);
|
||
result.put("newStatus", item.getStatus());
|
||
result.put("oldDeptId", oldDeptId);
|
||
result.put("oldDeptName", resolveDeptName(oldDeptId));
|
||
result.put("newDeptId", targetDeptId);
|
||
result.put("newDeptName", targetDept.getDeptName());
|
||
return result;
|
||
}
|
||
|
||
private String resolveDeptName(Long deptId) {
|
||
if (deptId == null) {
|
||
return "";
|
||
}
|
||
Department department = departmentService.getDepartmentById(deptId);
|
||
return department != null ? department.getDeptName() : "";
|
||
}
|
||
|
||
/**
|
||
* 获取优先级文本
|
||
*/
|
||
private String getPriorityText(Integer priority) {
|
||
if (priority == null) return "未设置";
|
||
return switch (priority) {
|
||
case 0 -> "低";
|
||
case 1 -> "普通";
|
||
case 2 -> "高";
|
||
case 3 -> "紧急";
|
||
default -> String.valueOf(priority);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 检查用户是否是管理员(ADMIN或SUPER_ADMIN)
|
||
*/
|
||
private boolean isAdminUser(Long userId) {
|
||
try {
|
||
var roles = roleService.getRolesByUserId(userId);
|
||
return roles.stream().anyMatch(role ->
|
||
"ADMIN".equals(role.getRoleCode()) ||
|
||
"SUPER_ADMIN".equals(role.getRoleCode())
|
||
);
|
||
} catch (Exception e) {
|
||
log.warn("检查用户角色失败: userId={}, error={}", userId, e.getMessage());
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 批量更新低时效任务的截止时间(应用最低1小时时效)
|
||
* @return 更新结果统计
|
||
*/
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public Map<String, Integer> batchUpdateLowHoursDeadlines() {
|
||
Map<String, Integer> result = new HashMap<>();
|
||
int taskUpdated = 0;
|
||
int itemUpdated = 0;
|
||
|
||
BigDecimal minHours = BigDecimal.ONE; // 最低1小时
|
||
|
||
// 1. 更新主任务的截止时间
|
||
LambdaQueryWrapper<Task> taskWrapper = new LambdaQueryWrapper<Task>()
|
||
.in(Task::getStatus, "pending", "in_progress")
|
||
.eq(Task::getDeleted, 0)
|
||
.lt(Task::getEstimatedHours, minHours)
|
||
.gt(Task::getEstimatedHours, BigDecimal.ZERO)
|
||
.isNotNull(Task::getStartTime); // 只更新已接单的任务
|
||
|
||
List<Task> lowHoursTasks = taskMapper.selectList(taskWrapper);
|
||
log.info("找到 {} 个低时效主任务需要更新", lowHoursTasks.size());
|
||
|
||
for (Task task : lowHoursTasks) {
|
||
try {
|
||
// 使用接单时间计算新的截止时间(应用最低1小时)
|
||
LocalDateTime newDeadline = workHoursCalculator.calculateDeadline(
|
||
task.getStartTime(),
|
||
minHours
|
||
);
|
||
if (newDeadline != null && !newDeadline.equals(task.getDeadline())) {
|
||
log.info("更新任务截止时间: taskNo={}, 原时效={}小时, 原截止={}, 新截止={}",
|
||
task.getTaskNo(), task.getEstimatedHours(), task.getDeadline(), newDeadline);
|
||
task.setDeadline(newDeadline);
|
||
task.setUpdateTime(LocalDateTime.now());
|
||
taskMapper.updateById(task);
|
||
taskUpdated++;
|
||
}
|
||
} catch (Exception e) {
|
||
log.error("更新任务截止时间失败: taskId={}, error={}", task.getId(), e.getMessage());
|
||
}
|
||
}
|
||
|
||
// 2. 更新子任务(TaskItem)的截止时间
|
||
LambdaQueryWrapper<TaskItem> itemWrapper = new LambdaQueryWrapper<TaskItem>()
|
||
.in(TaskItem::getStatus, "pending", "in_progress")
|
||
.lt(TaskItem::getEstimatedHours, minHours)
|
||
.gt(TaskItem::getEstimatedHours, BigDecimal.ZERO)
|
||
.isNotNull(TaskItem::getReceiverId); // 只更新已接单的子任务
|
||
|
||
List<TaskItem> lowHoursItems = taskItemMapper.selectList(itemWrapper);
|
||
log.info("找到 {} 个低时效子任务需要更新", lowHoursItems.size());
|
||
|
||
for (TaskItem item : lowHoursItems) {
|
||
try {
|
||
// 子任务使用 update_time 作为接单时间(如果没有专门的接单时间字段)
|
||
LocalDateTime startTime = item.getUpdateTime();
|
||
if (startTime == null) {
|
||
startTime = item.getCreateTime();
|
||
}
|
||
|
||
LocalDateTime newDeadline = workHoursCalculator.calculateDeadline(
|
||
startTime,
|
||
minHours
|
||
);
|
||
if (newDeadline != null && !newDeadline.equals(item.getDeadline())) {
|
||
log.info("更新子任务截止时间: itemNo={}, 原时效={}小时, 原截止={}, 新截止={}",
|
||
item.getItemNo(), item.getEstimatedHours(), item.getDeadline(), newDeadline);
|
||
item.setDeadline(newDeadline);
|
||
item.setUpdateTime(LocalDateTime.now());
|
||
taskItemMapper.updateById(item);
|
||
itemUpdated++;
|
||
}
|
||
} catch (Exception e) {
|
||
log.error("更新子任务截止时间失败: itemId={}, error={}", item.getId(), e.getMessage());
|
||
}
|
||
}
|
||
|
||
result.put("tasksFound", lowHoursTasks.size());
|
||
result.put("tasksUpdated", taskUpdated);
|
||
result.put("itemsFound", lowHoursItems.size());
|
||
result.put("itemsUpdated", itemUpdated);
|
||
|
||
log.info("批量更新低时效任务截止时间完成: {}", result);
|
||
return result;
|
||
}
|
||
}
|