package com.ruoyi.production.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.basic.mapper.ProductMapper; import com.ruoyi.basic.mapper.ProductModelMapper; import com.ruoyi.basic.pojo.Product; import com.ruoyi.basic.pojo.ProductModel; import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum; import com.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum; import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.bean.BeanUtils; import com.ruoyi.procurementrecord.utils.StockUtils; import com.ruoyi.production.dto.ProductStructureDto; import com.ruoyi.production.dto.ProductionProductMainDto; import com.ruoyi.production.mapper.*; import com.ruoyi.production.pojo.*; import com.ruoyi.production.service.ProductionProductMainService; import com.ruoyi.project.system.domain.SysUser; import com.ruoyi.project.system.mapper.SysUserMapper; import com.ruoyi.project.system.service.ISysNoticeService; import com.ruoyi.quality.mapper.*; import com.ruoyi.quality.pojo.*; import com.ruoyi.quality.service.IQualityInspectService; import com.ruoyi.stock.support.FinishedProductStockDimensionResolver; import lombok.AllArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @Service @AllArgsConstructor @Transactional(rollbackFor = Exception.class) public class ProductionProductMainServiceImpl extends ServiceImpl implements ProductionProductMainService { private static final String PROCESS_VOLTAGE_SORT = "电压分选"; private static final String PROCESS_OPTICAL_INSPECTION = "光检外观"; private static final String PROCESS_PACKAGING = "包装"; private IQualityInspectService qualityInspectService; private ProductionProductMainMapper productionProductMainMapper; private ProductWorkOrderMapper productWorkOrderMapper; private ProductProcessRouteItemMapper productProcessRouteItemMapper; private SysUserMapper userMapper; private ProductionProductOutputMapper productionProductOutputMapper; private ProductModelMapper productModelMapper; private QualityInspectMapper qualityInspectMapper; private QualityUnqualifiedMapper qualityUnqualifiedMapper; private ProductProcessMapper productProcessMapper; private ProductProcessRouteMapper productProcessRouteMapper; private ProductMapper productMapper; private QualityTestStandardParamMapper qualityTestStandardParamMapper; private QualityTestStandardMapper qualityTestStandardMapper; private QualityInspectParamMapper qualityInspectParamMapper; private ProductStructureMapper productStructureMapper; private ProductionProductInputMapper productionProductInputMapper; private ProductOrderMapper productOrderMapper; private SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper; private StockUtils stockUtils; /** * 解析生产报工对应的成品入库维度。 */ private FinishedProductStockDimensionResolver finishedProductStockDimensionResolver; private ISysNoticeService sysNoticeService; @Override public IPage listPageProductionProductMainDto(Page page, ProductionProductMainDto productionProductMainDto) { return productionProductMainMapper.listPageProductionProductMainDto(page, productionProductMainDto); } /** * 新增报工,并根据当前工序处理质检和入库逻辑。 */ @Override public Boolean addProductMain(ProductionProductMainDto dto) { SysUser user = userMapper.selectUserById(dto.getUserId()); ProductionProductMain productionProductMain = new ProductionProductMain(); //当前工艺路线对应的工序详情 ProductProcessRouteItem productProcessRouteItem = productProcessRouteItemMapper.selectById(dto.getProductProcessRouteItemId()); if (productProcessRouteItem == null) { throw new RuntimeException("工艺路线工序项不存在"); } //检查上一个工序是否已报工 Integer currentDragSort = productProcessRouteItem.getDragSort(); if (currentDragSort != null && currentDragSort > 1) { boolean isPreviousReported = productionProductMainMapper.checkPreviousProcessReported( productProcessRouteItem.getProductRouteId(), currentDragSort ); if (!isPreviousReported) { throw new RuntimeException("上一道工序尚未报工,当前工序不能报工"); } // 查询所有之前的工序(排序号小于当前工序) List previousItems = productProcessRouteItemMapper.selectList( Wrappers.lambdaQuery() .eq(ProductProcessRouteItem::getProductRouteId, productProcessRouteItem.getProductRouteId()) .lt(ProductProcessRouteItem::getDragSort, currentDragSort) ); if (CollectionUtils.isNotEmpty(previousItems)) { // 提取之前工序的名称列表 List previousProcessNames = new ArrayList<>(); for (ProductProcessRouteItem item : previousItems) { ProductProcess process = productProcessMapper.selectById(item.getProcessId()); if (process != null) { previousProcessNames.add(process.getName()); } } // 检查之前的工序是否有被隔离的不合格记录 List unqualifiedList = qualityUnqualifiedMapper.selectUnqualifiedByProcessNames(previousProcessNames); if (CollectionUtils.isNotEmpty(unqualifiedList)) { throw new RuntimeException("前序工序存在隔离记录,当前工序不能报工"); } } } //当前具体工序 ProductProcess productProcess = productProcessMapper.selectById(productProcessRouteItem.getProcessId()); //工艺路线中当前工序对应的产出规格型号 ProductModel productModel = productModelMapper.selectById(productProcessRouteItem.getProductModelId()); //查询该生产订单对应的bom ProductProcessRoute productProcessRoute = productProcessRouteMapper.selectById(productProcessRouteItem.getProductRouteId()); /*新增报工主表*/ //查询最大报工编号 String datePrefix = "BG" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyMMdd")); QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.select("MAX(product_no) as maxNo") .likeRight("product_no", datePrefix); List> resultList = productionProductMainMapper.selectMaps(queryWrapper); int sequenceNumber = 1; if (resultList != null && !resultList.isEmpty()) { Map result = resultList.get(0); if (result != null) { Object maxNoObj = result.get("maxNo"); if (maxNoObj != null) { String lastNo = maxNoObj.toString(); if (lastNo.startsWith(datePrefix)) { try { String seqStr = lastNo.substring(datePrefix.length()); sequenceNumber = Integer.parseInt(seqStr) + 1; } catch (NumberFormatException e) { sequenceNumber = 1; } } } } } String productNo = String.format("%s%03d", datePrefix, sequenceNumber); productionProductMain.setProductNo(productNo); Long userId = dto.getUserId(); String userName = dto.getUserName(); if (userId == null) { userId = SecurityUtils.getLoginUser().getUserId(); userName = SecurityUtils.getLoginUser().getNickName(); } productionProductMain.setUserId(userId); productionProductMain.setUserName(userName); productionProductMain.setProductProcessRouteItemId(dto.getProductProcessRouteItemId()); productionProductMain.setWorkOrderId(dto.getWorkOrderId()); productionProductMain.setStatus(0); productionProductMainMapper.insert(productionProductMain); /*新增报工投入表*/ List productStructureDtos = productStructureMapper.listBybomAndProcess(productProcessRoute.getBomId(), productProcess.getId()); if (productStructureDtos.isEmpty()) { //如果该工序没有产品结构的投入品,那这个投入品和产出品是同一个 ProductStructureDto productStructureDto = new ProductStructureDto(); productStructureDto.setProductModelId(productProcessRouteItem.getProductModelId()); productStructureDto.setUnitQuantity(BigDecimal.ONE); productStructureDtos.add(productStructureDto); } Set parentIds = productStructureDtos.stream() .map(ProductStructureDto::getParentId) .filter(Objects::nonNull) .collect(Collectors.toSet()); Map parentMap = new HashMap<>(); if (!parentIds.isEmpty()) { parentMap = productStructureMapper.selectByIds(parentIds) .stream() .collect(Collectors.toMap( ProductStructureDto::getId, Function.identity() )); } for (ProductStructureDto productStructureDto : productStructureDtos) { ProductionProductInput productionProductInput = new ProductionProductInput(); productionProductInput.setProductModelId(productStructureDto.getProductModelId()); // productionProductInput.setQuantity(productStructureDto.getUnitQuantity().multiply(dto.getQuantity())); BigDecimal childQty = productStructureDto.getUnitQuantity(); BigDecimal parentQty = BigDecimal.ONE; if (productStructureDto.getParentId() != null) { ProductStructureDto parent = parentMap.get(productStructureDto.getParentId()); if (parent != null) { parentQty = parent.getUnitQuantity(); } } // 核心计算 BigDecimal needQty = childQty.divide(parentQty, 6, RoundingMode.HALF_UP).multiply(dto.getQuantity()); productionProductInput.setQuantity(needQty); productionProductInput.setProductMainId(productionProductMain.getId()); productionProductInputMapper.insert(productionProductInput); stockUtils.substractStock(productStructureDto.getProductModelId(), productionProductInput.getQuantity(), StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode(), productionProductMain.getId(), null); } /*新增报工产出表*/ ProductionProductOutput productionProductOutput = new ProductionProductOutput(); productionProductOutput.setProductMainId(productionProductMain.getId()); productionProductOutput.setProductModelId(productProcessRouteItem.getProductModelId()); productionProductOutput.setQuantity(dto.getQuantity() != null ? dto.getQuantity() : BigDecimal.ZERO); productionProductOutput.setScrapQty(dto.getScrapQty() != null ? dto.getScrapQty() : BigDecimal.ZERO); productionProductOutput.setOtherData(dto.getOtherData() != null ? dto.getOtherData() : ""); productionProductOutputMapper.insert(productionProductOutput); ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(dto.getWorkOrderId()); ProductOrder productOrder = productOrderMapper.selectById(productWorkOrder.getProductOrderId()); //合格数量=报工数量-报废数量 BigDecimal productQty = productionProductOutput.getQuantity().subtract(productionProductOutput.getScrapQty()); List productProcessRouteItems = productProcessRouteItemMapper.selectList( Wrappers.lambdaQuery() .eq(ProductProcessRouteItem::getProductRouteId, productProcessRouteItem.getProductRouteId()) ); boolean isRouteLastProcess = productProcessRouteItem.getDragSort() == productProcessRouteItems.size(); ReportStockRule reportStockRule = resolveReportStockRule(productProcessRouteItem, productProcess, productProcessRouteItems); String processCategory = null; String voltage = null; if (productQty.compareTo(BigDecimal.ZERO) > 0 && reportStockRule.isFinishedGoodsStockIn()) { processCategory = finishedProductStockDimensionResolver.resolveProcessCategory(productionProductMain.getId()); voltage = finishedProductStockDimensionResolver.resolveVoltage(productionProductMain.getId()); } if (productQty.compareTo(BigDecimal.ZERO) > 0) { /*新增质检*/ if (productProcessRouteItem.getIsQuality()) { //对应的过程检或者出厂检 int inspectType = 1; String process = productProcess.getName(); if (reportStockRule.isFinishedGoodsStockIn()) { inspectType = 2; process = null; } Product product = productMapper.selectById(productModel.getProductId()); QualityInspect qualityInspect = new QualityInspect(); qualityInspect.setProductId(product.getId()); qualityInspect.setProductName(product.getProductName()); qualityInspect.setModel(productModel.getModel()); qualityInspect.setUnit(productModel.getUnit()); qualityInspect.setQuantity(productionProductOutput.getQuantity()); qualityInspect.setProcess(process); qualityInspect.setInspectState(0); qualityInspect.setInspectType(inspectType); qualityInspect.setDefectiveQuantity(productionProductOutput.getScrapQty()); qualityInspect.setProductMainId(productionProductMain.getId()); qualityInspect.setProductModelId(productModel.getId()); qualityInspectMapper.insert(qualityInspect); List qualityTestStandard = qualityTestStandardMapper.getQualityTestStandardByProductId(product.getId(), inspectType, process); if (qualityTestStandard.size() > 0) { qualityInspect.setTestStandardId(qualityTestStandard.get(0).getId()); qualityInspectMapper.updateById(qualityInspect); qualityTestStandardParamMapper.selectList( Wrappers.lambdaQuery() .eq(QualityTestStandardParam::getTestStandardId, qualityTestStandard.get(0).getId()) ) .forEach(qualityTestStandardParam -> { QualityInspectParam param = new QualityInspectParam(); BeanUtils.copyProperties(qualityTestStandardParam, param); param.setId(null); param.setInspectId(qualityInspect.getId()); qualityInspectParamMapper.insert(param); }); } } else { if (reportStockRule.shouldCreateStockIn()) { if (reportStockRule.isFinishedGoodsStockIn()) { stockUtils.addStock(productProcessRouteItem.getProductModelId(), productQty, StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(), productionProductMain.getId(), processCategory, voltage); } else { stockUtils.addStockNoReview(productProcessRouteItem.getProductModelId(), productQty, StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(), productionProductMain.getId()); } } if (productionProductOutput.getScrapQty().compareTo(BigDecimal.ZERO) > 0) { stockUtils.addUnStockNoReview(productProcessRouteItem.getProductModelId(), productionProductOutput.getScrapQty(), StockInUnQualifiedRecordTypeEnum.QUALITYINSPECT_UNSTOCK_IN.getCode(), productionProductMain.getId()); } } productWorkOrder.setCompleteQuantity(productWorkOrder.getCompleteQuantity().add(productQty)); if (ObjectUtils.isNull(productWorkOrder.getActualStartTime())) { productWorkOrder.setActualStartTime(LocalDate.now()); } if (productWorkOrder.getCompleteQuantity().compareTo(productWorkOrder.getPlanQuantity()) == 0) { productWorkOrder.setActualEndTime(LocalDate.now()); } productWorkOrderMapper.updateById(productWorkOrder); if (ObjectUtils.isNull(productOrder.getStartTime())) { productOrder.setStartTime(LocalDateTime.now()); } if (isRouteLastProcess) { productOrder.setCompleteQuantity(productOrder.getCompleteQuantity().add(productQty)); if (productOrder.getCompleteQuantity().compareTo(productOrder.getQuantity()) == 0) { productOrder.setEndTime(LocalDateTime.now()); } } productOrderMapper.updateById(productOrder); SalesLedgerProductionAccounting salesLedgerProductionAccounting = SalesLedgerProductionAccounting.builder() .productMainId(productionProductMain.getId()) .schedulingUserId(userId) .schedulingUserName(userName) .finishedNum(productQty) .workHours(productProcess.getSalaryQuota()) .process(productProcess.getName()) .schedulingDate(LocalDate.now()) .tenantId(dto.getTenantId()) .build(); salesLedgerProductionAccountingMapper.insert(salesLedgerProductionAccounting); } return true; } /** * 判断当前报工是否需要入库,以及是否按成品入库处理。 */ private ReportStockRule resolveReportStockRule(ProductProcessRouteItem currentRouteItem, ProductProcess currentProcess, List routeItems) { boolean isRouteLastProcess = currentRouteItem.getDragSort() != null && CollectionUtils.isNotEmpty(routeItems) && currentRouteItem.getDragSort().equals(routeItems.size()); String currentProcessName = normalizeProcessName(currentProcess == null ? null : currentProcess.getName()); if (PROCESS_VOLTAGE_SORT.equals(currentProcessName)) { return new ReportStockRule(false, false); } Map processNameMap = loadRouteProcessNameMap(routeItems); boolean hasVoltageSort = containsProcess(routeItems, processNameMap, PROCESS_VOLTAGE_SORT); boolean hasOpticalInspection = containsProcess(routeItems, processNameMap, PROCESS_OPTICAL_INSPECTION); boolean hasPackaging = containsProcess(routeItems, processNameMap, PROCESS_PACKAGING); if (hasPackaging && PROCESS_PACKAGING.equals(currentProcessName)) { return new ReportStockRule(true, true); } if (hasPackaging && PROCESS_OPTICAL_INSPECTION.equals(currentProcessName)) { return new ReportStockRule(false, false); } if (!hasPackaging && hasVoltageSort && hasOpticalInspection && PROCESS_OPTICAL_INSPECTION.equals(currentProcessName)) { return new ReportStockRule(true, true); } return new ReportStockRule(true, isRouteLastProcess); } /** * 批量加载工艺路线中的工序名称。 */ private Map loadRouteProcessNameMap(List routeItems) { if (CollectionUtils.isEmpty(routeItems)) { return Collections.emptyMap(); } Set processIds = routeItems.stream() .map(ProductProcessRouteItem::getProcessId) .filter(Objects::nonNull) .collect(Collectors.toSet()); if (processIds.isEmpty()) { return Collections.emptyMap(); } return productProcessMapper.selectBatchIds(processIds).stream() .collect(Collectors.toMap(ProductProcess::getId, process -> normalizeProcessName(process.getName()))); } /** * 判断工艺路线中是否包含指定工序。 */ private boolean containsProcess(List routeItems, Map processNameMap, String processName) { return routeItems.stream() .map(ProductProcessRouteItem::getProcessId) .map(processNameMap::get) .anyMatch(processName::equals); } /** * 统一工序名称格式,避免规则匹配时受空白字符影响。 */ private String normalizeProcessName(String processName) { return processName == null ? "" : processName.trim(); } /** * 单次报工对应的入库规则。 */ private static final class ReportStockRule { private final boolean createStockIn; private final boolean finishedGoodsStockIn; private ReportStockRule(boolean createStockIn, boolean finishedGoodsStockIn) { this.createStockIn = createStockIn; this.finishedGoodsStockIn = finishedGoodsStockIn; } private boolean shouldCreateStockIn() { return createStockIn; } private boolean isFinishedGoodsStockIn() { return finishedGoodsStockIn; } } @Override public Boolean removeProductMain(Long id) { List qualityInspects = qualityInspectMapper.selectList( Wrappers.lambdaQuery().eq(QualityInspect::getProductMainId, id) ); if (qualityInspects.size() > 0) { List qualityUnqualifieds = qualityUnqualifiedMapper.selectList( Wrappers.lambdaQuery() .in(QualityUnqualified::getInspectId, qualityInspects.stream().map(QualityInspect::getId).collect(Collectors.toList())) ); if (qualityUnqualifieds.size() > 0 && qualityUnqualifieds.get(0).getInspectState() == 1) { throw new ServiceException("该报工已完成不合格处理,不能删除"); } } ProductionProductMain productionProductMain = productionProductMainMapper.selectById(id); ProductProcessRouteItem productProcessRouteItem = productProcessRouteItemMapper.selectById(productionProductMain.getProductProcessRouteItemId()); ProductionProductOutput productionProductOutput = productionProductOutputMapper.selectList( Wrappers.lambdaQuery().eq(ProductionProductOutput::getProductMainId, productionProductMain.getId()) ).get(0); salesLedgerProductionAccountingMapper.delete( new LambdaQueryWrapper() .eq(SalesLedgerProductionAccounting::getProductMainId, productionProductMain.getId()) ); ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(productionProductMain.getWorkOrderId()); if (productWorkOrder != null && productionProductOutput != null) { BigDecimal outputQty = productionProductOutput.getQuantity() == null ? BigDecimal.ZERO : productionProductOutput.getQuantity(); BigDecimal scrapQty = productionProductOutput.getScrapQty() == null ? BigDecimal.ZERO : productionProductOutput.getScrapQty(); BigDecimal completeQty = productWorkOrder.getCompleteQuantity() == null ? BigDecimal.ZERO : productWorkOrder.getCompleteQuantity(); BigDecimal validQuantity = outputQty.subtract(scrapQty); productWorkOrder.setCompleteQuantity(completeQty.subtract(validQuantity)); productWorkOrder.setActualEndTime(null); productWorkOrderMapper.updateById(productWorkOrder); } else { throw new ServiceException("操作失败:工单信息或产出记录不存在"); } List productProcessRouteItems = productProcessRouteItemMapper.selectList( Wrappers.lambdaQuery().eq(ProductProcessRouteItem::getProductRouteId, productProcessRouteItem.getProductRouteId()) ); if (productProcessRouteItem.getDragSort() != null && productProcessRouteItems != null && productProcessRouteItem.getDragSort() == productProcessRouteItems.size()) { ProductOrder productOrder = productOrderMapper.selectById(productWorkOrder.getProductOrderId()); if (productOrder != null) { BigDecimal orderCompleteQty = productOrder.getCompleteQuantity() == null ? BigDecimal.ZERO : productOrder.getCompleteQuantity(); BigDecimal totalQty = productionProductOutput.getQuantity() != null ? productionProductOutput.getQuantity() : BigDecimal.ZERO; BigDecimal scrapQty = productionProductOutput.getScrapQty() != null ? productionProductOutput.getScrapQty() : BigDecimal.ZERO; BigDecimal actualQualifiedQty = totalQty.subtract(scrapQty); BigDecimal newCompleteQty = orderCompleteQty.subtract(actualQualifiedQty); productOrder.setCompleteQuantity(newCompleteQty.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : newCompleteQty); productOrder.setEndTime(null); productOrderMapper.updateById(productOrder); } else { throw new ServiceException("关联的生产订单不存在"); } } qualityInspectMapper.selectList( new LambdaQueryWrapper() .eq(QualityInspect::getProductMainId, productionProductMain.getId()) ).forEach(q -> { qualityInspectParamMapper.delete( new LambdaQueryWrapper() .eq(QualityInspectParam::getInspectId, q.getId()) ); qualityInspectMapper.deleteById(q.getId()); stockUtils.deleteStockInRecord(q.getId(), StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode()); }); productionProductOutputMapper.delete( new LambdaQueryWrapper() .eq(ProductionProductOutput::getProductMainId, productionProductMain.getId()) ); productionProductInputMapper.delete( new LambdaQueryWrapper() .eq(ProductionProductInput::getProductMainId, 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()); productionProductMainMapper.deleteById(productionProductMain.getId()); return true; } @Override public ArrayList listMain(List idList) { return productionProductMainMapper.listMain(idList); } @Override public List getByProductWorkOrderId(Long productWorkOrderId) { List productionProductMainDtos = productionProductMainMapper.getByProductWorkOrderId(productWorkOrderId); if (productionProductMainDtos == null || productionProductMainDtos.isEmpty()) { return productionProductMainDtos; } List productMainIds = productionProductMainDtos.stream() .map(ProductionProductMainDto::getId) .collect(Collectors.toList()); List qualityInspects = qualityInspectMapper.selectList( Wrappers.lambdaQuery() .in(QualityInspect::getProductMainId, productMainIds) ); if (!qualityInspects.isEmpty()) { List inspectIds = qualityInspects.stream() .map(QualityInspect::getId) .collect(Collectors.toList()); List qualityUnqualifieds = qualityUnqualifiedMapper.selectList( Wrappers.lambdaQuery() .in(QualityUnqualified::getInspectId, inspectIds) ); Map inspectIdToUnqualifiedMap = qualityUnqualifieds.stream() .collect(Collectors.toMap(QualityUnqualified::getInspectId, q -> q, (q1, q2) -> q1)); Map productMainIdToInspectMap = qualityInspects.stream() .collect(Collectors.toMap(QualityInspect::getProductMainId, q -> q, (q1, q2) -> q1)); productionProductMainDtos.forEach(p -> { QualityInspect qualityInspect = productMainIdToInspectMap.get(p.getId()); if (qualityInspect != null) { p.setDefectiveQuantity(qualityInspect.getDefectiveQuantity()); p.setQualifiedQty(p.getQuantity().subtract(p.getScrapQty()).subtract(p.getDefectiveQuantity())); QualityUnqualified qualityUnqualified = inspectIdToUnqualifiedMap.get(qualityInspect.getId()); if (qualityUnqualified != null) { p.setDealResult(qualityUnqualified.getDealResult() == null ? "" : qualityUnqualified.getDealResult()); } } }); } return productionProductMainDtos; } }