| | |
| | | import com.ruoyi.project.system.mapper.SysUserMapper; |
| | | import com.ruoyi.quality.mapper.*; |
| | | import com.ruoyi.quality.pojo.*; |
| | | import com.ruoyi.stock.dto.StockInventoryDto; |
| | | import com.ruoyi.stock.service.StockInventoryService; |
| | | import com.ruoyi.technology.mapper.TechnologyOperationMapper; |
| | | import com.ruoyi.technology.mapper.TechnologyRoutingOperationMapper; |
| | | import com.ruoyi.technology.pojo.TechnologyOperation; |
| | |
| | | import java.time.LocalDateTime; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.HashMap; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | | import java.util.Set; |
| | | import java.util.stream.Collectors; |
| | | |
| | | @Service |
| | |
| | | private final TechnologyRoutingOperationMapper technologyRoutingOperationMapper; |
| | | private final TechnologyOperationMapper technologyOperationMapper; |
| | | private final StockUtils stockUtils; |
| | | private final StockInventoryService stockInventoryService; |
| | | |
| | | @Override |
| | | public IPage<ProductionProductMainDto> listPageProductionProductMainDto(Page page, ProductionProductMainDto productionProductMainDto) { |
| | | return productionProductMainMapper.listPageProductionProductMainDto(page, productionProductMainDto); |
| | | IPage<ProductionProductMainDto> result = productionProductMainMapper.listPageProductionProductMainDto(page, productionProductMainDto); |
| | | fillOperationParamList(result.getRecords()); |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | |
| | | |
| | | @Override |
| | | public ProductionProductMainDto getProductionProductMainInfo(Long id) { |
| | | return productionProductMainMapper.listPageProductionProductMainDto(new Page<>(1, 1), new ProductionProductMainDto() {{ |
| | | return listPageProductionProductMainDto(new Page<>(1, 1), new ProductionProductMainDto() {{ |
| | | setId(id); |
| | | }}).getRecords().stream().findFirst().orElse(null); |
| | | } |
| | | |
| | | private void fillOperationParamList(List<ProductionProductMainDto> recordList) { |
| | | if (recordList == null || recordList.isEmpty()) { |
| | | return; |
| | | } |
| | | Set<Long> mainIdSet = recordList.stream() |
| | | .map(ProductionProductMainDto::getId) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toCollection(LinkedHashSet::new)); |
| | | if (mainIdSet.isEmpty()) { |
| | | recordList.forEach(item -> item.setProductionOperationParamList(Collections.emptyList())); |
| | | return; |
| | | } |
| | | |
| | | List<ProductionOrderRoutingOperationParam> paramList = productionOrderRoutingOperationParamMapper.selectList( |
| | | Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery() |
| | | .in(ProductionOrderRoutingOperationParam::getProductionProductMainId, mainIdSet) |
| | | .orderByAsc(ProductionOrderRoutingOperationParam::getId)); |
| | | Map<Long, List<ProductionOrderRoutingOperationParam>> paramGroupMap = new HashMap<>(); |
| | | for (ProductionOrderRoutingOperationParam param : paramList) { |
| | | if (param == null || param.getProductionProductMainId() == null) { |
| | | continue; |
| | | } |
| | | paramGroupMap.computeIfAbsent(param.getProductionProductMainId(), key -> new ArrayList<>()).add(param); |
| | | } |
| | | |
| | | Set<Long> missingMainIdSet = new LinkedHashSet<>(); |
| | | for (ProductionProductMainDto item : recordList) { |
| | | Long mainId = item.getId(); |
| | | if (mainId == null) { |
| | | item.setProductionOperationParamList(Collections.emptyList()); |
| | | continue; |
| | | } |
| | | List<ProductionOrderRoutingOperationParam> params = paramGroupMap.get(mainId); |
| | | if (params != null && !params.isEmpty()) { |
| | | item.setProductionOperationParamList(params); |
| | | continue; |
| | | } |
| | | missingMainIdSet.add(mainId); |
| | | } |
| | | if (missingMainIdSet.isEmpty()) { |
| | | return; |
| | | } |
| | | |
| | | // 兼容历史数据:旧报工记录没有按报工ID落参数快照时,回退展示工序模板参数。 |
| | | List<ProductionProductMain> mainList = productionProductMainMapper.selectBatchIds(missingMainIdSet); |
| | | Map<Long, Long> mainIdToTaskIdMap = mainList.stream() |
| | | .filter(Objects::nonNull) |
| | | .filter(item -> item.getId() != null) |
| | | .collect(Collectors.toMap(ProductionProductMain::getId, |
| | | ProductionProductMain::getProductionOperationTaskId, (left, right) -> left)); |
| | | Set<Long> taskIdSet = mainIdToTaskIdMap.values().stream() |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toCollection(LinkedHashSet::new)); |
| | | if (taskIdSet.isEmpty()) { |
| | | for (ProductionProductMainDto item : recordList) { |
| | | if (item.getId() != null && missingMainIdSet.contains(item.getId())) { |
| | | item.setProductionOperationParamList(Collections.emptyList()); |
| | | } |
| | | } |
| | | return; |
| | | } |
| | | |
| | | List<ProductionOperationTask> taskList = productionOperationTaskMapper.selectList( |
| | | Wrappers.<ProductionOperationTask>lambdaQuery() |
| | | .in(ProductionOperationTask::getId, taskIdSet)); |
| | | Map<Long, Long> taskIdToRoutingOperationIdMap = taskList.stream() |
| | | .filter(Objects::nonNull) |
| | | .filter(item -> item.getId() != null) |
| | | .collect(Collectors.toMap(ProductionOperationTask::getId, |
| | | ProductionOperationTask::getProductionOrderRoutingOperationId, (left, right) -> left)); |
| | | Set<Long> routingOperationIdSet = taskIdToRoutingOperationIdMap.values().stream() |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toCollection(LinkedHashSet::new)); |
| | | if (routingOperationIdSet.isEmpty()) { |
| | | for (ProductionProductMainDto item : recordList) { |
| | | if (item.getId() != null && missingMainIdSet.contains(item.getId())) { |
| | | item.setProductionOperationParamList(Collections.emptyList()); |
| | | } |
| | | } |
| | | return; |
| | | } |
| | | |
| | | List<ProductionOrderRoutingOperationParam> fallbackParamList = productionOrderRoutingOperationParamMapper.selectList( |
| | | Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery() |
| | | .in(ProductionOrderRoutingOperationParam::getProductionOrderRoutingOperationId, routingOperationIdSet) |
| | | .isNull(ProductionOrderRoutingOperationParam::getProductionProductMainId) |
| | | .orderByAsc(ProductionOrderRoutingOperationParam::getId)); |
| | | Map<Long, List<ProductionOrderRoutingOperationParam>> fallbackGroupMap = new HashMap<>(); |
| | | for (ProductionOrderRoutingOperationParam param : fallbackParamList) { |
| | | if (param == null || param.getProductionOrderRoutingOperationId() == null) { |
| | | continue; |
| | | } |
| | | fallbackGroupMap.computeIfAbsent(param.getProductionOrderRoutingOperationId(), key -> new ArrayList<>()).add(param); |
| | | } |
| | | |
| | | for (ProductionProductMainDto item : recordList) { |
| | | Long mainId = item.getId(); |
| | | if (mainId == null || !missingMainIdSet.contains(mainId)) { |
| | | continue; |
| | | } |
| | | Long taskId = mainIdToTaskIdMap.get(mainId); |
| | | Long routingOperationId = taskId == null ? null : taskIdToRoutingOperationIdMap.get(taskId); |
| | | if (routingOperationId == null) { |
| | | item.setProductionOperationParamList(Collections.emptyList()); |
| | | continue; |
| | | } |
| | | item.setProductionOperationParamList(fallbackGroupMap.getOrDefault(routingOperationId, Collections.emptyList())); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | |
| | | 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.setProductionOperationTaskId(taskId); |
| | | productionProductMain.setStatus(0); |
| | | productionProductMainMapper.insert(productionProductMain); |
| | | syncOperationParamInputValue(dto, routingOperation.getId(), productionProductMain.getId()); |
| | | |
| | | List<ProductStructureDto> productStructureDtos = resolveInputStructures( |
| | | productionOrder.getId(), routingOperation, productModel.getId()); |
| | | // 如果没有bom子节点了,那么投入就是他本身 |
| | | if (productStructureDtos.isEmpty()) { |
| | | throw new ServiceException("未找到当前工序对应的BOM投入节点"); |
| | | ProductStructureDto fallbackInput = new ProductStructureDto(); |
| | | fallbackInput.setProductModelId(productModel.getId()); |
| | | fallbackInput.setUnitQuantity(BigDecimal.ONE); |
| | | productStructureDtos.add(fallbackInput); |
| | | } |
| | | for (ProductStructureDto item : productStructureDtos) { |
| | | // 当前实现按工序成品直接作为投入,后续若接入领料记录可在这里替换来源。 |
| | |
| | | productionProductOutput.setQuantity(defaultDecimal(dto.getQuantity())); |
| | | productionProductOutput.setScrapQty(defaultDecimal(dto.getScrapQty())); |
| | | productionProductOutputMapper.insert(productionProductOutput); |
| | | BigDecimal productQty = productionProductOutput.getQuantity().subtract(productionProductOutput.getScrapQty()); |
| | | BigDecimal reportQty = defaultDecimal(productionProductOutput.getQuantity()); |
| | | BigDecimal productQty = reportQty; |
| | | |
| | | List<ProductionOrderRoutingOperation> routingOperationList = productionOrderRoutingOperationMapper.selectList( |
| | | Wrappers.<ProductionOrderRoutingOperation>lambdaQuery() |
| | |
| | | qualityInspect.setProductModelId(productModel.getId()); |
| | | qualityInspectMapper.insert(qualityInspect); |
| | | List<QualityTestStandard> qualityTestStandard = qualityTestStandardMapper.getQualityTestStandardByProductId(product.getId(), inspectType, process); |
| | | if (qualityTestStandard.size() > 0) { |
| | | if (!qualityTestStandard.isEmpty()) { |
| | | qualityInspect.setTestStandardId(qualityTestStandard.get(0).getId()); |
| | | qualityInspectMapper.updateById(qualityInspect); |
| | | qualityTestStandardParamMapper.selectList(Wrappers.<QualityTestStandardParam>lambdaQuery() |
| | |
| | | }); |
| | | } |
| | | } else { |
| | | stockUtils.addStock(productModel.getId(), productQty, |
| | | StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(), productionProductMain.getId()); |
| | | StockInventoryDto stockInventoryDto = new StockInventoryDto(); |
| | | stockInventoryDto.setRecordId(productionProductMain.getId()); |
| | | stockInventoryDto.setRecordType(String.valueOf(StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode())); |
| | | stockInventoryDto.setQualitity(productQty); |
| | | stockInventoryDto.setProductModelId(productModel.getId()); |
| | | stockInventoryService.addStockInRecordOnly(stockInventoryDto); |
| | | } |
| | | |
| | | productionOperationTask.setCompleteQuantity(defaultDecimal(productionOperationTask.getCompleteQuantity()).add(productQty)); |
| | |
| | | productionAccount.setSchedulingDate(LocalDateTime.now()); |
| | | productionAccountMapper.insert(productionAccount); |
| | | } |
| | | if (defaultDecimal(dto.getScrapQty()).compareTo(BigDecimal.ZERO) > 0) { |
| | | stockUtils.addUnStock(productModel.getId(), dto.getScrapQty(), |
| | | StockInUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode(), productionProductMain.getId()); |
| | | } |
| | | // if (defaultDecimal(dto.getScrapQty()).compareTo(BigDecimal.ZERO) > 0) { |
| | | // stockUtils.addUnStock(productModel.getId(), dto.getScrapQty(), |
| | | // StockInUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode(), productionProductMain.getId()); |
| | | // } |
| | | return true; |
| | | } |
| | | |
| | | private void syncOperationParamInputValue(ProductionProductMainDto dto, Long productionOrderRoutingOperationId) { |
| | | if (dto == null || productionOrderRoutingOperationId == null) { |
| | | private void syncOperationParamInputValue(ProductionProductMainDto dto, |
| | | Long productionOrderRoutingOperationId, |
| | | Long productionProductMainId) { |
| | | if (dto == null || productionOrderRoutingOperationId == null || productionProductMainId == null) { |
| | | return; |
| | | } |
| | | List<ProductionOrderRoutingOperationParam> paramList = dto.getProductionOperationParamList(); |
| | | if (paramList == null || paramList.isEmpty()) { |
| | | return; |
| | | } |
| | | Set<Long> sourceParamIdSet = paramList.stream() |
| | | .filter(Objects::nonNull) |
| | | .map(ProductionOrderRoutingOperationParam::getId) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toCollection(LinkedHashSet::new)); |
| | | if (sourceParamIdSet.isEmpty()) { |
| | | return; |
| | | } |
| | | |
| | | List<ProductionOrderRoutingOperationParam> dbParamList = productionOrderRoutingOperationParamMapper.selectList( |
| | | Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery() |
| | | .in(ProductionOrderRoutingOperationParam::getId, sourceParamIdSet) |
| | | .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)); |
| | |
| | | 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); |
| | | productionOrderRoutingOperationParamMapper.insert(buildReportParamSnapshot(dbParam, param.getInputValue(), productionProductMainId)); |
| | | } |
| | | } |
| | | |
| | | private ProductionOrderRoutingOperationParam buildReportParamSnapshot(ProductionOrderRoutingOperationParam source, |
| | | String inputValue, |
| | | Long productionProductMainId) { |
| | | ProductionOrderRoutingOperationParam target = new ProductionOrderRoutingOperationParam(); |
| | | target.setProductionOrderId(source.getProductionOrderId()); |
| | | target.setTechnologyRoutingOperationParamId(source.getTechnologyRoutingOperationParamId()); |
| | | target.setParamCode(source.getParamCode()); |
| | | target.setParamName(source.getParamName()); |
| | | target.setParamType(source.getParamType()); |
| | | target.setParamFormat(source.getParamFormat()); |
| | | target.setUnit(source.getUnit()); |
| | | target.setIsRequired(source.getIsRequired()); |
| | | target.setRemark(source.getRemark()); |
| | | target.setParamId(source.getParamId()); |
| | | target.setTechnologyOperationId(source.getTechnologyOperationId()); |
| | | target.setTechnologyOperationParamId(source.getTechnologyOperationParamId()); |
| | | target.setStandardValue(source.getStandardValue()); |
| | | target.setInputValue(inputValue); |
| | | target.setProductionOrderRoutingOperationId(source.getProductionOrderRoutingOperationId()); |
| | | target.setProductionProductMainId(productionProductMainId); |
| | | return target; |
| | | } |
| | | |
| | | private List<ProductStructureDto> resolveInputStructures(Long productionOrderId, |
| | |
| | | |
| | | ProductionOperationTask productionOperationTask = productionOperationTaskMapper.selectById(productionProductMain.getProductionOperationTaskId()); |
| | | if (productionOperationTask != null && productionProductOutput != null) { |
| | | BigDecimal validQuantity = defaultDecimal(productionProductOutput.getQuantity()).subtract(defaultDecimal(productionProductOutput.getScrapQty())); |
| | | productionOperationTask.setCompleteQuantity(defaultDecimal(productionOperationTask.getCompleteQuantity()).subtract(validQuantity)); |
| | | BigDecimal reportQuantity = defaultDecimal(productionProductOutput.getQuantity()); |
| | | productionOperationTask.setCompleteQuantity(defaultDecimal(productionOperationTask.getCompleteQuantity()).subtract(reportQuantity)); |
| | | productionOperationTask.setActualEndTime(null); |
| | | if (defaultDecimal(productionOperationTask.getCompleteQuantity()).compareTo(BigDecimal.ZERO) <= 0) { |
| | | productionOperationTask.setCompleteQuantity(BigDecimal.ZERO); |
| | |
| | | .eq(ProductionOrderRoutingOperation::getProductionOrderId, routingOperation.getProductionOrderId())); |
| | | boolean isLastOperation = routingOperation.getDragSort() != null && routingOperation.getDragSort().equals(routingOperationList.size()); |
| | | if (isLastOperation) { |
| | | BigDecimal newCompleteQty = defaultDecimal(productionOrder.getCompleteQuantity()).subtract(validQuantity); |
| | | BigDecimal newCompleteQty = defaultDecimal(productionOrder.getCompleteQuantity()).subtract(reportQuantity); |
| | | productionOrder.setCompleteQuantity(newCompleteQty.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : newCompleteQty); |
| | | productionOrder.setEndTime(null); |
| | | } |
| | |
| | | .eq(ProductionProductOutput::getProductionProductMainId, productionProductMain.getId())); |
| | | productionProductInputMapper.delete(new LambdaQueryWrapper<ProductionProductInput>() |
| | | .eq(ProductionProductInput::getProductionProductMainId, productionProductMain.getId())); |
| | | productionOrderRoutingOperationParamMapper.delete( |
| | | Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery() |
| | | .eq(ProductionOrderRoutingOperationParam::getProductionProductMainId, productionProductMain.getId())); |
| | | stockUtils.deleteStockInRecord(productionProductMain.getId(), StockInUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode()); |
| | | stockUtils.deleteStockInRecord(productionProductMain.getId(), StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode()); |
| | | stockUtils.deleteStockOutRecord(productionProductMain.getId(), StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode()); |