From e5229a67805aaf01af7d70042c4b2fe2dfd8d2da Mon Sep 17 00:00:00 2001
From: yiwenpeng <ywp303@163.com>
Date: Tue, 20 Aug 2024 09:42:52 +0800
Subject: [PATCH] feat:优化自动出库

---
 src/main/java/com/huaheng/api/wcs/controller/ArrivedNoticeController.java                                     |  17 ++++++++---------
 src/main/java/com/huaheng/pc/inventory/inventoryDetail/service/InventoryDetailService.java                    |   2 ++
 src/main/java/com/huaheng/pc/inventory/inventoryDetail/service/InventoryDetailServiceImpl.java                |   8 ++++++++
 src/main/java/com/huaheng/pc/inventory/inventoryHeader/service/InventoryHeaderService.java                    |   4 +++-
 src/main/java/com/huaheng/pc/inventory/inventoryHeader/service/InventoryHeaderServiceImpl.java                | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------------------------------
 src/main/java/com/huaheng/pc/monitor/job/task/RyTask.java                                                     |  73 +++++++++++++++++++++++++++++++++++++------------------------------------
 src/main/java/com/huaheng/pc/shipment/shipmentContainerHeader/service/ShipmentContainerHeaderServiceImpl.java | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------
 src/main/java/com/huaheng/pc/shipment/shipmentHeader/controller/ShipmentHeaderController.java                 |  26 +++++++++++++-------------
 src/main/java/com/huaheng/pc/shipment/shipmentHeader/service/ShipmentHeaderServiceImpl.java                   |  29 +++++++++++++++++------------
 src/main/java/com/huaheng/pc/task/taskHeader/service/ReceiptTaskService.java                                  |   9 ++++++---
 src/main/java/com/huaheng/pc/task/taskHeader/service/ShipmentTaskService.java                                 |  12 ++++++++----
 src/main/java/com/huaheng/pc/task/taskHeader/service/TransferTaskService.java                                 |   2 +-
 src/main/java/com/huaheng/pc/task/taskHeader/service/WorkTaskService.java                                     |  14 +++++++++-----
 src/main/resources/templates/shipment/shipmentHeader/shipmentHeader.html                                      |   8 ++++----
 14 files changed, 253 insertions(+), 179 deletions(-)

