浏览代码

分拣组盘、分拣出库、反拣组盘、反拣出库开发

zhangxin 1 年之前
父节点
当前提交
cd7dd4bb74
共有 24 个文件被更改,包括 794 次插入277 次删除
  1. 0 0
      base_sql/pallet_sql/yonghu_ddl_20230921.sql
  2. 21 0
      base_sql/pallet_sql/yonghu_dml_20230921.sql
  3. 0 0
      base_sql/quartz.sql
  4. 0 0
      base_sql/ry_20210908.sql
  5. 31 11
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/warewms/pda/PdaController.java
  6. 5 5
      ruoyi-admin/src/main/resources/application-dev.yml
  7. 3 2
      warewms-ams/src/main/java/com/ruoyi/ams/asn/dto/UnbindWmsBoxDTO.java
  8. 3 2
      warewms-ams/src/main/java/com/ruoyi/ams/inv/dto/InvLotAttPalletTotalDTO.java
  9. 44 4
      warewms-ams/src/main/java/com/ruoyi/ams/inv/service/IInvLotAttService.java
  10. 10 7
      warewms-ams/src/main/java/com/ruoyi/ams/inv/service/IInvLotLocIdService.java
  11. 95 11
      warewms-ams/src/main/java/com/ruoyi/ams/inv/service/impl/InvLotAttServiceImpl.java
  12. 12 0
      warewms-ams/src/main/java/com/ruoyi/ams/inv/service/impl/InvLotLocIdServiceImpl.java
  13. 2 6
      warewms-ams/src/main/java/com/ruoyi/ams/order/domain/PalletMatchLog.java
  14. 25 0
      warewms-ams/src/main/java/com/ruoyi/ams/order/dto/GroupDiskConvertDTO.java
  15. 4 4
      warewms-ams/src/main/java/com/ruoyi/ams/order/dto/PdaGroupDiskDTO.java
  16. 13 0
      warewms-ams/src/main/java/com/ruoyi/ams/order/dto/ReversePickConvertDTO.java
  17. 38 0
      warewms-ams/src/main/java/com/ruoyi/ams/order/dto/ReversePickGroupDiskDTO.java
  18. 17 0
      warewms-ams/src/main/java/com/ruoyi/ams/order/dto/ReversePickInventoryMatchDTO.java
  19. 7 1
      warewms-ams/src/main/java/com/ruoyi/ams/order/service/IPalletMatchLogService.java
  20. 16 4
      warewms-ams/src/main/java/com/ruoyi/ams/order/service/IWmsDocOrderDetailsService.java
  21. 42 17
      warewms-ams/src/main/java/com/ruoyi/ams/order/service/IWmsDocOrderHeaderService.java
  22. 16 1
      warewms-ams/src/main/java/com/ruoyi/ams/order/service/impl/PalletMatchLogServiceImpl.java
  23. 31 12
      warewms-ams/src/main/java/com/ruoyi/ams/order/service/impl/WmsDocOrderDetailsServiceImpl.java
  24. 359 190
      warewms-ams/src/main/java/com/ruoyi/ams/order/service/impl/WmsDocOrderHeaderServiceImpl.java

+ 0 - 0
base_sql/pallet_sql/yonghu_ddl_20230921.sql


+ 21 - 0
base_sql/pallet_sql/yonghu_dml_20230921.sql

