| | |
| | | package com.ruoyi.production.service.impl; |
| | | |
| | | import com.alibaba.fastjson2.JSON; |
| | | 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.ruoyi.common.enums.StockInQualifiedRecordTypeEnum; |
| | | 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.bean.dto.ProductStructureDto; |
| | | import com.ruoyi.production.bean.dto.ProductionProductMainDto; |
| | | import com.ruoyi.production.enums.ProductOrderStatusEnum; |
| | | import com.ruoyi.production.mapper.*; |
| | |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.time.Duration; |
| | | import java.time.LocalDate; |
| | | 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; |
| | |
| | | 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; |
| | |
| | | |
| | | @Override |
| | | public Boolean addProductMain(ProductionProductMainDto dto) { |
| | | // 新增生产报工主记录 |
| | | // 兼容旧流程:如果没有开始报工记录ID,走一步报工(自动创建+结束) |
| | | Long startRecordId = dto.resolveStartRecordId(); |
| | | if (startRecordId == null) { |
| | | return oneStepWork(dto); |
| | | } |
| | | dto.setId(startRecordId); |
| | | return finishWork(dto); |
| | | } |
| | | |
| | | @Override |
| | | public Boolean startWork(ProductionProductMainDto dto) { |
| | | // 开始报工:创建报工记录,标记实际开始时间 |
| | | Long taskId = resolveTaskId(dto); |
| | | if (taskId == null) { |
| | | throw new ServiceException("请传入生产工单ID"); |
| | | } |
| | | return addProductMainByProductionTask(dto); |
| | | } |
| | | |
| | | @Override |
| | | public Boolean saveProductionProductMain(ProductionProductMainDto productionProductMainDto) { |
| | | // 保存生产报工主记录 |
| | | return addProductMain(productionProductMainDto); |
| | | } |
| | | |
| | | @Override |
| | | public Boolean removeProductMain(Long id) { |
| | | // 删除生产报工主记录 |
| | | ProductionProductMain currentMain = productionProductMainMapper.selectById(id); |
| | | if (currentMain == null) { |
| | | return true; |
| | | } |
| | | return removeProductMainByProductionTask(currentMain); |
| | | } |
| | | |
| | | private Boolean addProductMainByProductionTask(ProductionProductMainDto dto) { |
| | | // 按生产任务新增报工主记录 |
| | | Long taskId = resolveTaskId(dto); |
| | | if (taskId == null) { |
| | | throw new ServiceException("生产工单ID不能为空"); |
| | | } |
| | | SysUser user = userMapper.selectUserById(dto.getUserId()); |
| | | ProductionOperationTask productionOperationTask = productionOperationTaskMapper.selectById(taskId); |
| | | if (productionOperationTask == null) { |
| | | ProductionOperationTask task = productionOperationTaskMapper.selectById(taskId); |
| | | if (task == null) { |
| | | throw new ServiceException("生产工单不存在"); |
| | | } |
| | | ProductionOrderRoutingOperation routingOperation = productionOrderRoutingOperationMapper.selectById(productionOperationTask.getProductionOrderRoutingOperationId()); |
| | | if (routingOperation == null) { |
| | | throw new ServiceException("订单工艺路线工序不存在"); |
| | | // 权限校验:已指派时仅被指派人可操作 |
| | | validateWorkerPermission(task); |
| | | |
| | | if (task.getStatus() != null && task.getStatus() != 2 && task.getStatus() != 3) { |
| | | throw new ServiceException("当前工单状态不允许开始报工,仅待生产或生产中状态的工单可操作"); |
| | | } |
| | | ProductionOrder productionOrder = productionOrderMapper.selectById(productionOperationTask.getProductionOrderId()); |
| | | if (productionOrder == null) { |
| | | throw new ServiceException("生产订单不存在"); |
| | | SysUser user = userMapper.selectUserById(dto.getUserId()); |
| | | ProductionProductMain main = new ProductionProductMain(); |
| | | main.setProductNo(generateProductNo()); |
| | | main.setUserId(user == null ? dto.getUserId() : user.getUserId()); |
| | | main.setUserName(user == null ? dto.getUserName() : user.getNickName()); |
| | | main.setProductionOperationTaskId(taskId); |
| | | main.setStatus(0); |
| | | main.setActualStartTime(LocalDateTime.now()); |
| | | productionProductMainMapper.insert(main); |
| | | |
| | | // 工单状态 -> 生产中 |
| | | task.setStatus(3); |
| | | if (task.getActualStartTime() == null) { |
| | | task.setActualStartTime(LocalDateTime.now()); |
| | | } |
| | | TechnologyRoutingOperation technologyRoutingOperation = technologyRoutingOperationMapper.selectById(routingOperation.getTechnologyRoutingOperationId()); |
| | | TechnologyOperation technologyOperation = technologyRoutingOperation == null ? null |
| | | : technologyOperationMapper.selectById(technologyRoutingOperation.getTechnologyOperationId()); |
| | | ProductModel productModel = productModelMapper.selectById( |
| | | routingOperation.getProductModelId() != null ? routingOperation.getProductModelId() : productionOrder.getProductModelId()); |
| | | productionOperationTaskMapper.updateById(task); |
| | | |
| | | // 生产订单 -> 生产进行中 |
| | | ProductionOrder productionOrder = productionOrderMapper.selectById(task.getProductionOrderId()); |
| | | if (productionOrder != null && productionOrder.getStartTime() == null) { |
| | | productionOrder.setStartTime(LocalDateTime.now()); |
| | | productionOrder.setStatus(ProductOrderStatusEnum.RUNNING.getCode()); |
| | | productionOrderMapper.updateById(productionOrder); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | private Boolean oneStepWork(ProductionProductMainDto dto) { |
| | | // 兼容旧一步报工流程:自动创建开始记录并立即结束 |
| | | Long taskId = resolveTaskId(dto); |
| | | if (taskId == null) { |
| | | throw new ServiceException("请传入生产工单ID"); |
| | | } |
| | | ProductionOperationTask task = productionOperationTaskMapper.selectById(taskId); |
| | | if (task == null) { |
| | | throw new ServiceException("生产工单不存在"); |
| | | } |
| | | validateWorkerPermission(task); |
| | | if (task.getStatus() != null && task.getStatus() != 2 && task.getStatus() != 3) { |
| | | throw new ServiceException("当前工单状态不允许报工"); |
| | | } |
| | | SysUser user = userMapper.selectUserById(dto.getUserId()); |
| | | ProductionProductMain main = new ProductionProductMain(); |
| | | main.setProductNo(generateProductNo()); |
| | | main.setUserId(user == null ? dto.getUserId() : user.getUserId()); |
| | | main.setUserName(user == null ? dto.getUserName() : user.getNickName()); |
| | | main.setProductionOperationTaskId(taskId); |
| | | main.setStatus(0); |
| | | main.setActualStartTime(LocalDateTime.now()); |
| | | productionProductMainMapper.insert(main); |
| | | |
| | | if (task.getActualStartTime() == null) { |
| | | task.setActualStartTime(LocalDateTime.now()); |
| | | } |
| | | task.setStatus(3); |
| | | productionOperationTaskMapper.updateById(task); |
| | | |
| | | ProductionOrder productionOrder = productionOrderMapper.selectById(task.getProductionOrderId()); |
| | | if (productionOrder != null && productionOrder.getStartTime() == null) { |
| | | productionOrder.setStartTime(LocalDateTime.now()); |
| | | productionOrder.setStatus(ProductOrderStatusEnum.RUNNING.getCode()); |
| | | productionOrderMapper.updateById(productionOrder); |
| | | } |
| | | |
| | | dto.setId(main.getId()); |
| | | return finishWork(dto); |
| | | } |
| | | |
| | | private Boolean finishWork(ProductionProductMainDto dto) { |
| | | // 结束报工:更新开始报工记录,创建产出、投入品、核算记录 |
| | | ProductionProductMain currentMain = productionProductMainMapper.selectById(dto.getId()); |
| | | if (currentMain == null) { |
| | | throw new ServiceException("开始报工记录不存在"); |
| | | } |
| | | if (currentMain.getStatus() == null || currentMain.getStatus() != 0) { |
| | | throw new ServiceException("该报工记录已结束或状态异常"); |
| | | } |
| | | Long taskId = currentMain.getProductionOperationTaskId(); |
| | | ProductionOperationTask task = productionOperationTaskMapper.selectById(taskId); |
| | | if (task == null) { |
| | | throw new ServiceException("生产工单不存在"); |
| | | } |
| | | validateWorkerPermission(task); |
| | | |
| | | // 更新报工记录为已结束,记录结束时间 |
| | | currentMain.setActualEndTime(LocalDateTime.now()); |
| | | currentMain.setStatus(1); |
| | | if (dto.getWorkHour() != null) { |
| | | currentMain.setWorkHour(dto.getWorkHour()); |
| | | } else if (currentMain.getActualStartTime() != null) { |
| | | // 根据开始/结束时间计算实际工时(小时) |
| | | long seconds = Duration.between(currentMain.getActualStartTime(), currentMain.getActualEndTime()).getSeconds(); |
| | | currentMain.setWorkHour(BigDecimal.valueOf(seconds).divide(BigDecimal.valueOf(3600), 4, RoundingMode.HALF_UP)); |
| | | } |
| | | productionProductMainMapper.updateById(currentMain); |
| | | |
| | | // 同步工序参数 |
| | | ProductionOrderRoutingOperation routingOperation = productionOrderRoutingOperationMapper.selectById(task.getProductionOrderRoutingOperationId()); |
| | | if (routingOperation != null) { |
| | | syncOperationParamInputValue(dto, routingOperation.getId(), currentMain.getId()); |
| | | } |
| | | |
| | | // 获取产品规格 |
| | | ProductModel productModel = null; |
| | | if (routingOperation != null) { |
| | | productModel = productModelMapper.selectById( |
| | | routingOperation.getProductModelId() != null ? routingOperation.getProductModelId() : getProductionOrderProductModelId(task)); |
| | | } |
| | | if (productModel == null) { |
| | | throw new ServiceException("产品规格不存在"); |
| | | } |
| | | |
| | | ProductionProductMain productionProductMain = new ProductionProductMain(); |
| | | productionProductMain.setProductNo(generateProductNo()); |
| | | productionProductMain.setUserId(user == null ? dto.getUserId() : user.getUserId()); |
| | | productionProductMain.setUserName(user == null ? dto.getUserName() : user.getNickName()); |
| | | productionProductMain.setProductionOperationTaskId(taskId); |
| | | productionProductMain.setStatus(0); |
| | | productionProductMain.setWorkHour(dto.getWorkHour()); |
| | | productionProductMainMapper.insert(productionProductMain); |
| | | syncOperationParamInputValue(dto, routingOperation.getId(), productionProductMain.getId()); |
| | | |
| | | List<ProductStructureDto> productStructureDtos = resolveInputStructures( |
| | | productionOrder.getId(), routingOperation, productModel.getId()); |
| | | // 如果没有bom子节点了,那么投入就是他本身 |
| | | if (productStructureDtos.isEmpty()) { |
| | | ProductStructureDto fallbackInput = new ProductStructureDto(); |
| | | fallbackInput.setProductModelId(productModel.getId()); |
| | | fallbackInput.setUnitQuantity(BigDecimal.ONE); |
| | | productStructureDtos.add(fallbackInput); |
| | | } |
| | | for (ProductStructureDto item : productStructureDtos) { |
| | | // 当前实现按工序成品直接作为投入,后续若接入领料记录可在这里替换来源。 |
| | | // 投入品 |
| | | ProductionProductInput productionProductInput = new ProductionProductInput(); |
| | | productionProductInput.setProductionProductMainId(productionProductMain.getId()); |
| | | productionProductInput.setProductModelId(item.getProductModelId()); |
| | | productionProductInput.setInputQuantity(item.getUnitQuantity().multiply(defaultDecimal(dto.getQuantity()))); |
| | | productionProductInput.setProductionProductMainId(currentMain.getId()); |
| | | productionProductInput.setProductModelId(productModel.getId()); |
| | | productionProductInput.setInputQuantity(defaultDecimal(dto.getQuantity())); |
| | | productionProductInput.setQuantity(productionProductInput.getInputQuantity()); |
| | | productionProductInputMapper.insert(productionProductInput); |
| | | } |
| | | |
| | | // 产出品 |
| | | ProductionProductOutput productionProductOutput = new ProductionProductOutput(); |
| | | productionProductOutput.setProductionProductMainId(productionProductMain.getId()); |
| | | productionProductOutput.setProductionProductMainId(currentMain.getId()); |
| | | productionProductOutput.setProductModelId(productModel.getId()); |
| | | productionProductOutput.setQuantity(defaultDecimal(dto.getQuantity())); |
| | | productionProductOutput.setScrapQty(defaultDecimal(dto.getScrapQty())); |
| | | productionProductOutputMapper.insert(productionProductOutput); |
| | | |
| | | BigDecimal reportQty = defaultDecimal(productionProductOutput.getQuantity()); |
| | | BigDecimal scrapQty = defaultDecimal(productionProductOutput.getScrapQty()); |
| | | BigDecimal productQty = reportQty; |
| | | String qualifiedBatchNo = null; |
| | | |
| | | List<ProductionOrderRoutingOperation> routingOperationList = productionOrderRoutingOperationMapper.selectList( |
| | | TechnologyRoutingOperation technologyRoutingOperation = routingOperation != null |
| | | ? technologyRoutingOperationMapper.selectById(routingOperation.getTechnologyRoutingOperationId()) : null; |
| | | TechnologyOperation technologyOperation = technologyRoutingOperation == null ? null |
| | | : technologyOperationMapper.selectById(technologyRoutingOperation.getTechnologyOperationId()); |
| | | |
| | | List<ProductionOrderRoutingOperation> routingOperationList = routingOperation != null ? productionOrderRoutingOperationMapper.selectList( |
| | | Wrappers.<ProductionOrderRoutingOperation>lambdaQuery() |
| | | .eq(ProductionOrderRoutingOperation::getOrderRoutingId, routingOperation.getOrderRoutingId()) |
| | | .eq(ProductionOrderRoutingOperation::getProductionOrderId, routingOperation.getProductionOrderId())); |
| | | boolean isLastOperation = routingOperation.getDragSort() != null && routingOperation.getDragSort().equals(routingOperationList.size()); |
| | | .eq(ProductionOrderRoutingOperation::getProductionOrderId, routingOperation.getProductionOrderId())) : new ArrayList<>(); |
| | | boolean isLastOperation = routingOperation != null && routingOperation.getDragSort() != null |
| | | && routingOperation.getDragSort().equals(routingOperationList.size()); |
| | | |
| | | if (productQty.compareTo(BigDecimal.ZERO) > 0) { |
| | | if (Boolean.TRUE.equals(routingOperation.getIsQuality())) { |
| | | // 质检工序先生成检验单,非质检工序直接入合格品库存。 |
| | | if (routingOperation != null && Boolean.TRUE.equals(routingOperation.getIsQuality())) { |
| | | int inspectType = isLastOperation ? 2 : 1; |
| | | String process = isLastOperation ? null : technologyOperation == null ? null : technologyOperation.getName(); |
| | | Product product = productMapper.selectById(productModel.getProductId()); |
| | |
| | | qualityInspect.setProcess(process); |
| | | qualityInspect.setInspectState(0); |
| | | qualityInspect.setInspectType(inspectType); |
| | | qualityInspect.setProductMainId(productionProductMain.getId()); |
| | | qualityInspect.setProductMainId(currentMain.getId()); |
| | | qualityInspect.setProductModelId(productModel.getId()); |
| | | qualityInspectMapper.insert(qualityInspect); |
| | | List<QualityTestStandard> qualityTestStandard = qualityTestStandardMapper.getQualityTestStandardByProductId(product.getId(), inspectType, process); |
| | |
| | | } |
| | | } else { |
| | | StockInventoryDto stockInventoryDto = new StockInventoryDto(); |
| | | stockInventoryDto.setRecordId(productionProductMain.getId()); |
| | | stockInventoryDto.setRecordId(currentMain.getId()); |
| | | stockInventoryDto.setRecordType(String.valueOf(StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode())); |
| | | stockInventoryDto.setQualitity(productQty); |
| | | stockInventoryDto.setProductModelId(productModel.getId()); |
| | | stockInventoryService.addStockInRecordOnly(stockInventoryDto); |
| | | qualifiedBatchNo = resolveLatestStockInBatchNo( |
| | | productionProductMain.getId(), |
| | | currentMain.getId(), |
| | | StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(), |
| | | productModel.getId(), |
| | | "0"); |
| | | } |
| | | |
| | | productionOperationTask.setCompleteQuantity(defaultDecimal(productionOperationTask.getCompleteQuantity()).add(productQty)); |
| | | if (ObjectUtils.isNull(productionOperationTask.getActualStartTime())) { |
| | | productionOperationTask.setActualStartTime(LocalDate.now()); |
| | | task.setCompleteQuantity(defaultDecimal(task.getCompleteQuantity()).add(productQty)); |
| | | if (task.getActualStartTime() == null) { |
| | | task.setActualStartTime(LocalDateTime.now()); |
| | | } |
| | | // 报工驱动工单状态流转:有产出即进行中,达到计划量即完工。 |
| | | productionOperationTask.setStatus(3); |
| | | if (productionOperationTask.getPlanQuantity() != null |
| | | && productionOperationTask.getCompleteQuantity().compareTo(productionOperationTask.getPlanQuantity()) >= 0) { |
| | | productionOperationTask.setActualEndTime(LocalDate.now()); |
| | | productionOperationTask.setStatus(4); |
| | | task.setStatus(3); |
| | | if (task.getPlanQuantity() != null |
| | | && task.getCompleteQuantity().compareTo(task.getPlanQuantity()) >= 0) { |
| | | task.setActualEndTime(LocalDateTime.now()); |
| | | task.setStatus(4); |
| | | } |
| | | productionOperationTaskMapper.updateById(productionOperationTask); |
| | | productionOperationTaskMapper.updateById(task); |
| | | |
| | | if (ObjectUtils.isNull(productionOrder.getStartTime())) { |
| | | ProductionOrder productionOrder = productionOrderMapper.selectById(task.getProductionOrderId()); |
| | | if (productionOrder != null) { |
| | | if (productionOrder.getStartTime() == null) { |
| | | productionOrder.setStartTime(LocalDateTime.now()); |
| | | } |
| | | // 订单状态由最后一道工序的合格产出推动,避免中间工序提前完工。 |
| | | productionOrder.setStatus(ProductOrderStatusEnum.RUNNING.getCode()); |
| | | if (isLastOperation) { |
| | | productionOrder.setCompleteQuantity(defaultDecimal(productionOrder.getCompleteQuantity()).add(productQty)); |
| | |
| | | } |
| | | } |
| | | productionOrderMapper.updateById(productionOrder); |
| | | } |
| | | |
| | | BigDecimal workHours = BigDecimal.ZERO; |
| | | if (technologyOperation != null && technologyOperation.getSalaryQuota() != null) { |
| | |
| | | : technologyOperation.getSalaryQuota(); |
| | | } |
| | | ProductionAccount productionAccount = new ProductionAccount(); |
| | | productionAccount.setProductionProductMainId(productionProductMain.getId()); |
| | | productionAccount.setSchedulingUserId(user == null ? null : user.getUserId()); |
| | | productionAccount.setSchedulingUserName(user == null ? dto.getUserName() : user.getNickName()); |
| | | productionAccount.setProductionProductMainId(currentMain.getId()); |
| | | SysUser user = userMapper.selectUserById(dto.getUserId()); |
| | | productionAccount.setSchedulingUserId(user == null ? currentMain.getUserId() : user.getUserId()); |
| | | productionAccount.setSchedulingUserName(user == null ? currentMain.getUserName() : user.getNickName()); |
| | | productionAccount.setFinishedNum(productQty); |
| | | productionAccount.setWorkHours(technologyOperation != null ? technologyOperation.getSalaryQuota() : null); |
| | | productionAccount.setTechnologyOperationName(technologyOperation == null ? null : technologyOperation.getName()); |
| | | productionAccount.setSchedulingDate(LocalDateTime.now()); |
| | | productionAccount.setSchedulingDate(currentMain.getActualEndTime() != null ? currentMain.getActualEndTime() : LocalDateTime.now()); |
| | | productionAccountMapper.insert(productionAccount); |
| | | } |
| | | if (scrapQty.compareTo(BigDecimal.ZERO) > 0) { |
| | |
| | | productModel.getId(), |
| | | scrapQty, |
| | | StockInQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode(), |
| | | productionProductMain.getId(), |
| | | currentMain.getId(), |
| | | qualifiedBatchNo); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | private Long getProductionOrderProductModelId(ProductionOperationTask task) { |
| | | // 从生产订单获取产品规格ID |
| | | if (task == null || task.getProductionOrderId() == null) { |
| | | return null; |
| | | } |
| | | ProductionOrder order = productionOrderMapper.selectById(task.getProductionOrderId()); |
| | | return order == null ? null : order.getProductModelId(); |
| | | } |
| | | |
| | | private void validateWorkerPermission(ProductionOperationTask task) { |
| | | // 校验当前用户是否有权操作此工单:未指派时人人可操作,已指派时仅被指派人可操作 |
| | | if (task == null) { |
| | | return; |
| | | } |
| | | String userIds = task.getUserIds(); |
| | | if (userIds == null || userIds.isEmpty() || "[]".equals(userIds.trim())) { |
| | | return; |
| | | } |
| | | Long currentUserId = SecurityUtils.getUserId(); |
| | | if (currentUserId == null) { |
| | | return; |
| | | } |
| | | List<Long> assignedIds = JSON.parseArray(userIds, Long.class); |
| | | if (assignedIds == null || !assignedIds.contains(currentUserId)) { |
| | | throw new ServiceException("您未被指派到此工单,无法操作"); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public Boolean saveProductionProductMain(ProductionProductMainDto productionProductMainDto) { |
| | | // 保存生产报工主记录 |
| | | return addProductMain(productionProductMainDto); |
| | | } |
| | | |
| | | @Override |
| | | public Boolean removeProductMain(Long id) { |
| | | // 删除生产报工主记录 |
| | | ProductionProductMain currentMain = productionProductMainMapper.selectById(id); |
| | | if (currentMain == null) { |
| | | return true; |
| | | } |
| | | return removeProductMainByProductionTask(currentMain); |
| | | } |
| | | |
| | | private String resolveLatestStockInBatchNo(Long recordId, |
| | |
| | | target.setProductionOrderRoutingOperationId(source.getProductionOrderRoutingOperationId()); |
| | | target.setProductionProductMainId(productionProductMainId); |
| | | return target; |
| | | } |
| | | |
| | | 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) { |