liu
昨天 cdf5605fb5caa0da0f134893bac350785250ea8a
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskServiceImpl.java
@@ -12,6 +12,7 @@
import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationMachineDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessParamDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.task.MesProTaskMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.feedback.MesProFeedbackMapper;
@@ -24,6 +25,7 @@
import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationMachineService;
import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService;
import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService;
import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessParamService;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductDO;
@@ -33,6 +35,7 @@
import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderProcessDO;
import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderProcessService;
import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderParamRecordService;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
@@ -58,6 +61,8 @@
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskPauseRecordDO;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.task.MesProTaskPauseRecordMapper;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskAssigneeDO;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.task.MesProTaskAssigneeMapper;
import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskPauseReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskResumeReqVO;
@@ -78,6 +83,9 @@
    @Resource
    private MesProTaskPauseRecordMapper taskPauseRecordMapper;
    @Resource
    private MesProTaskAssigneeMapper taskAssigneeMapper;
    @Resource
    @Lazy
@@ -101,6 +109,12 @@
    @Resource
    @Lazy
    private MesProWorkOrderProcessService workOrderProcessService;
    @Resource
    @Lazy
    private MesProWorkOrderParamRecordService workOrderParamRecordService;
    @Resource
    @Lazy
    private MesProProcessParamService processParamService;
    @Resource
    private MesMdAutoCodeRecordService autoCodeRecordService;
    @Resource
@@ -141,7 +155,28 @@
        }
        // 2.2 插入
        taskMapper.insert(task);
        // 2.2.1 参数快照:优先使用模板;无模板时回退到工序主数据绑定的工艺参数
        createTaskParamRecordWithFallback(task);
        // 2.3 保存指定报工人员
        updateTaskAssignees(task.getId(), createReqVO.getAssigneeUserIds());
        return task.getId();
    }
    /**
     * 为任务固化参数快照:优先使用路线/工单工序绑定的参数模板;无模板时回退到工序主数据绑定的工艺参数
     */
    private void createTaskParamRecordWithFallback(MesProTaskDO task) {
        if (task.getParamTemplateId() != null) {
            workOrderParamRecordService.createTaskParamRecord(task.getId(), task.getParamTemplateId());
            return;
        }
        // 无模板:从工序主数据解析绑定的工艺参数
        List<MesProProcessParamDO> processParams = processParamService.getProcessParamListByProcessId(task.getProcessId());
        if (CollUtil.isNotEmpty(processParams)) {
            workOrderParamRecordService.createTaskParamRecordFromProcessParams(task.getId(), processParams);
        }
    }
    @Override
@@ -173,6 +208,34 @@
        MesProTaskDO updateObj = BeanUtils.toBean(updateReqVO, MesProTaskDO.class)
                .setName(buildTaskName(item, quantity));
        taskMapper.updateById(updateObj);
        // 3. 更新指定报工人员(比对更新)
        updateTaskAssignees(task.getId(), updateReqVO.getAssigneeUserIds());
    }
    private void updateTaskAssignees(Long taskId, List<Long> assigneeUserIds) {
        if (assigneeUserIds == null) {
            assigneeUserIds = Collections.emptyList();
        }
        // 1. 查询数据库中原有的
        List<MesProTaskAssigneeDO> oldAssignees = taskAssigneeMapper.selectListByTaskId(taskId);
        Set<Long> oldUserIds = convertSet(oldAssignees, MesProTaskAssigneeDO::getUserId);
        Set<Long> newUserIds = new java.util.HashSet<>(assigneeUserIds);
        // 2. 计算需要新增的和需要删除的
        Set<Long> toAddUserIds = newUserIds.stream().filter(id -> !oldUserIds.contains(id)).collect(java.util.stream.Collectors.toSet());
        Set<Long> toRemoveUserIds = oldUserIds.stream().filter(id -> !newUserIds.contains(id)).collect(java.util.stream.Collectors.toSet());
        // 3. 新增
        if (CollUtil.isNotEmpty(toAddUserIds)) {
            List<MesProTaskAssigneeDO> addList = convertList(toAddUserIds, userId -> new MesProTaskAssigneeDO().setTaskId(taskId).setUserId(userId));
            taskAssigneeMapper.insertBatch(addList);
        }
        // 4. 删除
        if (CollUtil.isNotEmpty(toRemoveUserIds)) {
            taskAssigneeMapper.deleteByTaskIdAndUserIds(taskId, toRemoveUserIds);
        }
    }
    /**
@@ -220,6 +283,7 @@
                result.add(new MesProRouteProcessDO()
                        .setRouteId(routeId)
                        .setProcessId(wp.getProcessId())
                        .setParamTemplateId(wp.getParamTemplateId())
                        .setSort(wp.getSort())
                        .setKeyFlag(wp.getKeyFlag())
                        .setCheckFlag(wp.getCheckFlag())
@@ -245,8 +309,10 @@
        if (feedbackMapper.selectCountByTaskId(id) > 0) {
            throw exception(PRO_TASK_HAS_FEEDBACK);
        }
        // 3. 删除
        // 3. 删除任务主表
        taskMapper.deleteById(id);
        // 4. 删除关联的人员
        taskAssigneeMapper.deleteByTaskId(id);
    }
    @Override
@@ -270,6 +336,14 @@
            return Collections.emptyList();
        }
        return taskMapper.selectListByWorkOrderIds(workOrderIds);
    }
    @Override
    public List<MesProTaskAssigneeDO> getTaskAssigneeListByTaskIds(Collection<Long> taskIds) {
        if (CollUtil.isEmpty(taskIds)) {
            return Collections.emptyList();
        }
        return taskAssigneeMapper.selectListByTaskIds(taskIds);
    }
    @Override
@@ -337,6 +411,15 @@
        validateTaskExists(id);
        // 更新数量
        taskMapper.updateProducedQuantity(id, incrProducedQuantity, incrQualifyQuantity, incrUnqualifyQuantity);
        MesProTaskDO task = taskMapper.selectById(id);
        if (task != null) {
            LocalDateTime now = LocalDateTime.now();
            MesProTaskDO timeUpdate = new MesProTaskDO().setId(id).setLastFeedbackTime(now);
            if (task.getFirstFeedbackTime() == null) {
                timeUpdate.setFirstFeedbackTime(now);
            }
            taskMapper.updateById(timeUpdate);
        }
    }
    @Override
@@ -430,9 +513,12 @@
                    .setName(buildTaskName(item, workOrder.getQuantity()))
                    .setCode(autoCodeRecordService.generateAutoCode(MesMdAutoCodeRuleCodeEnum.PRO_TASK_CODE.getCode()))
                    .setStatus(MesProTaskStatusEnum.PREPARE.getStatus())
                    .setParamTemplateId(rp.getParamTemplateId())
                    .setClientId(workOrder.getClientId())
                    .setColorCode(rp.getColorCode());
            taskMapper.insert(task);
            // 参数快照:优先使用模板;无模板时回退到工序主数据绑定的工艺参数
            createTaskParamRecordWithFallback(task);
            taskIds.add(task.getId());
        }
        // 7. 更新工单已排产数量