cuilei
2025-05-30 6291e5799cf5165cd966a3923b1c70e2cd2621a8
lxzn-module-tms/src/main/java/org/jeecg/modules/tms/service/impl/OutboundOrderServiceImpl.java
@@ -134,7 +134,8 @@
      }
      String[] outStatuses = parameterMap.get("outStatus");
      if (outStatuses != null && outStatuses.length > 0) {
         queryWrapper.eq("t.out_status", outStatuses[0]);
         String[] statusArr = outStatuses[0].split(",");
         queryWrapper.in("t.out_status", statusArr);
      }
      String[] startTimes = parameterMap.get("startTime");
      if (startTimes != null && startTimes.length > 0) {
@@ -165,6 +166,7 @@
   }
    @Override
   @Transactional(rollbackFor = Exception.class)
    public void submit(String id) {
      OutboundOrder outboundOrder = getById(id);
      if (outboundOrder == null) {
@@ -173,12 +175,79 @@
      if (!Objects.equals(outboundOrder.getOrderStatus(), OutBillStatus.DRAFT.getValue())) {
         throw new JeecgBootException("无法提交非草稿状态的出库申请单!");
      }
      //启动流程
      if (triggerProcess(outboundOrder)) {
         outboundOrder.setOrderStatus(OutBillStatus.SUBMITTED.getValue());
      //锁定申请单明细中工具库存
      if (lockOutboundStock(id)) {
         //启动流程
         if (triggerProcess(outboundOrder)) {
            outboundOrder.setOrderStatus(OutBillStatus.SUBMITTED.getValue());
            updateById(outboundOrder);
         }
      }
      updateById(outboundOrder);
    }
   private boolean lockOutboundStock(String id) {
      List<OutboundDetail> outboundDetailList = outboundDetailService.list(new LambdaQueryWrapper<OutboundDetail>()
            .eq(OutboundDetail::getOutStorehouseId, id));
      LambdaQueryWrapper<ToolLedgerDetail> queryWrapper = new LambdaQueryWrapper<>();
      for (int i = 0; i < outboundDetailList.size(); i++) {
         if (i > 0) {
            queryWrapper.or();
         }
         OutboundDetail detail = outboundDetailList.get(i);
         queryWrapper.or(wrapper ->
               wrapper.eq(StrUtil.isNotBlank(detail.getToolCode()), ToolLedgerDetail::getToolCode, detail.getToolCode())
                     .eq(StrUtil.isNotBlank(detail.getToolId()), ToolLedgerDetail::getToolId, detail.getToolId()) //如果不管到把,该字段为空
         );
      }
      List<ToolLedgerDetail> toolLedgerDetailList = toolLedgerDetailService.list(queryWrapper);
      List<ToolLedgerDetail> toolLedgerDetailUpdateList = CollectionUtil.newArrayList();
      for (OutboundDetail detail : outboundDetailList) {
         String toolCode = detail.getToolCode();
         List<ToolLedgerDetail> ledgerDetailList = toolLedgerDetailList.stream().filter(item -> Objects.equals(item.getToolCode(), toolCode)
               && Objects.equals(item.getToolId(), detail.getToolId())).collect(Collectors.toList());
         if (CollectionUtil.isEmpty(ledgerDetailList)) {
            BaseTools tools = baseToolsService.getById(toolCode);
            throw new JeecgBootException("编码为【" + tools.getToolCode() + "】的工具,库存不足!");
         } else {
            ToolLedgerDetail toolLedgerDetail = ledgerDetailList.get(0);
            if (toolLedgerDetail.getQuantity().compareTo(detail.getOutboundQuantity()) < 0) {
               throw new JeecgBootException("编码为【" + toolLedgerDetail.getToolCode() + "】的工具,库存不足!");
            } else {
               //扣减台账明细中的库存,执行锁库
               if (StrUtil.isBlank(detail.getToolId())) {
                  //管到类的刀具
                  toolLedgerDetail.setQuantity(toolLedgerDetail.getQuantity().subtract(detail.getOutboundQuantity()));
               } else {
                  //管到把的刀具,数量只有 0和1
                  toolLedgerDetail.setQuantity(BigDecimal.ZERO);
               }
               toolLedgerDetailUpdateList.add(toolLedgerDetail);
            }
         }
      }
      Map<String, BigDecimal> outToolCodeQuantityMap = outboundDetailList.stream().collect(Collectors.groupingBy(OutboundDetail::getToolCode,
            Collectors.mapping(OutboundDetail::getOutboundQuantity, Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))));
      Map<String, ToolLedger> toolLedgerMap = toolLedgerService.list(new LambdaQueryWrapper<ToolLedger>().in(ToolLedger::getToolId, outToolCodeQuantityMap.keySet()))
            .stream().collect(Collectors.toMap(ToolLedger::getToolId, toolLedger -> toolLedger, (k1, k2) -> k1));
      List<ToolLedger> toolLedgerUpdateList = CollectionUtil.newArrayList();
      for (String toolCode : outToolCodeQuantityMap.keySet()) {
         BigDecimal outQuantity = outToolCodeQuantityMap.get(toolCode);
         ToolLedger toolLedger = toolLedgerMap.get(toolCode);
         BaseTools tools = baseToolsService.getById(toolCode);
         if (Objects.isNull(toolLedger) || toolLedger.getAvailableCount().compareTo(outQuantity) < 0) {
            throw new JeecgBootException("编码为【" + tools.getToolCode() + "】的工具,库存不足!");
         } else {
            //扣减台账主表中的可用存库,执行锁库
            toolLedger.setAvailableCount(toolLedger.getAvailableCount().subtract(outQuantity));
            toolLedgerUpdateList.add(toolLedger);
         }
      }
      toolLedgerDetailService.updateBatchById(toolLedgerDetailUpdateList);
      toolLedgerService.updateBatchById(toolLedgerUpdateList);
      return true;
   }
   @Transactional(rollbackFor = Exception.class)
   @Override
@@ -235,11 +304,63 @@
         if (OutBillStatus.REJECTED.getValue().equals(outBoundOrderFlowDto.getStatus())) {
            //如果驳回,审批单状态回到草稿
            outboundOrder.setOrderStatus(OutBillStatus.DRAFT.getValue());
            //释放申请单中锁定的库存
            releaseStock(outboundOrder);
         }
         outboundOrder.setAuditDate(new Date());
         outboundOrder.setApprovalOpinion(outBoundOrderFlowDto.getApprovalOpinion());
         updateById(outboundOrder);
      }
   }
   private void releaseStock(OutboundOrder outboundOrder) {
      List<OutboundDetail> outboundDetailList = outboundDetailService.list(new LambdaQueryWrapper<OutboundDetail>()
            .eq(OutboundDetail::getOutStorehouseId, outboundOrder.getId()));
      LambdaQueryWrapper<ToolLedgerDetail> queryWrapper = new LambdaQueryWrapper<>();
      for (int i = 0; i < outboundDetailList.size(); i++) {
         if (i > 0) {
            queryWrapper.or();
         }
         OutboundDetail detail = outboundDetailList.get(i);
         queryWrapper.or(wrapper ->
               wrapper.eq(StrUtil.isNotBlank(detail.getToolCode()), ToolLedgerDetail::getToolCode, detail.getToolCode())
                     .eq(StrUtil.isNotBlank(detail.getToolId()), ToolLedgerDetail::getToolId, detail.getToolId()) //如果不管到把,该字段为空
         );
      }
      List<ToolLedgerDetail> toolLedgerDetailList = toolLedgerDetailService.list(queryWrapper);
      List<ToolLedgerDetail> toolLedgerDetailUpdateList = CollectionUtil.newArrayList();
      for (OutboundDetail detail : outboundDetailList) {
         Optional<ToolLedgerDetail> optonal = toolLedgerDetailList.stream().filter(item -> Objects.equals(item.getToolCode(), detail.getToolCode())
               && Objects.equals(item.getToolId(), detail.getToolId())).findFirst();
         if (optonal.isPresent()) {
            ToolLedgerDetail toolLedgerDetail = optonal.get();
            if (StrUtil.isBlank(detail.getToolId())) {
               //到类
               toolLedgerDetail.setQuantity(toolLedgerDetail.getQuantity().add(detail.getOutboundQuantity()));
            } else {
               //到把
               toolLedgerDetail.setQuantity(BigDecimal.ONE);
            }
            toolLedgerDetailUpdateList.add(toolLedgerDetail);
         }
      }
      Map<String, BigDecimal> outToolCodeQuantityMap = outboundDetailList.stream().collect(Collectors.groupingBy(OutboundDetail::getToolCode,
            Collectors.mapping(OutboundDetail::getOutboundQuantity, Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))));
      Map<String, ToolLedger> toolLedgerMap = toolLedgerService.list(new LambdaQueryWrapper<ToolLedger>().in(ToolLedger::getToolId, outToolCodeQuantityMap.keySet()))
            .stream().collect(Collectors.toMap(ToolLedger::getToolId, toolLedger -> toolLedger, (k1, k2) -> k1));
      List<ToolLedger> toolLedgerUpdateList = new ArrayList<>();
      for (String baseToolId : outToolCodeQuantityMap.keySet()) {
         BigDecimal outQuantity = outToolCodeQuantityMap.get(baseToolId);
         ToolLedger toolLedger = toolLedgerMap.get(baseToolId);
         if (Objects.nonNull(toolLedger)) {
            toolLedger.setAvailableCount(toolLedger.getAvailableCount().add(outQuantity));
            toolLedgerUpdateList.add(toolLedger);
         }
      }
      toolLedgerDetailService.updateBatchById(toolLedgerDetailUpdateList);
      toolLedgerService.updateBatchById(toolLedgerUpdateList);
   }
   @Override
