云
2026-10-26 0857cf1830039d60ce73005f386f284cf575e511
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskServiceImpl.java
@@ -18,6 +18,8 @@
import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeRuleCodeEnum;
import cn.iocoder.yudao.module.mes.enums.pro.MesProTaskStatusEnum;
import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryService;
import cn.iocoder.yudao.module.mes.service.cal.team.MesCalTeamService;
import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamDO;
import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService;
import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService;
@@ -43,7 +45,9 @@
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -108,6 +112,8 @@
    @Resource
    @Lazy
    private MesDvMachineryService machineryService;
    @Resource
    private MesCalTeamService teamService;
    @Override
    public Long createTask(MesProTaskSaveReqVO createReqVO) {
@@ -116,17 +122,14 @@
        workstationService.validateWorkstationExists(createReqVO.getWorkstationId());
        routeService.validateRouteExists(createReqVO.getRouteId());
        processService.validateProcessExistsAndEnable(createReqVO.getProcessId());
        fillTeamInfo(createReqVO);
        // 2. 自动确定 itemId:优先前端传入 → 工艺路线工序的产出产品 → 工单成品
        Long itemId = createReqVO.getItemId();
        if (itemId == null) {
            MesProRouteProcessDO routeProcess = routeProcessService
                    .getRouteProcessByRouteIdAndProcessId(createReqVO.getRouteId(), createReqVO.getProcessId());
            if (routeProcess != null && routeProcess.getOutputItemId() != null) {
                itemId = Long.valueOf(routeProcess.getOutputItemId().split(",")[0].trim());
            } else {
                itemId = workOrder.getProductId();
            }
            itemId = resolveTaskItemId(routeProcess, workOrder.getProductId());
        }
        MesMdItemDO item = itemService.validateItemExists(itemId);
@@ -161,6 +164,7 @@
        if (updateReqVO.getProcessId() != null) {
            processService.validateProcessExistsAndEnable(updateReqVO.getProcessId());
        }
        fillTeamInfo(updateReqVO);
        MesMdItemDO item;
        if (updateReqVO.getItemId() != null) {
            item = itemService.validateItemExists(updateReqVO.getItemId());
@@ -173,6 +177,19 @@
        MesProTaskDO updateObj = BeanUtils.toBean(updateReqVO, MesProTaskDO.class)
                .setName(buildTaskName(item, quantity));
        taskMapper.updateById(updateObj);
    }
    /**
     * 校验班组存在并回填班组名称
     */
    private void fillTeamInfo(MesProTaskSaveReqVO reqVO) {
        if (reqVO.getTeamId() == null) {
            return;
        }
        MesCalTeamDO team = teamService.validateTeamExists(reqVO.getTeamId());
        if (team != null) {
            reqVO.setTeamName(team.getName());
        }
    }
    /**
@@ -237,6 +254,30 @@
        return routeProcesses;
    }
    /**
     * 任务产出物料:优先取工序在当前产品下的产出(按归属过滤),没有产出时取工单成品
     */
    private Long resolveTaskItemId(MesProRouteProcessDO routeProcess, Long productId) {
        if (routeProcess == null) {
            return productId;
        }
        if (routeProcess.getId() != null) {
            // 工艺路线模板:按产出归属过滤出当前产品的产出
            List<Long> outputIds = routeProcessService
                    .getOutputItemIdsByRouteProcessId(routeProcess.getId(), productId);
            if (outputIds != null) {
                // 有归属配置:该产品无产出时取工单成品;null 表示存量无归属数据,继续走聚合兜底
                return CollUtil.isNotEmpty(outputIds) ? outputIds.get(0) : productId;
            }
        }
        // 工单工序快照 / 存量无归属数据:产出已按产品过滤,取第一个
        String outputItemId = routeProcess.getOutputItemId();
        if (outputItemId != null && !outputItemId.isBlank()) {
            return Long.valueOf(outputItemId.split(",")[0].trim());
        }
        return productId;
    }
    @Override
    public void deleteTask(Long id) {
        // 1. 校验存在且非终态
@@ -255,6 +296,11 @@
    }
    @Override
    public MesProTaskDO getTaskByCode(String code) {
        return taskMapper.selectByCode(code);
    }
    @Override
    public PageResult<MesProTaskDO> getTaskPage(MesProTaskPageReqVO pageReqVO) {
        return taskMapper.selectPage(pageReqVO);
    }
@@ -262,6 +308,20 @@
    @Override
    public PageResult<MesProTaskDO> getPendingFeedbackPage(MesProTaskPageReqVO pageReqVO) {
        return taskMapper.selectPendingFeedbackPage(pageReqVO);
    }
    @Override
    public Map<Long, Long> getPendingFeedbackCountByWorkstation() {
        List<Map<String, Object>> rows = taskMapper.selectPendingFeedbackCountByWorkstation();
        Map<Long, Long> result = new HashMap<>(rows.size());
        for (Map<String, Object> row : rows) {
            Object workstationId = row.get("workstation_id");
            Object count = row.get("pending_count");
            if (workstationId instanceof Number && count instanceof Number) {
                result.put(((Number) workstationId).longValue(), ((Number) count).longValue());
            }
        }
        return result;
    }
    @Override
@@ -419,7 +479,7 @@
        List<Long> taskIds = new java.util.ArrayList<>();
        for (MesProRouteProcessDO rp : routeProcesses) {
            cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO proc = procMap.get(rp.getProcessId());
            Long itemId = rp.getOutputItemId() != null ? Long.valueOf(rp.getOutputItemId().split(",")[0].trim()) : workOrder.getProductId();
            Long itemId = resolveTaskItemId(rp, workOrder.getProductId());
            cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO item = itemService.validateItemExists(itemId);
            MesProTaskDO task = new MesProTaskDO()
                    .setWorkOrderId(workOrder.getId())
@@ -446,7 +506,8 @@
        // 1. 校验任务存在
        MesProTaskDO task = validateTaskExists(pauseReqVO.getId());
        // 2. 校验状态是否允许停工(如必须是 生产中 或 部分完成)
        if (!ObjectUtils.equalsAny(task.getStatus(), MesProTaskStatusEnum.PREPARE.getStatus())) {
        if (!ObjectUtils.equalsAny(task.getStatus(), MesProTaskStatusEnum.PRODUCING.getStatus(),
                MesProTaskStatusEnum.PARTIAL_FINISHED.getStatus())) {
            throw exception(PRO_TASK_CANNOT_PAUSE);
        }
        
@@ -476,7 +537,10 @@
        }
        // 3. 恢复任务状态
        Integer resumeStatus = MesProTaskStatusEnum.PREPARE.getStatus();
        Integer resumeStatus = task.getProducedQuantity() != null
                && task.getProducedQuantity().signum() > 0
                ? MesProTaskStatusEnum.PARTIAL_FINISHED.getStatus()
                : MesProTaskStatusEnum.PRODUCING.getStatus();
        taskMapper.updateById(new MesProTaskDO().setId(task.getId()).setStatus(resumeStatus));
        // 4. 更新最新的一条停工记录