@@ -0,0 +1,21 @@
+CREATE TABLE if not exists `pallet_match_log`
+(
+    `id`          varchar(255) NOT NULL COMMENT 'id',
+    `pallet_no`   varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '托盘',
+    `sku`         varchar(255)                                                  DEFAULT NULL COMMENT '物料/产品',
+    `total_qty`   varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '数量',
+    `order_nos`   varchar(2000)                                                 DEFAULT NULL COMMENT '所扫描出库单(多出库单以,隔开)',
+    `location_id` varchar(255)                                                  DEFAULT NULL COMMENT '库位id',
+    `agv_no`      varchar(255)                                                  DEFAULT NULL COMMENT 'agv车号',
+    `remark`      varchar(255)                                                  DEFAULT NULL COMMENT '备注',
+    `userdefine1` varchar(255)                                                  DEFAULT NULL,
+    `userdefine2` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci       DEFAULT NULL,
+    `userdefine3` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci       DEFAULT NULL,
+    `userdefine4` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci       DEFAULT NULL,
+    `userdefine5` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci       DEFAULT NULL,
+    `create_by`   varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT '' COMMENT '创建者',
+    `create_time` datetime                                                      DEFAULT NULL COMMENT '创建时间',
+    `update_by`   varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT '' COMMENT '更新者',
+    `update_time` datetime                                                      DEFAULT NULL COMMENT '更新时间',
+    PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='托盘匹配记录';

sql/quartz.sql → base_sql/quartz.sql


sql/ry_20210908.sql → base_sql/ry_20210908.sql


+ 31 - 11
ruoyi-admin/src/main/java/com/ruoyi/web/controller/warewms/pda/PdaController.java

@@ -4,7 +4,7 @@ import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.ruoyi.ams.asn.domain.WmsDocAsnDetails;
 import com.ruoyi.ams.asn.domain.WmsDocAsnHeader;
-import com.ruoyi.ams.asn.dto.UnbindWmsBoxDTO;
+import com.ruoyi.ams.asn.dto.UnbindDTO;
 import com.ruoyi.ams.asn.form.PaForm;
 import com.ruoyi.ams.asn.form.StockForm;
 import com.ruoyi.ams.asn.form.StockingListForm;
@@ -33,6 +33,7 @@ import com.ruoyi.ams.lineCall.service.ILineCallService;
 import com.ruoyi.ams.order.domain.ActAllocationDetails;
 import com.ruoyi.ams.order.domain.WmsDocOrderHeader;
 import com.ruoyi.ams.order.dto.PdaGroupDiskDTO;
+import com.ruoyi.ams.order.dto.ReversePickGroupDiskDTO;
 import com.ruoyi.ams.order.form.*;
 import com.ruoyi.ams.order.service.IActAllocationDetailsService;
 import com.ruoyi.ams.order.service.IWmsDocOrderHeaderService;
@@ -532,7 +533,17 @@ public class PdaController {
      */
     @PostMapping("/docOrder/inventoryMatching")
     public AjaxResult inventoryMatch(@RequestParam String orderNos) {
-        return AjaxResult.success(wmsDocOrderHeaderService.inventoryMatch(orderNos));
+        return AjaxResult.success(wmsDocOrderHeaderService.syncInventoryMatch(orderNos));
+    }
+
+    /**
+     * 反拣出库
+     * @param orderNos
+     * @return
+     */
+    @PostMapping("/docOrder/reversePickInventoryMatch")
+    public AjaxResult reversePickInventoryMatch(@RequestParam String orderNos) {
+        return AjaxResult.success(wmsDocOrderHeaderService.syncPdaReversePickInventoryMatch(orderNos));
     }
 
     /**
@@ -546,28 +557,37 @@ public class PdaController {
     }
 
     /**
-     * 组盘
-     * PDA备货组盘(传出库单号)
+     * 理货备货
+     * 1.PDA备货组盘(传出库单号) 2.PDA分拣组盘(不传出库单号)
      *
      * @return
      */
     @PostMapping("/docOrder/pdaGroupDisk")
     public AjaxResult pdaGroupDisk(@RequestBody PdaGroupDiskDTO pdaGroupDiskDTO) {
-        return wmsDocOrderHeaderService.syncPdaGroupDiskBH(pdaGroupDiskDTO);
+        return wmsDocOrderHeaderService.syncPdaGroupDisk(pdaGroupDiskDTO);
     }
 
-
     /**
-     * PDA解绑物料并发控制
-     * @param unbindWmsBoxDTO
+     * 反拣组盘
+     * PDA备货组盘(传出库单号)
+     *
      * @return
      */
-    @PostMapping("/docOrder/unbindWmsBox")
-    public AjaxResult unbindWmsBox(@RequestBody UnbindWmsBoxDTO unbindWmsBoxDTO) {
-        return wmsDocOrderHeaderService.syncUnbindWmsBox(unbindWmsBoxDTO);
+    @PostMapping("/docOrder/pdaReversePickGroupDisk")
+    public AjaxResult pdaReversePickGroupDisk(@RequestBody ReversePickGroupDiskDTO reversePickGroupDiskDTO) {
+        return wmsDocOrderHeaderService.syncPdaReversePickGroupDisk(reversePickGroupDiskDTO);
     }
 
 
+    /**
+     * PDA解绑物料并发控制
+     * @param unbindDTO
+     * @return
+     */
+    @PostMapping("/docOrder/pdaUnbind")
+    public AjaxResult pdaUnbind(@RequestBody UnbindDTO unbindDTO) {
+        return wmsDocOrderHeaderService.syncPdaUnbind(unbindDTO);
+    }
 
     /**
      * 分拣出库

+ 5 - 5
ruoyi-admin/src/main/resources/application-dev.yml

@@ -6,9 +6,9 @@ spring:
         druid:
             # 主库数据源
             master:
-                url: jdbc:mysql://47.100.220.92:3306/warewms-yonghu?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
-                username: warewms
-                password: warewms123
+                url: jdbc:mysql://localhost:3306/warewms_yonghu_zx?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
+                username: root
+                password: root
                 driverClassName: com.mysql.cj.jdbc.Driver
             # 从库数据源
             slave:
@@ -58,13 +58,13 @@ spring:
                         multi-statement-allow: true
     redis:
         # 地址
-        host: 154.12.20.200
+        host: 154.12.16.4
         # 端口,默认为6379
         port: 6379
         # 数据库索引
         database: 0
         # 密码
-        password:
+        password: 123499
         # 连接超时时间
         timeout: 10s
         lettuce:

+ 3 - 2
warewms-ams/src/main/java/com/ruoyi/ams/asn/dto/UnbindWmsBoxDTO.java

@@ -6,7 +6,7 @@ import lombok.Data;
 import java.io.Serializable;
 
 @Data
-public class UnbindWmsBoxDTO implements Serializable {
+public class UnbindDTO implements Serializable {
 
     @ApiModelProperty(value = "起始托盘")
     private String palletFrom;
@@ -23,5 +23,6 @@ public class UnbindWmsBoxDTO implements Serializable {
     @ApiModelProperty(value = "出库单号 不传为分拣组盘")
     private String erpNo;
 
-
+    @ApiModelProperty(value = "条码")
+    private String sn;
 }

+ 3 - 2
warewms-ams/src/main/java/com/ruoyi/ams/inv/dto/InvLotAttPalletTotalDTO.java

@@ -1,11 +1,9 @@
 package com.ruoyi.ams.inv.dto;
 
 import io.swagger.annotations.ApiModelProperty;
-import io.swagger.annotations.ApiOperation;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 
 @Data
 public class InvLotAttPalletTotalDTO implements Serializable {
@@ -23,5 +21,8 @@ public class InvLotAttPalletTotalDTO implements Serializable {
     @ApiModelProperty("库位id")
     private String locationId;
 
+    @ApiModelProperty("出库单号")
+    private String orderNo;
+
 
 }

+ 44 - 4
warewms-ams/src/main/java/com/ruoyi/ams/inv/service/IInvLotAttService.java

@@ -1,12 +1,13 @@
 package com.ruoyi.ams.inv.service;
 
+import com.ruoyi.ams.inv.domain.InvLotAtt;
+import com.ruoyi.ams.inv.dto.InvLotAttPalletTotalDTO;
+import com.ruoyi.ams.order.dto.ReversePickInventoryMatchDTO;
+
 import java.math.BigDecimal;
 import java.util.List;
 import java.util.Map;
 
-import com.ruoyi.ams.inv.domain.InvLotAtt;
-import com.ruoyi.ams.inv.dto.InvLotAttPalletTotalDTO;
-
 /**
  * 批次属性Service接口
  *
@@ -84,6 +85,13 @@ public interface IInvLotAttService
      */
     Map<String, List<InvLotAttPalletTotalDTO>> buildInvLotAttPalletTotalMap(List<String> skuList);
 
+    /**
+     * 根据出库单号以及sku获取不同sku各托盘上已备货总数
+     * @param reversePickInventoryMatchDTOList
+     * @return
+     */
+    Map<String, List<InvLotAttPalletTotalDTO>> buildReversePickInvLotAttPalletTotalMap(List<ReversePickInventoryMatchDTO> reversePickInventoryMatchDTOList);
+
     /**
      * 获取托盘产品数量
      * @param palletNo
@@ -103,9 +111,41 @@ public interface IInvLotAttService
 
     /**
      * 根据sn获取批次信息
-     * @param palletNoFrom
+     * @param palletNo
      * @param sn
      * @return
      */
     List<InvLotAtt> queryInvLotAtt(String palletNo, String sn);
+
+    /**
+     * 根据条码获取批次信息(退货情况下可能会有多批次信息)
+     * @param palletNo
+     * @param sn
+     * @param orderNo
+     * @return
+     */
+    List<InvLotAtt> queryInvLotAtt(String palletNo, String sn, String orderNo);
+
+    /**
+     * 根据出库单号及物料码查询出库单与扫描物料相同已分配数量
+     * @param sku
+     * @param orderNo
+     * @return
+     */
+    List<InvLotAtt> queryOrderSameSkuInvLotAttList(String sku, String orderNo);
+
+    /**
+     * 根据出库单号及物料码查询出库单与扫描物料相同已分配数量
+     */
+    List<InvLotAtt> queryOrderSameSkuInvLotAttList(String sku, List<String> orderNoList);
+
+    /**
+     * 根据出库单号及物料码查询出库单与扫描物料相同已分配数量
+     */
+    List<InvLotAtt> queryOrderSameSkuInvLotAttList(List<String> skuList, String orderNo);
+
+    /**
+     * 根据出库单号及物料码查询出库单与扫描物料相同已分配数量
+     */
+    List<InvLotAtt> queryOrderSameSkuInvLotAttList(List<String> skuList, List<String> orderNoList);
 }

+ 10 - 7
warewms-ams/src/main/java/com/ruoyi/ams/inv/service/IInvLotLocIdService.java

@@ -1,9 +1,5 @@
 package com.ruoyi.ams.inv.service;
 
-import java.math.BigDecimal;
-import java.util.List;
-
-import com.ruoyi.ams.asn.vo.StockingListVO;
 import com.ruoyi.ams.config.domain.dto.AgvCallDTO;
 import com.ruoyi.ams.config.domain.dto.LotattDTO;
 import com.ruoyi.ams.inv.domain.InvLotAtt;
@@ -15,11 +11,11 @@ import com.ruoyi.ams.inv.domain.form.InvLotLocIdMoveForm;
 import com.ruoyi.ams.inv.domain.vo.InvLotLocIdLotattVO;
 import com.ruoyi.ams.inv.dto.InvLotLocIdSurplusQtyDTO;
 import com.ruoyi.ams.order.form.LineReleaseFrom;
-import com.ruoyi.base.domain.BaseLocationInfo;
 import com.ruoyi.base.domain.form.BasLocationForm;
-import com.ruoyi.base.domain.vo.BaseLocationLotattVO;
 import com.ruoyi.common.core.domain.AjaxResult;
-import org.apache.ibatis.annotations.Param;
+
+import java.math.BigDecimal;
+import java.util.List;
 
 /**
  * 库位库存信息Service接口
@@ -412,6 +408,13 @@ public interface IInvLotLocIdService {
      */
     List<InvLotLocIdSurplusQtyDTO> buildInvLotLocIdSurplusQtyDTOList(List<String> skuList);
 
+    /**
+     * 根据批次lotnum查询对应库存库位信息
+     * @param lotnum
+     * @return
+     */
+    InvLotLocId queryInvLotLocIdByLotnum(String lotnum);
+
     /**
      * 根据批次lotnum查询对应库存库位信息
      * @param lotnumList

+ 95 - 11
warewms-ams/src/main/java/com/ruoyi/ams/inv/service/impl/InvLotAttServiceImpl.java

@@ -1,22 +1,30 @@
 package com.ruoyi.ams.inv.service.impl;
 
-import java.math.BigDecimal;
-import java.util.*;
-import java.util.stream.Collectors;
-
 import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.collection.ListUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.ruoyi.ams.inv.domain.InvLotAtt;
 import com.ruoyi.ams.inv.domain.InvLotLocId;
 import com.ruoyi.ams.inv.dto.InvLotAttPalletTotalDTO;
 import com.ruoyi.ams.inv.dto.InvLotLocIdSurplusQtyDTO;
+import com.ruoyi.ams.inv.mapper.InvLotAttMapper;
+import com.ruoyi.ams.inv.service.IInvLotAttService;
 import com.ruoyi.ams.inv.service.IInvLotLocIdService;
+import com.ruoyi.ams.order.dto.ReversePickInventoryMatchDTO;
+import com.ruoyi.common.utils.ConvertUtils;
 import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import com.ruoyi.ams.inv.mapper.InvLotAttMapper;
-import com.ruoyi.ams.inv.domain.InvLotAtt;
-import com.ruoyi.ams.inv.service.IInvLotAttService;
+
+import java.math.BigDecimal;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * 批次属性Service业务层处理
@@ -134,10 +142,33 @@ public class InvLotAttServiceImpl implements IInvLotAttService {
         if (CollectionUtil.isEmpty(invLotAttList)) {
             return new HashMap<>();
         }
-        Map<String, List<InvLotAttPalletTotalDTO>> result = new HashMap<>();
-
         //根据sku对批次分类
         Map<String, List<InvLotAtt>> skuInvLotAttMap = invLotAttList.stream().filter(item -> StringUtils.isBlank(item.getLotatt14()) && StringUtils.isBlank(item.getLotatt15())).collect(Collectors.groupingBy(InvLotAtt::getSku));
+        //根据sku分类各托盘剩余数量信息
+        return buildInvLotAttPalletTotalGroupBySkuMap(lotNumQtyMap, skuInvLotAttMap);
+    }
+
+    /**
+     * 根据出库单号以及sku获取不同sku各托盘上已备货总数
+     */
+    @Override
+    public Map<String, List<InvLotAttPalletTotalDTO>> buildReversePickInvLotAttPalletTotalMap(List<ReversePickInventoryMatchDTO> reversePickInventoryMatchDTOList){
+        LambdaQueryWrapper<InvLotAtt> wrapper = Wrappers.lambdaQuery();
+        reversePickInventoryMatchDTOList.forEach(item -> wrapper.or(a -> a.eq(InvLotAtt::getSku, item.getSku()).eq(InvLotAtt::getLotatt14, item.getOrderNo())));
+        List<InvLotAtt> invLotAttList = invLotAttMapper.selectList(wrapper);
+        List<InvLotLocId> invLotLocIdList = invLotLocIdService.queryInvLotLocIdByLotnum(invLotAttList.stream().map(InvLotAtt::getLotnum).collect(Collectors.toList()));
+        Map<String, InvLotLocIdSurplusQtyDTO> lotNumQtyMap = invLotLocIdList.stream().collect(Collectors.toMap(InvLotLocId::getLotnum, item -> {
+            InvLotLocIdSurplusQtyDTO invLotLocIdSurplusQtyDTO = ConvertUtils.sourceToTarget(item, InvLotLocIdSurplusQtyDTO.class);
+            invLotLocIdSurplusQtyDTO.setSurplusQty(item.getQtyallocated());
+            return invLotLocIdSurplusQtyDTO;
+        }));
+        Map<String, List<InvLotAtt>> skuInvLotAttMap = invLotAttList.stream().filter(item -> invLotLocIdList.stream().map(InvLotLocId::getLotnum).collect(Collectors.toList()).contains(item.getLotnum())).collect(Collectors.groupingBy(InvLotAtt::getSku));
+        //根据sku分类各托盘剩余数量信息
+        return buildInvLotAttPalletTotalGroupBySkuMap(lotNumQtyMap, skuInvLotAttMap);
+    }
+
+    private Map<String, List<InvLotAttPalletTotalDTO>> buildInvLotAttPalletTotalGroupBySkuMap(Map<String, InvLotLocIdSurplusQtyDTO> lotNumQtyMap, Map<String, List<InvLotAtt>> skuInvLotAttMap){
+        Map<String, List<InvLotAttPalletTotalDTO>> result = new HashMap<>();
         skuInvLotAttMap.forEach((key, value) -> {
             //相同sku根据托盘分类,计算托盘上产品数量
             Map<String, List<InvLotAtt>> palletMap = value.stream().filter(item -> StringUtils.isNotBlank(item.getLotatt07())).collect(Collectors.groupingBy(InvLotAtt::getLotatt07));
@@ -148,11 +179,12 @@ public class InvLotAttServiceImpl implements IInvLotAttService {
                 invLotAttPalletTotalDTO.setPalletNo(item.getKey());
                 invLotAttPalletTotalDTO.setTotalQty(item.getValue().stream().map(invLotAtt -> lotNumQtyMap.get(invLotAtt.getLotnum()).getSurplusQty()).reduce(BigDecimal.ZERO, BigDecimal::add).toString());
                 invLotAttPalletTotalDTO.setLocationId(lotNumQtyMap.get(item.getValue().stream().map(InvLotAtt::getLotnum).findFirst().orElseGet(() -> null)).getLocationId());
+                //托盘只能备货统一出库单的货物
+                invLotAttPalletTotalDTO.setOrderNo(ObjectUtil.isNotNull(item.getValue().stream().map(InvLotAtt::getLotatt14)) ? item.getValue().stream().findFirst().orElseGet(() -> null).getLotatt14() : null);
                 return invLotAttPalletTotalDTO;
             }).sorted(Comparator.comparing(InvLotAttPalletTotalDTO::getTotalQty)).collect(Collectors.toList());
             result.put(key, invLotAttPalletTotalDTOList);
         });
-        //根据sku分类各托盘剩余数量信息
         return result;
     }
 
@@ -195,7 +227,59 @@ public class InvLotAttServiceImpl implements IInvLotAttService {
      */
     @Override
     public List<InvLotAtt> queryInvLotAtt(String palletNo, String sn){
-        return invLotAttMapper.selectList(Wrappers.<InvLotAtt>lambdaQuery().eq(StringUtils.isNotBlank(sn), InvLotAtt::getLotatt02, sn).eq(InvLotAtt::getLotatt07, palletNo));
+        return queryInvLotAtt(palletNo, sn, null);
+    }
+
+    /**
+     * 根据条码获取批次信息(退货情况下可能会有多批次信息)
+     * @param palletNo
+     * @param sn
+     * @param orderNo
+     * @return
+     */
+    @Override
+    public List<InvLotAtt> queryInvLotAtt(String palletNo, String sn, String orderNo){
+        return invLotAttMapper.selectList(Wrappers.<InvLotAtt>lambdaQuery()
+                .eq(StringUtils.isNotBlank(sn), InvLotAtt::getLotatt02, sn)
+                .eq(InvLotAtt::getLotatt07, palletNo)
+                .eq(StringUtils.isNotBlank(orderNo), InvLotAtt::getLotatt14, orderNo));
+    }
+
+    /**
+     * 根据出库单号及物料码查询出库单与扫描物料相同已分配数量
+     * @param sku
+     * @param orderNo
+     * @return
+     */
+    @Override
+    public List<InvLotAtt> queryOrderSameSkuInvLotAttList(String sku, String orderNo){
+        return queryOrderSameSkuInvLotAttList(ListUtil.toList(sku), ListUtil.toList(orderNo));
+    }
+
+    /**
+     * 根据出库单号及物料码查询出库单与扫描物料相同已分配数量
+     */
+    @Override
+    public List<InvLotAtt> queryOrderSameSkuInvLotAttList(String sku, List<String> orderNoList){
+        return queryOrderSameSkuInvLotAttList(ListUtil.toList(sku), orderNoList);
+    }
+
+    /**
+     * 根据出库单号及物料码查询出库单与扫描物料相同已分配数量
+     */
+    @Override
+    public List<InvLotAtt> queryOrderSameSkuInvLotAttList(List<String> skuList, String orderNo){
+        return queryOrderSameSkuInvLotAttList(skuList, ListUtil.toList(orderNo));
+    }
+
+    /**
+     * 根据出库单号及物料码查询出库单与扫描物料相同已分配数量
+     */
+    @Override
+    public List<InvLotAtt> queryOrderSameSkuInvLotAttList(List<String> skuList, List<String> orderNoList){
+        return invLotAttMapper.selectList(Wrappers.<InvLotAtt>lambdaQuery()
+                .in(InvLotAtt::getSku, skuList)
+                .in(InvLotAtt::getLotatt14, orderNoList));
     }
 
     private List<InvLotAtt> queryInvLotAttByLotNumList(List<String> lotNumList){

+ 12 - 0
warewms-ams/src/main/java/com/ruoyi/ams/inv/service/impl/InvLotLocIdServiceImpl.java

@@ -1,6 +1,7 @@
 package com.ruoyi.ams.inv.service.impl;
 
 import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.collection.ListUtil;
 import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.ruoyi.ams.box.domain.WmsBoxInfo;
@@ -33,6 +34,7 @@ import com.ruoyi.base.utils.IdSequenceUtils;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.redis.RedisCache;
 import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.exception.base.BaseException;
 import com.ruoyi.common.utils.ConvertUtils;
 import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.StringUtils;
@@ -1128,6 +1130,16 @@ public class InvLotLocIdServiceImpl implements IInvLotLocIdService {
                 .in(InvLotLocId::getLocationId, baseLocationInfoList.stream().map(item -> String.valueOf(item.getId())).collect(Collectors.toList())));
     }
 
+    /**
+     * 根据批次lotnum查询对应库存库位信息
+     * @param lotnum
+     * @return
+     */
+    @Override
+    public InvLotLocId queryInvLotLocIdByLotnum(String lotnum){
+        return queryInvLotLocIdByLotnum(ListUtil.toList(lotnum)).stream().findFirst().orElseThrow(() -> new BaseException("库位库存批次信息丢失!"));
+    }
+
     /**
      * 根据批次lotnum查询对应库存库位信息
      * @param lotnumList

+ 2 - 6
warewms-ams/src/main/java/com/ruoyi/ams/order/domain/PalletMatchLog.java

@@ -1,14 +1,11 @@
 package com.ruoyi.ams.order.domain;
 
 import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
-import org.apache.commons.lang3.builder.ToStringBuilder;
-import org.apache.commons.lang3.builder.ToStringStyle;
 import com.ruoyi.common.annotation.Excel;
 import com.ruoyi.common.core.domain.BaseEntity;
-
-import static com.baomidou.mybatisplus.annotation.IdType.ASSIGN_UUID;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
 
 /**
  * 托盘匹配记录对象 pallet_match_log
@@ -49,7 +46,6 @@ public class PalletMatchLog extends BaseEntity
     private String agvNo;
 
     /** 逻辑删除*/
-    @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
     private String userdefine1;
 
     /** $column.columnComment */

+ 25 - 0
warewms-ams/src/main/java/com/ruoyi/ams/order/dto/GroupDiskConvertDTO.java

@@ -0,0 +1,25 @@
+package com.ruoyi.ams.order.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class GroupDiskConvertDTO extends PdaGroupDiskDTO{
+
+    @ApiModelProperty("产品/物料")
+    private String sku;
+
+    @ApiModelProperty("组盘数量")
+    private BigDecimal groupDiskQty;
+
+    @ApiModelProperty("出库单号")
+    private String wmsOrderNo;
+
+    @ApiModelProperty("批次号")
+    private String lotNum;
+
+    @ApiModelProperty("区域id")
+    private String locationId;
+}

+ 4 - 4
warewms-ams/src/main/java/com/ruoyi/ams/order/dto/PdaGroupDiskDTO.java

@@ -13,12 +13,12 @@ public class PdaGroupDiskDTO implements Serializable {
      * 起始托盘
      */
     @NotBlank(message = "起始托盘不能为空")
-    private String palletNoFrom;
+    private String palletFrom;
     /**
      * 目标托盘
      */
     @NotBlank(message = "目标托盘不能为空")
-    private String palletNoTo;
+    private String palletTo;
     /**
      * 箱子
      */
@@ -28,11 +28,11 @@ public class PdaGroupDiskDTO implements Serializable {
      */
     @NotBlank(message = "条码号不能为空")
     private String sn;
+
     /**
      * 出库单号(理货备货才会传入)
      */
-    @NotBlank(message = "出库单号不能为空")
-    private String orderNo;
+    private String erpNo;
 
     /**
      * 组盘数量

+ 13 - 0
warewms-ams/src/main/java/com/ruoyi/ams/order/dto/ReversePickConvertDTO.java

@@ -0,0 +1,13 @@
+package com.ruoyi.ams.order.dto;
+
+import lombok.Data;
+
+@Data
+public class ReversePickConvertDTO extends ReversePickGroupDiskDTO{
+
+    private String sku;
+
+    private String palletFrom;
+
+    private String orderNo;
+}

+ 38 - 0
warewms-ams/src/main/java/com/ruoyi/ams/order/dto/ReversePickGroupDiskDTO.java

@@ -0,0 +1,38 @@
+package com.ruoyi.ams.order.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import java.io.Serializable;
+
+@Data
+public class ReversePickGroupDiskDTO implements Serializable {
+    private static final long serialVersionUID = -5918088014815517706L;
+    /**
+     * 起始托盘
+     */
+    @NotBlank(message = "起始托盘不能为空")
+    private String palletFrom;
+    /**
+     * 目标托盘
+     */
+    @NotBlank(message = "目标托盘不能为空")
+    private String palletTo;
+    /**
+     * 条码号
+     */
+    @NotBlank(message = "条码号不能为空")
+    private String sn;
+    /**
+     * 出库单号
+     */
+    @NotBlank(message = "出库单号不能为空")
+    private String erpNo;
+
+    /**
+     * 组盘数量
+     */
+    @NotBlank(message = "组盘数量不能为空")
+    private String qty;
+
+}

+ 17 - 0
warewms-ams/src/main/java/com/ruoyi/ams/order/dto/ReversePickInventoryMatchDTO.java

@@ -0,0 +1,17 @@
+package com.ruoyi.ams.order.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+@Data
+public class ReversePickInventoryMatchDTO implements Serializable {
+
+    private String sku;
+
+    private String orderNo;
+
+    private BigDecimal qty;
+
+}

+ 7 - 1
warewms-ams/src/main/java/com/ruoyi/ams/order/service/IPalletMatchLogService.java

@@ -1,7 +1,6 @@
 package com.ruoyi.ams.order.service;
 
 import com.ruoyi.ams.order.domain.PalletMatchLog;
-import com.ruoyi.ams.order.dto.PalletMatchLogDTO;
 import com.ruoyi.framework.service.BaseService;
 
 import java.util.List;
@@ -23,6 +22,13 @@ public interface IPalletMatchLogService extends BaseService<PalletMatchLog>
      */
     List<PalletMatchLog> selectPalletMatchLogList(PalletMatchLog palletMatchLog);
 
+    /**
+     * 检验出库单库位推荐记录并获取 若推荐过则将之前推荐记录逻辑删除
+     * @param orderList
+     * @return
+     */
+    List<PalletMatchLog> checkOrderNoAndGetPalletMatchLogList(List<String> orderList);
+
     /**
      * 根据单号获取托盘匹配信息(本次匹配托盘)
      * @param orderNos

+ 16 - 4
warewms-ams/src/main/java/com/ruoyi/ams/order/service/IWmsDocOrderDetailsService.java

@@ -1,10 +1,10 @@
 package com.ruoyi.ams.order.service;
 
+import com.ruoyi.ams.order.domain.WmsDocOrderDetails;
+
 import java.util.HashMap;
 import java.util.List;
 
-import com.ruoyi.ams.order.domain.WmsDocOrderDetails;
-
 /**
  * 出库单Service接口
  *
@@ -88,12 +88,24 @@ public interface IWmsDocOrderDetailsService {
      * @param orderNo
      * @return
      */
-    List<WmsDocOrderDetails> queryWmsDocOrderDetailsByOrderNo(String orderNo);
+    List<WmsDocOrderDetails> queryWmsDocOrderDetails(String orderNo);
+
+    /**
+     * 根据出库单号和绑定物料获取明细
+     * @param orderNo 入库单号list
+     * @return
+     */
+    List<WmsDocOrderDetails> queryWmsDocOrderDetails(String orderNo, String sku);
 
     /**
      * 根据入库单号list获取明细
      * @param orderNoList 入库单号list
      * @return
      */
-    List<WmsDocOrderDetails> queryWmsDocOrderDetailsByOrderNo(List<String> orderNoList);
+    List<WmsDocOrderDetails> queryWmsDocOrderDetails(List<String> orderNoList);
+
+    /**
+     * 根据出库单号和绑定物料获取明细
+     */
+    List<WmsDocOrderDetails> queryWmsDocOrderDetails(List<String> orderNoList, String sku);
 }

+ 42 - 17
warewms-ams/src/main/java/com/ruoyi/ams/order/service/IWmsDocOrderHeaderService.java

@@ -1,13 +1,13 @@
 package com.ruoyi.ams.order.service;
 
-import com.ruoyi.ams.asn.dto.UnbindWmsBoxDTO;
+import com.ruoyi.ams.asn.dto.UnbindDTO;
 import com.ruoyi.ams.erp.domain.ErpOrderList;
 import com.ruoyi.ams.inv.domain.vo.InvLotLocIdLotattVO;
-import com.ruoyi.ams.order.domain.PalletMatchLog;
 import com.ruoyi.ams.order.domain.WmsDocOrderDetails;
 import com.ruoyi.ams.order.domain.WmsDocOrderHeader;
 import com.ruoyi.ams.order.dto.PalletMatchLogDTO;
 import com.ruoyi.ams.order.dto.PdaGroupDiskDTO;
+import com.ruoyi.ams.order.dto.ReversePickGroupDiskDTO;
 import com.ruoyi.ams.order.form.*;
 import com.ruoyi.ams.order.vo.CheckOutVO;
 import com.ruoyi.ams.order.vo.PickingListVO;
@@ -252,26 +252,12 @@ public interface IWmsDocOrderHeaderService {
      */
     AjaxResult groupDiskBHCheck(GroupDiskFrom groupDiskFrom);
 
-    /**
-     * PDA解绑物料并发控制
-     * @param unbindWmsBoxDTO
-     * @return
-     */
-    AjaxResult syncUnbindWmsBox(UnbindWmsBoxDTO unbindWmsBoxDTO);
-
-    /**
-     * PDA理货备货并发控制
-     * @param pdaGroupDiskDTO
-     * @return
-     */
-    AjaxResult syncPdaGroupDiskBH(PdaGroupDiskDTO pdaGroupDiskDTO);
-
     /**
      * PDA理货备货
      * @param pdaGroupDiskDTO
      * @return
      */
-    AjaxResult pdaGroupDiskBH(PdaGroupDiskDTO pdaGroupDiskDTO);
+    AjaxResult pdaGroupDisk(PdaGroupDiskDTO pdaGroupDiskDTO);
 
     /**
      * 组盘(备货)
@@ -438,6 +424,40 @@ public interface IWmsDocOrderHeaderService {
     AjaxResult modifystockCompletionStatusAsnUntie(String orderNo, String sku, BigDecimal qty
             ,String sn);
 
+    /**
+     * PDA解绑物料并发控制
+     * @param unbindDTO
+     * @return
+     */
+    AjaxResult syncPdaUnbind(UnbindDTO unbindDTO);
+
+    /**
+     * PDA理货备货并发控制
+     * @param pdaGroupDiskDTO
+     * @return
+     */
+    AjaxResult syncPdaGroupDisk(PdaGroupDiskDTO pdaGroupDiskDTO);
+
+    /**
+     * PDA反拣组盘并发控制
+     */
+    AjaxResult syncPdaReversePickGroupDisk(ReversePickGroupDiskDTO reversePickGroupDiskDTO);
+
+    /**
+     * PDA库存匹配并发控制
+     */
+    Boolean syncInventoryMatch(String orderNos);
+
+    /**
+     * PDA反拣出库并发控制
+     */
+    Boolean syncPdaReversePickInventoryMatch(String orderNos);
+
+    /**
+     * PDA反拣组盘
+     */
+    AjaxResult pdaReversePickGroupDisk(ReversePickGroupDiskDTO reversePickGroupDiskDTO);
+
     /**
      * 库存分配
      * @param orderNos
@@ -445,6 +465,11 @@ public interface IWmsDocOrderHeaderService {
      */
     Boolean inventoryMatch(String orderNos);
 
+    /**
+     * 反拣出库
+     */
+    Boolean reversePickInventoryMatch(String orderNos);
+
     /**
      * 获取库存分配反馈
      * @param orderNos

+ 16 - 1
warewms-ams/src/main/java/com/ruoyi/ams/order/service/impl/PalletMatchLogServiceImpl.java

@@ -1,9 +1,9 @@
 package com.ruoyi.ams.order.service.impl;
 
+import cn.hutool.core.collection.CollectionUtil;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.ruoyi.ams.order.domain.PalletMatchLog;
-import com.ruoyi.ams.order.dto.PalletMatchLogDTO;
 import com.ruoyi.ams.order.mapper.PalletMatchLogMapper;
 import com.ruoyi.ams.order.service.IPalletMatchLogService;
 import com.ruoyi.common.constant.Constants;
@@ -35,6 +35,21 @@ public class PalletMatchLogServiceImpl extends BaseServiceImpl<PalletMatchLogMap
         return baseDao.selectPalletMatchLogList(palletMatchLog);
     }
 
+    /**
+     * 检验出库单库位推荐记录并获取 若推荐过则将之前推荐记录逻辑删除
+     * @param orderList
+     * @return
+     */
+    @Override
+    public List<PalletMatchLog> checkOrderNoAndGetPalletMatchLogList(List<String> orderList){
+        String order = orderList.stream().collect(Collectors.joining(","));
+        List<PalletMatchLog> palletMatchLogList = queryAllPalletMatchLogByOrderNos(order);
+        if (CollectionUtil.isNotEmpty(palletMatchLogList)) {
+            logicalDeletionPalletMatchLog(palletMatchLogList);
+        }
+        return palletMatchLogList;
+    }
+
     /**
      * 根据单号获取托盘匹配信息(本次匹配托盘)
      * @param orderNos

+ 31 - 12
warewms-ams/src/main/java/com/ruoyi/ams/order/service/impl/WmsDocOrderDetailsServiceImpl.java

@@ -1,17 +1,17 @@
 package com.ruoyi.ams.order.service.impl;
 
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.ruoyi.ams.inv.domain.InvLotLocId;
+import com.ruoyi.ams.order.domain.WmsDocOrderDetails;
+import com.ruoyi.ams.order.mapper.WmsDocOrderDetailsMapper;
+import com.ruoyi.ams.order.service.IWmsDocOrderDetailsService;
 import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import com.ruoyi.ams.order.mapper.WmsDocOrderDetailsMapper;
-import com.ruoyi.ams.order.domain.WmsDocOrderDetails;
-import com.ruoyi.ams.order.service.IWmsDocOrderDetailsService;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
 
 /**
  * 出库单Service业务层处理
@@ -138,8 +138,18 @@ public class WmsDocOrderDetailsServiceImpl implements IWmsDocOrderDetailsService
      * @return
      */
     @Override
-    public List<WmsDocOrderDetails> queryWmsDocOrderDetailsByOrderNo(String orderNo){
-        return queryWmsDocOrderDetailsByOrderNo(Arrays.asList(orderNo));
+    public List<WmsDocOrderDetails> queryWmsDocOrderDetails(String orderNo){
+        return queryWmsDocOrderDetails(Arrays.asList(orderNo));
+    }
+
+    /**
+     * 根据出库单号和绑定物料获取明细
+     * @param orderNo 入库单号list
+     * @return
+     */
+    @Override
+    public List<WmsDocOrderDetails> queryWmsDocOrderDetails(String orderNo, String sku){
+        return queryWmsDocOrderDetails(Arrays.asList(orderNo), sku);
     }
 
     /**
@@ -148,8 +158,17 @@ public class WmsDocOrderDetailsServiceImpl implements IWmsDocOrderDetailsService
      * @return
      */
     @Override
-    public List<WmsDocOrderDetails> queryWmsDocOrderDetailsByOrderNo(List<String> orderNoList){
-        return wmsDocOrderDetailsMapper.selectList(Wrappers.<WmsDocOrderDetails>lambdaQuery().in(WmsDocOrderDetails::getOrderNo, orderNoList).orderByAsc(WmsDocOrderDetails::getOrderLineNo));
+    public List<WmsDocOrderDetails> queryWmsDocOrderDetails(List<String> orderNoList){
+        return queryWmsDocOrderDetails(orderNoList, null);
+    }
+
+    /**
+     * 根据出库单号和绑定物料获取明细
+     */
+    @Override
+    public List<WmsDocOrderDetails> queryWmsDocOrderDetails(List<String> orderNoList, String sku){
+        return wmsDocOrderDetailsMapper.selectList(Wrappers.<WmsDocOrderDetails>lambdaQuery().in(WmsDocOrderDetails::getOrderNo, orderNoList)
+                .eq(StringUtils.isNotBlank(sku), WmsDocOrderDetails::getSku, sku).orderByAsc(WmsDocOrderDetails::getOrderLineNo));
     }
 
 }

+ 359 - 190
warewms-ams/src/main/java/com/ruoyi/ams/order/service/impl/WmsDocOrderHeaderServiceImpl.java

@@ -8,7 +8,7 @@ import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.fastjson.JSONArray;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.ruoyi.ams.asn.dto.UnbindWmsBoxDTO;
+import com.ruoyi.ams.asn.dto.UnbindDTO;
 import com.ruoyi.ams.asn.service.IWmsDocAsnHeaderService;
 import com.ruoyi.ams.box.domain.WmsBoxInfo;
 import com.ruoyi.ams.box.mapper.WmsBoxInfoMapper;
@@ -37,8 +37,7 @@ import com.ruoyi.ams.order.domain.ActAllocationDetails;
 import com.ruoyi.ams.order.domain.PalletMatchLog;
 import com.ruoyi.ams.order.domain.WmsDocOrderDetails;
 import com.ruoyi.ams.order.domain.WmsDocOrderHeader;
-import com.ruoyi.ams.order.dto.PalletMatchLogDTO;
-import com.ruoyi.ams.order.dto.PdaGroupDiskDTO;
+import com.ruoyi.ams.order.dto.*;
 import com.ruoyi.ams.order.form.*;
 import com.ruoyi.ams.order.mapper.WmsDocOrderDetailsMapper;
 import com.ruoyi.ams.order.mapper.WmsDocOrderHeaderMapper;
@@ -2735,54 +2734,312 @@ public class WmsDocOrderHeaderServiceImpl implements IWmsDocOrderHeaderService {
 
     /**
      * PDA解绑物料并发控制
-     * @param unbindWmsBoxDTO
+     */
+    @Override
+    public synchronized AjaxResult syncPdaUnbind(UnbindDTO unbindDTO){
+        return pdaUnbind(unbindDTO);
+    }
+
+    /**
+     * PDA理货备货并发控制
+     */
+    @Override
+    public synchronized AjaxResult syncPdaGroupDisk(PdaGroupDiskDTO pdaGroupDiskDTO){
+        return pdaGroupDisk(pdaGroupDiskDTO);
+    }
+
+    /**
+     * PDA反拣组盘并发控制
+     */
+    @Override
+    public synchronized AjaxResult syncPdaReversePickGroupDisk(ReversePickGroupDiskDTO reversePickGroupDiskDTO){
+        return pdaReversePickGroupDisk(reversePickGroupDiskDTO);
+    }
+    /**
+     * PDA库存匹配并发控制
+     */
+    @Override
+    public synchronized Boolean syncInventoryMatch(String orderNos){
+        return inventoryMatch(orderNos);
+    }
+
+    /**
+     * PDA反拣出库并发控制
+     */
+    @Override
+    public synchronized Boolean syncPdaReversePickInventoryMatch(String orderNos){
+        return reversePickInventoryMatch(orderNos);
+    }
+
+    /**
+     * 库存匹配
+     */
+    @Override
+    @Transactional(propagation = Propagation.REQUIRES_NEW)
+    public Boolean inventoryMatch(String orderNos) {
+        List<String> orderList = JSONArray.parseArray(orderNos, String.class);
+        List<PalletMatchLog> palletMatchLogList = palletMatchLogService.checkOrderNoAndGetPalletMatchLogList(orderList);
+        List<InvLotAttPalletTotalDTO> result = buildInventoryMatchList(orderList, palletMatchLogList);
+        return palletMatchLogService.insertBatch(buildPalletMatchLogList(result, orderList));
+    }
+
+    /**
+     * 反拣出库
+     */
+    @Override
+    @Transactional(propagation = Propagation.REQUIRES_NEW)
+    public Boolean reversePickInventoryMatch(String orderNos) {
+        List<String> orderList = JSONArray.parseArray(orderNos, String.class);
+        List<PalletMatchLog> palletMatchLogList = palletMatchLogService.checkOrderNoAndGetPalletMatchLogList(orderList);
+        LinkedList<Object> reversePickInventoryMatchList = buildReversePickInventoryMatchList(orderList, palletMatchLogList);
+        Boolean flag = (Boolean) reversePickInventoryMatchList.pop();
+        List<InvLotAttPalletTotalDTO> result = (List<InvLotAttPalletTotalDTO>) reversePickInventoryMatchList.pop();
+        if (flag) result.addAll(buildInventoryMatchList(orderList, palletMatchLogList));
+        return palletMatchLogService.insertBatch(buildPalletMatchLogList(result, orderList));
+    }
+
+    private List<InvLotAttPalletTotalDTO> buildInventoryMatchList(List<String> orderList, List<PalletMatchLog> palletMatchLogList){
+        //根据erp单号获取出库单头列表
+        List<WmsDocOrderHeader> wmsDocOrderHeaderList = wmsDocOrderHeaderMapper.selectList(Wrappers.<WmsDocOrderHeader>lambdaQuery().in(WmsDocOrderHeader::getSoReference1, orderList).orderByDesc(WmsDocOrderHeader::getCreateTime));
+        if (CollectionUtil.isEmpty(wmsDocOrderHeaderList)) {
+            throw new BaseException("请扫描正确的出库单号");
+        }
+        List<WmsDocOrderHeader> wmsDocOrderHeaderFilterList = wmsDocOrderHeaderList.stream().filter(item -> item.getOrderStatus().equals(Constant.ORDER_STS.STS00.getValue())
+                || item.getOrderStatus().equals(Constant.ORDER_STS.STS10.getValue()) || item.getOrderStatus().equals(Constant.ORDER_STS.STS22.getValue())).collect(Collectors.toList());
+        if (CollectionUtil.isEmpty(wmsDocOrderHeaderFilterList)) {
+            throw new BaseException("出库单状态不可进行库存匹配!");
+        }
+        List<WmsDocOrderDetails> wmsDocOrderDetailsList = wmsDocOrderDetailsService.queryWmsDocOrderDetails(
+                wmsDocOrderHeaderFilterList.stream().filter(item -> StringUtils.isNotBlank(item.getOrderNo()))
+                        .map(WmsDocOrderHeader::getOrderNo).collect(Collectors.toList()));
+        if (CollectionUtil.isEmpty(wmsDocOrderDetailsList)) {
+            throw new BaseException("出库单明细为空!");
+        }
+        Map<String, List<WmsDocOrderDetails>> wmsDocOrderDetailsGroupBySkuMap = wmsDocOrderDetailsList.stream().filter(item -> StringUtils.isNotBlank(item.getSku())).collect(Collectors.groupingBy(WmsDocOrderDetails::getSku));
+        if (CollectionUtil.isEmpty(wmsDocOrderDetailsGroupBySkuMap)) {
+            throw new BaseException("出库单明细绑定sku为空!");
+        }
+
+        Map<String, List<InvLotAttPalletTotalDTO>> invLotAttPalletTotalMap = invLotAttService.buildInvLotAttPalletTotalMap(ListUtil.toList(wmsDocOrderDetailsGroupBySkuMap.keySet()));
+        if (CollectionUtil.isEmpty(invLotAttPalletTotalMap)) {
+            throw new BaseException("所选出库单绑定sku无库存!");
+        }
+        //所需出库托盘
+        List<InvLotAttPalletTotalDTO> result = new ArrayList<>();
+        for (Map.Entry<String, List<WmsDocOrderDetails>> wmsDocOrderDetailsGroupBySkuMapEntry : wmsDocOrderDetailsGroupBySkuMap.entrySet()) {
+            //扫描出库单各sku需求总数
+            BigDecimal total = wmsDocOrderDetailsGroupBySkuMapEntry.getValue().stream().filter(item -> ObjectUtil.isNotNull(item.getQtyOrdered())).map(item -> ObjectUtil.isNotNull(item.getQtyAllocated())
+                    ? item.getQtyOrdered().subtract(item.getQtyAllocated()) : item.getQtyOrdered()).reduce(BigDecimal.ZERO, BigDecimal::add);
+            if (CompareUtil.compare(total, BigDecimal.ZERO) <= 0) continue;
+            List<InvLotAttPalletTotalDTO> skuPalletTotalList = invLotAttPalletTotalMap.get(wmsDocOrderDetailsGroupBySkuMapEntry.getKey());
+            if (CollectionUtil.isEmpty(skuPalletTotalList)) continue;
+            List<InvLotAttPalletTotalDTO> invLotAttPalletTotalList = buildInvLotAttPalletTotalList(skuPalletTotalList, total, palletMatchLogList);
+            result.addAll(invLotAttPalletTotalList);
+        }
+        return result;
+    }
+
+    private LinkedList<Object> buildReversePickInventoryMatchList(List<String> orderList, List<PalletMatchLog> palletMatchLogList){
+        //根据erp单号获取出库单头列表
+        List<WmsDocOrderHeader> wmsDocOrderHeaderList = wmsDocOrderHeaderMapper.selectList(Wrappers.<WmsDocOrderHeader>lambdaQuery().in(WmsDocOrderHeader::getSoReference1, orderList).orderByDesc(WmsDocOrderHeader::getCreateTime));
+        if (CollectionUtil.isEmpty(wmsDocOrderHeaderList)) {
+            throw new BaseException("请扫描正确的出库单号");
+        }
+        List<WmsDocOrderDetails> wmsDocOrderDetailsList = wmsDocOrderDetailsService.queryWmsDocOrderDetails(
+                wmsDocOrderHeaderList.stream().filter(item -> StringUtils.isNotBlank(item.getOrderNo()))
+                        .map(WmsDocOrderHeader::getOrderNo).collect(Collectors.toList()));
+        if (CollectionUtil.isEmpty(wmsDocOrderDetailsList)) {
+            throw new BaseException("出库单明细为空!");
+        }
+        //所需出库托盘
+        List<InvLotAttPalletTotalDTO> invLotAttPalletTotalDTOList = new ArrayList<>();
+        Boolean flag = Boolean.FALSE;
+        Map<String, List<WmsDocOrderDetails>> wmsDocOrderDetailsGroupByOrderNoMap = wmsDocOrderDetailsList.stream().collect(Collectors.groupingBy(WmsDocOrderDetails::getOrderNo));
+        List<ReversePickInventoryMatchDTO> reversePickInventoryMatchDTOList = new ArrayList<>();
+        for (Map.Entry<String, List<WmsDocOrderDetails>> wmsDocOrderDetailsGroupByOrderNoEntry : wmsDocOrderDetailsGroupByOrderNoMap.entrySet()) {
+            List<String> skuList = wmsDocOrderDetailsGroupByOrderNoEntry.getValue().stream().map(WmsDocOrderDetails::getSku).distinct().collect(Collectors.toList());
+            for (String sku : skuList) {
+                //判断反拣类型为解绑还是扩容 如果大于零则为该解绑得数量
+                BigDecimal qty = judgeReversePickType(sku, wmsDocOrderDetailsGroupByOrderNoEntry.getKey());
+                if (CompareUtil.compare(qty, BigDecimal.ZERO) < 0) {
+                    flag = Boolean.TRUE;
+                    continue;
+                }
+                //解绑情况下 推荐已绑定该出库单号的库存托盘 小的先出
+                ReversePickInventoryMatchDTO reversePickInventoryMatchDTO = new ReversePickInventoryMatchDTO();
+                reversePickInventoryMatchDTO.setOrderNo(wmsDocOrderDetailsGroupByOrderNoEntry.getKey());
+                reversePickInventoryMatchDTO.setQty(qty);
+                reversePickInventoryMatchDTO.setSku(sku);
+                reversePickInventoryMatchDTOList.add(reversePickInventoryMatchDTO);
+            }
+        }
+        Map<String, List<InvLotAttPalletTotalDTO>> invLotAttPalletTotalMap = invLotAttService.buildReversePickInvLotAttPalletTotalMap(reversePickInventoryMatchDTOList);
+        if (CollectionUtil.isEmpty(invLotAttPalletTotalMap)) {
+            throw new BaseException("所选出库单无分配库存!");
+        }
+        //所需出库托盘
+        for (ReversePickInventoryMatchDTO reversePickInventoryMatchDTO : reversePickInventoryMatchDTOList) {
+            List<InvLotAttPalletTotalDTO> skuPalletTotalList = invLotAttPalletTotalMap.get(reversePickInventoryMatchDTO.getSku());
+            if (CollectionUtil.isEmpty(skuPalletTotalList)) continue;
+            List<InvLotAttPalletTotalDTO> palletTotalFilterByOrderNoList = skuPalletTotalList.stream().filter(item -> reversePickInventoryMatchDTO.getOrderNo().equals(item.getOrderNo())).collect(Collectors.toList());
+            List<InvLotAttPalletTotalDTO> invLotAttPalletTotalList = buildInvLotAttPalletTotalList(palletTotalFilterByOrderNoList, reversePickInventoryMatchDTO.getQty(), palletMatchLogList);
+            invLotAttPalletTotalDTOList.addAll(invLotAttPalletTotalList);
+        }
+        LinkedList<Object> result = ListUtil.toLinkedList(flag, invLotAttPalletTotalDTOList);
+        return result;
+    }
+
+
+
+
+    private List<InvLotAttPalletTotalDTO> buildInvLotAttPalletTotalList(List<InvLotAttPalletTotalDTO> lotAttPalletTotalDTOList, BigDecimal qty, List<PalletMatchLog> palletMatchLogList){
+        //所需出库托盘
+        List<InvLotAttPalletTotalDTO> result = new ArrayList<>();
+        //sku出库单需求总数
+        if (CollectionUtil.isNotEmpty(palletMatchLogList)){
+            List<InvLotAttPalletTotalDTO> invLotAttMatchPalletTotalList = lotAttPalletTotalDTOList.stream().filter(item -> !palletMatchLogList.stream().map(PalletMatchLog::getPalletNo).collect(Collectors.toList()).contains(item.getPalletNo())).collect(Collectors.toList());
+            if (CollectionUtil.isEmpty(invLotAttMatchPalletTotalList)) {
+                result.addAll(lotAttPalletTotalDTOList);
+                return result;
+            }
+            lotAttPalletTotalDTOList = invLotAttMatchPalletTotalList;
+        }
+
+        for (InvLotAttPalletTotalDTO invLotAttPalletTotalDTO : lotAttPalletTotalDTOList) {
+            BigDecimal palletTotal = new BigDecimal(invLotAttPalletTotalDTO.getTotalQty());
+            if (CompareUtil.compare(qty, palletTotal) <= 0) {
+                result.add(invLotAttPalletTotalDTO);
+                break;
+            }
+            qty = qty.subtract(palletTotal);
+            result.add(invLotAttPalletTotalDTO);
+        }
+        return result;
+    }
+
+    /**
+     * 托盘出库回显推荐列表
+     * @param orderNos
      * @return
      */
     @Override
-    public synchronized AjaxResult syncUnbindWmsBox(UnbindWmsBoxDTO unbindWmsBoxDTO){
-        return unbindWmsBox(unbindWmsBoxDTO);
+    public List<PalletMatchLogDTO> queryPalletMatchInfoList(String orderNos) {
+        List<String> orderList = JSONArray.parseArray(orderNos, String.class);
+        String order = String.join(",", orderList);
+        List<PalletMatchLog> palletMatchLogList = palletMatchLogService.queryPalletMatchLogByOrderNos(order);
+        List<BaseLocationInfo> baseLocationInfoList = baseLocationInfoService.selectBaseLocationInfoList(palletMatchLogList.stream().map(PalletMatchLog::getLocationId).collect(Collectors.toList()));
+
+        return palletMatchLogList.stream().map(item -> {
+            PalletMatchLogDTO palletMatchLogDTO = ConvertUtils.sourceToTarget(item, PalletMatchLogDTO.class);
+            BaseLocationInfo locationInfo = baseLocationInfoList.stream().filter(baseLocationInfo -> baseLocationInfo.getId().equals(Long.parseLong(item.getLocationId()))).findFirst().orElseThrow(() -> new BaseException("库位信息有误"));
+            palletMatchLogDTO.setLocationNo(locationInfo.getLocationNo());
+            return palletMatchLogDTO;
+        }).collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(PalletMatchLogDTO::getPalletNo))), ArrayList::new));
+    }
+
+    /**
+     * PDA理货备货/分拣组盘(不传出库单号)
+     */
+    @Override
+    @Transactional(propagation = Propagation.REQUIRES_NEW)
+    public AjaxResult pdaGroupDisk(PdaGroupDiskDTO pdaGroupDiskDTO) {
+        GroupDiskConvertDTO groupDiskConvertDTO = buildGroupDiskConvertDTO(pdaGroupDiskDTO);
+        String locationId = invLotLocGroupDisk(groupDiskConvertDTO);
+        BigDecimal palletTotal = invLotAttService.queryPalletTotal(groupDiskConvertDTO.getPalletTo());
+        if (StringUtils.isBlank(groupDiskConvertDTO.getWmsOrderNo())) return AjaxResult.success("组盘成功!托盘数量: " + palletTotal);
+        groupDiskConvertDTO.setLocationId(locationId);
+        wmsDocOrderGroupDisk(groupDiskConvertDTO);
+        return AjaxResult.success("当前托盘备货成功!托盘数量: " + palletTotal);
+    }
+
+    /**
+     * PDA反拣组盘
+     */
+    @Override
+    @Transactional(propagation = Propagation.REQUIRES_NEW)
+    public AjaxResult pdaReversePickGroupDisk(ReversePickGroupDiskDTO reversePickGroupDiskDTO){
+        ReversePickConvertDTO reversePickConvertDTO = buildReversePickConvertDTO(reversePickGroupDiskDTO);
+        //判断反拣类型为解绑还是扩容
+        BigDecimal qty = judgeReversePickType(reversePickConvertDTO.getSku(), reversePickConvertDTO.getOrderNo());
+        //1. 理货备货
+        if (CompareUtil.compare(qty, BigDecimal.ZERO) < 0){
+            PdaGroupDiskDTO pdaGroupDiskDTO = ConvertUtils.sourceToTarget(reversePickConvertDTO, PdaGroupDiskDTO.class);
+            return pdaGroupDisk(pdaGroupDiskDTO);
+        }
+        //2. 解绑当前物料
+        //反拣情况下原托盘为目标解绑托盘 新托盘为目标绑定托盘
+        Long locationId = unbindWmsBox(reversePickConvertDTO.getPalletFrom(), reversePickConvertDTO.getPalletTo());
+        List<InvLotAtt> invLotAttList = invLotAttService.queryInvLotAtt(reversePickConvertDTO.getPalletFrom(), reversePickConvertDTO.getSn(), reversePickConvertDTO.getOrderNo());
+        unbindInvLotLoc(invLotAttList.stream().map(InvLotAtt::getLotnum).collect(Collectors.toList()), locationId, reversePickConvertDTO.getPalletTo(), reversePickConvertDTO.getSku());
+        //删除条码扫描记录
+        erpBarcodesService.untieRecordErpBarcodeListAsnSo(reversePickConvertDTO.getErpNo(), null, reversePickConvertDTO.getSn());
+        return AjaxResult.success("条码:" + reversePickConvertDTO.getSn() + "与出库单:" + reversePickGroupDiskDTO.getErpNo() + "解绑成功!");
     }
 
+    /**
+     * PDA解绑物料
+     */
     @Transactional(propagation = Propagation.REQUIRES_NEW)
-    public AjaxResult unbindWmsBox(UnbindWmsBoxDTO unbindWmsBoxDTO) {
-        WmsBoxInfo wmsBoxToInfo = wmsBoxInfoService.selectWmsBoxInfoByBoxNo(unbindWmsBoxDTO.getPalletTo());
+    public AjaxResult pdaUnbind(UnbindDTO unbindDTO) {
+        InvLotLocId invLotLocId = invLotLocIdService.queryInvLotLocIdByLotnum(unbindDTO.getLotnum());
+        Long locationId = unbindWmsBox(unbindDTO.getPalletTo(), unbindDTO.getPalletFrom());
+        unbindInvLotLoc(unbindDTO.getLotnum(), locationId, unbindDTO.getPalletFrom(), unbindDTO.getSku());
+        if (StringUtils.isBlank(unbindDTO.getErpNo())) return AjaxResult.success("托盘:" + unbindDTO.getPalletTo() + "解绑成功!托盘数量: " + invLotAttService.queryPalletTotal(unbindDTO.getPalletTo()));
+        // 删除条码扫描记录
+        erpBarcodesService.untieRecordErpBarcodeListAsnSo(unbindDTO.getErpNo(), null, unbindDTO.getSn());
+        unbindWmsDocOrder(unbindDTO.getErpNo(), invLotLocId.getQty());
+        return AjaxResult.success("托盘:" + unbindDTO.getPalletTo() + "解绑成功!托盘数量: " + invLotAttService.queryPalletTotal(unbindDTO.getPalletTo()));
+    }
+
+    /**
+     * 解绑托盘
+     * @param palletTo 目标解绑托盘
+     * @param palletFrom 目标绑定托盘
+     * @return
+     */
+    private Long unbindWmsBox(String palletTo, String palletFrom){
+        WmsBoxInfo wmsBoxToInfo = wmsBoxInfoService.selectWmsBoxInfoByBoxNo(palletTo);
         if (ObjectUtil.isNull(wmsBoxToInfo)) {
-            throw new BaseException("查询不到目标托盘:" + unbindWmsBoxDTO.getPalletTo());
+            throw new BaseException("查询不到目标托盘:" + palletTo);
         }
-        WmsBoxInfo wmsBoxFromInfo = wmsBoxInfoService.selectWmsBoxInfoByBoxNo(unbindWmsBoxDTO.getPalletFrom());
+        WmsBoxInfo wmsBoxFromInfo = wmsBoxInfoService.selectWmsBoxInfoByBoxNo(palletFrom);
         if (ObjectUtil.isNull(wmsBoxFromInfo)){
-            throw new BaseException("查询不到起始托盘:" + unbindWmsBoxDTO.getPalletFrom());
+            throw new BaseException("查询不到起始托盘:" + palletFrom);
         }
-        Long locationId = Optional.ofNullable(wmsBoxFromInfo.getLocationId()).orElseThrow(() -> new BaseException("起始托盘库位信息被清空:" + unbindWmsBoxDTO.getPalletFrom()));
+        Long locationId = Optional.ofNullable(wmsBoxFromInfo.getLocationId()).orElseThrow(() -> new BaseException("起始托盘库位信息被清空:" + palletFrom));
         //把目标托盘设置成非满拖
         wmsBoxToInfo.setIsFull("N");
         wmsBoxInfoService.updateWmsBoxInfo(wmsBoxToInfo);
+        return locationId;
+    }
 
-        List<InvLotLocId> invLotLocIdList = invLotLocIdService.selectInvLotLocIdByLotnum(unbindWmsBoxDTO.getLotnum());
-        if (CollectionUtil.isEmpty(invLotLocIdList)) {
-            throw new BaseException("该托盘不存在库存:" + unbindWmsBoxDTO.getPalletTo());
-        }
-        InvLotLocId invLotLocId = invLotLocIdList.stream().findFirst().get();
-        InvLotAtt invLotAtt = invLotAttService.selectInvLotAttByLotnum(invLotLocId.getLotnum());
+    private void unbindInvLotLoc(List<String> lotNumList, Long locationId, String palletNo, String sku){
+        List<InvLotLocId> invLotLocIdList = invLotLocIdService.queryInvLotLocIdByLotnum(lotNumList);
+        InvLotLocId invLotLocId = invLotLocIdList.stream().findFirst().orElseThrow(() -> new BaseException("库位库存信息丢失!"));
+        unbindInvLotLoc(invLotLocId.getLotnum(), locationId, palletNo, sku);
+    }
+
+    private void unbindInvLotLoc(String lotNum, Long locationId, String palletNo, String sku){
+        InvLotAtt invLotAtt = invLotAttService.selectInvLotAttByLotnum(lotNum);
         //创建新批次
-        String lotNum = IdWorker.getIdStr();
-        invLotAttService.insertInvLotAtt(buildInvLotAtt(lotNum, unbindWmsBoxDTO.getPalletFrom(), null, invLotAtt.getLotatt02()
-                , unbindWmsBoxDTO.getSku(), StringUtils.isNotBlank(invLotAtt.getLotatt08()) ? invLotAtt.getLotatt08() : null));
+        String newLotNum = IdWorker.getIdStr();
+        invLotAttService.insertInvLotAtt(buildInvLotAtt(newLotNum, palletNo, null, invLotAtt.getLotatt02()
+                , sku, StringUtils.isNotBlank(invLotAtt.getLotatt08()) ? invLotAtt.getLotatt08() : null));
         //修改库存
-        invLotLocIdService.updateInvLotLocIdLotNum(invLotLocId.getLotnum(), lotNum, String.valueOf(locationId), BigDecimal.ZERO);
-        if (StringUtils.isBlank(unbindWmsBoxDTO.getErpNo())) return AjaxResult.success("托盘:" + unbindWmsBoxDTO.getPalletTo() + "解绑成功!");
+        invLotLocIdService.updateInvLotLocIdLotNum(lotNum, newLotNum, String.valueOf(locationId), BigDecimal.ZERO);
+    }
 
-        WmsDocOrderHeader wmsDocOrderHeader = selectWmsDocOrderHeaderByErpNo(unbindWmsBoxDTO.getErpNo());
+    private void unbindWmsDocOrder(String erpNo, BigDecimal qty){
+        WmsDocOrderHeader wmsDocOrderHeader = selectWmsDocOrderHeaderByErpNo(erpNo);
         if (ObjectUtil.isNull(wmsDocOrderHeader)) throw new BaseException("出库单号错误!");
         String orderNo = wmsDocOrderHeader.getOrderNo();
-        List<WmsDocOrderDetails> wmsDocOrderDetailsList = wmsDocOrderDetailsService.queryWmsDocOrderDetailsByOrderNo(orderNo);
+        List<WmsDocOrderDetails> wmsDocOrderDetailsList = wmsDocOrderDetailsService.queryWmsDocOrderDetails(orderNo);
         if (CollectionUtil.isEmpty(wmsDocOrderDetailsList)) throw new BaseException("出库单明细为空!");
         wmsDocOrderDetailsList = ListUtil.reverse(wmsDocOrderDetailsList.stream().filter(item -> ObjectUtil.isNotNull(item.getQtyAllocated())
                 || !NumberUtil.equals(item.getQtyAllocated(), BigDecimal.ZERO)).collect(Collectors.toList()));
-        BigDecimal qty = invLotLocId.getQty();
 
         for (WmsDocOrderDetails wmsDocOrderDetails : wmsDocOrderDetailsList) {
-            Boolean flag = CompareUtil.compare(qty, wmsDocOrderDetails.getQtyAllocated()) >= 0;
+            boolean flag = CompareUtil.compare(qty, wmsDocOrderDetails.getQtyAllocated()) >= 0;
             wmsDocOrderDetails.setQtyAllocated(flag ? BigDecimal.ZERO : wmsDocOrderDetails.getQtyAllocated().subtract(qty));
             wmsDocOrderDetails.setQtyAllocatedEach(wmsDocOrderDetails.getQtyAllocated());
             wmsDocOrderDetails.setLineStatus(flag ? Constant.ORDER_STS.STS00.getValue() : Constant.ORDER_STS.STS10.getValue());
@@ -2793,75 +3050,92 @@ public class WmsDocOrderHeaderServiceImpl implements IWmsDocOrderHeaderService {
         //修改出库单单据状态
         wmsDocOrderHeaderMapper.update(new WmsDocOrderHeader(), Wrappers.<WmsDocOrderHeader>lambdaUpdate()
                 .set(WmsDocOrderHeader::getOrderStatus, Constant.ORDER_STS.STS22.getValue()).eq(WmsDocOrderHeader::getOrderNo, orderNo));
+    }
 
-        // 删除条码扫描记录
-        erpBarcodesService.untieRecordErpBarcodeListAsnSo(unbindWmsBoxDTO.getErpNo(), null, invLotAtt.getLotatt02());
-        return AjaxResult.success("托盘:" + unbindWmsBoxDTO.getPalletTo() + "解绑成功!");
+    private ReversePickConvertDTO buildReversePickConvertDTO(ReversePickGroupDiskDTO reversePickGroupDiskDTO) {
+        ReversePickConvertDTO reversePickConvertDTO = ConvertUtils.sourceToTarget(reversePickGroupDiskDTO, ReversePickConvertDTO.class);
+        // 根据条码获取物料号
+        CodeSkuRelationshipVO codeSkuRelationshipVO = codeSkuRelationshipService.checkIsProduct(reversePickConvertDTO.getSn());
+        String sku = codeSkuRelationshipVO.getSku();
+        WmsDocOrderHeader wmsDocOrderHeader = selectWmsDocOrderHeaderByErpNo(reversePickConvertDTO.getErpNo());
+        String orderNo = Optional.ofNullable(wmsDocOrderHeader).orElseThrow(() -> new BaseException("请扫描正确的出库单号!")).getOrderNo();
+        reversePickConvertDTO.setOrderNo(orderNo);
+        reversePickConvertDTO.setSku(sku);
+        return reversePickConvertDTO;
     }
 
     /**
-     * PDA理货备货并发控制
-     * @param pdaGroupDiskDTO
-     * @return
+     * 判断反拣类型为解绑还是扩容 返回负数扩容 正数解绑
      */
-    @Override
-    public synchronized AjaxResult syncPdaGroupDiskBH(PdaGroupDiskDTO pdaGroupDiskDTO){
-        return pdaGroupDiskBH(pdaGroupDiskDTO);
+    private BigDecimal judgeReversePickType(String sku, String orderNo){
+        List<InvLotAtt> invLotAttList = invLotAttService.queryOrderSameSkuInvLotAttList(sku, orderNo);
+        if (CollectionUtil.isEmpty(invLotAttList)) throw new BaseException("该出库单未进行理货备货,无法反拣!");
+        List<InvLotLocId> invLotLocIdList = invLotLocIdService.queryInvLotLocIdByLotnum(invLotAttList.stream().map(InvLotAtt::getLotnum).collect(Collectors.toList()));
+        List<WmsDocOrderDetails> wmsDocOrderDetailsList = wmsDocOrderDetailsService.queryWmsDocOrderDetails(orderNo, sku);
+        BigDecimal orderAllocatedQty = invLotLocIdList.stream().map(InvLotLocId::getQtyallocated).reduce(BigDecimal.ZERO, BigDecimal::add);
+        BigDecimal orderRequireQty = wmsDocOrderDetailsList.stream().map(WmsDocOrderDetails::getQtyOrdered).reduce(BigDecimal.ZERO, BigDecimal::add);
+        if (CompareUtil.compare(orderAllocatedQty, orderRequireQty) == 0) throw new BaseException("出库单该品号不存在反拣情况!");
+        return NumberUtil.sub(orderAllocatedQty, orderRequireQty);
     }
 
-    /**
-     * PDA理货备货
-     *
-     * @param pdaGroupDiskDTO
-     * @return
-     */
-    @Override
-    @Transactional(propagation = Propagation.REQUIRES_NEW)
-    public AjaxResult pdaGroupDiskBH(PdaGroupDiskDTO pdaGroupDiskDTO) {
-        String palletNoFrom = pdaGroupDiskDTO.getPalletNoFrom(); // 起始托盘
-        String palletNoTo = pdaGroupDiskDTO.getPalletNoTo(); // 目标托盘
-        String sn = pdaGroupDiskDTO.getSn(); // 条码号
-        String boxNo = StringUtils.isNotBlank(pdaGroupDiskDTO.getBoxNo()) ? pdaGroupDiskDTO.getBoxNo() : palletNoTo; //箱号
-        BigDecimal qty = new BigDecimal(pdaGroupDiskDTO.getQty()); // 数量
+    private GroupDiskConvertDTO buildGroupDiskConvertDTO(PdaGroupDiskDTO pdaGroupDiskDTO) {
+        GroupDiskConvertDTO groupDiskConvertDTO = ConvertUtils.sourceToTarget(pdaGroupDiskDTO, GroupDiskConvertDTO.class);
+        String boxNo = StringUtils.isNotBlank(pdaGroupDiskDTO.getBoxNo()) ? pdaGroupDiskDTO.getBoxNo() : pdaGroupDiskDTO.getPalletTo();
+        String lotNum = IdWorker.getIdStr();
+        groupDiskConvertDTO.setBoxNo(boxNo);
+        groupDiskConvertDTO.setGroupDiskQty(new BigDecimal(pdaGroupDiskDTO.getQty()));
+        groupDiskConvertDTO.setLotNum(lotNum);
         // 根据条码获取物料号
-        CodeSkuRelationshipVO codeSkuRelationshipVO = codeSkuRelationshipService.checkIsProduct(sn);
+        CodeSkuRelationshipVO codeSkuRelationshipVO = codeSkuRelationshipService.checkIsProduct(pdaGroupDiskDTO.getSn());
         // 物料编码
         String sku = codeSkuRelationshipVO.getSku();
-        WmsDocOrderHeader wmsDocOrderHeader = selectWmsDocOrderHeaderByErpNo(pdaGroupDiskDTO.getOrderNo());
-        String orderNo = wmsDocOrderHeader.getOrderNo();
-        List<WmsDocOrderDetails> wmsDocOrderDetailsList = wmsDocOrderDetailsService.queryWmsDocOrderDetailsByOrderNo(orderNo);
-        List<WmsDocOrderDetails> wmsDocOrderDetailsMatchSkuList = wmsDocOrderDetailsList.stream().filter(item -> item.getSku().equals(sku)).collect(Collectors.toList());
-        if (CollectionUtil.isEmpty(wmsDocOrderDetailsMatchSkuList)){
-            throw new BaseException("出库明细未绑定此类产品!");
-        }
-        //筛选出相同sku并且数量未分配或未分配完的明细信息
-        List<WmsDocOrderDetails> wmsDocOrderDetailsFilterList = wmsDocOrderDetailsMatchSkuList.stream()
-                .filter(item -> CompareUtil.compare(item.getQtyOrdered().subtract(item.getQtyAllocated()), BigDecimal.ZERO) > 0).collect(Collectors.toList());
-        if (CollectionUtil.isEmpty(wmsDocOrderDetailsFilterList)){
-            throw new BaseException("出库单该产品已备货完成!");
-        }
-
-        //验证托盘相关信息并获取指向托盘库位信息
-        String locationId = verifyInvLotAndGetLocationId(palletNoTo, sn, orderNo);
+        groupDiskConvertDTO.setSku(sku);
+        if (StringUtils.isBlank(pdaGroupDiskDTO.getErpNo())) return groupDiskConvertDTO;
+        WmsDocOrderHeader wmsDocOrderHeader = selectWmsDocOrderHeaderByErpNo(pdaGroupDiskDTO.getErpNo());
+        groupDiskConvertDTO.setWmsOrderNo(Optional.ofNullable(wmsDocOrderHeader).orElseThrow(() -> new BaseException("请扫描正确的出库单号!")).getOrderNo());
+        return groupDiskConvertDTO;
+    }
 
-        List<InvLotAtt> invLotAttList = invLotAttService.queryInvLotAtt(palletNoFrom, sn);
+    private String invLotLocGroupDisk(GroupDiskConvertDTO groupDiskConvertDTO){
+        List<InvLotAtt> invLotAttList = invLotAttService.queryInvLotAtt(groupDiskConvertDTO.getPalletFrom(), groupDiskConvertDTO.getSn());
         List<InvLotLocId> invLotLocIdList = invLotLocIdService.queryInvLotLocIdByLotnum(invLotAttList.stream().map(InvLotAtt::getLotnum).collect(Collectors.toList()));
+        String orderNo = StringUtils.isNotBlank(groupDiskConvertDTO.getWmsOrderNo()) ? groupDiskConvertDTO.getWmsOrderNo() : null;
         //创建新批次
-        String lotNum = IdWorker.getIdStr();
         InvLotLocId invLotLocId = invLotLocIdList.stream().findFirst().orElseThrow(() -> new BaseException("库位库存信息丢失!"));
         String asnNo = invLotAttList.stream().filter(item -> item.getLotnum().equals(invLotLocId.getLotnum())).map(InvLotAtt::getLotatt08).findFirst().orElseThrow(() -> new BaseException("此批次入库信息丢失!"));
-        invLotAttService.insertInvLotAtt(buildInvLotAtt(lotNum, palletNoTo, orderNo, sn, sku, asnNo));
+        String sku = groupDiskConvertDTO.getSku();
+        invLotAttService.insertInvLotAtt(buildInvLotAtt(groupDiskConvertDTO.getLotNum(), groupDiskConvertDTO.getPalletTo(), orderNo, groupDiskConvertDTO.getSn(), sku, asnNo));
         BigDecimal qtyAllocated = ObjectUtil.isNotNull(invLotLocId.getQtyallocated()) ? invLotLocId.getQtyallocated() : BigDecimal.ZERO;
         BigDecimal invLotLocQty = invLotLocId.getQty().subtract(qtyAllocated);
+        //验证托盘相关信息并获取指向托盘库位信息
+        String locationId = verifyInvLotAndGetLocationId(groupDiskConvertDTO.getPalletTo(), groupDiskConvertDTO.getSn(), orderNo);
         locationId = StringUtils.isNotBlank(locationId) ? locationId : invLotLocId.getLocationId();
-        if (CompareUtil.compare(qty, invLotLocQty) >= 0) {
-            invLotLocIdService.updateInvLotLocId(invLotLocId.getLotnum(), lotNum, invLotLocQty, sku, locationId);
+        if (CompareUtil.compare(groupDiskConvertDTO.getGroupDiskQty(), invLotLocQty) >= 0) {
+            invLotLocIdService.updateInvLotLocId(invLotLocId.getLotnum(), groupDiskConvertDTO.getLotNum(), invLotLocQty, sku, locationId);
         } else {
             // 拆分库存
             // 修改原库存
-            invLotLocIdService.updateInvLotLocId(invLotLocId.getLotnum(), qtyAllocated.add(qty), invLotLocId.getSku());
+            invLotLocIdService.updateInvLotLocId(invLotLocId.getLotnum(), qtyAllocated.add(groupDiskConvertDTO.getGroupDiskQty()), invLotLocId.getSku());
             // 插入新库存
-            invLotLocIdService.insertInvLotLocId(buildInvLotLocId(lotNum, qty, locationId, orderNo, sku));
+            invLotLocIdService.insertInvLotLocId(buildInvLotLocId(groupDiskConvertDTO.getLotNum(), groupDiskConvertDTO.getGroupDiskQty(), locationId, invLotLocId.getTraceid(), sku));
+        }
+        // 更新托盘
+        wmsBoxInfoService.updateWmsBoxLocationIdByBoxNo(groupDiskConvertDTO.getBoxNo(), Long.parseLong(locationId));
+        return locationId;
+    }
+
+    private void wmsDocOrderGroupDisk(GroupDiskConvertDTO groupDiskConvertDTO){
+        BigDecimal qty = groupDiskConvertDTO.getGroupDiskQty();
+        List<WmsDocOrderDetails> wmsDocOrderDetailsList = wmsDocOrderDetailsService.queryWmsDocOrderDetails(groupDiskConvertDTO.getWmsOrderNo());
+        List<WmsDocOrderDetails> wmsDocOrderDetailsMatchSkuList = wmsDocOrderDetailsList.stream().filter(item -> item.getSku().equals(groupDiskConvertDTO.getSku())).collect(Collectors.toList());
+        if (CollectionUtil.isEmpty(wmsDocOrderDetailsMatchSkuList)){
+            throw new BaseException("出库明细未绑定此类产品!");
+        }
+        //筛选出相同sku并且数量未分配或未分配完的明细信息
+        List<WmsDocOrderDetails> wmsDocOrderDetailsFilterList = wmsDocOrderDetailsMatchSkuList.stream()
+                .filter(item -> CompareUtil.compare(item.getQtyOrdered().subtract(item.getQtyAllocated()), BigDecimal.ZERO) > 0).collect(Collectors.toList());
+        if (CollectionUtil.isEmpty(wmsDocOrderDetailsFilterList)){
+            throw new BaseException("出库单该产品已备货完成!");
         }
 
         for (WmsDocOrderDetails wmsDocOrderDetails : wmsDocOrderDetailsFilterList) {
@@ -2871,29 +3145,27 @@ public class WmsDocOrderHeaderServiceImpl implements IWmsDocOrderHeaderService {
             BigDecimal wmsDocOrderDetailsQty = wmsDocOrderDetails.getQtyOrdered().subtract(wmsDocOrderDetailsQtyAllocated);
             //理货备货数量小于单个明细所需数量判断
             BigDecimal remainQty = qty.subtract(wmsDocOrderDetailsQty);
-            Boolean flag = CompareUtil.compare(remainQty, BigDecimal.ZERO) < 0;
+            boolean flag = CompareUtil.compare(remainQty, BigDecimal.ZERO) < 0;
 
             wmsDocOrderDetails.setQtyAllocated(flag ? wmsDocOrderDetailsQtyAllocated.add(qty) : wmsDocOrderDetails.getQtyOrdered());
             wmsDocOrderDetails.setQtyAllocatedEach(wmsDocOrderDetails.getQtyAllocated());
             wmsDocOrderDetails.setLineStatus(flag ? Constant.ORDER_STS.STS10.getValue() : Constant.ORDER_STS.STS20.getValue());
             wmsDocOrderDetailsService.updateWmsDocOrderDetails(wmsDocOrderDetails);
             //生成分配明细
-            actAllocationDetailsService.addActAllocationDetails(lotNum, locationId, qty, wmsDocOrderDetails
+            actAllocationDetailsService.addActAllocationDetails(groupDiskConvertDTO.getLotNum(), groupDiskConvertDTO.getLocationId(), qty, wmsDocOrderDetails
                     , wmsDocOrderDetails.getLineStatus());
             // 记录扫码数据
-            erpBarcodesService.recordErpBarcodeListSo(wmsDocOrderDetails, sn
-                    , "SORTATION01", palletNoTo, BigDecimal.ONE, boxNo);
+            erpBarcodesService.recordErpBarcodeListSo(wmsDocOrderDetails, groupDiskConvertDTO.getSn()
+                    , "SORTATION01", groupDiskConvertDTO.getPalletTo(), BigDecimal.ONE, groupDiskConvertDTO.getBoxNo());
             qty = remainQty;
             if (flag || CompareUtil.compare(qty, BigDecimal.ZERO) == 0) break;
         }
-        // 更新托盘
-        wmsBoxInfoService.updateWmsBoxLocationIdByBoxNo(boxNo, Long.parseLong(locationId));
-        List<WmsDocOrderDetails> wmsDocOrderDetailsByOrderNo = wmsDocOrderDetailsService.queryWmsDocOrderDetailsByOrderNo(orderNo);
+
+        List<WmsDocOrderDetails> wmsDocOrderDetailsByOrderNo = wmsDocOrderDetailsService.queryWmsDocOrderDetails(groupDiskConvertDTO.getWmsOrderNo());
         List<WmsDocOrderDetails> docOrderDetailsList = wmsDocOrderDetailsByOrderNo.stream()
                 .filter(item -> CompareUtil.compare(item.getLineStatus(), Constant.ORDER_STS.STS20.getValue()) != 0).collect(Collectors.toList());
         wmsDocOrderHeaderMapper.update(new WmsDocOrderHeader(), Wrappers.<WmsDocOrderHeader>lambdaUpdate()
-                .set(WmsDocOrderHeader::getOrderStatus, CollectionUtil.isNotEmpty(docOrderDetailsList) ? Constant.ORDER_STS.STS22.getValue() : Constant.ORDER_STS.STS23.getValue()).eq(WmsDocOrderHeader::getOrderNo, orderNo));
-        return AjaxResult.success("当前托盘备货成功!托盘数量: " + invLotAttService.queryPalletTotal(palletNoTo));
+                .set(WmsDocOrderHeader::getOrderStatus, CollectionUtil.isNotEmpty(docOrderDetailsList) ? Constant.ORDER_STS.STS22.getValue() : Constant.ORDER_STS.STS23.getValue()).eq(WmsDocOrderHeader::getOrderNo, groupDiskConvertDTO.getWmsOrderNo()));
     }
 
     private String verifyInvLotAndGetLocationId(String palletNoTo, String sn, String orderNo) {
@@ -2906,11 +3178,13 @@ public class WmsDocOrderHeaderServiceImpl implements IWmsDocOrderHeaderService {
         //验证是否已经有不同出库单备货了
         List<InvLotLocId> invLotLocIdList = invLotLocIdService.queryInvLotLocIdByLotnum(palletNoToInvLotAttList.stream().map(InvLotAtt::getLotnum).collect(Collectors.toList()));
         if (CollectionUtil.isEmpty(invLotLocIdList)) return null;
+        String locationId = invLotLocIdList.stream().filter(item -> StringUtils.isNotBlank(item.getLocationId())).map(InvLotLocId::getLocationId).findFirst().orElseThrow(() -> new BaseException("指向托盘库位信息丢失!"));
+        if (StringUtils.isBlank(orderNo)) return locationId;
         List<InvLotAtt> invLotAttList = palletNoToInvLotAttList.stream().filter(item ->
                 invLotLocIdList.stream().map(InvLotLocId::getLotnum).collect(Collectors.toList()).contains(item.getLotnum())).collect(Collectors.toList());
         List<InvLotAtt> invLotAttFilterList = invLotAttList.stream().filter(item -> StringUtils.isNotBlank(item.getLotatt14()) && !item.getLotatt14().equals(orderNo)).collect(Collectors.toList());
         if (CollectionUtil.isNotEmpty(invLotAttFilterList)) throw new BaseException("该托盘已备货其他出库单: " + invLotAttFilterList.stream().map(InvLotAtt::getLotatt14).collect(Collectors.joining(",")));
-        return invLotLocIdList.stream().filter(item -> StringUtils.isNotBlank(item.getLocationId())).map(InvLotLocId::getLocationId).findFirst().orElseThrow(() -> new BaseException("指向托盘库位信息丢失!"));
+        return locationId;
     }
 
     private InvLotLocId buildInvLotLocId(String lotNum, BigDecimal qty, String locationId, String traceId, String sku) {
@@ -2940,113 +3214,8 @@ public class WmsDocOrderHeaderServiceImpl implements IWmsDocOrderHeaderService {
         return invLotAtt;
     }
 
-    /**
-     * 验证出库单
-     *
-     * @param orderNo
-     */
-    private void verifyWmsDocOrder(String orderNo) {
-        WmsDocOrderHeader header = wmsDocOrderHeaderService.selectWmsDocOrderHeaderByOrderNo(orderNo);
-        if (ObjectUtil.isNull(header)) throw new BaseException("查无此出库单数据" + orderNo);
-        if (!header.getOrderType().equals(Constant.ORDER_TYP.BH.getValue())) {
-            throw new BaseException("出库单类型不可备货组盘!");
-        }
-        if (!header.getOrderStatus().equals(Constant.ORDER_STS.STS10.getValue())
-                && !header.getOrderStatus().equals(Constant.ORDER_STS.STS20.getValue())
-                && !header.getOrderStatus().equals(Constant.ORDER_STS.STS22.getValue())) {
-            throw new BaseException("出库单状态不可备货组盘!");
-        }
-    }
-
-    /**
-     * 库存分配
-     *
-     * @param
-     * orderNos
-     * @return
-     */
-    @Override
-    @Transactional
-    public Boolean inventoryMatch(String orderNos) {
-        List<String> orderList = JSONArray.parseArray(orderNos, String.class);
-        String order = orderList.stream().collect(Collectors.joining(","));
-        List<PalletMatchLog> palletMatchLogList = palletMatchLogService.queryAllPalletMatchLogByOrderNos(order);
-        if (CollectionUtil.isNotEmpty(palletMatchLogList)) {
-            palletMatchLogService.logicalDeletionPalletMatchLog(palletMatchLogList);
-        }
-
-        //根据erp单号获取出库单头列表
-        List<WmsDocOrderHeader> wmsDocOrderHeaderList = wmsDocOrderHeaderMapper.selectList(Wrappers.<WmsDocOrderHeader>lambdaQuery().in(WmsDocOrderHeader::getSoReference1, orderList).orderByDesc(WmsDocOrderHeader::getCreateTime));
-        if (CollectionUtil.isEmpty(wmsDocOrderHeaderList)) {
-            throw new BaseException("请扫描正确的出库单号");
-        }
-        List<WmsDocOrderHeader> wmsDocOrderHeaderFilterList = wmsDocOrderHeaderList.stream().filter(item -> item.getOrderStatus().equals(Constant.ORDER_STS.STS00.getValue())
-                || item.getOrderStatus().equals(Constant.ORDER_STS.STS10.getValue()) || item.getOrderStatus().equals(Constant.ORDER_STS.STS22.getValue())).collect(Collectors.toList());
-        if (CollectionUtil.isEmpty(wmsDocOrderHeaderFilterList)) {
-            throw new BaseException("出库单状态不可进行库存匹配!");
-        }
-        List<WmsDocOrderDetails> wmsDocOrderDetailsList = wmsDocOrderDetailsService.queryWmsDocOrderDetailsByOrderNo(
-                wmsDocOrderHeaderFilterList.stream().filter(item -> StringUtils.isNotBlank(item.getOrderNo()))
-                        .map(WmsDocOrderHeader::getOrderNo).collect(Collectors.toList()));
-        if (CollectionUtil.isEmpty(wmsDocOrderDetailsList)) {
-            throw new BaseException("出库单明细为空!");
-        }
-        Map<String, List<WmsDocOrderDetails>> wmsDocOrderDetailsGroupBySkuMap = wmsDocOrderDetailsList.stream().filter(item -> StringUtils.isNotBlank(item.getSku())).collect(Collectors.groupingBy(WmsDocOrderDetails::getSku));
-        if (CollectionUtil.isEmpty(wmsDocOrderDetailsGroupBySkuMap)) {
-            throw new BaseException("出库单明细绑定sku为空!");
-        }
-        Map<String, List<InvLotAttPalletTotalDTO>> invLotAttPalletTotalMap = invLotAttService.buildInvLotAttPalletTotalMap(wmsDocOrderDetailsGroupBySkuMap.entrySet().stream().map(Map.Entry::getKey).collect(Collectors.toList()));
-        if (CollectionUtil.isEmpty(invLotAttPalletTotalMap)) {
-            throw new BaseException("所选出库单绑定sku无库存!");
-        }
-        //所需出库托盘
-        List<InvLotAttPalletTotalDTO> result = new ArrayList<>();
-        for (Map.Entry<String, List<WmsDocOrderDetails>> wmsDocOrderDetailsGroupBySkuMapEntry : wmsDocOrderDetailsGroupBySkuMap.entrySet()) {
-            //扫描出库单各sku需求总数
-            BigDecimal total = wmsDocOrderDetailsGroupBySkuMapEntry.getValue().stream().filter(item -> ObjectUtil.isNotNull(item.getQtyOrdered())).map(item -> ObjectUtil.isNotNull(item.getQtyAllocated())
-                    ? item.getQtyOrdered().subtract(item.getQtyAllocated()) : item.getQtyOrdered()).reduce(BigDecimal.ZERO, BigDecimal::add);
-            if (CompareUtil.compare(total, BigDecimal.ZERO) <= 0) continue;
-            List<InvLotAttPalletTotalDTO> invLotAttPalletTotalDTOList = invLotAttPalletTotalMap.get(wmsDocOrderDetailsGroupBySkuMapEntry.getKey());
-            if (CollectionUtil.isEmpty(invLotAttPalletTotalDTOList)) continue;
-            if (CollectionUtil.isNotEmpty(palletMatchLogList)){
-                List<InvLotAttPalletTotalDTO> invLotAttPalletTotalList = invLotAttPalletTotalDTOList.stream().filter(item -> !palletMatchLogList.stream().map(palletMatchLog -> palletMatchLog.getPalletNo()).collect(Collectors.toList()).contains(item.getPalletNo())).collect(Collectors.toList());
-                if (CollectionUtil.isEmpty(invLotAttPalletTotalList)) {
-                    result.addAll(invLotAttPalletTotalDTOList);
-                    continue;
-                }
-                invLotAttPalletTotalDTOList = invLotAttPalletTotalList;
-            }
-
-            for (InvLotAttPalletTotalDTO invLotAttPalletTotalDTO : invLotAttPalletTotalDTOList) {
-                BigDecimal palletTotal = new BigDecimal(invLotAttPalletTotalDTO.getTotalQty());
-                if (CompareUtil.compare(total, palletTotal) <= 0) {
-                    result.add(invLotAttPalletTotalDTO);
-                    break;
-                }
-                total = total.subtract(palletTotal);
-                result.add(invLotAttPalletTotalDTO);
-            }
-        }
-        return palletMatchLogService.insertBatch(buildPalletMatchLogList(result, orderList));
-    }
-
-    @Override
-    public List<PalletMatchLogDTO> queryPalletMatchInfoList(String orderNos) {
-        List<String> orderList = JSONArray.parseArray(orderNos, String.class);
-        String order = orderList.stream().collect(Collectors.joining(","));
-        List<PalletMatchLog> palletMatchLogList = palletMatchLogService.queryPalletMatchLogByOrderNos(order);
-        List<BaseLocationInfo> baseLocationInfoList = baseLocationInfoService.selectBaseLocationInfoList(palletMatchLogList.stream().map(PalletMatchLog::getLocationId).collect(Collectors.toList()));
-
-        return palletMatchLogList.stream().map(item -> {
-            PalletMatchLogDTO palletMatchLogDTO = ConvertUtils.sourceToTarget(item, PalletMatchLogDTO.class);
-            BaseLocationInfo locationInfo = baseLocationInfoList.stream().filter(baseLocationInfo -> baseLocationInfo.getId().equals(Long.parseLong(item.getLocationId()))).findFirst().orElseThrow(() -> new BaseException("库位信息有误"));
-            palletMatchLogDTO.setLocationNo(locationInfo.getLocationNo());
-            return palletMatchLogDTO;
-        }).collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(PalletMatchLogDTO::getPalletNo))), ArrayList::new));
-    }
-
     private List<PalletMatchLog> buildPalletMatchLogList(List<InvLotAttPalletTotalDTO> invLotAttPalletTotalDTOList, List<String> orderList) {
-        String orderNos = orderList.stream().collect(Collectors.joining(","));
+        String orderNos = String.join(",", orderList);
         Date createTime = DateUtils.getNowDate();
         return invLotAttPalletTotalDTOList.stream().map(item -> {
             PalletMatchLog palletMatchLog = ConvertUtils.sourceToTarget(item, PalletMatchLog.class);