| | |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.MesProRouteSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessOutputDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductBomDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; |
| | |
| | | import java.util.Set; |
| | | import java.util.Comparator; |
| | | import java.util.Arrays; |
| | | import java.util.Objects; |
| | | import java.util.stream.Collectors; |
| | | import java.util.concurrent.atomic.AtomicInteger; |
| | | |
| | |
| | | .max(Comparator.comparing(MesProRouteProcessDO::getSort)).orElseThrow(); |
| | | for (MesProRouteProcessDO process : processList) { |
| | | Set<Long> outputIds = parseOutputItemIds(process.getOutputItemId()); |
| | | boolean last = process.getId().equals(lastProcess.getId()); |
| | | if (CollUtil.isEmpty(outputIds)) { |
| | | throw exception(PRO_ROUTE_PROCESS_OUTPUT_REQUIRED, process.getProcessId()); |
| | | // 中间工序不一定形成可入库的独立半成品,允许不配置产出;末道工序必须产出成品。 |
| | | if (last) { |
| | | throw exception(PRO_ROUTE_LAST_OUTPUT_INVALID, process.getProcessId()); |
| | | } |
| | | continue; |
| | | } |
| | | for (Long outputId : outputIds) { |
| | | if (!boundItemIds.contains(outputId)) { |
| | |
| | | throw exception(PRO_ROUTE_PROCESS_OUTPUT_NOT_BOUND, item.getName()); |
| | | } |
| | | } |
| | | if (process.getId().equals(lastProcess.getId())) { |
| | | if (last) { |
| | | if (finishedItemIds.isEmpty() || !outputIds.equals(finishedItemIds)) { |
| | | throw exception(PRO_ROUTE_LAST_OUTPUT_INVALID, process.getProcessId()); |
| | | } |
| | |
| | | throw exception(PRO_ROUTE_MIDDLE_OUTPUT_INVALID, process.getProcessId()); |
| | | } |
| | | } |
| | | // 4. 末道工序成品产出必须按产品归属,避免“通用”产出串到其它产品的工单 |
| | | List<MesProRouteProcessOutputDO> lastOutputs = routeProcessService |
| | | .getRouteProcessOutputListByRouteProcessIds(Collections.singletonList(lastProcess.getId())); |
| | | if (CollUtil.isNotEmpty(lastOutputs)) { |
| | | boolean attributionInvalid = lastOutputs.stream().anyMatch(output -> |
| | | output.getProductId() == null || !output.getProductId().equals(output.getItemId())); |
| | | Set<Long> attributedProducts = lastOutputs.stream() |
| | | .map(MesProRouteProcessOutputDO::getProductId) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toSet()); |
| | | if (attributionInvalid || !attributedProducts.containsAll(finishedItemIds)) { |
| | | throw exception(PRO_ROUTE_LAST_OUTPUT_ATTRIBUTION_REQUIRED, lastProcess.getProcessId()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private Set<Long> parseOutputItemIds(String value) { |