@@ -308,26 +429,21 @@
         //更新台账明细
         toolLedgerDetailList.stream().filter(item -> item.getToolCode().equals(detail.getToolCode()) && item.getToolId().equals(detail.getToolId()))
               .findFirst().ifPresent(item -> {
                  if (StrUtil.isNotBlank(item.getToolId())) {
                     item.setQuantity(BigDecimal.ZERO);
                     switch (outStorehouseType) {
                        case TOOL_BORROW:
                           item.setStatus(ToolCirculationStatus.BORROWED.getValue());
                           break;
                        case MAINTENANCE_OUTBOUND:
                           item.setStatus(ToolCirculationStatus.REPAIRING.getValue());
                           break;
                        case CALIBRATION_OUTBOUND:
                           item.setStatus(ToolCirculationStatus.INSPECTING.getValue());
                           break;
                        case GRINDING_OUTBOUND:
                           item.setStatus(ToolCirculationStatus.GRINDING.getValue());
                           break;
                        default:
                           throw new JeecgBootException("未知的出库类型!");
                     }
                  } else {
                     item.setQuantity(item.getQuantity().subtract(outboundQuantity));
                  switch (outStorehouseType) {
                     case TOOL_BORROW:
                        item.setStatus(ToolCirculationStatus.BORROWED.getValue());
                        break;
                     case MAINTENANCE_OUTBOUND:
                        item.setStatus(ToolCirculationStatus.REPAIRING.getValue());
                        break;
                     case CALIBRATION_OUTBOUND:
                        item.setStatus(ToolCirculationStatus.INSPECTING.getValue());
                        break;
                     case GRINDING_OUTBOUND:
                        item.setStatus(ToolCirculationStatus.GRINDING.getValue());
                        break;
                     default:
                        throw new JeecgBootException("未知的出库类型!");
                  }
                  toolLedgerDetailUpdateList.add(item);
               });