14 小时以前 757c7e03bee3560bb4d7766fddd03673e2c2e611
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskServiceImpl.java
@@ -3,6 +3,8 @@
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskAutoGeneratePreviewRespVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskAutoGenerateReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskPageReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskSaveReqVO;
import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
@@ -19,12 +21,18 @@
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.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;
import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProcessService;
import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProductService;
import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteService;
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 jakarta.annotation.Resource;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.math.BigDecimal;
@@ -70,6 +78,12 @@
    @Resource
    @Lazy
    private MesProRouteProcessService routeProcessService;
    @Resource
    @Lazy
    private MesProRouteProductService routeProductService;
    @Resource
    @Lazy
    private MesProWorkOrderProcessService workOrderProcessService;
    @Resource
    private MesMdAutoCodeRecordService autoCodeRecordService;
@@ -151,6 +165,54 @@
            }
        }
        return item.getName() + "【" + quantity + "】" + unitName;
    }
    /**
     * 确定排产使用的工艺路线 ID:优先请求指定 → 工单关联 → 产品关联
     */
    private Long resolveRouteId(Long reqRouteId, MesProWorkOrderDO workOrder) {
        if (reqRouteId != null) {
            return reqRouteId;
        }
        if (workOrder.getRouteId() != null) {
            return workOrder.getRouteId();
        }
        // 从产品关联的工艺路线获取
        MesProRouteProductDO routeProduct = routeProductService.getRouteProductByItemId(workOrder.getProductId());
        if (routeProduct == null) {
            throw exception(cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_ROUTE_NOT_EXISTS);
        }
        return routeProduct.getRouteId();
    }
    /**
     * 构建工序列表:优先使用工单已保存的工序 → 回退到工艺路线模板工序
     */
    private List<MesProRouteProcessDO> buildRouteProcessList(Long routeId, Long workOrderId) {
        // 1. 优先使用工单已保存的工序
        List<MesProWorkOrderProcessDO> woProcesses = workOrderProcessService
                .getWorkOrderProcessListByWorkOrderId(workOrderId);
        if (CollUtil.isNotEmpty(woProcesses)) {
            List<MesProRouteProcessDO> result = new java.util.ArrayList<>();
            for (MesProWorkOrderProcessDO wp : woProcesses) {
                result.add(new MesProRouteProcessDO()
                        .setRouteId(routeId)
                        .setProcessId(wp.getProcessId())
                        .setSort(wp.getSort())
                        .setKeyFlag(wp.getKeyFlag())
                        .setCheckFlag(wp.getCheckFlag())
                        .setBackflushFlag(wp.getBackflushFlag())
                        .setOutputItemId(wp.getOutputItemId())
                        .setColorCode(wp.getColorCode()));
            }
            return result;
        }
        // 2. 回退到工艺路线模板工序
        List<MesProRouteProcessDO> routeProcesses = routeProcessService.getRouteProcessListByRouteId(routeId);
        if (CollUtil.isEmpty(routeProcesses)) {
            throw exception(cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_ROUTE_ENABLE_NO_PROCESS);
        }
        return routeProcesses;
    }
    @Override
