| | |
| | | import java.time.LocalDateTime; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.ArrayList; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | | import java.util.stream.Collectors; |
| | | |
| | | @Service |
| | |
| | | private final ProductionAccountMapper productionAccountMapper; |
| | | private final ProductionOperationTaskMapper productionOperationTaskMapper; |
| | | private final ProductionOrderMapper productionOrderMapper; |
| | | private final ProductionOrderBomMapper productionOrderBomMapper; |
| | | private final ProductionBomStructureMapper productionBomStructureMapper; |
| | | private final ProductionOrderRoutingOperationMapper productionOrderRoutingOperationMapper; |
| | | private final ProductionOrderRoutingOperationParamMapper productionOrderRoutingOperationParamMapper; |
| | | private final TechnologyRoutingOperationMapper technologyRoutingOperationMapper; |
| | | private final TechnologyOperationMapper technologyOperationMapper; |
| | | private final StockUtils stockUtils; |
| | |
| | | |
| | | @Override |
| | | public Boolean addProductMain(ProductionProductMainDto dto) { |
| | | if (dto.getProductionOperationTaskId() == null) { |
| | | Long taskId = resolveTaskId(dto); |
| | | if (taskId == null) { |
| | | throw new ServiceException("请传入生产工单ID"); |
| | | } |
| | | return addProductMainByProductionTask(dto); |
| | |
| | | |
| | | private Boolean addProductMainByProductionTask(ProductionProductMainDto dto) { |
| | | // 报工以订单工序快照为准,避免工艺主数据变更后影响历史工单执行。 |
| | | Long taskId = resolveTaskId(dto); |
| | | if (taskId == null) { |
| | | throw new ServiceException("productionOperationTaskId can not be null"); |
| | | } |
| | | SysUser user = userMapper.selectUserById(dto.getUserId()); |
| | | ProductionOperationTask productionOperationTask = productionOperationTaskMapper.selectById(dto.getProductionOperationTaskId()); |
| | | ProductionOperationTask productionOperationTask = productionOperationTaskMapper.selectById(taskId); |
| | | if (productionOperationTask == null) { |
| | | throw new ServiceException("生产工单不存在"); |
| | | } |
| | | ProductionOrderRoutingOperation routingOperation = productionOrderRoutingOperationMapper.selectById(productionOperationTask.getTechnologyRoutingOperationId()); |
| | | ProductionOrderRoutingOperation routingOperation = productionOrderRoutingOperationMapper.selectById(productionOperationTask.getProductionOrderRoutingOperationId()); |
| | | if (routingOperation == null) { |
| | | throw new ServiceException("订单工艺路线工序不存在"); |
| | | } |
| | |
| | | if (productionOrder == null) { |
| | | throw new ServiceException("生产订单不存在"); |
| | | } |
| | | syncOperationParamInputValue(dto, routingOperation.getId()); |
| | | TechnologyRoutingOperation technologyRoutingOperation = technologyRoutingOperationMapper.selectById(routingOperation.getTechnologyRoutingOperationId()); |
| | | TechnologyOperation technologyOperation = technologyRoutingOperation == null ? null |
| | | : technologyOperationMapper.selectById(technologyRoutingOperation.getTechnologyOperationId()); |
| | |
| | | |
| | | ProductionProductMain productionProductMain = new ProductionProductMain(); |
| | | productionProductMain.setProductNo(generateProductNo()); |
| | | productionProductMain.setUserId(dto.getUserId()); |
| | | productionProductMain.setUserName(dto.getUserName()); |
| | | productionProductMain.setProductionOperationTaskId(productionOperationTask.getId()); |
| | | productionProductMain.setWorkOrderId(productionOperationTask.getId()); |
| | | productionProductMain.setUserId(user == null ? dto.getUserId() : user.getUserId()); |
| | | productionProductMain.setUserName(user == null ? dto.getUserName() : user.getNickName()); |
| | | productionProductMain.setProductionOperationTaskId(taskId); |
| | | productionProductMain.setStatus(0); |
| | | productionProductMainMapper.insert(productionProductMain); |
| | | |
| | | List<ProductStructureDto> productStructureDtos = new ArrayList<>(); |
| | | ProductStructureDto productStructureDto = new ProductStructureDto(); |
| | | productStructureDto.setProductModelId(productModel.getId()); |
| | | productStructureDto.setUnitQuantity(BigDecimal.ONE); |
| | | productStructureDtos.add(productStructureDto); |
| | | List<ProductStructureDto> productStructureDtos = resolveInputStructures( |
| | | productionOrder.getId(), routingOperation, productModel.getId()); |
| | | if (productStructureDtos.isEmpty()) { |
| | | throw new ServiceException("未找到当前工序对应的BOM投入节点"); |
| | | } |
| | | for (ProductStructureDto item : productStructureDtos) { |
| | | // 当前实现按工序成品直接作为投入,后续若接入领料记录可在这里替换来源。 |
| | | ProductionProductInput productionProductInput = new ProductionProductInput(); |
| | |
| | | productionProductInput.setInputQuantity(item.getUnitQuantity().multiply(defaultDecimal(dto.getQuantity()))); |
| | | productionProductInput.setQuantity(productionProductInput.getInputQuantity()); |
| | | productionProductInputMapper.insert(productionProductInput); |
| | | stockUtils.substractStock(item.getProductModelId(), productionProductInput.getInputQuantity(), |
| | | StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode(), productionProductMain.getId()); |
| | | } |
| | | |
| | | ProductionProductOutput productionProductOutput = new ProductionProductOutput(); |
| | |
| | | |
| | | List<ProductionOrderRoutingOperation> routingOperationList = productionOrderRoutingOperationMapper.selectList( |
| | | Wrappers.<ProductionOrderRoutingOperation>lambdaQuery() |
| | | .eq(ProductionOrderRoutingOperation::getTechnologyRoutingId, routingOperation.getTechnologyRoutingId()) |
| | | .eq(ProductionOrderRoutingOperation::getOrderRoutingId, routingOperation.getOrderRoutingId()) |
| | | .eq(ProductionOrderRoutingOperation::getProductionOrderId, routingOperation.getProductionOrderId())); |
| | | boolean isLastOperation = routingOperation.getDragSort() != null && routingOperation.getDragSort().equals(routingOperationList.size()); |
| | | if (productQty.compareTo(BigDecimal.ZERO) > 0) { |
| | |
| | | } |
| | | ProductionAccount productionAccount = new ProductionAccount(); |
| | | productionAccount.setProductionProductMainId(productionProductMain.getId()); |
| | | productionAccount.setSalesLedgerId(productionOrder.getSalesLedgerId()); |
| | | productionAccount.setSalesLedgerProductId(productionOrder.getSalesLedgerProductId() == null ? null : productionOrder.getSalesLedgerProductId().longValue()); |
| | | // productionAccount.setSalesLedgerId(productionOrder.getSalesLedgerId()); |
| | | // productionAccount.setSalesLedgerProductId(productionOrder.getSalesLedgerProductId() == null ? null : productionOrder.getSalesLedgerProductId().longValue()); |
| | | productionAccount.setSchedulingUserId(user == null ? null : user.getUserId()); |
| | | productionAccount.setSchedulingUserName(user == null ? dto.getUserName() : user.getNickName()); |
| | | productionAccount.setFinishedNum(productQty); |
| | |
| | | StockInUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode(), productionProductMain.getId()); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | private void syncOperationParamInputValue(ProductionProductMainDto dto, Long productionOrderRoutingOperationId) { |
| | | if (dto == null || productionOrderRoutingOperationId == null) { |
| | | return; |
| | | } |
| | | List<ProductionOrderRoutingOperationParam> paramList = dto.getProductionOperationParamList(); |
| | | if (paramList == null || paramList.isEmpty()) { |
| | | return; |
| | | } |
| | | List<ProductionOrderRoutingOperationParam> dbParamList = productionOrderRoutingOperationParamMapper.selectList( |
| | | Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery() |
| | | .eq(ProductionOrderRoutingOperationParam::getProductionOrderRoutingOperationId, productionOrderRoutingOperationId)); |
| | | if (dbParamList == null || dbParamList.isEmpty()) { |
| | | return; |
| | | } |
| | | Map<Long, ProductionOrderRoutingOperationParam> dbParamMap = dbParamList.stream() |
| | | .filter(item -> item != null && item.getId() != null) |
| | | .collect(Collectors.toMap(ProductionOrderRoutingOperationParam::getId, item -> item, (left, right) -> left)); |
| | | for (ProductionOrderRoutingOperationParam param : paramList) { |
| | | if (param == null || param.getId() == null) { |
| | | continue; |
| | | } |
| | | ProductionOrderRoutingOperationParam dbParam = dbParamMap.get(param.getId()); |
| | | if (dbParam == null) { |
| | | throw new ServiceException("工序参数不存在或不属于当前工单工序,ID=" + param.getId()); |
| | | } |
| | | if (Objects.equals(dbParam.getInputValue(), param.getInputValue())) { |
| | | continue; |
| | | } |
| | | ProductionOrderRoutingOperationParam updateParam = new ProductionOrderRoutingOperationParam(); |
| | | updateParam.setId(dbParam.getId()); |
| | | updateParam.setInputValue(param.getInputValue()); |
| | | productionOrderRoutingOperationParamMapper.updateById(updateParam); |
| | | } |
| | | } |
| | | |
| | | private List<ProductStructureDto> resolveInputStructures(Long productionOrderId, |
| | | ProductionOrderRoutingOperation routingOperation, |
| | | Long outputProductModelId) { |
| | | if (productionOrderId == null || routingOperation == null || routingOperation.getTechnologyOperationId() == null) { |
| | | return new ArrayList<>(); |
| | | } |
| | | ProductionOrderBom orderBom = productionOrderBomMapper.selectOne( |
| | | Wrappers.<ProductionOrderBom>lambdaQuery() |
| | | .eq(ProductionOrderBom::getProductionOrderId, productionOrderId) |
| | | .orderByDesc(ProductionOrderBom::getId) |
| | | .last("limit 1")); |
| | | if (orderBom == null || orderBom.getId() == null) { |
| | | return new ArrayList<>(); |
| | | } |
| | | |
| | | List<ProductionBomStructure> bomNodeList = productionBomStructureMapper.selectList( |
| | | Wrappers.<ProductionBomStructure>lambdaQuery() |
| | | .eq(ProductionBomStructure::getProductionOrderBomId, orderBom.getId()) |
| | | .orderByAsc(ProductionBomStructure::getId)); |
| | | if (bomNodeList.isEmpty()) { |
| | | return new ArrayList<>(); |
| | | } |
| | | |
| | | Map<Long, ProductionBomStructure> nodeMap = bomNodeList.stream() |
| | | .filter(item -> item != null && item.getId() != null) |
| | | .collect(Collectors.toMap(ProductionBomStructure::getId, item -> item, (left, right) -> left)); |
| | | Long currentOutputModelId = routingOperation.getProductModelId() != null |
| | | ? routingOperation.getProductModelId() |
| | | : outputProductModelId; |
| | | |
| | | Map<Long, BigDecimal> unitQtyByProductModel = new LinkedHashMap<>(); |
| | | for (ProductionBomStructure node : bomNodeList) { |
| | | if (node == null || node.getParentId() == null || node.getProductModelId() == null) { |
| | | continue; |
| | | } |
| | | if (!Objects.equals(node.getTechnologyOperationId(), routingOperation.getTechnologyOperationId())) { |
| | | continue; |
| | | } |
| | | ProductionBomStructure parent = nodeMap.get(node.getParentId()); |
| | | if (parent == null || !Objects.equals(parent.getProductModelId(), currentOutputModelId)) { |
| | | continue; |
| | | } |
| | | unitQtyByProductModel.merge(node.getProductModelId(), defaultDecimal(node.getUnitQuantity()), BigDecimal::add); |
| | | } |
| | | |
| | | List<ProductStructureDto> result = new ArrayList<>(); |
| | | for (Map.Entry<Long, BigDecimal> entry : unitQtyByProductModel.entrySet()) { |
| | | if (entry.getValue().compareTo(BigDecimal.ZERO) <= 0) { |
| | | continue; |
| | | } |
| | | ProductStructureDto item = new ProductStructureDto(); |
| | | item.setProductModelId(entry.getKey()); |
| | | item.setUnitQuantity(entry.getValue()); |
| | | result.add(item); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | private Boolean removeProductMainByProductionTask(ProductionProductMain productionProductMain) { |
| | |
| | | productionOperationTaskMapper.updateById(productionOperationTask); |
| | | |
| | | ProductionOrder productionOrder = productionOrderMapper.selectById(productionOperationTask.getProductionOrderId()); |
| | | ProductionOrderRoutingOperation routingOperation = productionOrderRoutingOperationMapper.selectById(productionOperationTask.getTechnologyRoutingOperationId()); |
| | | ProductionOrderRoutingOperation routingOperation = productionOrderRoutingOperationMapper.selectById(productionOperationTask.getProductionOrderRoutingOperationId()); |
| | | if (productionOrder != null && routingOperation != null) { |
| | | // 只有最后一道工序的报工才会影响生产订单完工数量。 |
| | | List<ProductionOrderRoutingOperation> routingOperationList = productionOrderRoutingOperationMapper.selectList( |
| | | Wrappers.<ProductionOrderRoutingOperation>lambdaQuery() |
| | | .eq(ProductionOrderRoutingOperation::getTechnologyRoutingId, routingOperation.getTechnologyRoutingId()) |
| | | .eq(ProductionOrderRoutingOperation::getOrderRoutingId, routingOperation.getOrderRoutingId()) |
| | | .eq(ProductionOrderRoutingOperation::getProductionOrderId, routingOperation.getProductionOrderId())); |
| | | boolean isLastOperation = routingOperation.getDragSort() != null && routingOperation.getDragSort().equals(routingOperationList.size()); |
| | | if (isLastOperation) { |
| | |
| | | return value == null ? BigDecimal.ZERO : value; |
| | | } |
| | | |
| | | private Long resolveTaskId(ProductionProductMainDto dto) { |
| | | if (dto == null) { |
| | | return null; |
| | | } |
| | | return dto.getProductionOperationTaskId(); |
| | | } |
| | | |
| | | @Override |
| | | public ArrayList<Long> listMain(List<Long> idList) { |
| | | return productionProductMainMapper.listMain(idList); |