cuilei
2025-05-26 89dcf021bcb3c3393e03e2ebcb4b26e54aa360ad
lxzn-module-tms/src/main/java/org/jeecg/modules/tms/service/impl/OutboundOrderServiceImpl.java
@@ -26,22 +26,25 @@
import org.jeecg.modules.flowable.service.IFlowDefinitionService;
import org.jeecg.modules.flowable.service.IFlowTaskService;
import org.jeecg.modules.system.service.ISysBusinessCodeRuleService;
import org.jeecg.modules.tms.entity.OutboundOrder;
import org.jeecg.modules.tms.entity.OutboundDetail;
import org.jeecg.modules.tms.entity.*;
import org.jeecg.modules.tms.entity.dto.OutBoundOrderFlowDto;
import org.jeecg.modules.tms.entity.dto.OutBoundRequestDto;
import org.jeecg.modules.tms.entity.dto.OutboundOrderAndDetailDto;
import org.jeecg.modules.tms.enums.OutBillStatus;
import org.jeecg.modules.tms.enums.OutBoundStatusEnum;
import org.jeecg.modules.tms.enums.OutStorehouseType;
import org.jeecg.modules.tms.enums.ToolCirculationStatus;
import org.jeecg.modules.tms.mapper.OutboundDetailMapper;
import org.jeecg.modules.tms.mapper.OutboundOrderMapper;
import org.jeecg.modules.tms.service.IOutboundDetailService;
import org.jeecg.modules.tms.service.IOutboundOrderService;
import org.jeecg.modules.tms.service.*;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
/**
 * @Description: tms_outbound_order
@@ -55,6 +58,12 @@
   @Autowired
   private IOutboundDetailService outboundDetailService;
   @Autowired
   private IToolLedgerService toolLedgerService;
   @Autowired
   private IToolLedgerDetailService toolLedgerDetailService;
   @Autowired
   private IOutStoreDetailService outStoreDetailService;
   @Autowired
   private ISysBusinessCodeRuleService businessCodeRuleService;
   @Autowired
@@ -207,9 +216,13 @@
      //根据任务完成结果更新申请单状态
      if (result.isSuccess()) {
         outboundOrder.setOrderStatus(outBoundOrderFlowDto.getStatus());
         if (OutBillStatus.APPROVED.getValue().equals(outBoundOrderFlowDto.getStatus())) {
            outboundOrder.setOutStatus(OutBoundStatusEnum.NOT_OUTBOUND.getValue());
            outboundOrder.setOrderStatus(OutBillStatus.APPROVED.getValue());
         }
         if (OutBillStatus.REJECTED.getValue().equals(outBoundOrderFlowDto.getStatus())) {
            //如果驳回,审批单状态回到草稿
            outboundOrder.setOrderStatus(OutBillStatus.DRAFT.getValue());
         }
         outboundOrder.setAuditDate(new Date());
         outboundOrder.setApprovalOpinion(outBoundOrderFlowDto.getApprovalOpinion());
@@ -217,6 +230,158 @@
      }
   }
   @Override
   @Transactional(rollbackFor = Exception.class)
   public void outBound(List<OutBoundRequestDto> outBoundRequestList) {
      //校验是否来自一个申请单
      if (!fromOneApply(outBoundRequestList)) {
         throw new JeecgBootException("出库明细必须来自同一出库申请单!");
      }
      //是否可出库校验
      if (!readyToOutbound(outBoundRequestList)) {
         throw new JeecgBootException("未经审批通过的申请单不能出库!");
      }
      //开始出库
      OutboundOrder outboundOrder = getById(outBoundRequestList.get(0).getOutBoundOrderId());
      List<String> detailIds = outBoundRequestList.stream().map(OutBoundRequestDto::getOutboundDetailId).collect(Collectors.toList());
      List<OutboundDetail> outboundDetailList = outboundDetailService.listByIds(detailIds);
      List<String> toolIdList = outboundDetailList.stream().map(OutboundDetail::getToolCode).collect(Collectors.toList());
      Map<String, BigDecimal> outBoundRequestMap = outBoundRequestList.stream()
            .collect(Collectors.toMap(OutBoundRequestDto::getOutboundDetailId, OutBoundRequestDto::getOutboundQuantity));
      //处理库存台账及台账明细
      Map<String, ToolLedger> toolLedgerMap = toolLedgerService.list(new LambdaQueryWrapper<ToolLedger>().in(ToolLedger::getToolId, toolIdList)).stream()
            .collect(Collectors.toMap(ToolLedger::getToolId, item -> item, (k1, k2) -> k1));
      LambdaQueryWrapper<ToolLedgerDetail> queryWrapper = new LambdaQueryWrapper<>();
      for (int i = 0; i < outboundDetailList.size(); i++) {
         if (i > 0) {
            queryWrapper.or();
         }
         OutboundDetail detail = outboundDetailList.get(i);
         queryWrapper.and(wrapper ->
               wrapper.eq(ToolLedgerDetail::getToolCode, detail.getToolCode())
                     .eq(ToolLedgerDetail::getToolId, detail.getToolId()) //如果不管到把,该字段为空
         );
      }
      List<ToolLedgerDetail> toolLedgerDetailList = toolLedgerDetailService.list(queryWrapper);
      List<ToolLedger> toolLedgerUpdateList = CollectionUtil.newArrayList();
      List<ToolLedgerDetail> toolLedgerDetailUpdateList = CollectionUtil.newArrayList();
      List<OutStoreDetail> outStoreAddList = CollectionUtil.newArrayList();
      List<OutboundDetail> outboundDetailUpdateList = CollectionUtil.newArrayList();
      for (OutboundDetail detail : outboundDetailList) {
         //更新库存台账
         ToolLedger toolLedger = toolLedgerMap.get(detail.getToolCode());
         BigDecimal outboundQuantity = outBoundRequestMap.get(detail.getId());
         OutStorehouseType outStorehouseType = OutStorehouseType.getByValue(outboundOrder.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("未知的出库类型!");
         }
         toolLedgerUpdateList.add(toolLedger);
         //更新台账明细
         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));
                  }
                  toolLedgerDetailUpdateList.add(item);
               });
         //记录出库流水
         OutStoreDetail outStoreDetail = new OutStoreDetail()
               .setToolCode(detail.getToolCode())
               .setToolId(detail.getToolId())
               .setOutStorehouseType(outboundOrder.getOutStorehouseType())
               .setGoodsShelvesCode(detail.getOutboundLocation())
               .setOutNumber(outboundQuantity)
               .setOutStorehouseId(outboundOrder.getId())
               .setOperateType("1");//1:按申请单
         outStoreAddList.add(outStoreDetail);
         //更新申请单明细
         detail.setOutActualCount(detail.getOutActualCount().add(outboundQuantity));
         detail.setOutboundTime(new Date());
         if (detail.getOutActualCount().compareTo(detail.getOutboundQuantity()) == 0) {
            detail.setStatus(OutBoundStatusEnum.COMPLETED.getValue());
         } else {
            detail.setStatus(OutBoundStatusEnum.PARTIAL_OUTBOUND.getValue());
         }
         outboundDetailUpdateList.add(detail);
      }
      toolLedgerService.updateBatchById(toolLedgerUpdateList);
      toolLedgerDetailService.updateBatchById(toolLedgerDetailUpdateList);
      outStoreDetailService.saveBatch(outStoreAddList);
      outboundDetailService.updateBatchById(outboundDetailUpdateList);
      //更新申请单
      boolean allMatch = outboundDetailService.list(new LambdaQueryWrapper<OutboundDetail>()
                  .eq(OutboundDetail::getOutStorehouseId, outboundOrder.getId()))
            .stream().filter(i -> !detailIds.contains(i.getId()))
            .allMatch(i -> i.getStatus().equals(OutBoundStatusEnum.COMPLETED.getValue()));
      List<OutboundDetail> partialOutboundList = outboundDetailUpdateList.stream()
            .filter(i -> !i.getStatus().equals(OutBoundStatusEnum.COMPLETED.getValue())).collect(Collectors.toList());
      if (allMatch && partialOutboundList.isEmpty()) {
         outboundOrder.setOutStatus(OutBoundStatusEnum.COMPLETED.getValue());
      } else {
         outboundOrder.setOutStatus(OutBoundStatusEnum.PARTIAL_OUTBOUND.getValue());
      }
      outboundOrder.setOutboundTime(new Date());
      updateById(outboundOrder);
   }
   private boolean fromOneApply(List<OutBoundRequestDto> outBoundRequestList) {
      long count = outBoundRequestList.stream().map(OutBoundRequestDto::getOutBoundOrderId).distinct().count();
      if (count > 1) {
         return false;
      }
      List<String> outDetailIds = outBoundRequestList.stream().map(OutBoundRequestDto::getOutboundDetailId).collect(Collectors.toList());
      String outboundDetailId = outBoundRequestList.get(0).getOutboundDetailId();
      OutboundDetail outboundDetail = outboundDetailService.getById(outboundDetailId);
      List<String> detailIds = outboundDetailService.list(new LambdaQueryWrapper<OutboundDetail>()
            .eq(OutboundDetail::getOutStorehouseId, outboundDetail.getOutStorehouseId())).stream()
            .map(OutboundDetail::getId).collect(Collectors.toList());
        return new HashSet<>(detailIds).containsAll(outDetailIds);
    }
   private boolean readyToOutbound(List<OutBoundRequestDto> outBoundRequestList) {
      String outBoundOrderId = outBoundRequestList.get(0).getOutBoundOrderId();
      OutboundOrder outboundOrder = getById(outBoundOrderId);
        return OutBillStatus.APPROVED.getValue().equals(outboundOrder.getOrderStatus());
    }
   public boolean triggerProcess(OutboundOrder outboundOrder) {
      flowCommonService.initActBusiness("单号为:" + outboundOrder.getOutNum() + " 的出库申请,开始进行审批",
            outboundOrder.getId(), "outboundOrderServiceImpl", "tool_out_storage", null);