@@ -255,4 +317,78 @@
        taskMapper.updateProducedQuantity(id, incrProducedQuantity, incrQualifyQuantity, incrUnqualifyQuantity);
    }
    @Override
    public MesProTaskAutoGeneratePreviewRespVO previewAutoGenerate(MesProTaskAutoGenerateReqVO reqVO) {
        // 1. 校验工单已确认
        MesProWorkOrderDO workOrder = workOrderService.validateWorkOrderConfirmed(reqVO.getWorkOrderId());
        // 2. 确定工艺路线:优先请求指定 → 工单关联 → 产品关联
        Long routeId = resolveRouteId(reqVO.getRouteId(), workOrder);
        MesProRouteDO route = routeService.validateRouteExists(routeId);
        // 3. 获取工序列表:优先工单工序 → 工艺路线工序
        List<MesProRouteProcessDO> routeProcesses = buildRouteProcessList(routeId, reqVO.getWorkOrderId());
        // 按序号排序
        routeProcesses.sort(java.util.Comparator.comparing(MesProRouteProcessDO::getSort, java.util.Comparator.nullsLast(java.util.Comparator.naturalOrder())));
        // 4. 查询工序名称
        java.util.Set<Long> processIds = routeProcesses.stream().map(MesProRouteProcessDO::getProcessId).collect(java.util.stream.Collectors.toSet());
        java.util.Map<Long, cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO> procMap = processService.getProcessMap(processIds);
        // 5. 组装预览
        MesProTaskAutoGeneratePreviewRespVO vo = new MesProTaskAutoGeneratePreviewRespVO()
                .setWorkOrderId(workOrder.getId())
                .setRouteId(routeId)
                .setRouteName(route.getName());
        java.util.List<MesProTaskAutoGeneratePreviewRespVO.TaskPreview> taskList = new java.util.ArrayList<>();
        for (MesProRouteProcessDO rp : routeProcesses) {
            cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO proc = procMap.get(rp.getProcessId());
            taskList.add(new MesProTaskAutoGeneratePreviewRespVO.TaskPreview()
                    .setProcessId(rp.getProcessId())
                    .setProcessName(proc != null ? proc.getName() : null)
                    .setSort(rp.getSort())
                    .setQuantity(workOrder.getQuantity())
                    .setKeyFlag(rp.getKeyFlag()));
        }
        vo.setTaskList(taskList);
        return vo;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<Long> autoGenerateTasks(MesProTaskAutoGenerateReqVO reqVO) {
        // 1. 校验工单已确认
        MesProWorkOrderDO workOrder = workOrderService.validateWorkOrderConfirmed(reqVO.getWorkOrderId());
        // 2. 确定工艺路线:优先请求指定 → 工单关联 → 产品关联
        Long routeId = resolveRouteId(reqVO.getRouteId(), workOrder);
        routeService.validateRouteExists(routeId);
        // 3. 校验排产数量
        workOrderService.validateScheduleQuantity(reqVO.getWorkOrderId(), workOrder.getQuantity());
        // 4. 获取工序列表:优先工单工序 → 工艺路线工序
        List<MesProRouteProcessDO> routeProcesses = buildRouteProcessList(routeId, reqVO.getWorkOrderId());
        routeProcesses.sort(java.util.Comparator.comparing(MesProRouteProcessDO::getSort, java.util.Comparator.nullsLast(java.util.Comparator.naturalOrder())));
        // 5. 查询工序信息
        java.util.Set<Long> processIds = routeProcesses.stream().map(MesProRouteProcessDO::getProcessId).collect(java.util.stream.Collectors.toSet());
        java.util.Map<Long, cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO> procMap = processService.getProcessMap(processIds);
        // 6. 为每个工序创建任务
        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 ? rp.getOutputItemId() : workOrder.getProductId();
            cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO item = itemService.validateItemExists(itemId);
            MesProTaskDO task = new MesProTaskDO()
                    .setWorkOrderId(workOrder.getId())
                    .setRouteId(routeId)
                    .setProcessId(rp.getProcessId())
                    .setItemId(itemId)
                    .setQuantity(workOrder.getQuantity())
                    .setName(buildTaskName(item, workOrder.getQuantity()))
                    .setCode(autoCodeRecordService.generateAutoCode(MesMdAutoCodeRuleCodeEnum.PRO_TASK_CODE.getCode()))
                    .setStatus(MesProTaskStatusEnum.PREPARE.getStatus())
                    .setClientId(workOrder.getClientId())
                    .setColorCode(rp.getColorCode());
            taskMapper.insert(task);
            taskIds.add(task.getId());
        }
        // 7. 更新工单已排产数量
        workOrderService.updateScheduledQuantity(workOrder.getId(), workOrder.getQuantity());
        return taskIds;
    }
}