cuilei
2025-05-28 62ad99ee2a374c1726730146335ed82cbcfacebb
lxzn-module-tms/src/main/java/org/jeecg/modules/tms/service/impl/OutboundOrderServiceImpl.java
@@ -7,6 +7,7 @@
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -27,6 +28,7 @@
import org.jeecg.modules.flowable.service.IFlowTaskService;
import org.jeecg.modules.system.service.ISysBusinessCodeRuleService;
import org.jeecg.modules.tms.entity.*;
import org.jeecg.modules.tms.entity.dto.OutBoundAddDto;
import org.jeecg.modules.tms.entity.dto.OutBoundOrderFlowDto;
import org.jeecg.modules.tms.entity.dto.OutBoundRequestDto;
import org.jeecg.modules.tms.entity.dto.OutboundOrderAndDetailDto;
@@ -64,6 +66,8 @@
   private IToolLedgerDetailService toolLedgerDetailService;
   @Autowired
   private IOutStoreDetailService outStoreDetailService;
   @Autowired
   private IBaseToolsService baseToolsService;
   @Autowired
   private ISysBusinessCodeRuleService businessCodeRuleService;
   @Autowired
@@ -125,9 +129,13 @@
      if (outStorehouseTypes != null && outStorehouseTypes.length > 0) {
         queryWrapper.eq("t.out_storehouse_type", outStorehouseTypes[0]);
      }
      String[] statuses = parameterMap.get("orderStatus");
      if (statuses != null && statuses.length > 0) {
         queryWrapper.eq("t.order_status", statuses[0]);
      String[] orderStatuses = parameterMap.get("orderStatus");
      if (orderStatuses != null && orderStatuses.length > 0) {
         queryWrapper.eq("t.order_status", orderStatuses[0]);
      }
      String[] outStatuses = parameterMap.get("outStatus");
      if (outStatuses != null && outStatuses.length > 0) {
         queryWrapper.eq("t.out_status", outStatuses[0]);
      }
      String[] startTimes = parameterMap.get("startTime");
      if (startTimes != null && startTimes.length > 0) {
@@ -219,6 +227,11 @@
         if (OutBillStatus.APPROVED.getValue().equals(outBoundOrderFlowDto.getStatus())) {
            outboundOrder.setOutStatus(OutBoundStatusEnum.NOT_OUTBOUND.getValue());
            outboundOrder.setOrderStatus(OutBillStatus.APPROVED.getValue());
            //初始化申请明细信息的出库状态/实际出库数量字段
            outboundDetailService.update(new LambdaUpdateWrapper<OutboundDetail>()
                  .eq(OutboundDetail::getOutStorehouseId, outboundOrder.getId())
                  .set(OutboundDetail::getStatus, OutBoundStatusEnum.NOT_OUTBOUND.getValue())
                  .set(OutboundDetail::getOutActualCount, BigDecimal.ZERO));
         }
         if (OutBillStatus.REJECTED.getValue().equals(outBoundOrderFlowDto.getStatus())) {
            //如果驳回,审批单状态回到草稿
@@ -232,7 +245,7 @@
   @Override
   @Transactional(rollbackFor = Exception.class)
   public void outBound(List<OutBoundRequestDto> outBoundRequestList) {
   public void outBoundByApply(List<OutBoundRequestDto> outBoundRequestList) {
      //校验是否来自一个申请单
      if (!fromOneApply(outBoundRequestList)) {
         throw new JeecgBootException("出库明细必须来自同一出库申请单!");
@@ -259,7 +272,7 @@
            queryWrapper.or();
         }
         OutboundDetail detail = outboundDetailList.get(i);
         queryWrapper.and(wrapper ->
         queryWrapper.or(wrapper ->
               wrapper.eq(ToolLedgerDetail::getToolCode, detail.getToolCode())
                     .eq(ToolLedgerDetail::getToolId, detail.getToolId()) //如果不管到把,该字段为空
         );
@@ -362,6 +375,105 @@
      updateById(outboundOrder);
   }
   @Override
   @Transactional(rollbackFor = Exception.class)
   public void outBoundByAdd(List<OutBoundAddDto> boundAddList) {
      //校验台账主表库存数量
      Map<String, BigDecimal> toolBoundQuantityMap = boundAddList.stream()
            .collect(Collectors.groupingBy(OutBoundAddDto::getToolCode,
                  Collectors.mapping(OutBoundAddDto::getOutboundQuantity, Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))));
      Map<String, ToolLedger> toolLedgerMap = toolLedgerService.list(new LambdaQueryWrapper<ToolLedger>().in(ToolLedger::getToolId, toolBoundQuantityMap.keySet()))
            .stream().collect(Collectors.toMap(ToolLedger::getToolId, item -> item, (k1, k2) -> k1));
      List<ToolLedger> toolLedgerUpdateList = CollectionUtil.newArrayList();
      for (String toolCode : toolBoundQuantityMap.keySet()) {
         ToolLedger toolLedger = toolLedgerMap.get(toolCode);
         BigDecimal outBoundQuantity = toolBoundQuantityMap.get(toolCode);
         if (Objects.isNull(toolLedger) || toolLedger.getAvailableCount().compareTo(outBoundQuantity) < 0) {
            BaseTools tools = baseToolsService.getById(toolCode);
            throw new JeecgBootException("编码为【" + tools.getToolCode() + "】的工具,库存不足!");
         } else {
            OutStorehouseType outStorehouseType = OutStorehouseType.getByValue(boundAddList.get(0).getOutStorehouseType());
            switch (outStorehouseType) {
               case TOOL_BORROW:
                  toolLedger.setLendCount(toolLedger.getLendCount().add(outBoundQuantity));
                  break;
               case MAINTENANCE_OUTBOUND:
                  toolLedger.setRepairCount(toolLedger.getRepairCount().add(outBoundQuantity));
                  break;
               case CALIBRATION_OUTBOUND:
                  toolLedger.setDetectionCount(toolLedger.getDetectionCount().add(outBoundQuantity));
                  break;
               case GRINDING_OUTBOUND:
                  toolLedger.setSharpeningCount(toolLedger.getSharpeningCount().add(outBoundQuantity));
                  break;
               default:
                  throw new JeecgBootException("未知的出库类型!");
            }
            //扣减台账主表可用库存
            toolLedger.setAvailableCount(toolLedger.getAvailableCount().subtract(outBoundQuantity));
            toolLedgerUpdateList.add(toolLedger);
         }
      }
      //校验台账明细库存数量
      Map<String, OutBoundAddDto> boundAddDtoMap = boundAddList.stream().collect(Collectors
            .toMap(OutBoundAddDto::getToolLedgerDetailId, item -> item, (k1, k2) -> k1));
      Map<String, ToolLedgerDetail> toolLedgerDetailMap = toolLedgerDetailService.listByIds(boundAddDtoMap.keySet()).stream()
            .collect(Collectors.toMap(ToolLedgerDetail::getId, item -> item, (k1, k2) -> k1));
      List<ToolLedgerDetail> toolLedgerDetailUpdateList = CollectionUtil.newArrayList();
      for (String toolLedgerDetailId : boundAddDtoMap.keySet()) {
         OutBoundAddDto outBoundAddDto = boundAddDtoMap.get(toolLedgerDetailId);
         BigDecimal outboundQuantity = outBoundAddDto.getOutboundQuantity();
         ToolLedgerDetail toolLedgerDetail = toolLedgerDetailMap.get(toolLedgerDetailId);
         if (Objects.isNull(toolLedgerDetail) || toolLedgerDetail.getQuantity().compareTo(outboundQuantity) < 0) {
            BaseTools tools = baseToolsService.getById(outBoundAddDto.getToolCode());
            throw new JeecgBootException("编码为【" + tools.getToolCode() + "】的工具,库存不足!");
         } else {
            //扣减台账明细库存
            if (StrUtil.isBlank(toolLedgerDetail.getToolId())) {
               //没有唯一编码,不管到把的
               toolLedgerDetail.setQuantity(toolLedgerDetail.getQuantity().subtract(outboundQuantity));
            } else {
               //有唯一编码,管道把的
               toolLedgerDetail.setQuantity(BigDecimal.ZERO);//数量只会是0和1
               OutStorehouseType outStorehouseType = OutStorehouseType.getByValue(boundAddList.get(0).getOutStorehouseType());
               switch (outStorehouseType) {
                  case TOOL_BORROW:
                     toolLedgerDetail.setStatus(ToolCirculationStatus.BORROWED.getValue());
                     break;
                  case MAINTENANCE_OUTBOUND:
                     toolLedgerDetail.setStatus(ToolCirculationStatus.REPAIRING.getValue());
                     break;
                  case CALIBRATION_OUTBOUND:
                     toolLedgerDetail.setStatus(ToolCirculationStatus.INSPECTING.getValue());
                     break;
                  case GRINDING_OUTBOUND:
                     toolLedgerDetail.setStatus(ToolCirculationStatus.GRINDING.getValue());
                     break;
                  default:
                     throw new JeecgBootException("未知的出库类型!");
               }
            }
            toolLedgerDetailUpdateList.add(toolLedgerDetail);
         }
      }
      toolLedgerService.updateBatchById(toolLedgerUpdateList);
      toolLedgerDetailService.updateBatchById(toolLedgerDetailUpdateList);
      //记录出库流水
      List<OutStoreDetail> outStoreAddList = CollectionUtil.newArrayList();
      for (OutBoundAddDto outBoundAddDto : boundAddList) {
         OutStoreDetail outStoreDetail = new OutStoreDetail()
               .setToolCode(outBoundAddDto.getToolCode())
               .setToolId(outBoundAddDto.getToolId())
               .setOutStorehouseType(outBoundAddDto.getOutStorehouseType())
               .setGoodsShelvesCode(outBoundAddDto.getOutboundLocation())
               .setOutNumber(outBoundAddDto.getOutboundQuantity())
               .setOperateType("2");//2:手工操作
         outStoreAddList.add(outStoreDetail);
      }
      outStoreDetailService.saveBatch(outStoreAddList);
   }
   private boolean fromOneApply(List<OutBoundRequestDto> outBoundRequestList) {
      long count = outBoundRequestList.stream().map(OutBoundRequestDto::getOutBoundOrderId).distinct().count();
      if (count > 1) {