diff --git a/src/main/java/com/huaheng/api/wcs/controller/ArrivedNoticeController.java b/src/main/java/com/huaheng/api/wcs/controller/ArrivedNoticeController.java
index 1f3ac01..8c3665c 100644
--- a/src/main/java/com/huaheng/api/wcs/controller/ArrivedNoticeController.java
+++ b/src/main/java/com/huaheng/api/wcs/controller/ArrivedNoticeController.java
@@ -42,10 +42,10 @@ public class ArrivedNoticeController extends BaseController {
 
     @PostMapping("/arrivedNotice")
     @ApiOperation("到达拣选台")
-    @ApiLogger(apiName = "wcs到达拣选台", from="ROBOT")
+    @ApiLogger(apiName = "wcs到达拣选台", from = "ROBOT")
     @Transactional(rollbackFor = Exception.class)
     @ResponseBody
-    public AjaxResult arrivedNotice(@RequestBody Map<String,String> map) {
+    public AjaxResult arrivedNotice(@RequestBody Map<String, String> map) {
         //String warehouseCode = "CS0001";
         String taskNo = map.get("taskNo");
         //String port = map.get("port");
@@ -54,18 +54,17 @@ public class ArrivedNoticeController extends BaseController {
         LambdaQueryWrapper<TaskHeader> taskHeaderLambdaQueryWrapper = Wrappers.lambdaQuery();
         taskHeaderLambdaQueryWrapper.eq(TaskHeader::getId, taskNo);
         TaskHeader taskHeader = taskHeaderService.getOne(taskHeaderLambdaQueryWrapper);
-        if(taskHeader != null) {
+        if (taskHeader != null) {
+            int status = taskHeader.getStatus();
+            if (status == QuantityConstant.TASK_STATUS_COMPLETED) {
+                return AjaxResult.success("更新到达站台成功, 任务已经完成,不要重复更新");
+            }
             taskHeader.setStatus(QuantityConstant.TASK_STATUS_ARRIVED_STATION);
         } else {
             return AjaxResult.error("没有找到任务taskNo:" + taskNo);
         }
-        //int taskType = taskHeader.getTaskType();
-        int status = taskHeader.getStatus();
-        if(status == QuantityConstant.TASK_STATUS_COMPLETED) {
-            return AjaxResult.success("更新到达站台成功, 任务已经完成");
-        }
         boolean result = taskHeaderService.updateById(taskHeader);
-        if(!result) {
+        if (!result) {
             return AjaxResult.error("更新到达站台失败");
         }
         return AjaxResult.success("更新到达站台成功");
diff --git a/src/main/java/com/huaheng/pc/inventory/inventoryDetail/service/InventoryDetailService.java b/src/main/java/com/huaheng/pc/inventory/inventoryDetail/service/InventoryDetailService.java
index 742e93c..a4ca425 100644
--- a/src/main/java/com/huaheng/pc/inventory/inventoryDetail/service/InventoryDetailService.java
+++ b/src/main/java/com/huaheng/pc/inventory/inventoryDetail/service/InventoryDetailService.java
@@ -48,6 +48,8 @@ public interface InventoryDetailService extends IService<InventoryDetail> {
      * @return
      */
     List<InventoryDetail> queryReceiptDetailById(Integer inventoryHeaderId);
+
+    InventoryDetail getByIdForUpdate(Integer toInventoryId);
 }
 
 
diff --git a/src/main/java/com/huaheng/pc/inventory/inventoryDetail/service/InventoryDetailServiceImpl.java b/src/main/java/com/huaheng/pc/inventory/inventoryDetail/service/InventoryDetailServiceImpl.java
index cabbfa6..1026621 100644
--- a/src/main/java/com/huaheng/pc/inventory/inventoryDetail/service/InventoryDetailServiceImpl.java
+++ b/src/main/java/com/huaheng/pc/inventory/inventoryDetail/service/InventoryDetailServiceImpl.java
@@ -286,6 +286,14 @@ public class InventoryDetailServiceImpl extends ServiceImpl<InventoryDetailMappe
         return this.list(lam);
     }
 
+    @Override
+    public InventoryDetail getByIdForUpdate(Integer toInventoryId) {
+        LambdaQueryWrapper<InventoryDetail> queryWrapper = new LambdaQueryWrapper<>();
+        return inventoryDetailMapper.selectOne(queryWrapper
+                .eq(InventoryDetail::getId, toInventoryId)
+                .last("FOR UPDATE"));
+    }
+
 }
 
 
diff --git a/src/main/java/com/huaheng/pc/inventory/inventoryHeader/service/InventoryHeaderService.java b/src/main/java/com/huaheng/pc/inventory/inventoryHeader/service/InventoryHeaderService.java
index 7206671..94eaa8d 100644
--- a/src/main/java/com/huaheng/pc/inventory/inventoryHeader/service/InventoryHeaderService.java
+++ b/src/main/java/com/huaheng/pc/inventory/inventoryHeader/service/InventoryHeaderService.java
@@ -63,7 +63,7 @@ public interface InventoryHeaderService extends IService<InventoryHeader> {
      */
     AjaxResult getLocationForecast(String code, int type);
 
-    AjaxResult organizationalTransfers(String materialCode, BigDecimal qty, String beforeCompanyCode, String endCompanyCode);
+    //AjaxResult organizationalTransfers(String materialCode, BigDecimal qty, String beforeCompanyCode, String endCompanyCode);
 
     //判断任务
     boolean getUncompleteReceiptTask(String locationCode);
@@ -87,6 +87,8 @@ public interface InventoryHeaderService extends IService<InventoryHeader> {
     List<Integer> findInventoryHeaderIdsByMaterialCode(String materialCode);
 
     List<InventoryHeaderVO> inventoryToDto(List<InventoryHeader> originList);
+
+    InventoryHeader getByIdForUpdate(Integer inventoryHeaderId);
 }
 
 
diff --git a/src/main/java/com/huaheng/pc/inventory/inventoryHeader/service/InventoryHeaderServiceImpl.java b/src/main/java/com/huaheng/pc/inventory/inventoryHeader/service/InventoryHeaderServiceImpl.java
index e0446be..1700f95 100644
--- a/src/main/java/com/huaheng/pc/inventory/inventoryHeader/service/InventoryHeaderServiceImpl.java
+++ b/src/main/java/com/huaheng/pc/inventory/inventoryHeader/service/InventoryHeaderServiceImpl.java
@@ -35,6 +35,7 @@ import com.huaheng.pc.config.warehouse.domain.Warehouse;
 import com.huaheng.pc.config.zone.domain.Zone;
 import com.huaheng.pc.config.zone.service.ZoneService;
 import com.huaheng.pc.inventory.inventoryDetail.domain.InventoryDetail;
+import com.huaheng.pc.inventory.inventoryDetail.mapper.InventoryDetailMapper;
 import com.huaheng.pc.inventory.inventoryDetail.service.InventoryDetailService;
 import com.huaheng.pc.inventory.inventoryHeader.domain.InventoryHeader;
 import com.huaheng.pc.inventory.inventoryHeader.domain.dto.InventoryHeaderVO;
@@ -57,6 +58,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.Transformer;
 import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -113,10 +115,12 @@ public class InventoryHeaderServiceImpl extends ServiceImpl<InventoryHeaderMappe
     private ShipmentTaskService shipmentTaskService;
     @Resource
     private ShipmentHeaderService shipmentHeaderService;
-
+    @Autowired
+    private InventoryDetailMapper inventoryDetailMapper;
     @Resource
     private InventoryHeaderService inventoryHeaderService;
 
+
     /**
      * 生成移库任务
      */
@@ -432,60 +436,60 @@ public class InventoryHeaderServiceImpl extends ServiceImpl<InventoryHeaderMappe
         return AjaxResult.success(inventoryDetailList);
     }
 
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public AjaxResult organizationalTransfers(String materialCode, BigDecimal qty, String beforeCompanyCode, String endCompanyCode) {
-        /* 查询库存*/
-        LambdaQueryWrapper<InventoryDetail> detailLambdaQueryWrapper = Wrappers.lambdaQuery();
-        detailLambdaQueryWrapper.eq(InventoryDetail::getMaterialCode, materialCode)
-                .eq(InventoryDetail::getCompanyCode, beforeCompanyCode);
-        List<InventoryDetail> detailList = inventoryDetailService.list(detailLambdaQueryWrapper);
-
-        /* 计算该物料总数量*/
-        BigDecimal totalQty = new BigDecimal(0);
-        for (InventoryDetail inventoryDetail : detailList) {
-            totalQty = totalQty.add(inventoryDetail.getQty());
-        }
-
-        if (totalQty.compareTo(qty) < 1) {
-            return AjaxResult.error("库存数量不足");
-        } else {
-            /**
-             *  遍历库存,当数量大于0时,执行调拨
-             *  库存单条记录数量小于调拨数量时,copy实体修改新实体货主编码 添加新库存记录删除原库存、调拨数量减去记录数量
-             *  库存单条记录数量等于调拨数量时,copy实体修改新实体货主编码 添加新库存记录删除原库存、调拨数量减去记录数量
-             *  库存单条记录数量大于调拨数量时,copy实体修改新实体货主编码 库存数量,原实体数量更新,更新两个实体
-             */
-            for (InventoryDetail inventoryDetail : detailList) {
-                if (qty.compareTo(new BigDecimal(0)) == 1) {
-                    if (inventoryDetail.getQty().compareTo(qty) == 1) {
-                        InventoryDetail inventoryDetail1 = inventoryDetail;
-                        inventoryDetail1.setId(null);
-                        inventoryDetail1.setCompanyCode(endCompanyCode);
-                        qty = qty.subtract(inventoryDetail.getQty());
-                        inventoryDetailService.removeById(inventoryDetail.getId());
-                        inventoryDetailService.save(inventoryDetail1);
-                    } else if (inventoryDetail.getQty().compareTo(qty) == 0) {
-                        InventoryDetail inventoryDetail1 = inventoryDetail;
-                        inventoryDetail1.setId(null);
-                        inventoryDetail1.setCompanyCode(endCompanyCode);
-                        qty = qty.subtract(inventoryDetail.getQty());
-                        inventoryDetailService.removeById(inventoryDetail.getId());
-                        inventoryDetailService.save(inventoryDetail1);
-                    } else if (inventoryDetail.getQty().compareTo(qty) == -1) {
-                        InventoryDetail inventoryDetail1 = inventoryDetail;
-                        inventoryDetail1.setQty(qty);
-                        inventoryDetail1.setCompanyCode(endCompanyCode);
-                        inventoryDetail1.setId(null);
-                        inventoryDetail.setQty(inventoryDetail.getQty().subtract(qty));
-                        inventoryDetailService.updateById(inventoryDetail);
-                        inventoryDetailService.save(inventoryDetail1);
-                    }
-                }
-            }
-        }
-        return AjaxResult.success("");
-    }
+    //@Override
+    //@Transactional(rollbackFor = Exception.class)
+    //public AjaxResult organizationalTransfers(String materialCode, BigDecimal qty, String beforeCompanyCode, String endCompanyCode) {
+    //    /* 查询库存*/
+    //    LambdaQueryWrapper<InventoryDetail> detailLambdaQueryWrapper = Wrappers.lambdaQuery();
+    //    detailLambdaQueryWrapper.eq(InventoryDetail::getMaterialCode, materialCode)
+    //            .eq(InventoryDetail::getCompanyCode, beforeCompanyCode);
+    //    List<InventoryDetail> detailList = inventoryDetailService.list(detailLambdaQueryWrapper);
+    //
+    //    /* 计算该物料总数量*/
+    //    BigDecimal totalQty = new BigDecimal(0);
+    //    for (InventoryDetail inventoryDetail : detailList) {
+    //        totalQty = totalQty.add(inventoryDetail.getQty());
+    //    }
+    //
+    //    if (totalQty.compareTo(qty) < 1) {
+    //        return AjaxResult.error("库存数量不足");
+    //    } else {
+    //        /**
+    //         *  遍历库存,当数量大于0时,执行调拨
+    //         *  库存单条记录数量小于调拨数量时,copy实体修改新实体货主编码 添加新库存记录删除原库存、调拨数量减去记录数量
+    //         *  库存单条记录数量等于调拨数量时,copy实体修改新实体货主编码 添加新库存记录删除原库存、调拨数量减去记录数量
+    //         *  库存单条记录数量大于调拨数量时,copy实体修改新实体货主编码 库存数量,原实体数量更新,更新两个实体
+    //         */
+    //        for (InventoryDetail inventoryDetail : detailList) {
+    //            if (qty.compareTo(new BigDecimal(0)) == 1) {
+    //                if (inventoryDetail.getQty().compareTo(qty) == 1) {
+    //                    InventoryDetail inventoryDetail1 = inventoryDetail;
+    //                    inventoryDetail1.setId(null);
+    //                    inventoryDetail1.setCompanyCode(endCompanyCode);
+    //                    qty = qty.subtract(inventoryDetail.getQty());
+    //                    inventoryDetailService.removeById(inventoryDetail.getId());
+    //                    inventoryDetailService.save(inventoryDetail1);
+    //                } else if (inventoryDetail.getQty().compareTo(qty) == 0) {
+    //                    InventoryDetail inventoryDetail1 = inventoryDetail;
+    //                    inventoryDetail1.setId(null);
+    //                    inventoryDetail1.setCompanyCode(endCompanyCode);
+    //                    qty = qty.subtract(inventoryDetail.getQty());
+    //                    inventoryDetailService.removeById(inventoryDetail.getId());
+    //                    inventoryDetailService.save(inventoryDetail1);
+    //                } else if (inventoryDetail.getQty().compareTo(qty) == -1) {
+    //                    InventoryDetail inventoryDetail1 = inventoryDetail;
+    //                    inventoryDetail1.setQty(qty);
+    //                    inventoryDetail1.setCompanyCode(endCompanyCode);
+    //                    inventoryDetail1.setId(null);
+    //                    inventoryDetail.setQty(inventoryDetail.getQty().subtract(qty));
+    //                    inventoryDetailService.updateById(inventoryDetail);
+    //                    inventoryDetailService.save(inventoryDetail1);
+    //                }
+    //            }
+    //        }
+    //    }
+    //    return AjaxResult.success("");
+    //}
 
     @Override
     public boolean getUncompleteReceiptTask(String locationCode) {
@@ -826,6 +830,15 @@ public class InventoryHeaderServiceImpl extends ServiceImpl<InventoryHeaderMappe
                 .collect(Collectors.toList());
     }
 
+    @Override
+    public InventoryHeader getByIdForUpdate(Integer inventoryHeaderId) {
+        LambdaQueryWrapper<InventoryHeader> queryWrapper = new LambdaQueryWrapper<>();
+        return inventoryHeaderMapper.selectOne(queryWrapper
+                .eq(InventoryHeader::getId, inventoryHeaderId)
+                .last("FOR UPDATE"));
+
+    }
+
     /**
      * 找到库存对应所有的入库单
      *
diff --git a/src/main/java/com/huaheng/pc/monitor/job/task/RyTask.java b/src/main/java/com/huaheng/pc/monitor/job/task/RyTask.java
index 05ca24d..cd7223d 100644
--- a/src/main/java/com/huaheng/pc/monitor/job/task/RyTask.java
+++ b/src/main/java/com/huaheng/pc/monitor/job/task/RyTask.java
@@ -183,7 +183,7 @@ public class RyTask extends BaseController {
         //如果上一条出库单未完成,就不执行下一条
         ShipmentHeader header = shipmentHeaderService.getOne(new LambdaQueryWrapper<ShipmentHeader>()
                 .eq(ShipmentHeader::getDeleted, 0)
-                .in(ShipmentHeader::getAutoShipmentStatus, 2)//已自动出库
+                .in(ShipmentHeader::getAutoShipmentStatus, 2, 3)
                 .last("ORDER BY requestedStartDate asc,id asc limit 1"));
         if (header != null) {
             if (header.getLastStatus() < QuantityConstant.SHIPMENT_HEADER_COMPLETED) {//尾状态小于拣货完成(出库单未完成),就不继续走了
@@ -781,8 +781,9 @@ public class RyTask extends BaseController {
     }
 
 
-    //每天计算呆滞库存
+    @Transactional(rollbackFor = Exception.class)
     public void expiringInventoryHandle() {
+        // 获取库存信息
         List<InventoryDetail> inventoryDetails = inventoryDetailService.list();
         if (CollectionUtils.isEmpty(inventoryDetails)) {
             return;
@@ -796,49 +797,49 @@ public class RyTask extends BaseController {
         // 获取所有物料编码
         Set<String> materialCodes = inventoryDetails.stream()
                 .map(InventoryDetail::getMaterialCode).collect(Collectors.toSet());
-
         List<Material> materials = materialService.list(new LambdaQueryWrapper<Material>().in(Material::getCode, materialCodes));
 
         // 创建物料编码和物料对象的映射关系
-        Map<String, Material> materialMap = new HashMap<>();
-        for (Material material : materials) {
-            materialMap.put(material.getCode(), material);
-        }
+        Map<String, Material> materialMap = materials.stream()
+                .collect(Collectors.toMap(Material::getCode, material -> material));
 
-        List<InventoryDetail> updatedInventoryDetails = inventoryDetails.stream()
-                .map(inventoryDetail -> {
-                    // 计算库存的更新时间和当前时间之间的差距
-                    long difference = DateUtils.difference(DateUtils.getNowDate(), inventoryDetail.getRealUpdated());
+        for (InventoryDetail inventoryDetail : inventoryDetails) {
+            // 计算库存的更新时间和当前时间之间的差距
+            long difference = DateUtils.difference(DateUtils.getNowDate(), inventoryDetail.getRealUpdated());
 
-                    // 从 Map 中获取物料信息
-                    Material material = materialMap.get(inventoryDetail.getMaterialCode());
-                    if (material == null) {
-                        return inventoryDetail;
-                    }
+            // 从 Map 中获取物料信息
+            Material material = materialMap.get(inventoryDetail.getMaterialCode());
+            if (material == null) {
+                continue;
+            }
 
-                    int materialDays = days;
-                    if (Objects.equals(material.getIsFlammable(), "是")) {
-                        materialDays = Math.min(materialDays, daysFlammable);
-                    } else if (Objects.equals(material.getIsBatch(), "是")) {
-                        materialDays = Math.min(materialDays, daysBatch);
-                    }
+            int materialDays = days;
+            if (Objects.equals(material.getIsFlammable(), "是")) {
+                materialDays = Math.min(materialDays, daysFlammable);
+            } else if (Objects.equals(material.getIsBatch(), "是")) {
+                materialDays = Math.min(materialDays, daysBatch);
+            }
 
-                    // 计算呆滞时长
-                    int differenceDay = DateUtils.secondToDays(difference);
-                    int deadTime = Math.max(differenceDay - materialDays, 0);
-                    if (deadTime == 0) {
-                        inventoryDetail.setDeadTime("");
-                    } else {
-                        inventoryDetail.setDeadTime(deadTime + "天");
-                    }
+            // 计算呆滞时长
+            int differenceDay = DateUtils.secondToDays(difference);
+            int deadTime = Math.max(differenceDay - materialDays, 0);
 
-                    return inventoryDetail;
-                })
-                .collect(Collectors.toList());
+            if (deadTime == 0 && !inventoryDetail.getDeadTime().isEmpty()) {
+                LambdaUpdateWrapper<InventoryDetail> updateWrapper = Wrappers.lambdaUpdate();
+                updateWrapper
+                        .eq(InventoryDetail::getId, inventoryDetail.getId())
+                        .set(InventoryDetail::getDeadTime, "");
+                inventoryDetailService.update(updateWrapper);
+            }
 
-        // 保存更新后的库存信息
-        inventoryDetailService.updateBatchById(updatedInventoryDetails);
+            if (deadTime > 0) {
+                LambdaUpdateWrapper<InventoryDetail> updateWrapper = Wrappers.lambdaUpdate();
+                updateWrapper
+                        .eq(InventoryDetail::getId, inventoryDetail.getId())
+                        .set(InventoryDetail::getDeadTime, deadTime + "天");
+                inventoryDetailService.update(updateWrapper);
+            }
+        }
     }
 
-
 }
diff --git a/src/main/java/com/huaheng/pc/shipment/shipmentContainerHeader/service/ShipmentContainerHeaderServiceImpl.java b/src/main/java/com/huaheng/pc/shipment/shipmentContainerHeader/service/ShipmentContainerHeaderServiceImpl.java
index 178e445..1d1ed2a 100644
--- a/src/main/java/com/huaheng/pc/shipment/shipmentContainerHeader/service/ShipmentContainerHeaderServiceImpl.java
+++ b/src/main/java/com/huaheng/pc/shipment/shipmentContainerHeader/service/ShipmentContainerHeaderServiceImpl.java
@@ -55,6 +55,8 @@ import com.huaheng.pc.shipment.shipmentContainerHeader.domain.ShipmentContainerH
 import com.huaheng.pc.shipment.shipmentContainerHeader.mapper.ShipmentContainerHeaderMapper;
 import org.springframework.transaction.annotation.Transactional;
 
+import static com.huaheng.common.constant.QuantityConstant.*;
+
 @Service
 public class ShipmentContainerHeaderServiceImpl extends ServiceImpl<ShipmentContainerHeaderMapper, ShipmentContainerHeader> implements ShipmentContainerHeaderService {
 
@@ -193,12 +195,15 @@ public class ShipmentContainerHeaderServiceImpl extends ServiceImpl<ShipmentCont
         } else if (i < 0) {
             throw new ServiceException("出库数量不能大于单据数量!");
         }
-
-        //限制组盘数量
-        AjaxResult ajaxResult = limitCombinationCount(inventoryDetail);
-        if (ajaxResult.hasErr()) {
-            throw new ServiceException(ajaxResult.getMsg());
+        //限制立库组盘数量
+        if (container.getFlat() == null || container.getFlat() != 1) {
+            AjaxResult ajaxResult = limitCombinationCount(inventoryDetail);
+            if (ajaxResult.hasErr()) {
+                throw new ServiceException(ajaxResult.getMsg());
+            }
         }
+
+
         shipmentDetailService.saveOrUpdate(shipmentDetail);
 
         //自动判定出库任务状态,根据库存数量减去预定库存相等就是整盘出--预计任务状态
@@ -609,17 +614,17 @@ public class ShipmentContainerHeaderServiceImpl extends ServiceImpl<ShipmentCont
             }
             inventoryList.removeAll(removeInventoryList);
             if (inventoryList.isEmpty() && lock) {
-                return AjaxResult.error("'物料名称:" + item.getMaterialName() + ",物料编码:" + item.getMaterialCode() + "' 所在托盘全部处于锁定状态,请完成或取消任务后再进行组盘");
+                return AjaxResult.error("'物料名称:" + item.getMaterialName() + ",物料编码:" + item.getMaterialCode() + "' 所在托盘全部处于锁定状态,请完成或取消任务或入库组盘后再进行组盘");
             }
 
-            if (inventoryList.isEmpty() && item.getWaveId() != 0) {
-                Wave wave = waveService.getById(item.getWaveId());
-                wave.setStatus(QuantityConstant.WAVE_STATUS_ERROR);
-                wave.setCurrentWaveStep(QuantityConstant.WAVE_STEP_ERROR);
-                wave.setLastWaveStep(QuantityConstant.WAVE_STEP_BUILD);
-                waveService.updateById(wave);
-                throw new ServiceException("主单为" + item.getShipmentCode() + "子单id为" + item.getId() + "的单据没有库存,波次失败");
-            }
+            //if (inventoryList.isEmpty() && item.getWaveId() != 0) {
+            //    Wave wave = waveService.getById(item.getWaveId());
+            //    wave.setStatus(QuantityConstant.WAVE_STATUS_ERROR);
+            //    wave.setCurrentWaveStep(QuantityConstant.WAVE_STEP_ERROR);
+            //    wave.setLastWaveStep(QuantityConstant.WAVE_STEP_BUILD);
+            //    waveService.updateById(wave);
+            //    throw new ServiceException("主单为" + item.getShipmentCode() + "子单id为" + item.getId() + "的单据没有库存,波次失败");
+            //}
             if (inventoryList.isEmpty()) {
                 num = num + 1;
             } else {
@@ -629,12 +634,13 @@ public class ShipmentContainerHeaderServiceImpl extends ServiceImpl<ShipmentCont
                         break;
                     }
 
-                    //限制组盘数量
-                    AjaxResult ajaxResult = limitCombinationCount(inventory);
-                    if (ajaxResult.hasErr()) {
-                        throw new ServiceException(ajaxResult.getMsg());
+                    //限制立库组盘数量
+                    if (inventory.getIsFlatWarehouse() == 0) {
+                        AjaxResult ajaxResult = limitCombinationCount(inventory);
+                        if (ajaxResult.hasErr()) {
+                            throw new ServiceException(ajaxResult.getMsg());
+                        }
                     }
-
                     BigDecimal inventoryQty = inventory.getQty().subtract(inventory.getTaskQty());
                     ShipmentCombinationModel shipmentCombination = new ShipmentCombinationModel();
                     shipmentCombination.setInventoryDetailId(inventory.getId());
@@ -668,25 +674,52 @@ public class ShipmentContainerHeaderServiceImpl extends ServiceImpl<ShipmentCont
         // 获取巷道信息
         String roadway = location.getRoadway();
 
-        // 使用三元运算符根据巷道信息确定限制数量
-        int limit = roadway.equals(QuantityConstant.DYNAMIC_ROADWAY) ?
-                Integer.parseInt(configService.getKey("shipmentTaskBy5RoadLimit")) :
-                Integer.parseInt(configService.getKey("shipmentContainerTaskLimit"));
-
-        // 使用三元运算符根据巷道信息确定任务数量
-        int shipmentTaskCount = roadway.equals(QuantityConstant.DYNAMIC_ROADWAY) ?
-                taskHeaderService.getShipmentTaskBy5Road() :
-                taskHeaderService.getShipmentContainerTask(roadway);
+        LambdaQueryWrapper<Location> wrapper = Wrappers.lambdaQuery();
+        wrapper.eq(Location::getRoadway, roadway)
+                .eq(Location::getStatus, STATUS_LOCATION_EMPTY)
+                .eq(Location::getHigh, location.getHigh())
+                .eq(Location::getContainerCode, "")
+                .eq(Location::getSelfCreated, NO_TSELFCREATED)
+                .eq(Location::getOnlyEmptyContainer, NO_EMPTY_CONTAINER_LOCATION);
+        List<Location> locationList = locationService.list(wrapper);
+
+        if (locationList.size() < 3) {
+            return AjaxResult.error("该库存出库可能无法回库了");
+        }
 
-        // 检查任务数量是否超过限制
-        if (shipmentTaskCount >= limit) {
-            // 根据巷道信息拼接错误信息
-            String errorMessage = roadway.equals(QuantityConstant.DYNAMIC_ROADWAY) ?
-                    "5号巷道不能存在超过" + limit + "个组盘和任务" :
-                    "不能存在超过" + limit + "个组盘和任务";
-            return AjaxResult.error(errorMessage);
+        List<Location> availableLocations = new ArrayList<>();
+        for (Location location1 : locationList) {
+            // 如果库位内侧没有未完成的任务,则将其添加到可用库位列表中
+            if (taskHeaderService.getUncompleteTaskInNear(location1) == 0) {
+                availableLocations.add(location1);
+            }
+            // 如果已经找到了 3 个可用库位,则直接返回成功
+            if (availableLocations.size() >= 3) {
+                return AjaxResult.success();
+            }
         }
-        return AjaxResult.success();
+
+        return AjaxResult.error("该库存出库可能无法回库了,可能是空闲库位内/外测有任务了");
+
+
+        //// 使用三元运算符根据巷道信息确定限制数量
+        //int limit = roadway.equals(QuantityConstant.DYNAMIC_ROADWAY) ?
+        //        Integer.parseInt(configService.getKey("shipmentTaskBy5RoadLimit")) :
+        //        Integer.parseInt(configService.getKey("shipmentContainerTaskLimit"));
+        //
+        //// 使用三元运算符根据巷道信息确定任务数量
+        //int shipmentTaskCount = roadway.equals(QuantityConstant.DYNAMIC_ROADWAY) ?
+        //        taskHeaderService.getShipmentTaskBy5Road() :
+        //        taskHeaderService.getShipmentContainerTask(roadway);
+        //
+        //// 检查任务数量是否超过限制
+        //if (shipmentTaskCount >= limit) {
+        //    // 根据巷道信息拼接错误信息
+        //    String errorMessage = roadway.equals(QuantityConstant.DYNAMIC_ROADWAY) ?
+        //            "5号巷道不能存在超过" + limit + "个组盘和任务" :
+        //            "不能存在超过" + limit + "个组盘和任务";
+        //    return AjaxResult.error(errorMessage);
+        //}
     }
 
     /**
diff --git a/src/main/java/com/huaheng/pc/shipment/shipmentHeader/controller/ShipmentHeaderController.java b/src/main/java/com/huaheng/pc/shipment/shipmentHeader/controller/ShipmentHeaderController.java
index 8f52f6c..94006b4 100644
--- a/src/main/java/com/huaheng/pc/shipment/shipmentHeader/controller/ShipmentHeaderController.java
+++ b/src/main/java/com/huaheng/pc/shipment/shipmentHeader/controller/ShipmentHeaderController.java
@@ -562,19 +562,19 @@ public class ShipmentHeaderController extends BaseController {
         return prefix + "/addWave";
     }
 
-    /**
-     * 查询波次列表
-     */
-    @RequiresPermissions("shipment:bill:wave")
-    //@Log(title = "出库-出库单", operating = "查询库区列表", action = BusinessType.GRANT)
-    @PostMapping("/waveList")
-    @ResponseBody
-    public TableDataInfo waveList() {
-        LambdaQueryWrapper<WaveMaster> lam = Wrappers.lambdaQuery();
-        lam.eq(WaveMaster::getWarehouseCode, ShiroUtils.getWarehouseCode());
-        List<WaveMaster> waveMasters = waveMasterService.list(lam);
-        return getDataTable(waveMasters);
-    }
+    ///**
+    // * 查询波次列表
+    // */
+    //@RequiresPermissions("shipment:bill:wave")
+    ////@Log(title = "出库-出库单", operating = "查询库区列表", action = BusinessType.GRANT)
+    //@PostMapping("/waveList")
+    //@ResponseBody
+    //public TableDataInfo waveList() {
+    //    LambdaQueryWrapper<WaveMaster> lam = Wrappers.lambdaQuery();
+    //    lam.eq(WaveMaster::getWarehouseCode, ShiroUtils.getWarehouseCode());
+    //    List<WaveMaster> waveMasters = waveMasterService.list(lam);
+    //    return getDataTable(waveMasters);
+    //}
 
 
     /**
diff --git a/src/main/java/com/huaheng/pc/shipment/shipmentHeader/service/ShipmentHeaderServiceImpl.java b/src/main/java/com/huaheng/pc/shipment/shipmentHeader/service/ShipmentHeaderServiceImpl.java
index d94b624..5979988 100644
--- a/src/main/java/com/huaheng/pc/shipment/shipmentHeader/service/ShipmentHeaderServiceImpl.java
+++ b/src/main/java/com/huaheng/pc/shipment/shipmentHeader/service/ShipmentHeaderServiceImpl.java
@@ -16,6 +16,8 @@ import com.huaheng.framework.web.domain.AjaxResult;
 import com.huaheng.framework.web.service.ConfigService;
 import com.huaheng.pc.config.address.service.AddressService;
 import com.huaheng.pc.config.company.service.CompanyService;
+import com.huaheng.pc.config.container.domain.Container;
+import com.huaheng.pc.config.container.service.ContainerService;
 import com.huaheng.pc.config.customer.domain.Customer;
 import com.huaheng.pc.config.customer.service.CustomerServiceImpl;
 import com.huaheng.pc.config.location.domain.Location;
@@ -25,6 +27,8 @@ import com.huaheng.pc.config.shipmentType.service.ShipmentTypeService;
 import com.huaheng.pc.inventory.inventoryDetail.domain.InventoryDetail;
 import com.huaheng.pc.inventory.inventoryDetail.service.InventoryDetailService;
 import com.huaheng.pc.receipt.receiptHeader.domain.ReceiptHeader;
+import com.huaheng.pc.shipment.shipmentContainerDetail.domain.ShipmentContainerDetail;
+import com.huaheng.pc.shipment.shipmentContainerDetail.service.ShipmentContainerDetailService;
 import com.huaheng.pc.shipment.shipmentContainerHeader.domain.ShipmentContainerHeader;
 import com.huaheng.pc.shipment.shipmentContainerHeader.service.ShipmentContainerHeaderService;
 import com.huaheng.pc.shipment.shipmentDetail.domain.ShipmentDetail;
@@ -62,7 +66,10 @@ import java.util.stream.Collectors;
 public class ShipmentHeaderServiceImpl extends ServiceImpl<ShipmentHeaderMapper, ShipmentHeader> implements ShipmentHeaderService {
     @Resource
     private ShipmentTaskService shipmentTaskService;
-
+    @Resource
+    private ShipmentContainerDetailService shipmentContainerDetailService;
+    @Resource
+    private ContainerService containerService;
     @Resource
     private ConfigService configService;
     @Resource
@@ -573,20 +580,19 @@ public class ShipmentHeaderServiceImpl extends ServiceImpl<ShipmentHeaderMapper,
 
     @Override
     public void autoShipmentExecute(ShipmentHeader shipmentHeader) {
-        shipmentHeader.setAutoShipmentStatus(4);
+        shipmentHeader.setAutoShipmentStatus(3);
         shipmentHeader.setErrorMsg("自动组盘过程中程序错误,请手动组盘");
         updateById(shipmentHeader);
         //自动组盘
         AjaxResult containerResult = shipmentContainerHeaderService.autoCombination(shipmentHeader.getCode(), true);
-        //如果出库单明细全部为出库组盘,就不改状态了,找一些其他地方是不是也修改了,这个修改了应该就直接返回了呀,为什么还完成了单据呢
         if (!updateShipmentErrorMsg(containerResult, shipmentHeader)) {
             return;
         }
-        shipmentHeader.setAutoShipmentStatus(4);
+
+        //生成任务
+        shipmentHeader.setAutoShipmentStatus(3);
         shipmentHeader.setErrorMsg("自生成任务过程中程序错误,请手动生成任务");
         updateById(shipmentHeader);
-
-
         List<ShipmentContainerHeader> shipmentContainerHeaders = shipmentContainerHeaderService.list(new LambdaQueryWrapper<ShipmentContainerHeader>()
                 .eq(ShipmentContainerHeader::getStatus, QuantityConstant.SHIPMENT_CONTAINER_BUILD));
         for (ShipmentContainerHeader item : shipmentContainerHeaders) {
@@ -598,21 +604,20 @@ public class ShipmentHeaderServiceImpl extends ServiceImpl<ShipmentHeaderMapper,
             }
         }
 
-        //生成任务
         //List<Integer> ids = (List<Integer>) containerResult.getData();
         //AjaxResult taskResult = shipmentContainerHeaderService.createAutoTask(ids);
         //if (!updateShipmentErrorMsg(taskResult, shipmentHeader)) {
         //    return;
         //}
-        
+
         //自动打印
         int isPrint = Integer.parseInt(configService.getKey(QuantityConstant.AUTO_SHIPMENT_PRINT));
         if (isPrint == 1) {
-            shipmentHeader.setAutoShipmentStatus(4);
+            shipmentHeader.setAutoShipmentStatus(3);
             shipmentHeader.setErrorMsg("自动打印过程中程序错误,请手动打印");
             updateById(shipmentHeader);
             AjaxResult reportResult = shipmentHeaderService.autoReportShipment(-1, shipmentHeader.getCode(), "1");
-            if (updateShipmentErrorMsg(reportResult, shipmentHeader)) {
+            if (!updateShipmentErrorMsg(reportResult, shipmentHeader)) {
                 return;
             }
         }
@@ -620,7 +625,7 @@ public class ShipmentHeaderServiceImpl extends ServiceImpl<ShipmentHeaderMapper,
         //自动出库完成
         shipmentHeader.setAutoShipmentStatus(2);
         shipmentHeader.setErrorMsg("");
-        updateById(shipmentHeader);
+        shipmentHeaderService.updateById(shipmentHeader);
     }
 
 
@@ -632,7 +637,7 @@ public class ShipmentHeaderServiceImpl extends ServiceImpl<ShipmentHeaderMapper,
                 errorMsg = errorMsg.substring(0, 500);
             }
             shipmentHeader.setErrorMsg(errorMsg);
-            updateById(shipmentHeader);
+            shipmentHeaderService.updateById(shipmentHeader);
             return false;
         }
         return true;
diff --git a/src/main/java/com/huaheng/pc/task/taskHeader/service/ReceiptTaskService.java b/src/main/java/com/huaheng/pc/task/taskHeader/service/ReceiptTaskService.java
index 653fb3d..4b8a720 100644
--- a/src/main/java/com/huaheng/pc/task/taskHeader/service/ReceiptTaskService.java
+++ b/src/main/java/com/huaheng/pc/task/taskHeader/service/ReceiptTaskService.java
@@ -356,9 +356,12 @@ public class ReceiptTaskService {
                 List<InventoryDetail> inventoryDetails = inventoryDetailService.list(new LambdaQueryWrapper<InventoryDetail>().eq(InventoryDetail::getInventoryHeaderId, inventoryHeader.getId()));
                 if (inventoryDetails != null && !inventoryDetails.isEmpty()) {
                     for (InventoryDetail inventoryDetail : inventoryDetails) {
-                        inventoryDetail.setLocationCode(toLocation.getCode());
-                        inventoryDetail.setZoneCode(toLocation.getZoneCode());
-                        if (!inventoryDetailService.updateById(inventoryDetail)) {
+                        LambdaUpdateWrapper<InventoryDetail> updateWrapper = Wrappers.lambdaUpdate();
+                        updateWrapper
+                                .eq(InventoryDetail::getId, inventoryDetail.getId())
+                                .set(InventoryDetail::getLocationCode, toLocation.getCode())
+                                .set(InventoryDetail::getZoneCode, toLocation.getZoneCode());
+                        if (!inventoryDetailService.update(updateWrapper)) {
                             throw new ServiceException("补充入库,更新库存明细失败");
                         }
                     }
diff --git a/src/main/java/com/huaheng/pc/task/taskHeader/service/ShipmentTaskService.java b/src/main/java/com/huaheng/pc/task/taskHeader/service/ShipmentTaskService.java
index 670b957..c936b12 100644
--- a/src/main/java/com/huaheng/pc/task/taskHeader/service/ShipmentTaskService.java
+++ b/src/main/java/com/huaheng/pc/task/taskHeader/service/ShipmentTaskService.java
@@ -365,8 +365,11 @@ public class ShipmentTaskService {
                 List<InventoryDetail> inventoryDetails = inventoryDetailService.list(new LambdaQueryWrapper<InventoryDetail>().eq(InventoryDetail::getInventoryHeaderId, inventoryHeader.getId()));
                 if (inventoryDetails != null && !inventoryDetails.isEmpty()) {
                     for (InventoryDetail inventoryDetail : inventoryDetails) {
-                        inventoryDetail.setLocationCode(task.getToLocation());
-                        if (!inventoryDetailService.updateById(inventoryDetail)) {
+
+                        LambdaUpdateWrapper<InventoryDetail> updateWrapper = Wrappers.lambdaUpdate();
+                        updateWrapper.eq(InventoryDetail::getId, inventoryDetail.getId())
+                                .set(InventoryDetail::getLocationCode, task.getToLocation());
+                        if (!inventoryDetailService.update(updateWrapper)) {
                             throw new ServiceException("完成出库任务,库存修改目标库位时失败" + inventoryDetail.getId());
                         }
                     }
@@ -381,13 +384,14 @@ public class ShipmentTaskService {
                 //获取出库组盘明细
                 ShipmentContainerDetail shipmentContainerDetail = shipmentContainerDetailService.getById(taskDetail.getAllocationId());
                 //获取对应库存记录
-                InventoryDetail inventoryDetail = inventoryDetailService.getById(taskDetail.getToInventoryId());
+                InventoryDetail inventoryDetail = inventoryDetailService.getByIdForUpdate(taskDetail.getToInventoryId());
                 if (inventoryDetail == null) {
                     throw new ServiceException("任务明细对应的库存ID【" + taskDetail.getToInventoryId().toString() + "】不存在!");
                 }
                 inventoryDetail.setLastUpdatedBy(taskDetail.getLastUpdatedBy());
                 //减扣库存单
-                inventoryHeader = inventoryHeaderService.getById(inventoryDetail.getInventoryHeaderId());
+                // 使用悲观锁查询库存主表
+                inventoryHeader = inventoryHeaderService.getByIdForUpdate(inventoryDetail.getInventoryHeaderId());
 
                 //扣减库存明细
                 inventoryDetail.setTaskQty(inventoryDetail.getTaskQty().subtract(taskDetail.getQty()));
diff --git a/src/main/java/com/huaheng/pc/task/taskHeader/service/TransferTaskService.java b/src/main/java/com/huaheng/pc/task/taskHeader/service/TransferTaskService.java
index ac3c10f..281bb58 100644
--- a/src/main/java/com/huaheng/pc/task/taskHeader/service/TransferTaskService.java
+++ b/src/main/java/com/huaheng/pc/task/taskHeader/service/TransferTaskService.java
@@ -191,7 +191,7 @@ public class TransferTaskService {
             taskDetail.setFromInventoryId(inventoryDetail.getId());
             taskDetail.setToInventoryId(inventoryDetail.getId());
             taskDetail.setLastUpdatedBy(ShiroUtils.getName());
-            if (!taskDetailService.save(taskDetail) || !inventoryDetailService.updateById(inventoryDetail)) {
+            if (!taskDetailService.save(taskDetail)) {
                 throw new ServiceException("创建任务失败");
             }
         }
diff --git a/src/main/java/com/huaheng/pc/task/taskHeader/service/WorkTaskService.java b/src/main/java/com/huaheng/pc/task/taskHeader/service/WorkTaskService.java
index 340d871..76f58ac 100644
--- a/src/main/java/com/huaheng/pc/task/taskHeader/service/WorkTaskService.java
+++ b/src/main/java/com/huaheng/pc/task/taskHeader/service/WorkTaskService.java
@@ -769,8 +769,7 @@ public class WorkTaskService {
                 taskDetail.setMaterialName(inventoryDetail.getMaterialName());
                 taskDetail.setMaterialSpec(inventoryDetail.getMaterialSpec());
                 taskDetail.setMaterialUnit(inventoryDetail.getMaterialUnit());
-                if (!taskDetailService.save(taskDetail) ||
-                        !inventoryDetailService.updateById(inventoryDetail)) {
+                if (!taskDetailService.save(taskDetail)) {
                     throw new ServiceException("任务创建失败");
                 }
             }
@@ -843,7 +842,7 @@ public class WorkTaskService {
             if (inventoryDetail.getId().equals(inventoryDetail2.getId())) {
                 taskDetail.setInventoryTransactionId(inventoryTransactionId);
             }
-            if (!taskDetailService.save(taskDetail) || !inventoryDetailService.updateById(inventoryDetail)) {
+            if (!taskDetailService.save(taskDetail)) {
                 throw new ServiceException("任务创建失败");
             }
         }
@@ -919,8 +918,13 @@ public class WorkTaskService {
             List<InventoryDetail> inventoryDetails = inventoryDetailService.list(lambdaQueryWrapper2);
             if (inventoryDetails != null && !inventoryDetails.isEmpty()) {
                 for (InventoryDetail inventoryDetail : inventoryDetails) {
-                    inventoryDetail.setLocationCode(taskHeader.getToLocation());
-                    inventoryDetailService.updateById(inventoryDetail);
+                    LambdaUpdateWrapper<InventoryDetail> updateWrapper = Wrappers.lambdaUpdate();
+                    updateWrapper.eq(InventoryDetail::getId, inventoryDetail.getId())
+                            .set(InventoryDetail::getLocationCode, taskHeader.getToLocation());
+                    if (!inventoryDetailService.update(updateWrapper)) {
+                        throw new ServiceException("库存修改目标库位时失败" + inventoryDetail.getId());
+                    }
+
                 }
                 containerService.updateStatus(containerCode, QuantityConstant.STATUS_CONTAINER_SOME, warehouseCode);
             }
diff --git a/src/main/resources/templates/shipment/shipmentHeader/shipmentHeader.html b/src/main/resources/templates/shipment/shipmentHeader/shipmentHeader.html
index cb957fa..ed2cd72 100644
--- a/src/main/resources/templates/shipment/shipmentHeader/shipmentHeader.html
+++ b/src/main/resources/templates/shipment/shipmentHeader/shipmentHeader.html
@@ -289,10 +289,10 @@
                             <i class="fa fa-code-fork"></i> 自动组盘
                         </a>
 
-                        <a class="btn btn-outline btn-primary btn-rounded auto-shipment-task" onclick="Toshipping(2)"
-                           shiro:hasPermission="shipment:shippingCombination:combination">
-                            <i class="fa fa-code-fork"></i> 自动组盘并生成任务
-                        </a>
+                        <!--                        <a class="btn btn-outline btn-primary btn-rounded auto-shipment-task" onclick="Toshipping(2)"-->
+                        <!--                           shiro:hasPermission="shipment:shippingCombination:combination">-->
+                        <!--                            <i class="fa fa-code-fork"></i> 自动组盘并生成任务-->
+                        <!--                        </a>-->
                         <a class="btn btn-outline btn-primary btn-rounded auto-shipment" onclick="Toshipping(3)"
                            shiro:hasPermission="shipment:shippingCombination:combination">
                             <i class="fa fa-code-fork"></i> 自动平库组盘
--
libgit2 0.22.2