| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | @Resource |
| | | @Lazy |
| | | private MesProRouteProcessService routeProcessService; |
| | | @Resource |
| | | @Lazy |
| | | private MesProRouteProductService routeProductService; |
| | | @Resource |
| | | @Lazy |
| | | private MesProWorkOrderProcessService workOrderProcessService; |
| | | @Resource |
| | | private MesMdAutoCodeRecordService autoCodeRecordService; |
| | | |
| | |
| | | } |
| | | } |
| | | 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 |
| | |
| | | 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; |
| | | } |
| | | |
| | | } |