Parcourir la source

Merge remote-tracking branch 'origin/bionutrition_dev' into bionutrition

zhangxin il y a 1 an
Parent
commit
ad7eef0995
38 fichiers modifiés avec 930 ajouts et 222 suppressions
  1. 14 5
      ruoyi-admin/src/main/java/com/ruoyi/bionutrition/pda/controller/PdaAgvCallController.java
  2. 20 6
      ruoyi-admin/src/main/java/com/ruoyi/bionutrition/pda/controller/PdaDocQcController.java
  3. 11 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/warewms/doc/BionutritionDocHeaderController.java
  4. 39 39
      ruoyi-admin/src/test/java/com/ruoyi/admin/test/base/WarehouseTest.java
  5. 15 16
      ruoyi-common/src/main/java/com/ruoyi/common/handler/FieldMetaObjectHandler.java
  6. 1 1
      warewms-ams/src/main/java/com/ruoyi/ams/agv/ndc/AciService.java
  7. 2 0
      warewms-ams/src/main/java/com/ruoyi/ams/agv/ndc/service/impl/StatusUpdateServiceImpl.java
  8. 3 0
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/domain/BionutritionDocDetails.java
  9. 3 0
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/BionutritionDocDetailsDTO.java
  10. 2 0
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/service/BionutritionDocHeaderService.java
  11. 1 13
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/service/impl/BionutritionDocDetailsServiceImpl.java
  12. 18 8
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/service/impl/BionutritionDocHeaderServiceImpl.java
  13. 10 0
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/dto/AsnAgvCallDTO.java
  14. 43 0
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/dto/QcIntoStorageDTO.java
  15. 25 0
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/dto/QcOutboundDTO.java
  16. 52 0
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/dto/ReturningInventoryDTO.java
  17. 13 4
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/pda/IPdaAgvCallService.java
  18. 16 6
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/pda/IPdaDocQcService.java
  19. 194 53
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/pda/impl/PdaAgvCallServiceImpl.java
  20. 136 20
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/pda/impl/PdaDocQcServiceImpl.java
  21. 73 1
      warewms-ams/src/main/java/com/ruoyi/ams/business/BusinessServiceImpl.java
  22. 7 0
      warewms-ams/src/main/java/com/ruoyi/ams/business/IBusinessService.java
  23. 5 1
      warewms-ams/src/main/java/com/ruoyi/ams/config/domain/dto/AgvCallDTO.java
  24. 6 0
      warewms-ams/src/main/java/com/ruoyi/ams/config/domain/dto/AgvCallItemDTO.java
  25. 7 1
      warewms-ams/src/main/java/com/ruoyi/ams/config/domain/dto/LotattDTO.java
  26. 20 13
      warewms-ams/src/main/java/com/ruoyi/ams/config/mapper/FlowConfigHeaderMapper.java
  27. 10 8
      warewms-ams/src/main/java/com/ruoyi/ams/config/service/IFlowConfigHeaderService.java
  28. 5 0
      warewms-ams/src/main/java/com/ruoyi/ams/config/service/impl/FlowConfigHeaderServiceImpl.java
  29. 9 0
      warewms-ams/src/main/java/com/ruoyi/ams/inv/domain/InvLotLocId.java
  30. 6 0
      warewms-ams/src/main/java/com/ruoyi/ams/inv/mapper/InvLotLocIdMapper.java
  31. 6 0
      warewms-ams/src/main/java/com/ruoyi/ams/inv/service/IInvLotLocIdService.java
  32. 22 13
      warewms-ams/src/main/java/com/ruoyi/ams/inv/service/impl/InvLotLocIdServiceImpl.java
  33. 10 6
      warewms-ams/src/main/java/com/ruoyi/ams/task/service/impl/WcsTaskServiceImpl.java
  34. 13 0
      warewms-ams/src/main/resources/mapper/ams/FlowConfigHeaderMapper.xml
  35. 2 2
      warewms-ams/src/main/resources/mapper/ams/InvLotAttMapper.xml
  36. 34 4
      warewms-ams/src/main/resources/mapper/ams/InvLotLocIdMapper.xml
  37. 75 2
      warewms-base/src/main/java/com/ruoyi/base/constant/Constant.java
  38. 2 0
      warewms-base/src/main/java/com/ruoyi/base/constant/type/BizEnum.java

+ 14 - 5
ruoyi-admin/src/main/java/com/ruoyi/bionutrition/pda/controller/PdaAgvCallController.java

@@ -1,17 +1,19 @@
 package com.ruoyi.bionutrition.pda.controller;
 
-import cn.hutool.core.lang.Assert;
 import com.ruoyi.ams.bionutrition.dto.AsnAgvCallDTO;
 import com.ruoyi.ams.bionutrition.dto.GroundingDTO;
+import com.ruoyi.ams.bionutrition.dto.ReturningInventoryDTO;
 import com.ruoyi.ams.bionutrition.pda.IPdaAgvCallService;
 import com.ruoyi.ams.business.IBusinessService;
 import com.ruoyi.ams.task.service.IWcsTaskService;
 import com.ruoyi.common.core.domain.AjaxResult;
-import com.ruoyi.common.utils.StringUtils;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
 
 import javax.validation.Valid;
 
@@ -38,12 +40,19 @@ public class PdaAgvCallController {
         return AjaxResult.success("入库任务下发成功");
     }
 
-    @ApiOperation("pda上架入库")
+    @ApiOperation("pda回库任务")
+    @PostMapping("/returningToInventory")
+    public AjaxResult returningToInventory(@RequestBody @Valid ReturningInventoryDTO returningInventoryDTO) {
+        pdaAgvCallService.returningToInventory(returningInventoryDTO);
+        return AjaxResult.success("回库任务下发成功");
+    }
+
+    /*@ApiOperation("pda上架入库")
     @PostMapping("/grounding")
     public AjaxResult grounding(@RequestBody @Valid GroundingDTO groundingDTO) {
         pdaAgvCallService.grounding(groundingDTO);
         return AjaxResult.success("上架成功");
-    }
+    }*/
 
     @PostMapping("/testCallBack")
     public AjaxResult testCallBack(@RequestBody CallBackDTO callBackDTO){

+ 20 - 6
ruoyi-admin/src/main/java/com/ruoyi/bionutrition/pda/controller/PdaDocQcController.java

@@ -2,6 +2,8 @@ package com.ruoyi.bionutrition.pda.controller;
 
 import com.ruoyi.ams.bionutrition.dto.AsnAgvCallDTO;
 import com.ruoyi.ams.bionutrition.dto.DocQcDTO;
+import com.ruoyi.ams.bionutrition.dto.QcIntoStorageDTO;
+import com.ruoyi.ams.bionutrition.dto.QcOutboundDTO;
 import com.ruoyi.ams.bionutrition.pda.IPdaAgvCallService;
 import com.ruoyi.ams.bionutrition.pda.IPdaDocQcService;
 import com.ruoyi.common.core.controller.BaseController;
@@ -41,14 +43,26 @@ public class PdaDocQcController extends BaseController {
     }
 
     /**
-     * 质检提交
-     * @param docQcDTO
+     * 质检出库
+     * @param qcOutboundDTO
      * @return
      */
-    @ApiOperation("pda质检")
-    @PostMapping("/submit")
-    public AjaxResult docQcSubmit(@RequestBody @Valid DocQcDTO docQcDTO) {
-        pdaDocQcService.docQcSubmit(docQcDTO, getUsername());
+    @ApiOperation("pda质检出库")
+    @PostMapping("/qcOutbound")
+    public AjaxResult qcOutbound(@RequestBody @Valid QcOutboundDTO qcOutboundDTO) {
+        pdaDocQcService.qcOutbound(qcOutboundDTO, getUsername());
+        return AjaxResult.success();
+    }
+
+    /**
+     * 质检入库
+     * @param qcIntoStorageDTO
+     * @return
+     */
+    @ApiOperation("pda质检入库")
+    @PostMapping("/qcIntoStorage")
+    public AjaxResult qcIntoStorage(@RequestBody @Valid QcIntoStorageDTO qcIntoStorageDTO) {
+        pdaDocQcService.qcIntoStorage(qcIntoStorageDTO, getUsername());
         return AjaxResult.success();
     }
 

+ 11 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/warewms/doc/BionutritionDocHeaderController.java

@@ -109,6 +109,17 @@ public class BionutritionDocHeaderController extends BaseController {
         return AjaxResult.success(docBaseDTOList);
     }
 
+    /**
+     * 获取出库单据信息
+     */
+    @PreAuthorize("@ss.hasPermi('docAsn:docAsn:query')")
+    @GetMapping("/getSODocInfo")
+    public AjaxResult getSODocInfo()
+    {
+        List<BionutritionDocBaseDTO> docBaseDTOList = bionutritionDocHeaderService.getSODocInfo();;
+        return AjaxResult.success(docBaseDTOList);
+    }
+
     /**
      * 新增单据明细
      */

+ 39 - 39
ruoyi-admin/src/test/java/com/ruoyi/admin/test/base/WarehouseTest.java

@@ -357,44 +357,44 @@ public class WarehouseTest {
     @Test
     public void testInsertBaseLocationInfo(){
         String s = "[\n" +
-                "{\"第1层\":\"G01-01\",\"站点编号1\":901,\"第2层\":\"G02-01\",\"站点编号2\":902,\"第3层\":\"G03-01\",\"站点编号3\":903,\"第4层\":\"G04-01\",\"站点编号4\":904},\n" +
-                "{\"第1层\":\"G01-02\",\"站点编号1\":905,\"第2层\":\"G02-02\",\"站点编号2\":906,\"第3层\":\"G03-02\",\"站点编号3\":907,\"第4层\":\"G04-02\",\"站点编号4\":908},\n" +
-                "{\"第1层\":\"G01-03\",\"站点编号1\":909,\"第2层\":\"G02-03\",\"站点编号2\":910,\"第3层\":\"G03-03\",\"站点编号3\":911,\"第4层\":\"G04-03\",\"站点编号4\":912},\n" +
-                "{\"第1层\":\"G01-04\",\"站点编号1\":913,\"第2层\":\"G02-04\",\"站点编号2\":914,\"第3层\":\"G03-04\",\"站点编号3\":915,\"第4层\":\"G04-04\",\"站点编号4\":916},\n" +
-                "{\"第1层\":\"G01-05\",\"站点编号1\":917,\"第2层\":\"G02-05\",\"站点编号2\":918,\"第3层\":\"G03-05\",\"站点编号3\":919,\"第4层\":\"G04-05\",\"站点编号4\":920},\n" +
-                "{\"第1层\":\"G01-06\",\"站点编号1\":921,\"第2层\":\"G02-06\",\"站点编号2\":922,\"第3层\":\"G03-06\",\"站点编号3\":923,\"第4层\":\"G04-06\",\"站点编号4\":924},\n" +
-                "{\"第1层\":\"G01-07\",\"站点编号1\":925,\"第2层\":\"G02-07\",\"站点编号2\":926,\"第3层\":\"G03-07\",\"站点编号3\":927,\"第4层\":\"G04-07\",\"站点编号4\":928},\n" +
-                "{\"第1层\":\"G01-08\",\"站点编号1\":929,\"第2层\":\"G02-08\",\"站点编号2\":930,\"第3层\":\"G03-08\",\"站点编号3\":931,\"第4层\":\"G04-08\",\"站点编号4\":932},\n" +
-                "{\"第1层\":\"G01-09\",\"站点编号1\":933,\"第2层\":\"G02-09\",\"站点编号2\":934,\"第3层\":\"G03-09\",\"站点编号3\":935,\"第4层\":\"G04-09\",\"站点编号4\":936},\n" +
-                "{\"第1层\":\"G01-10\",\"站点编号1\":937,\"第2层\":\"G02-10\",\"站点编号2\":938,\"第3层\":\"G03-10\",\"站点编号3\":939,\"第4层\":\"G04-10\",\"站点编号4\":940},\n" +
-                "{\"第1层\":\"G01-11\",\"站点编号1\":941,\"第2层\":\"G02-11\",\"站点编号2\":942,\"第3层\":\"G03-11\",\"站点编号3\":943,\"第4层\":\"G04-11\",\"站点编号4\":944},\n" +
-                "{\"第1层\":\"G01-12\",\"站点编号1\":945,\"第2层\":\"G02-12\",\"站点编号2\":946,\"第3层\":\"G03-12\",\"站点编号3\":947,\"第4层\":\"G04-12\",\"站点编号4\":948},\n" +
-                "{\"第1层\":\"G01-13\",\"站点编号1\":949,\"第2层\":\"G02-13\",\"站点编号2\":950,\"第3层\":\"G03-13\",\"站点编号3\":951,\"第4层\":\"G04-13\",\"站点编号4\":952},\n" +
-                "{\"第1层\":\"G01-14\",\"站点编号1\":953,\"第2层\":\"G02-14\",\"站点编号2\":954,\"第3层\":\"G03-14\",\"站点编号3\":955,\"第4层\":\"G04-14\",\"站点编号4\":956},\n" +
-                "{\"第1层\":\"G01-15\",\"站点编号1\":957,\"第2层\":\"G02-15\",\"站点编号2\":958,\"第3层\":\"G03-15\",\"站点编号3\":959,\"第4层\":\"G04-15\",\"站点编号4\":960},\n" +
-                "{\"第1层\":\"G01-16\",\"站点编号1\":961,\"第2层\":\"G02-16\",\"站点编号2\":962,\"第3层\":\"G03-16\",\"站点编号3\":963,\"第4层\":\"G04-16\",\"站点编号4\":964},\n" +
-                "{\"第1层\":\"G01-17\",\"站点编号1\":965,\"第2层\":\"G02-17\",\"站点编号2\":966,\"第3层\":\"G03-17\",\"站点编号3\":967,\"第4层\":\"G04-17\",\"站点编号4\":968},\n" +
-                "{\"第1层\":\"G01-18\",\"站点编号1\":969,\"第2层\":\"G02-18\",\"站点编号2\":970,\"第3层\":\"G03-18\",\"站点编号3\":971,\"第4层\":\"G04-18\",\"站点编号4\":972},\n" +
-                "{\"第1层\":\"G01-19\",\"站点编号1\":973,\"第2层\":\"G02-19\",\"站点编号2\":974,\"第3层\":\"G03-19\",\"站点编号3\":975,\"第4层\":\"G04-19\",\"站点编号4\":976},\n" +
-                "{\"第1层\":\"G01-20\",\"站点编号1\":977,\"第2层\":\"G02-20\",\"站点编号2\":978,\"第3层\":\"G03-20\",\"站点编号3\":979,\"第4层\":\"G04-20\",\"站点编号4\":980},\n" +
-                "{\"第1层\":\"G01-21\",\"站点编号1\":981,\"第2层\":\"G02-21\",\"站点编号2\":982,\"第3层\":\"G03-21\",\"站点编号3\":983,\"第4层\":\"G04-21\",\"站点编号4\":984},\n" +
-                "{\"第1层\":\"G01-22\",\"站点编号1\":985,\"第2层\":\"G02-22\",\"站点编号2\":986,\"第3层\":\"G03-22\",\"站点编号3\":987,\"第4层\":\"G04-22\",\"站点编号4\":988},\n" +
-                "{\"第1层\":\"G01-23\",\"站点编号1\":989,\"第2层\":\"G02-23\",\"站点编号2\":990,\"第3层\":\"G03-23\",\"站点编号3\":991,\"第4层\":\"G04-23\",\"站点编号4\":992},\n" +
-                "{\"第1层\":\"G01-24\",\"站点编号1\":993,\"第2层\":\"G02-24\",\"站点编号2\":994,\"第3层\":\"G03-24\",\"站点编号3\":995,\"第4层\":\"G04-24\",\"站点编号4\":996},\n" +
-                "{\"第1层\":\"G01-25\",\"站点编号1\":997,\"第2层\":\"G02-25\",\"站点编号2\":998,\"第3层\":\"G03-25\",\"站点编号3\":999,\"第4层\":\"G04-25\",\"站点编号4\":1000},\n" +
-                "{\"第1层\":\"G01-26\",\"站点编号1\":1001,\"第2层\":\"G02-26\",\"站点编号2\":1002,\"第3层\":\"G03-26\",\"站点编号3\":1003,\"第4层\":\"G04-26\",\"站点编号4\":1004},\n" +
-                "{\"第1层\":\"G01-27\",\"站点编号1\":1005,\"第2层\":\"G02-27\",\"站点编号2\":1006,\"第3层\":\"G03-27\",\"站点编号3\":1007,\"第4层\":\"G04-27\",\"站点编号4\":1008},\n" +
-                "{\"第1层\":\"G01-28\",\"站点编号1\":1009,\"第2层\":\"G02-28\",\"站点编号2\":1010,\"第3层\":\"G03-28\",\"站点编号3\":1011,\"第4层\":\"G04-28\",\"站点编号4\":1012},\n" +
-                "{\"第1层\":\"G01-29\",\"站点编号1\":1013,\"第2层\":\"G02-29\",\"站点编号2\":1014,\"第3层\":\"G03-29\",\"站点编号3\":1015,\"第4层\":\"G04-29\",\"站点编号4\":1016},\n" +
-                "{\"第1层\":\"G01-30\",\"站点编号1\":1017,\"第2层\":\"G02-30\",\"站点编号2\":1018,\"第3层\":\"G03-30\",\"站点编号3\":1019,\"第4层\":\"G04-30\",\"站点编号4\":1020},\n" +
-                "{\"第1层\":\"G01-31\",\"站点编号1\":1021,\"第2层\":\"G02-31\",\"站点编号2\":1022,\"第3层\":\"G03-31\",\"站点编号3\":1023,\"第4层\":\"G04-31\",\"站点编号4\":1024},\n" +
-                "{\"第1层\":\"G01-32\",\"站点编号1\":1025,\"第2层\":\"G02-32\",\"站点编号2\":1026,\"第3层\":\"G03-32\",\"站点编号3\":1027,\"第4层\":\"G04-32\",\"站点编号4\":1028},\n" +
-                "{\"第1层\":\"G01-33\",\"站点编号1\":1029,\"第2层\":\"G02-33\",\"站点编号2\":1030,\"第3层\":\"G03-33\",\"站点编号3\":1031,\"第4层\":\"G04-33\",\"站点编号4\":1032},\n" +
-                "{\"第1层\":\"G01-34\",\"站点编号1\":1033,\"第2层\":\"G02-34\",\"站点编号2\":1034,\"第3层\":\"G03-34\",\"站点编号3\":1035,\"第4层\":\"G04-34\",\"站点编号4\":1036},\n" +
-                "{\"第1层\":\"G01-35\",\"站点编号1\":1037,\"第2层\":\"G02-35\",\"站点编号2\":1038,\"第3层\":\"G03-35\",\"站点编号3\":1039,\"第4层\":\"G04-35\",\"站点编号4\":1040},\n" +
-                "{\"第1层\":\"G01-36\",\"站点编号1\":1041,\"第2层\":\"G02-36\",\"站点编号2\":1042,\"第3层\":\"G03-36\",\"站点编号3\":1043,\"第4层\":\"G04-36\",\"站点编号4\":1044},\n" +
-                "{\"第1层\":\"G01-37\",\"站点编号1\":1045,\"第2层\":\"G02-37\",\"站点编号2\":1046,\"第3层\":\"G03-37\",\"站点编号3\":1047,\"第4层\":\"G04-37\",\"站点编号4\":1048},\n" +
-                "{\"第1层\":\"G01-38\",\"站点编号1\":1049,\"第2层\":\"G02-38\",\"站点编号2\":1050,\"第3层\":\"G03-38\",\"站点编号3\":1051,\"第4层\":\"G04-38\",\"站点编号4\":1052}\n" +
+                "{\"第1层\":\"o01-01\",\"站点编号1\":1981,\"第2层\":\"o02-01\",\"站点编号2\":1982,\"第3层\":\"o03-01\",\"站点编号3\":1983,\"第4层\":\"o04-01\",\"站点编码4\":1984},\n" +
+                "{\"第1层\":\"o01-02\",\"站点编号1\":1985,\"第2层\":\"o02-02\",\"站点编号2\":1986,\"第3层\":\"o03-02\",\"站点编号3\":1987,\"第4层\":\"o04-02\",\"站点编码4\":1988},\n" +
+                "{\"第1层\":\"o01-03\",\"站点编号1\":1989,\"第2层\":\"o02-03\",\"站点编号2\":1990,\"第3层\":\"o03-03\",\"站点编号3\":1991,\"第4层\":\"o04-03\",\"站点编码4\":1992},\n" +
+                "{\"第1层\":\"o01-04\",\"站点编号1\":1993,\"第2层\":\"o02-04\",\"站点编号2\":1994,\"第3层\":\"o03-04\",\"站点编号3\":1995,\"第4层\":\"o04-04\",\"站点编码4\":1996},\n" +
+                "{\"第1层\":\"o01-05\",\"站点编号1\":1997,\"第2层\":\"o02-05\",\"站点编号2\":1998,\"第3层\":\"o03-05\",\"站点编号3\":1999,\"第4层\":\"o04-05\",\"站点编码4\":2000},\n" +
+                "{\"第1层\":\"o01-06\",\"站点编号1\":2001,\"第2层\":\"o02-06\",\"站点编号2\":2002,\"第3层\":\"o03-06\",\"站点编号3\":2003,\"第4层\":\"o04-06\",\"站点编码4\":2004},\n" +
+                "{\"第1层\":\"o01-07\",\"站点编号1\":2005,\"第2层\":\"o02-07\",\"站点编号2\":2006,\"第3层\":\"o03-07\",\"站点编号3\":2007,\"第4层\":\"o04-07\",\"站点编码4\":2008},\n" +
+                "{\"第1层\":\"o01-08\",\"站点编号1\":2009,\"第2层\":\"o02-08\",\"站点编号2\":2010,\"第3层\":\"o03-08\",\"站点编号3\":2011,\"第4层\":\"o04-08\",\"站点编码4\":2012},\n" +
+                "{\"第1层\":\"o01-09\",\"站点编号1\":2013,\"第2层\":\"o02-09\",\"站点编号2\":2014,\"第3层\":\"o03-09\",\"站点编号3\":2015,\"第4层\":\"o04-09\",\"站点编码4\":2016},\n" +
+                "{\"第1层\":\"o01-10\",\"站点编号1\":2017,\"第2层\":\"o02-10\",\"站点编号2\":2018,\"第3层\":\"o03-10\",\"站点编号3\":2019,\"第4层\":\"o04-10\",\"站点编码4\":2020},\n" +
+                "{\"第1层\":\"o01-11\",\"站点编号1\":2021,\"第2层\":\"o02-11\",\"站点编号2\":2022,\"第3层\":\"o03-11\",\"站点编号3\":2023,\"第4层\":\"o04-11\",\"站点编码4\":2024},\n" +
+                "{\"第1层\":\"o01-12\",\"站点编号1\":2025,\"第2层\":\"o02-12\",\"站点编号2\":2026,\"第3层\":\"o03-12\",\"站点编号3\":2027,\"第4层\":\"o04-12\",\"站点编码4\":2028},\n" +
+                "{\"第1层\":\"o01-13\",\"站点编号1\":2029,\"第2层\":\"o02-13\",\"站点编号2\":2030,\"第3层\":\"o03-13\",\"站点编号3\":2031,\"第4层\":\"o04-13\",\"站点编码4\":2032},\n" +
+                "{\"第1层\":\"o01-14\",\"站点编号1\":2033,\"第2层\":\"o02-14\",\"站点编号2\":2034,\"第3层\":\"o03-14\",\"站点编号3\":2035,\"第4层\":\"o04-14\",\"站点编码4\":2036},\n" +
+                "{\"第1层\":\"o01-15\",\"站点编号1\":2037,\"第2层\":\"o02-15\",\"站点编号2\":2038,\"第3层\":\"o03-15\",\"站点编号3\":2039,\"第4层\":\"o04-15\",\"站点编码4\":2040},\n" +
+                "{\"第1层\":\"o01-16\",\"站点编号1\":2041,\"第2层\":\"o02-16\",\"站点编号2\":2042,\"第3层\":\"o03-16\",\"站点编号3\":2043,\"第4层\":\"o04-16\",\"站点编码4\":2044},\n" +
+                "{\"第1层\":\"o01-17\",\"站点编号1\":2045,\"第2层\":\"o02-17\",\"站点编号2\":2046,\"第3层\":\"o03-17\",\"站点编号3\":2047,\"第4层\":\"o04-17\",\"站点编码4\":2048},\n" +
+                "{\"第1层\":\"o01-18\",\"站点编号1\":2049,\"第2层\":\"o02-18\",\"站点编号2\":2050,\"第3层\":\"o03-18\",\"站点编号3\":2051,\"第4层\":\"o04-18\",\"站点编码4\":2052},\n" +
+                "{\"第1层\":\"o01-19\",\"站点编号1\":2053,\"第2层\":\"o02-19\",\"站点编号2\":2054,\"第3层\":\"o03-19\",\"站点编号3\":2055,\"第4层\":\"o04-19\",\"站点编码4\":2906},\n" +
+                "{\"第1层\":\"o01-20\",\"站点编号1\":2056,\"第2层\":\"o02-20\",\"站点编号2\":2057,\"第3层\":\"o03-20\",\"站点编号3\":2058,\"第4层\":\"o04-20\",\"站点编码4\":2907},\n" +
+                "{\"第1层\":\"o01-21\",\"站点编号1\":2059,\"第2层\":\"o02-21\",\"站点编号2\":2060,\"第3层\":\"o03-21\",\"站点编号3\":2061,\"第4层\":\"o04-21\",\"站点编码4\":2062},\n" +
+                "{\"第1层\":\"o01-22\",\"站点编号1\":2063,\"第2层\":\"o02-22\",\"站点编号2\":2064,\"第3层\":\"o03-22\",\"站点编号3\":2065,\"第4层\":\"o04-22\",\"站点编码4\":2066},\n" +
+                "{\"第1层\":\"o01-23\",\"站点编号1\":2067,\"第2层\":\"o02-23\",\"站点编号2\":2068,\"第3层\":\"o03-23\",\"站点编号3\":2069,\"第4层\":\"o04-23\",\"站点编码4\":2070},\n" +
+                "{\"第1层\":\"o01-24\",\"站点编号1\":2071,\"第2层\":\"o02-24\",\"站点编号2\":2072,\"第3层\":\"o03-24\",\"站点编号3\":2073,\"第4层\":\"o04-24\",\"站点编码4\":2074},\n" +
+                "{\"第1层\":\"o01-25\",\"站点编号1\":2075,\"第2层\":\"o02-25\",\"站点编号2\":2076,\"第3层\":\"o03-25\",\"站点编号3\":2077,\"第4层\":\"o04-25\",\"站点编码4\":2078},\n" +
+                "{\"第1层\":\"o01-26\",\"站点编号1\":2079,\"第2层\":\"o02-26\",\"站点编号2\":2080,\"第3层\":\"o03-26\",\"站点编号3\":2081,\"第4层\":\"o04-26\",\"站点编码4\":2082},\n" +
+                "{\"第1层\":\"o01-27\",\"站点编号1\":2083,\"第2层\":\"o02-27\",\"站点编号2\":2084,\"第3层\":\"o03-27\",\"站点编号3\":2085,\"第4层\":\"o04-27\",\"站点编码4\":2086},\n" +
+                "{\"第1层\":\"o01-28\",\"站点编号1\":2087,\"第2层\":\"o02-28\",\"站点编号2\":2088,\"第3层\":\"o03-28\",\"站点编号3\":2089,\"第4层\":\"o04-28\",\"站点编码4\":2090},\n" +
+                "{\"第1层\":\"o01-29\",\"站点编号1\":2091,\"第2层\":\"o02-29\",\"站点编号2\":2092,\"第3层\":\"o03-29\",\"站点编号3\":2093,\"第4层\":\"o04-29\",\"站点编码4\":2094},\n" +
+                "{\"第1层\":\"o01-30\",\"站点编号1\":2095,\"第2层\":\"o02-30\",\"站点编号2\":2096,\"第3层\":\"o03-30\",\"站点编号3\":2097,\"第4层\":\"o04-30\",\"站点编码4\":2098},\n" +
+                "{\"第1层\":\"o01-31\",\"站点编号1\":2099,\"第2层\":\"o02-31\",\"站点编号2\":2100,\"第3层\":\"o03-31\",\"站点编号3\":2101,\"第4层\":\"o04-31\",\"站点编码4\":2102},\n" +
+                "{\"第1层\":\"o01-32\",\"站点编号1\":2103,\"第2层\":\"o02-32\",\"站点编号2\":2104,\"第3层\":\"o03-32\",\"站点编号3\":2105,\"第4层\":\"o04-32\",\"站点编码4\":2106},\n" +
+                "{\"第1层\":\"o01-33\",\"站点编号1\":2107,\"第2层\":\"o02-33\",\"站点编号2\":2108,\"第3层\":\"o03-33\",\"站点编号3\":2109,\"第4层\":\"o04-33\",\"站点编码4\":2110},\n" +
+                "{\"第1层\":\"o01-34\",\"站点编号1\":2111,\"第2层\":\"o02-34\",\"站点编号2\":2112,\"第3层\":\"o03-34\",\"站点编号3\":2113,\"第4层\":\"o04-34\",\"站点编码4\":2114},\n" +
+                "{\"第1层\":\"o01-35\",\"站点编号1\":2115,\"第2层\":\"o02-35\",\"站点编号2\":2116,\"第3层\":\"o03-35\",\"站点编号3\":2117,\"第4层\":\"o04-35\",\"站点编码4\":2118},\n" +
+                "{\"第1层\":\"o01-36\",\"站点编号1\":2119,\"第2层\":\"o02-36\",\"站点编号2\":2120,\"第3层\":\"o03-36\",\"站点编号3\":2121,\"第4层\":\"o04-36\",\"站点编码4\":2122},\n" +
+                "{\"第1层\":\"o01-37\",\"站点编号1\":2123,\"第2层\":\"o02-37\",\"站点编号2\":2124,\"第3层\":\"o03-37\",\"站点编号3\":2125,\"第4层\":\"o04-37\",\"站点编码4\":2126},\n" +
+                "{\"第1层\":\"o01-38\",\"站点编号1\":2127,\"第2层\":\"o02-38\",\"站点编号2\":2128,\"第3层\":\"o03-38\",\"站点编号3\":2129,\"第4层\":\"o04-38\",\"站点编码4\":2130},\n" +
                 "]";
         JSONArray jsonArray = JSONUtil.parseArray(s);
         List<Dict> dicts = JSONUtil.toList(jsonArray, Dict.class);
@@ -437,7 +437,7 @@ public class WarehouseTest {
                 baseLocationInfo.setColIndex(Long.parseLong(split[1]));
                 System.out.println(baseLocationInfo);
 
-                baseLocationInfoService.insertBaseLocationInfo(baseLocationInfo);
+//                baseLocationInfoService.insertBaseLocationInfo(baseLocationInfo);
             }
 
         }

+ 15 - 16
ruoyi-common/src/main/java/com/ruoyi/common/handler/FieldMetaObjectHandler.java

@@ -25,28 +25,27 @@ public class FieldMetaObjectHandler implements MetaObjectHandler {
 
     @Override
     public void insertFill(MetaObject metaObject) {
-        /*try {
-            if (ObjectUtil.isNotNull(metaObject) && metaObject.getOriginalObject() instanceof BaseEntity) {
-                BaseExtEntity baseExtEntity = (BaseExtEntity) metaObject.getOriginalObject();
-                Date currentDate = ObjectUtil.isNotNull(baseExtEntity.getCreateDate())
-                        ? baseExtEntity.getCreateDate() : new Date();
-                baseExtEntity.setCreateDate(currentDate).setUpdateDate(currentDate);
-                String operateUser = StringUtils.isNotBlank(baseExtEntity.getCreator())
-                        ? baseExtEntity.getCreator() : SecurityUtils.getUsername();
-                baseExtEntity.setCreator(operateUser).setUpdater(operateUser);
-            }
+        String userName;
+        try {
+            userName = SecurityUtils.getUsername();
         } catch (Exception e) {
-            throw new ServiceException("自动注入异常 => " + e.getMessage(), HttpStatus.HTTP_UNAUTHORIZED);
-        }*/
-        strictInsertFill(metaObject, CREATOR, String.class, SecurityUtils.getUsername());
+            userName = "PDA";
+        }
+        strictInsertFill(metaObject, CREATOR, String.class, userName);
         strictInsertFill(metaObject, CREATE_DATE, Date.class, DateUtil.date());
-        strictInsertFill(metaObject, UPDATER, String.class, SecurityUtils.getUsername());
+        strictInsertFill(metaObject, UPDATER, String.class, userName);
         strictInsertFill(metaObject, UPDATE_DATE, Date.class, DateUtil.date());
     }
 
     @Override
     public void updateFill(MetaObject metaObject) {
-        strictInsertFill(metaObject, UPDATER, String.class, SecurityUtils.getUsername());
+        String userName;
+        try {
+            userName = SecurityUtils.getUsername();
+        } catch (Exception e) {
+            userName = "PDA";
+        }
+        strictInsertFill(metaObject, UPDATER, String.class, userName);
         strictInsertFill(metaObject, UPDATE_DATE, Date.class, DateUtil.date());
     }
-}
+}

+ 1 - 1
warewms-ams/src/main/java/com/ruoyi/ams/agv/ndc/AciService.java

@@ -37,7 +37,7 @@ public class AciService {
 
     private static final int BUFF_SIZE = 2048;
 
-    private static final String IP_ADDR = "192.168.88.137";
+    private static final String IP_ADDR = "192.168.88.132";
 
     private static final int IP_PORT = 30002;
 

+ 2 - 0
warewms-ams/src/main/java/com/ruoyi/ams/agv/ndc/service/impl/StatusUpdateServiceImpl.java

@@ -103,6 +103,8 @@ public class StatusUpdateServiceImpl implements StatusUpdateService {
 
     @Override
     public synchronized void confirmAnalysis(String taskNo, Integer aciIndex, String type, Integer carNo) {
+
+        // todo 读取plc信号 1.12
         AmsTask amsTask = new AmsTask();
         amsTask.setTaskNo(taskNo);
         amsTask = amsTaskService.selectAmsTaskByModel(amsTask);

+ 3 - 0
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/domain/BionutritionDocDetails.java

@@ -86,4 +86,7 @@ public class BionutritionDocDetails extends WarewmsExtEntity {
     @ApiModelProperty("已搬运数量")
     private String transferredQty;
 
+    @ApiModelProperty("单据关联信息")
+    private String relatesInformation;
+
 }

+ 3 - 0
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/BionutritionDocDetailsDTO.java

@@ -82,4 +82,7 @@ public class BionutritionDocDetailsDTO extends WarewmsExtDTO {
 
     @ApiModelProperty("已搬运数量")
     private String transferredQty;
+
+    @ApiModelProperty("单据关联信息")
+    private String relatesInformation;
 }

+ 2 - 0
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/service/BionutritionDocHeaderService.java

@@ -109,4 +109,6 @@ public interface BionutritionDocHeaderService extends CrudService<BionutritionDo
     void updateDocStatus(WcsTask wcsTask);
 
     List<BionutritionDocBaseDTO> buildBionutritionDocBaseDTOByIdList(String docNo, String docType);
+
+    List<BionutritionDocBaseDTO> getSODocInfo();
 }

+ 1 - 13
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/service/impl/BionutritionDocDetailsServiceImpl.java

@@ -151,19 +151,7 @@ public class BionutritionDocDetailsServiceImpl extends CrudServiceImpl<Bionutrit
     @Override
     public List<BionutritionDocBaseDTO> selectDetailsByDocNoAndDocType(String docNo, String docType) {
         List<BionutritionDocBaseDTO> docBaseDTOList = bionutritionDocHeaderService.buildBionutritionDocBaseDTOByIdList(docNo, docType);
-        if (StringUtils.isNotBlank(docType)) return docBaseDTOList;
-        // 上架入库
-        return docBaseDTOList.stream().map(item->{
-            BionutritionDocBaseDTO bionutritionDocBaseDTO = item;
-            // 只返回完全入库的明细
-            List<BionutritionDocDetailsBaseDTO> docBaseDTOFilterList = item.getBionutritionDocDetailsBaseDTOList().stream().filter(
-                        details -> StringUtils.equals(details.getLineStatus(), Constant.ASN_STS.STS40.getValue()))
-                        .collect(Collectors.toList());
-            bionutritionDocBaseDTO.setBionutritionDocDetailsBaseDTOList(docBaseDTOFilterList);
-            return bionutritionDocBaseDTO;
-            }).filter(item->CollUtil.isNotEmpty(item.getBionutritionDocDetailsBaseDTOList())
-                && !StringUtils.equals(item.getBionutritionDocHeaderBaseDTO().getDocType(), BizEnum.BionutritionHeaderDocTypeEnum.PURCHASE_RECEIPT.getDocType()))
-                .collect(Collectors.toList());
+        return docBaseDTOList;
     }
 
     public List<BionutritionDocDetailsDTO> getBionutritionDocDetailsDTOList(List<String> docHeaderIdList, String skuCode) {

+ 18 - 8
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/service/impl/BionutritionDocHeaderServiceImpl.java

@@ -18,10 +18,7 @@ import com.github.pagehelper.Page;
 import com.github.pagehelper.PageInfo;
 import com.google.common.collect.Lists;
 import com.ruoyi.ams.bionutrition.doc.domain.BionutritionDocHeader;
-import com.ruoyi.ams.bionutrition.doc.dto.BionutritionDocBaseDTO;
-import com.ruoyi.ams.bionutrition.doc.dto.BionutritionDocDetailsDTO;
-import com.ruoyi.ams.bionutrition.doc.dto.BionutritionDocHeaderDTO;
-import com.ruoyi.ams.bionutrition.doc.dto.DocExcelQueryDTO;
+import com.ruoyi.ams.bionutrition.doc.dto.*;
 import com.ruoyi.ams.bionutrition.doc.dto.detail.BionutritionDocDetailsBaseDTO;
 import com.ruoyi.ams.bionutrition.doc.dto.header.BionutritionDocHeaderBaseDTO;
 import com.ruoyi.ams.bionutrition.doc.dto.header.FinishedProductReceiptHeaderDTO;
@@ -517,7 +514,19 @@ public class BionutritionDocHeaderServiceImpl extends CrudServiceImpl<Bionutriti
      * @return
      */
     public List<BionutritionDocBaseDTO> buildBionutritionDocBaseDTOByIdList(String docNo, String docType) {
-        List<BionutritionDocHeaderDTO> bionutritionDocHeaderDTOList = getLikeBionutritionDocHeaderDTOList(docNo, docType);
+        List<BionutritionDocHeaderDTO> bionutritionDocHeaderDTOList = getLikeBionutritionDocHeaderDTOList(docNo, docType, null);
+        List<String> docTypeList = bionutritionDocHeaderDTOList.stream().map(item -> item.getDocType()).distinct().collect(Collectors.toList());
+        return NumberUtil.isGreater(BigDecimal.valueOf(docTypeList.size()), BigDecimal.ONE) ?
+                buildBionutritionDocDifferentTypeList(bionutritionDocHeaderDTOList) : buildBionutritionDocSameTypeList(bionutritionDocHeaderDTOList);
+    }
+
+    /**
+     * 获取出库类型单据
+     * @return
+     */
+    @Override
+    public List<BionutritionDocBaseDTO> getSODocInfo() {
+        List<BionutritionDocHeaderDTO> bionutritionDocHeaderDTOList = getLikeBionutritionDocHeaderDTOList(null, null, Constant.BUSINESS_TYPE.ORDER.getValue());
         List<String> docTypeList = bionutritionDocHeaderDTOList.stream().map(item -> item.getDocType()).distinct().collect(Collectors.toList());
         return NumberUtil.isGreater(BigDecimal.valueOf(docTypeList.size()), BigDecimal.ONE) ?
                 buildBionutritionDocDifferentTypeList(bionutritionDocHeaderDTOList) : buildBionutritionDocSameTypeList(bionutritionDocHeaderDTOList);
@@ -626,7 +635,6 @@ public class BionutritionDocHeaderServiceImpl extends CrudServiceImpl<Bionutriti
     public void updateDocStatus(WcsTask wcsTask) {
         // 不是出入库任务直接返回
         if (StringUtils.isEmpty(wcsTask.getExt5())) return;
-
         String ext5 = wcsTask.getExt5();
         String docNo = null;
         String docLineNo = null;
@@ -669,6 +677,7 @@ public class BionutritionDocHeaderServiceImpl extends CrudServiceImpl<Bionutriti
         log.info("===更改出库单据状态,单号{},明细行号{},单头状态更改为{},明细状态更改为{}",
                 bionutritionDocHeaderBaseDTO.getDocNo(), docDetails.getDocLineNo()
                 , bionutritionDocHeaderBaseDTO.getDocStatus(), docDetails.getLineStatus());
+
     }
 
     /**
@@ -794,10 +803,11 @@ public class BionutritionDocHeaderServiceImpl extends CrudServiceImpl<Bionutriti
         return getBionutritionDocHeaderDTOList(null, null, docType);
     }
 
-    private List<BionutritionDocHeaderDTO> getLikeBionutritionDocHeaderDTOList(String docNo, String docType) {
+    private List<BionutritionDocHeaderDTO> getLikeBionutritionDocHeaderDTOList(String docNo, String docType, String businessType) {
         List<BionutritionDocHeader> bionutritionDocHeaderList = baseDao.selectList(Wrappers.<BionutritionDocHeader>lambdaQuery()
                 .like(StringUtils.isNotEmpty(docNo), BionutritionDocHeader::getDocNo, docNo)
-                .eq(StringUtils.isNotBlank(docType), BionutritionDocHeader::getDocType, docType));
+                .eq(StringUtils.isNotBlank(docType), BionutritionDocHeader::getDocType, docType)
+                .eq(StringUtils.isNotBlank(businessType), BionutritionDocHeader::getBusinessType, businessType));
         return ConvertUtils.sourceToTarget(bionutritionDocHeaderList, BionutritionDocHeaderDTO.class);
     }
 

+ 10 - 0
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/dto/AsnAgvCallDTO.java

@@ -49,6 +49,16 @@ public class AsnAgvCallDTO implements Serializable {
     @NotBlank(message = "请填写明细行号")
     private String lineNo;
 
+    /**
+     * 质量状态
+     */
+    private String status;
+
+    /**
+     * 是否为取样库存 Y:是 N:不是
+     */
+    private String ifSample;
+
     /**
      * 操作人
      */

+ 43 - 0
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/dto/QcIntoStorageDTO.java

@@ -0,0 +1,43 @@
+package com.ruoyi.ams.bionutrition.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotEmpty;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+@Data
+public class QcIntoStorageDTO implements Serializable {
+    private static final long serialVersionUID = 2291385412711706433L;
+
+    /**
+     * 批次号
+     */
+    @NotBlank(message = "批次号不能为空")
+    private String batchNumber;
+
+    /**
+     * 起始点
+     */
+    @NotBlank(message = "请选择起始点")
+    private String locationFrom;
+    /**
+     * 物料编号
+     */
+    @NotBlank(message = "请填写物料信息")
+    private String skuCode;
+    /**
+     * 物料总量
+     */
+    private BigDecimal totalAmount;
+    /**
+     * 批次状态
+     * HG:合格 BHG:不合格 DJ:待检 FX:放行{@link com.ruoyi.base.constant.Constant.QUALITY_STATUS}
+     */
+    @NotBlank(message = "状态不能为空")
+    private String status;
+
+    private String user;
+
+}

+ 25 - 0
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/dto/QcOutboundDTO.java

@@ -0,0 +1,25 @@
+package com.ruoyi.ams.bionutrition.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+@Data
+public class QcOutboundDTO implements Serializable {
+
+    private static final long serialVersionUID = 158592050776754469L;
+
+    private String lotnum;
+
+    /**
+     * 起始点
+     */
+    private String locationFrom;
+
+    /**
+     * 目标点
+     */
+    private String locationTo;
+
+    private String user;
+
+}

+ 52 - 0
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/dto/ReturningInventoryDTO.java

@@ -0,0 +1,52 @@
+package com.ruoyi.ams.bionutrition.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+@Data
+public class ReturningInventoryDTO implements Serializable {
+    private static final long serialVersionUID = 93127792182314672L;
+    /**
+     * 单据号
+     */
+    @NotBlank(message = "请填写单据号")
+    private String docNo ;
+    /**
+     * 起始库位
+     */
+    @NotBlank(message = "请选择起始点位")
+    private String locationFrom;
+    /**
+     * 产品批号
+     */
+    @NotBlank(message = "请填写产品批号")
+    private String batchNumber;
+    /**
+     * 物料总量
+     */
+    private BigDecimal totalAmount;
+    /**
+     * 物料编号
+     */
+    @NotBlank(message = "请填写物料信息")
+    private String skuCode;
+    /**
+     * 单据类型
+     */
+    @NotBlank(message = "单据类型不确定")
+    private String docType;
+    /**
+     * 明细行号
+     */
+    @NotBlank(message = "请填写明细行号")
+    private String lineNo;
+    /**
+     * 操作人
+     */
+    private String user;
+}

+ 13 - 4
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/pda/IPdaAgvCallService.java

@@ -6,10 +6,13 @@ import com.ruoyi.ams.bionutrition.doc.dto.header.BionutritionDocHeaderBaseDTO;
 import com.ruoyi.ams.bionutrition.dto.AsnAgvCallDTO;
 import com.ruoyi.ams.bionutrition.dto.GroundingDTO;
 import com.ruoyi.ams.bionutrition.dto.OrderAgvCallDTO;
+import com.ruoyi.ams.bionutrition.dto.ReturningInventoryDTO;
 import com.ruoyi.ams.config.domain.dto.AgvCallDTO;
 import com.ruoyi.ams.config.domain.dto.LotattDTO;
 import com.ruoyi.base.domain.BaseSku;
 
+import java.util.List;
+
 /**
  * 佰穗莱pda呼叫AGV生成搬运任务
  */
@@ -24,14 +27,14 @@ public interface IPdaAgvCallService {
      * 上架
      * @param groundingDTO
      */
-    void grounding(GroundingDTO groundingDTO);
+//    void grounding(GroundingDTO groundingDTO);
 
     /**
      * 根据单据类型获取流程id
      * @param docType
      * @return
      */
-    Long getFlowIdByDocType(String docType);
+    List<Long> getFlowIdByDocTypeOrSkuType(String docType, String skuType);
 
     /**
      * 构建批次属性对象
@@ -40,7 +43,13 @@ public interface IPdaAgvCallService {
      * @param baseSku
      * @return
      */
-    LotattDTO buildLotattArgument(BionutritionDocHeaderBaseDTO docHeaderBaseDTO,BionutritionDocDetailsBaseDTO docDetailsBaseDTO, DocLotattDTO docLotattDTO, BaseSku baseSku);
+    LotattDTO buildLotattArgument(BionutritionDocHeaderBaseDTO docHeaderBaseDTO,BionutritionDocDetailsBaseDTO docDetailsBaseDTO, DocLotattDTO docLotattDTO, BaseSku baseSku, String status);
+
+    AgvCallDTO getOrderAgvCallDTO(OrderAgvCallDTO orderAgvCallDTO, BionutritionDocHeaderBaseDTO docHeaderBaseDTO, BionutritionDocDetailsBaseDTO docDetailsBaseDTO);
 
-    AgvCallDTO getOrderAgvCallDTO(OrderAgvCallDTO orderAgvCallDTO);
+    /**
+     * pda回库任务
+     * @param returningInventoryDTO
+     */
+    void returningToInventory(ReturningInventoryDTO returningInventoryDTO);
 }

+ 16 - 6
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/pda/IPdaDocQcService.java

@@ -1,6 +1,8 @@
 package com.ruoyi.ams.bionutrition.pda;
 
 import com.ruoyi.ams.bionutrition.dto.DocQcDTO;
+import com.ruoyi.ams.bionutrition.dto.QcIntoStorageDTO;
+import com.ruoyi.ams.bionutrition.dto.QcOutboundDTO;
 
 import java.util.List;
 
@@ -9,15 +11,23 @@ import java.util.List;
  */
 public interface IPdaDocQcService {
 
-    /**
-     * 质检提交
-     * @param docQcDTO
-     */
-    void docQcSubmit(DocQcDTO docQcDTO, String updateBy);
-
     /**
      * 获取质检列表
      * @return
      */
     List<DocQcDTO> getQcList(String sku);
+
+    /**
+     * 质检出库
+     * @param qcOutboundDTO
+     * @param username
+     */
+    void qcOutbound(QcOutboundDTO qcOutboundDTO, String username);
+
+    /**
+     * 质检入库
+     * @param qcIntoStorageDTO
+     * @param username
+     */
+    void qcIntoStorage(QcIntoStorageDTO qcIntoStorageDTO, String username);
 }

+ 194 - 53
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/pda/impl/PdaAgvCallServiceImpl.java

@@ -11,6 +11,7 @@ import cn.hutool.json.JSONArray;
 import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+import com.google.common.collect.Lists;
 import com.ruoyi.ams.agv.ndc.common.Aci;
 import com.ruoyi.ams.bionutrition.doc.domain.BionutritionDocDetails;
 import com.ruoyi.ams.bionutrition.doc.domain.BionutritionDocHeader;
@@ -27,32 +28,45 @@ import com.ruoyi.ams.bionutrition.doc.service.BionutritionDocHeaderService;
 import com.ruoyi.ams.bionutrition.dto.AsnAgvCallDTO;
 import com.ruoyi.ams.bionutrition.dto.GroundingDTO;
 import com.ruoyi.ams.bionutrition.dto.OrderAgvCallDTO;
+import com.ruoyi.ams.bionutrition.dto.ReturningInventoryDTO;
 import com.ruoyi.ams.bionutrition.pda.IPdaAgvCallService;
 import com.ruoyi.ams.business.IBusinessService;
 import com.ruoyi.ams.config.domain.dto.AgvCallDTO;
 import com.ruoyi.ams.config.domain.dto.AgvCallItemDTO;
 import com.ruoyi.ams.config.domain.dto.LotattDTO;
+import com.ruoyi.ams.config.domain.vo.FlowConfigHeaderVO;
+import com.ruoyi.ams.config.service.IFlowConfigHeaderService;
+import com.ruoyi.ams.inv.domain.InvLotAtt;
+import com.ruoyi.ams.inv.domain.InvLotLocId;
+import com.ruoyi.ams.inv.domain.vo.InvLotLocIdLotattVO;
+import com.ruoyi.ams.inv.service.IInvLotAttService;
+import com.ruoyi.ams.inv.service.IInvLotLocIdService;
 import com.ruoyi.base.constant.Constant;
 import com.ruoyi.base.constant.type.BizEnum;
 import com.ruoyi.base.domain.BaseSku;
 import com.ruoyi.base.service.IBaseSkuService;
+import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.constant.base.EnumUtils;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.ConvertUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.system.service.ISysConfigService;
 import lombok.extern.slf4j.Slf4j;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import javax.validation.constraints.NotEmpty;
 import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
+import java.math.RoundingMode;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 
 @Slf4j
 @Service
@@ -68,6 +82,12 @@ public class PdaAgvCallServiceImpl implements IPdaAgvCallService {
     private ISysConfigService iSysConfigService;
     @Autowired
     private IBaseSkuService skuService;
+    @Autowired
+    private IFlowConfigHeaderService flowConfigHeaderService;
+    @Autowired
+    private IInvLotLocIdService invLotLocIdService;
+    @Autowired
+    private IInvLotAttService invLotAttService;
 
     /**
      * 根据单号和单据类型生成入库任务
@@ -84,16 +104,11 @@ public class PdaAgvCallServiceImpl implements IPdaAgvCallService {
         Assert.isTrue(ObjectUtil.isNotNull(bionutritionDocBaseDTO), "该单据不存在");
         BionutritionDocHeaderBaseDTO bionutritionDocHeaderBaseDTO = bionutritionDocBaseDTO.getBionutritionDocHeaderBaseDTO();
         String docType = bionutritionDocHeaderBaseDTO.getDocType();
-        Assert.isTrue(StringUtils.isNotEmpty(docType), "单据信息中单据类型为空");
         Assert.isTrue(StringUtils.equals(bionutritionDocHeaderBaseDTO.getBusinessType(),Constant.BUSINESS_TYPE.ASN.getValue())
                 || StringUtils.equals(bionutritionDocHeaderBaseDTO.getBusinessType(),Constant.BUSINESS_TYPE.PO.getValue())
                 , "该单据不是入库单据");
-        List<BionutritionDocDetailsBaseDTO> docDetailsList = bionutritionDocBaseDTO.getBionutritionDocDetailsBaseDTOList();
-        Assert.isTrue(CollUtil.isNotEmpty(docDetailsList), "单据明细数据为空");
         // 2.根据明细行号筛选明细信息
-        BionutritionDocDetailsBaseDTO docDetailsBaseDTO = docDetailsList.stream().filter(item -> StringUtils.equals(item.getDocLineNo(), asnAgvCallDTO.getLineNo()))
-                .findFirst().orElse(null);
-        Assert.isTrue(ObjectUtil.isNotEmpty(docDetailsBaseDTO), "对应明细行号数据未找到");
+        BionutritionDocDetailsBaseDTO docDetailsBaseDTO = this.filterBionutritionDocDetailsBaseDTOByLineNo(asnAgvCallDTO.getLineNo(), bionutritionDocBaseDTO);
         // 3.判断数量是否超出范围
         // 记录当前明细已搬运数量
         BigDecimal transferredQty = NumberUtil.add(docDetailsBaseDTO.getTransferredQty(), asnAgvCallDTO.getQty());
@@ -102,57 +117,65 @@ public class PdaAgvCallServiceImpl implements IPdaAgvCallService {
                 , "入库数量超出范围,剩余数量"+NumberUtil.sub(docDetailsBaseDTO.getSkuQty(), docDetailsBaseDTO.getTransferredQty()));
         docDetailsBaseDTO.setTransferredQty(transferredQty.toString());
         bionutritionDocDetailsService.updateDocDetails(ConvertUtils.sourceToTarget(docDetailsBaseDTO, BionutritionDocDetailsDTO.class));
-
         // 如果是采购入库 需要根据采购单生成采购入库单
         if (StringUtils.equals(docType, BizEnum.BionutritionExcelDocTitleEnum.PURCHASE_ORDER.getDocType())) {
             this.addPurchaseReceiptDoc(bionutritionDocBaseDTO, docDetailsBaseDTO, asnAgvCallDTO);
         }
-        // 4.获取配置信息单据类型对应流程id
-        Long flowId = this.getFlowIdByDocType(docType);
+        // 4.获取配置信息单据类型或物料类型对应流程id
+        List<Long> flowIds = this.getFlowIdByDocTypeOrSkuType(docType, docDetailsBaseDTO.getSkuCode());
+        List<FlowConfigHeaderVO> flowConfigHeaderVOList = flowConfigHeaderService.selectFlowConfigHeaderByIds(flowIds);
+        Long flowId = flowConfigHeaderVOList.stream().filter(f -> StringUtils.equals(Constant.BUSINESS_TYPE.ASN.getValue(), f.getFlowType()))
+                .map(FlowConfigHeaderVO::getId)
+                .findFirst().orElse(null);
         // 5.生成agv呼叫对象,生成对应wcs任务
-        AgvCallDTO agvCallDTO = this.getASNAgvCallDTO(asnAgvCallDTO, bionutritionDocHeaderBaseDTO, docDetailsBaseDTO);
+        AgvCallDTO agvCallDTO = this.getASNAgvCallDTO(asnAgvCallDTO, bionutritionDocHeaderBaseDTO, docDetailsBaseDTO, null);
         businessService.agvCall(flowId, agvCallDTO);
     }
 
     /**
-     * 上架
-     * @param groundingDTO
+     * 根据明细行号筛选明细
+     * @param lineNo
+     * @param bionutritionDocBaseDTO
+     * @return
      */
-    @Override
-    @Transactional(rollbackFor = RuntimeException.class)
-    public void grounding(GroundingDTO groundingDTO) {
-        // 根据单号和单据类型查询单据信息
-        BionutritionDocBaseDTO bionutritionDocBaseDTO =
-                bionutritionDocHeaderService.selectDocByDocNoAndDocType(groundingDTO.getDocNo(), groundingDTO.getDocType());
-        Assert.isTrue(ObjectUtil.isNotNull(bionutritionDocBaseDTO), "该单据不存在");
+    @Nullable
+    private BionutritionDocDetailsBaseDTO filterBionutritionDocDetailsBaseDTOByLineNo(String lineNo, BionutritionDocBaseDTO bionutritionDocBaseDTO) {
         List<BionutritionDocDetailsBaseDTO> docDetailsList = bionutritionDocBaseDTO.getBionutritionDocDetailsBaseDTOList();
         Assert.isTrue(CollUtil.isNotEmpty(docDetailsList), "单据明细数据为空");
-        BionutritionDocDetailsBaseDTO docDetailsBaseDTO = docDetailsList.stream().filter(item -> StringUtils.equals(item.getDocLineNo(), groundingDTO.getLineNo()))
+        BionutritionDocDetailsBaseDTO docDetailsBaseDTO = docDetailsList.stream().filter(item -> StringUtils.equals(item.getDocLineNo(), lineNo))
                 .findFirst().orElse(null);
-        Assert.isTrue(ObjectUtil.isNotEmpty(docDetailsBaseDTO), "行号对应明细数据未找到");
-        // 修改单据明细状态为完全上架
-        docDetailsBaseDTO.setLineStatus(Constant.ASN_STS.STS60.getValue());
-        bionutritionDocDetailsService.updateDocDetails(ConvertUtils.sourceToTarget(docDetailsBaseDTO, BionutritionDocDetailsDTO.class));
+        Assert.isTrue(ObjectUtil.isNotEmpty(docDetailsBaseDTO), "对应明细行号数据未找到");
+        return docDetailsBaseDTO;
     }
 
     /**
-     * 根据单据类型获取流程id
+     * 根据单据类型或者物料类型获取流程id
      * @param docType
      * @return
      */
     @NotNull
-    public Long getFlowIdByDocType(String docType) {
+    public List<Long> getFlowIdByDocTypeOrSkuType(String docType, String skuCode) {
         JSONArray docTypeFlowObjects = JSONUtil.parseArray(iSysConfigService.selectConfigByKey("sys.docType.corresponding.business"));
-        JSONObject jsonObject = docTypeFlowObjects.stream().map(o -> JSONUtil.parseObj(o.toString()))
-                .filter(entry -> StringUtils.equals(docType, (String) entry.get("docType"))).findFirst().orElse(null);
-        Assert.notNull(jsonObject, "未查找到该单据号对应单据类型");
-        Assert.notNull(jsonObject.get("flowId"), "未找到对应的任务下发流程");
-        Long flowId = Long.parseLong(jsonObject.get("flowId").toString());
-        return flowId;
+        List<JSONObject> jsonObjects = docTypeFlowObjects.stream().map(o -> JSONUtil.parseObj(o.toString()))
+                .filter(entry -> StringUtils.equals(docType, (String) entry.get("docType"))).collect(Collectors.toList());
+        // 如果根据单据类型查询不到流程,则根据物料类型获取
+        if (CollUtil.isEmpty(jsonObjects)){
+            BaseSku queryBaseSku = new BaseSku();
+            queryBaseSku.setSku(skuCode);
+            List<BaseSku> baseSkuList = skuService.selectBaseSkuList(queryBaseSku);
+            Assert.isTrue(CollUtil.isNotEmpty(baseSkuList), "未找到对应物料信息");
+            BaseSku baseSku = baseSkuList.stream().findFirst().get();
+            jsonObjects = docTypeFlowObjects.stream().map(o -> JSONUtil.parseObj(o.toString()))
+                    .filter(entry -> StringUtils.equals(String.valueOf(baseSku.getSkuType()), (String) entry.get("skuType")))
+                    .collect(Collectors.toList());
+        }
+        Assert.isTrue(CollUtil.isNotEmpty(jsonObjects), "未找到对应的任务下发流程");
+        List<Long> flowIds = jsonObjects.stream().map(o->Long.parseLong(o.get("flowId").toString())).collect(Collectors.toList());
+        return flowIds;
     }
 
     /**
-     * 添加采购入库单
+     * 生成采购入库单
      * @param bionutritionDocBaseDTO
      * @param docDetailsBaseDTO
      */
@@ -219,56 +242,79 @@ public class PdaAgvCallServiceImpl implements IPdaAgvCallService {
      * @param asnAgvCallDTO
      * @return
      */
-    private AgvCallDTO getASNAgvCallDTO(AsnAgvCallDTO asnAgvCallDTO, BionutritionDocHeaderBaseDTO docHeaderBaseDTO, BionutritionDocDetailsBaseDTO docDetailsBaseDTO) {
+    private AgvCallDTO getASNAgvCallDTO(AsnAgvCallDTO asnAgvCallDTO, BionutritionDocHeaderBaseDTO docHeaderBaseDTO, BionutritionDocDetailsBaseDTO docDetailsBaseDTO, BigDecimal totalAmount) {
         DocLotattDTO docLotattDTO = ConvertUtils.sourceToTarget(docDetailsBaseDTO, DocLotattDTO.class);
         // 根据物料编码查询物料信息
-        BaseSku baseSku = skuService.selectBaseSkuByCustomerId("default", asnAgvCallDTO.getSkuCode());
+        BaseSku baseSku = skuService.selectBaseSkuByCustomerId(Constants.DEFAULT_CUSTOMER_ID, asnAgvCallDTO.getSkuCode());
         Assert.isTrue(ObjectUtil.isNotEmpty(baseSku), "物料信息未找到");
         List<AgvCallItemDTO> agvCallItemDTOList = new ArrayList<>();
         AgvCallItemDTO agvCallItemDTO = new AgvCallItemDTO();
         // 构建批次属性
-        LotattDTO lotattDTO = this.buildLotattArgument(docHeaderBaseDTO, docDetailsBaseDTO, docLotattDTO, baseSku);
+        LotattDTO lotattDTO = this.buildLotattArgument(docHeaderBaseDTO, docDetailsBaseDTO, docLotattDTO, baseSku, asnAgvCallDTO.getStatus());
 
         agvCallItemDTO.setSku(asnAgvCallDTO.getSkuCode());
         agvCallItemDTO.setQty(Double.valueOf(asnAgvCallDTO.getQty()));
+        // 计算一托盘总量
+        if (ObjectUtil.isEmpty(totalAmount)) totalAmount = this.buildTotalAmount(baseSku, asnAgvCallDTO.getQty());
+        agvCallItemDTO.setTotalAmount(totalAmount);
         agvCallItemDTO.setLotattDTO(lotattDTO);
         agvCallItemDTOList.add(agvCallItemDTO);
         AgvCallDTO agvCallDTO = new AgvCallDTO();
+        if (StringUtils.isNotBlank(asnAgvCallDTO.getIfSample())) agvCallDTO.setIfSample(asnAgvCallDTO.getIfSample());
         agvCallDTO.setLocationFrom(asnAgvCallDTO.getLocationFrom());
+        agvCallDTO.setDocNo(asnAgvCallDTO.getDocNo());
+        agvCallDTO.setDocType(asnAgvCallDTO.getDocType());
         agvCallDTO.setAgvCallItemDTOList(agvCallItemDTOList);
-        agvCallDTO.setDocNo(asnAgvCallDTO.getDocNo());// 设置单号
+        agvCallDTO.setHeaderId(docHeaderBaseDTO.getId());// 设置单头id
         agvCallDTO.setDocLineNo(asnAgvCallDTO.getLineNo()); // 设置明细行号
         agvCallDTO.setBusinessType(Constant.BUSINESS_TYPE.ASN.getValue()); // 设置单据业务类型 -- 入库
-        agvCallDTO.setDocType(asnAgvCallDTO.getDocType()); // 设置单据类型
         agvCallDTO.setCreateUser(asnAgvCallDTO.getUser()); // 设置操作人
         return agvCallDTO;
     }
 
+    /**
+     * 构建单拖库存总量(可能是数量、质量、体积)
+     * @param baseSku
+     * @param qty
+     * @return
+     */
+    public BigDecimal buildTotalAmount(BaseSku baseSku, String qty) {
+        String packagingSpecs = baseSku.getSkuPackagingSpecs();
+        if (StringUtils.isBlank(packagingSpecs)) return BigDecimal.ZERO;
+        Pattern pattern = Pattern.compile("^\\d+(\\.\\d+)?");
+        Matcher matcher = pattern.matcher(packagingSpecs.trim());
+        if (!matcher.find()) return BigDecimal.ZERO;
+        String numStr = matcher.group();
+        BigDecimal c = new BigDecimal(numStr);
+        BigDecimal specs = c.stripTrailingZeros();
+        return specs.multiply(new BigDecimal(qty));
+    }
+
     /**
      * 构建批次属性
      * @param docHeaderBaseDTO
      * @param docLotattDTO
      * @param baseSku
      */
-    public LotattDTO buildLotattArgument(BionutritionDocHeaderBaseDTO docHeaderBaseDTO, BionutritionDocDetailsBaseDTO docDetailsBaseDTO, DocLotattDTO docLotattDTO, BaseSku baseSku) {
+    public LotattDTO buildLotattArgument(BionutritionDocHeaderBaseDTO docHeaderBaseDTO, BionutritionDocDetailsBaseDTO docDetailsBaseDTO, DocLotattDTO docLotattDTO, BaseSku baseSku, String status) {
         LotattDTO lotattDTO = new LotattDTO();
         lotattDTO.setLotatt01(docLotattDTO.getVendorCode());// 供应商编码
-        if (StringUtils.equals(BizEnum.BionutritionDetailDocTypeEnum.PURCHASE_ORDER.getDocType(), docHeaderBaseDTO.getDocType())){
-            lotattDTO.setLotatt02(docLotattDTO.getOriginalLotNumber()); // 采购收货:原厂批号
-        } else if (StringUtils.equals(BizEnum.BionutritionDetailDocTypeEnum.PRODUCTION_RETURN_ORDER.getDocType(), docHeaderBaseDTO.getDocType())){
-            lotattDTO.setLotatt02(docLotattDTO.getIncomeLotNumber()); // 成品入库、销售退库:产品批号
+        if (StringUtils.equals(BizEnum.BionutritionDetailDocTypeEnum.PURCHASE_ORDER.getDocType(), docHeaderBaseDTO.getDocType())
+            || StringUtils.equals(BizEnum.BionutritionDetailDocTypeEnum.PRODUCTION_RETURN_ORDER.getDocType(), docHeaderBaseDTO.getDocType())
+            || StringUtils.equals(BizEnum.BionutritionDetailDocTypeEnum.PURCHASE_RECEIPT.getDocType(), docHeaderBaseDTO.getDocType())){
+            lotattDTO.setLotatt02(docLotattDTO.getIncomeLotNumber()); // 采购收货、生产退料:进厂批号
         } else {
-            lotattDTO.setLotatt02(docLotattDTO.getProductLotNumber()); // 生产退库:进厂批号
+            lotattDTO.setLotatt02(docLotattDTO.getProductLotNumber()); // 成品入库、销售退库:产品批号
         }
         String manufactureDate = DateUtil.format(docLotattDTO.getManufactureDate(), "yyyy-MM-dd");
         lotattDTO.setLotatt03(manufactureDate);// 生产日期
         // 计算有效截止日期:生产日期加上有效期(天)
         DateTime dateTime = DateUtil.offsetDay(DateUtil.parse(manufactureDate), baseSku.getSkuShelflife());
         lotattDTO.setLotatt04(DateUtil.format(dateTime,"yyyy-MM-dd"));// 有效截止日期
-        lotattDTO.setLotatt05(Constant.QUALITY_STATUS.DJ.getValue());// 质检状态 默认待检
+        lotattDTO.setLotatt05(StringUtils.isNotBlank(status) ? status : Constant.QUALITY_STATUS.DJ.getValue());// 质检状态 默认待检
         lotattDTO.setLotatt06(DateUtil.format(new Date(), "yyyy-MM-dd"));// 入库日期
         lotattDTO.setLotatt07(docLotattDTO.getIncomeLotNumber());// 进厂批号
-        lotattDTO.setLotatt08(docLotattDTO.getProductLotNumber());// 产批号
+        lotattDTO.setLotatt08(docLotattDTO.getProductLotNumber());// 产批号
         lotattDTO.setLotatt09(docHeaderBaseDTO.getId());// 入库单头id
         lotattDTO.setLotatt10(docDetailsBaseDTO.getDocLineNo()); // 明细行号
         return lotattDTO;
@@ -280,24 +326,119 @@ public class PdaAgvCallServiceImpl implements IPdaAgvCallService {
      * @return
      */
     @Override
-    public AgvCallDTO getOrderAgvCallDTO(OrderAgvCallDTO orderAgvCallDTO) {
+    public AgvCallDTO getOrderAgvCallDTO(OrderAgvCallDTO orderAgvCallDTO, BionutritionDocHeaderBaseDTO docHeaderBaseDTO, BionutritionDocDetailsBaseDTO docDetailsBaseDTO) {
         // 根据物料编码查询物料信息
-        BaseSku baseSku = skuService.selectBaseSkuByCustomerId("default", orderAgvCallDTO.getSkuCode());
+        BaseSku baseSku = skuService.selectBaseSkuByCustomerId(Constants.DEFAULT_CUSTOMER_ID, orderAgvCallDTO.getSkuCode());
         Assert.isTrue(ObjectUtil.isNotEmpty(baseSku), "物料信息未找到");
         List<AgvCallItemDTO> agvCallItemDTOList = new ArrayList<>();
         AgvCallItemDTO agvCallItemDTO = new AgvCallItemDTO();
 
         agvCallItemDTO.setSku(orderAgvCallDTO.getSkuCode());
         agvCallItemDTO.setQty(Double.valueOf(orderAgvCallDTO.getQty()));
+        LotattDTO lotattDTO = new LotattDTO();
+        lotattDTO.setLotatt02(orderAgvCallDTO.getBatchNumber());
+        agvCallItemDTO.setLotattDTO(lotattDTO);
         agvCallItemDTOList.add(agvCallItemDTO);
         AgvCallDTO agvCallDTO = new AgvCallDTO();
+        agvCallDTO.setDocDetailsBaseDTO(docDetailsBaseDTO);
         agvCallDTO.setLocationFrom(orderAgvCallDTO.getLocationTo());
         agvCallDTO.setAgvCallItemDTOList(agvCallItemDTOList);
-        agvCallDTO.setDocNo(orderAgvCallDTO.getDocNo());// 设置单号
+        agvCallDTO.setDocNo(orderAgvCallDTO.getDocNo());
+        agvCallDTO.setDocType(orderAgvCallDTO.getDocType());
+        agvCallDTO.setHeaderId(docHeaderBaseDTO.getId());// 设置单头id
         agvCallDTO.setDocLineNo(orderAgvCallDTO.getLineNo()); // 设置明细行号
         agvCallDTO.setBusinessType(Constant.BUSINESS_TYPE.ORDER.getValue()); // 设置单据业务类型 -- 出库
         agvCallDTO.setDocType(orderAgvCallDTO.getDocType()); // 设置单据类型
         agvCallDTO.setCreateUser(orderAgvCallDTO.getUser()); // 设置操作人
         return agvCallDTO;
     }
+
+    /**
+     * 回库任务下发
+     * @param returningInventoryDTO
+     */
+    @Override
+    @Transactional(rollbackFor = RuntimeException.class)
+    public void returningToInventory(ReturningInventoryDTO returningInventoryDTO) {
+        // 1.校验参数
+        // 根据单号和单据类型查询出库单据信息
+        BionutritionDocBaseDTO bionutritionDocBaseDTO =
+                bionutritionDocHeaderService.selectDocByDocNoAndDocType(returningInventoryDTO.getDocNo(), returningInventoryDTO.getDocType());
+        Assert.isTrue(ObjectUtil.isNotNull(bionutritionDocBaseDTO), "该单据不存在");
+        BionutritionDocHeaderBaseDTO soDocHeaderBaseDTO = bionutritionDocBaseDTO.getBionutritionDocHeaderBaseDTO();
+        Assert.isTrue(StringUtils.equals(soDocHeaderBaseDTO.getBusinessType(),Constant.BUSINESS_TYPE.ORDER.getValue())
+                , "该单据不是出库单据");
+        // 2.根据明细行号筛选明细信息
+        BionutritionDocDetailsBaseDTO soDocDetailsBaseDTO = this.filterBionutritionDocDetailsBaseDTOByLineNo(returningInventoryDTO.getLineNo(), bionutritionDocBaseDTO);
+        // 3.更新出库单明细的已搬运数量--之前的已搬运数量减去回库的数量
+        String qty = this.getQtyBySpecs(returningInventoryDTO.getSkuCode(), returningInventoryDTO.getTotalAmount());
+        BigDecimal transferredQty = NumberUtil.sub(soDocDetailsBaseDTO.getTransferredQty(), qty);
+        Assert.isTrue(transferredQty.compareTo(BigDecimal.ZERO) >= 0, "回库数量大于出库数量");
+
+        // 4.更新库存信息
+        // 根据库位id查询库存
+//        List<InvLotLocIdLotattVO> invLotLocIdLotattVOS = invLotLocIdService.selectInvLocIdLotattByLocationId(Long.parseLong(returningInventoryDTO.getLocationFrom()));
+        List<InvLotLocId> invLotLocIdList = invLotLocIdService.selectInvLotLocIdList(Long.parseLong(returningInventoryDTO.getLocationFrom()));
+        Assert.isTrue(CollUtil.isNotEmpty(invLotLocIdList), "未找到对应库位库存信息");
+        InvLotLocId invLotLocId = invLotLocIdList.stream().findFirst().orElse(null);
+        // 获取库存对应批次信息
+        InvLotAtt invLotAtt = invLotAttService.selectInvLotAttByLotnum(invLotLocId.getLotnum());
+        // 库位id更新为出库终点位, 更新分配数量
+        int updateNum = invLotLocIdService.updateInvLotLocIdByLocationId(invLotAtt.getLotnum(), Long.parseLong(invLotLocId.getLocationId()), Constant.LOC_SORTATION_FINISH.toString(), transferredQty);
+        if (!(updateNum > 0)) throw new ServiceException("库存信息修改失败");
+        // 如果回库数量为0,只修改库存的locationId,和分配数量,不修改单据已搬运数量,也无需生成搬运任务
+        if (returningInventoryDTO.getTotalAmount().equals(BigDecimal.ZERO)) return;
+        soDocDetailsBaseDTO.setTransferredQty(String.valueOf(transferredQty));
+        bionutritionDocDetailsService.updateDocDetails(ConvertUtils.sourceToTarget(soDocDetailsBaseDTO, BionutritionDocDetailsDTO.class));
+
+        // 5.构建入库搬运任务DTO
+        AsnAgvCallDTO asnAgvCallDTO = new AsnAgvCallDTO();
+        asnAgvCallDTO.setSkuCode(soDocDetailsBaseDTO.getSkuCode());
+        asnAgvCallDTO.setQty(qty);
+        asnAgvCallDTO.setLocationFrom(returningInventoryDTO.getLocationFrom());
+        // 根据批次查询入库单据
+        List<BionutritionDocBaseDTO> docBaseDTOList = bionutritionDocHeaderService.getDicListByIds(Lists.newArrayList(invLotAtt.getLotatt09()));
+        Assert.isTrue(CollUtil.isNotEmpty(docBaseDTOList), "入库单据信息未找到");
+        BionutritionDocBaseDTO asnDocBaseDTO = docBaseDTOList.stream().findFirst().get();
+        BionutritionDocHeaderBaseDTO asnDocHeaderBaseDTO = asnDocBaseDTO.getBionutritionDocHeaderBaseDTO();
+        BionutritionDocDetailsBaseDTO asnDocDetailsBaseDTO = this.filterBionutritionDocDetailsBaseDTOByLineNo(invLotAtt.getLotatt10(), asnDocBaseDTO);
+        asnAgvCallDTO.setDocNo(asnDocHeaderBaseDTO.getDocNo());
+        asnAgvCallDTO.setLineNo(asnDocDetailsBaseDTO.getDocLineNo());
+        asnAgvCallDTO.setDocType(asnDocHeaderBaseDTO.getDocType());
+        asnAgvCallDTO.setStatus(invLotAtt.getLotatt05());
+        AgvCallDTO agvCallDTO = this.getASNAgvCallDTO(asnAgvCallDTO, asnDocHeaderBaseDTO, asnDocDetailsBaseDTO, returningInventoryDTO.getTotalAmount());
+        // 6.生成搬运任务
+        List<Long> flowIds = this.getFlowIdByDocTypeOrSkuType(asnDocHeaderBaseDTO.getDocType(), asnDocDetailsBaseDTO.getSkuCode());
+        List<FlowConfigHeaderVO> flowConfigHeaderVOList = flowConfigHeaderService.selectFlowConfigHeaderByIds(flowIds);
+        Long flowId = flowConfigHeaderVOList.stream().filter(f -> StringUtils.equals(Constant.BUSINESS_TYPE.ASN.getValue(), f.getFlowType()))
+                .map(FlowConfigHeaderVO::getId)
+                .findFirst().orElse(null);
+        businessService.agvCall(flowId, agvCallDTO);
+//        throw new ServiceException("ddd");
+    }
+
+    /**
+     * 根据物料总量计算物料对应包装规格下的数量
+     * @param skuCode
+     * @param totalAmount
+     * @return
+     */
+    private String getQtyBySpecs(String skuCode, BigDecimal totalAmount){
+        Assert.isTrue(ObjectUtil.isNotEmpty(totalAmount),"请填写回库物料总量");
+        // 根据物料编码查询物料信息
+        BaseSku baseSku = skuService.selectBaseSkuByCustomerId("default", skuCode);
+        Assert.isTrue(ObjectUtil.isNotEmpty(baseSku), "物料信息未找到");
+        String packagingSpecs = baseSku.getSkuPackagingSpecs();
+        if (StringUtils.isBlank(packagingSpecs)) String.valueOf(BigDecimal.ZERO);
+        // 提取规格中前面的数字
+        Pattern pattern = Pattern.compile("^\\d+(\\.\\d+)?");
+        Matcher matcher = pattern.matcher(packagingSpecs.trim());
+        if (!matcher.find()) return String.valueOf(BigDecimal.ZERO);
+        String numStr = matcher.group();
+        BigDecimal c = new BigDecimal(numStr);
+        BigDecimal specs = c.stripTrailingZeros();
+        // 计算当前总量下对应的包装数量, 向上取整
+        BigDecimal qtyBigDecimal = totalAmount.divide(specs, BigDecimal.ROUND_CEILING);
+        return String.valueOf(qtyBigDecimal);
+    }
 }

+ 136 - 20
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/pda/impl/PdaDocQcServiceImpl.java

@@ -13,17 +13,26 @@ import com.ruoyi.ams.bionutrition.doc.dto.BionutritionDocHeaderDTO;
 import com.ruoyi.ams.bionutrition.doc.service.BionutritionDocDetailsService;
 import com.ruoyi.ams.bionutrition.doc.service.BionutritionDocHeaderService;
 import com.ruoyi.ams.bionutrition.dto.DocQcDTO;
+import com.ruoyi.ams.bionutrition.dto.QcIntoStorageDTO;
+import com.ruoyi.ams.bionutrition.dto.QcOutboundDTO;
 import com.ruoyi.ams.bionutrition.pda.IPdaDocQcService;
+import com.ruoyi.ams.bionutrition.sku.service.ISkuService;
 import com.ruoyi.ams.business.IBusinessService;
 import com.ruoyi.ams.config.domain.dto.LotattDTO;
 import com.ruoyi.ams.inv.domain.InvLotAtt;
 import com.ruoyi.ams.inv.domain.InvLotLocId;
+import com.ruoyi.ams.inv.domain.form.InvLocIdSearchFrom;
+import com.ruoyi.ams.inv.domain.vo.InvLotLocIdLotattVO;
 import com.ruoyi.ams.inv.dto.InvMoveDTO;
 import com.ruoyi.ams.inv.service.IInvLotAttService;
 import com.ruoyi.ams.inv.service.IInvLotLocIdService;
 import com.ruoyi.base.constant.Constant;
 import com.ruoyi.base.domain.BaseLocationInfo;
+import com.ruoyi.base.domain.BaseSku;
 import com.ruoyi.base.service.IBaseLocationInfoService;
+import com.ruoyi.base.service.IBaseSkuService;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.redis.RedisKey;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.DateUtils;
@@ -54,13 +63,15 @@ public class PdaDocQcServiceImpl implements IPdaDocQcService {
     private BionutritionDocHeaderService bionutritionDocHeaderService;
     @Autowired
     private BionutritionDocDetailsService bionutritionDocDetailsService;
+    @Autowired
+    private IBaseSkuService baseSkuService;
 
     /**
      * PDA质检
      * @param docQcDTO
      * @param updateBy
      */
-    @Override
+    /*@Override
     @Transactional(rollbackFor = RuntimeException.class)
     public void docQcSubmit(DocQcDTO docQcDTO, String updateBy) {
         // 根据物料编码和批号查询批次信息
@@ -98,7 +109,7 @@ public class PdaDocQcServiceImpl implements IPdaDocQcService {
                 createConveyTaskToBHGZone(updateBy, lotNumNew, docQcDTO);
             }
         }
-    }
+    }*/
 
     /**
      * 生成搬运任务到不合格区
@@ -106,16 +117,16 @@ public class PdaDocQcServiceImpl implements IPdaDocQcService {
      * @param updateBy
      * @param lotNumNew
      */
-    private void createConveyTaskToBHGZone(String updateBy, String lotNumNew, DocQcDTO docQcDTO) {
+    private void createConveyTaskToBHGZone(String updateBy, String lotNumNew, String user) {
         List<InvLotLocId> invLotLocIdList = invLotLocIdService.selectInvLotLocIdByLotnum(lotNumNew);
         Assert.isTrue(CollUtil.isNotEmpty(invLotLocIdList), "未找到批号对应库存");
         int availableLocNumber = 0;
         // 同一批次多个库位库存都需要搬运至不合格区
         for (InvLotLocId invLotLocId : invLotLocIdList) {
+            BaseLocationInfo locationInfo = null;
             // 获取所有不合格区库位
             List<BaseLocationInfo> baseLocationToList = baseLocationInfoService.selectSortedLocatinListByZoneId(
                     Long.parseLong(Constant.LOCATION_ZONE.BHG_ZONE.getValue()), Constant.WAREHOUSE_ID, null);
-            BaseLocationInfo locationInfo = null;
             for (BaseLocationInfo b : baseLocationToList) {
                 // 获取一个没有任务且为空的库位
                 if (StringUtils.equals(b.getStockStatus(), Constant.STOCK_STATUS.STOCK00.getValue())
@@ -129,15 +140,20 @@ public class PdaDocQcServiceImpl implements IPdaDocQcService {
             if (locationInfo == null) {
                 throw new ServiceException("当前批次库存有" + invLotLocIdList.size() + "托,不合格区可用库位有"+availableLocNumber+"个");
             }
-            InvMoveDTO invMoveDTO = new InvMoveDTO(invLotLocId.getLocationId(), String.valueOf(locationInfo.getId()), docQcDTO.getUser());
+            InvMoveDTO invMoveDTO = new InvMoveDTO(invLotLocId.getLocationId(), String.valueOf(locationInfo.getId()), user);
             invLotLocIdService.move(invMoveDTO, updateBy);
         }
     }
 
+    /**
+     * 获取质检列表
+     * @param sku
+     * @return
+     */
     @Override
     public List<DocQcDTO> getQcList(String sku) {
-        //1.查出所有状态为60的明细 List<Details>
-        List<BionutritionDocDetailsDTO> docDetailsDTOList = bionutritionDocDetailsService.getBionutritionDocDetailsDTOListByLineStatus(Constant.ASN_STS.STS60.getValue());
+        //1.查出所有状态为40的明细 List<Details>
+        List<BionutritionDocDetailsDTO> docDetailsDTOList = bionutritionDocDetailsService.getBionutritionDocDetailsDTOListByLineStatus(Constant.ASN_STS.STS40.getValue());
         Assert.isTrue(CollUtil.isNotEmpty(docDetailsDTOList), "没有状态为上架的信息");
         //2. 查出单据 List<Header>
         List<String> headerIdList = docDetailsDTOList.stream().filter(item->StringUtils.isNotBlank(item.getDocHeaderId()))
@@ -155,29 +171,129 @@ public class PdaDocQcServiceImpl implements IPdaDocQcService {
 
         //对每一个库存: 找到对应的批次 根据批次的lot10 找到对应的明细
         List<String> lotNumListHasLoc = invLotLocIds.stream().map(InvLotLocId::getLotnum).distinct().collect(Collectors.toList());
-        // 所有状态为60的明细行号
+        // 所有状态为40的明细行号
         List<String> lineNoList = docDetailsDTOList.stream().map(item -> item.getDocLineNo()).collect(Collectors.toList());
         List<DocQcDTO> docQcDTOList = invLotAttList.stream().filter(item -> CollUtil.contains(lotNumListHasLoc, item.getLotnum()))
                 .filter(item -> CollUtil.contains(lineNoList, item.getLotatt10()))
+                .filter(item->StringUtils.equals(item.getLotatt05(), Constant.QUALITY_STATUS.HG.getValue()))
                 .map(item -> {
                     DocQcDTO docQcDTO = new DocQcDTO();
                     docQcDTO.setBatchNumber(item.getLotatt02());
                     docQcDTO.setSkuCode(item.getSku());
                     docQcDTO.setDocNo(map.get(item.getLotatt09()));
-                    docQcDTO.setStatus(Constant.ASN_STS.STS60.getValue());
+                    docQcDTO.setStatus(item.getLotatt05());
                     return docQcDTO;
-                }).collect(Collectors.toList());
+                }).distinct().collect(Collectors.toList());
 //        invLotAttService.selectInvLotAttByLotnum()
-        // 5. 构建质检列表
-        /*List<DocQcDTO> docQcDTOList = docDetailsDTOList.stream().filter().map(item -> {
-            DocQcDTO docQcDTO = new DocQcDTO();
-            docQcDTO.setBatchNumber(item.getOriginalLotNumber());
-            docQcDTO.setSkuCode(item.getSkuCode());
-            docQcDTO.setDocNo(map.get(item.getDocHeaderId()));
-            docQcDTO.setStatus(Constant.ASN_STS.STS60.getValue());
-            return docQcDTO;
-        }).collect(Collectors.toList());invLotAttService.getQcList(sku)
-        */
         return docQcDTOList;
     }
+
+    /**
+     * 质检出库
+     * @param qcOutboundDTO
+     * @param username
+     */
+    @Override
+    @Transactional(rollbackFor = RuntimeException.class)
+    public void qcOutbound(QcOutboundDTO qcOutboundDTO, String username) {
+        // 1.将需要质检出库的库存设置质检标记
+        InvLotLocId invLotLocIdQuery = new InvLotLocId();
+        invLotLocIdQuery.setLocationId(qcOutboundDTO.getLocationFrom());
+        invLotLocIdQuery.setLotnum(qcOutboundDTO.getLotnum());
+        InvLotLocId invLotLocId = invLotLocIdService.selectInvLotLocIdByModel(invLotLocIdQuery);
+        invLotLocId.setIfSample(Constant.IS_YES.Y.name());
+        invLotLocIdService.updateInvLotLocId(invLotLocId);
+        // 2.生成移库任务
+        InvMoveDTO invMoveDTO = new InvMoveDTO();
+        invMoveDTO.setSourceLocationId(qcOutboundDTO.getLocationFrom());
+        invMoveDTO.setTargetLocationId(qcOutboundDTO.getLocationTo());
+        invMoveDTO.setUser(qcOutboundDTO.getUser());
+        invLotLocIdService.move(invMoveDTO, username);
+    }
+
+    /**
+     * 质检入库
+     * @param qcIntoStorageDTO
+     * @param username
+     */
+    @Override
+    @Transactional(rollbackFor = RuntimeException.class)
+    public void qcIntoStorage(QcIntoStorageDTO qcIntoStorageDTO, String username) {
+        // 1.更改批次状态
+        // 根据物料编码和批号查询批次信息
+        List<InvLotAtt> invLotAttList = invLotAttService.selectInvLotAttByBatchNum(qcIntoStorageDTO.getBatchNumber(), qcIntoStorageDTO.getSkuCode());
+        Assert.isTrue(CollUtil.isNotEmpty(invLotAttList), "所属批次信息未找到");
+        String lotNumNew = "";
+        for (InvLotAtt invLotAtt : invLotAttList) {
+            String lotnum = invLotAtt.getLotnum();
+            // 根据批次号查询库存信息
+            List<InvLotLocId> invLotLocIds = invLotLocIdService.selectInvLotLocIdByLotnum(lotnum);
+            // 如果没有对应的库存信息,遍历下一条批次数据 因为根据物料和批号会匹配到多条仅仅是质检状态不同批次数据
+            if (CollUtil.isEmpty(invLotLocIds)) continue;
+            invLotAtt.setLotatt05(qcIntoStorageDTO.getStatus());
+            // 构建lotatt19属性
+            LotattDTO lotattDTO = new LotattDTO();
+            BeanUtils.copyProperties(invLotAtt, lotattDTO);
+            String lotatt19 = invLotLocIdService.buildLotatt19(lotattDTO);
+            // 判断是否存在相同批次的数据
+            InvLotAtt invLotAttSame = invLotAttService.selectInvLotAttByLotatt19(lotatt19);
+            lotNumNew = IdWorker.getIdStr();
+            if (ObjectUtil.isEmpty(invLotAttSame)){ // 没有相同批次的数据,就添加批次信息
+                // 更新批次号
+                invLotAtt.setLotnum(lotNumNew);
+                invLotAtt.setLotatt19(lotatt19);
+                invLotAtt.setCreateTime(DateUtils.getNowDate());
+                invLotAttService.insertInvLotAtt(invLotAtt);
+            }else {
+                lotNumNew = invLotAttSame.getLotnum();
+            }
+            // 修改库存表对应的批次号
+            invLotLocIdService.updateInvLotLocIdByLotNum(lotnum, lotNumNew);
+            // 如果是不合格 将同批号的所有库存搬运到不合格区(生成搬运任务到不合格区)
+            if (StringUtils.equals(qcIntoStorageDTO.getStatus(), Constant.QUALITY_STATUS.BHG.getValue())) {
+                createConveyTaskToBHGZone(username, lotNumNew, qcIntoStorageDTO.getUser());
+            }
+        }
+        // 如果质量状态是放行 无需生成搬运任务
+        if (StringUtils.equals(qcIntoStorageDTO.getStatus(), Constant.QUALITY_STATUS.FX.getValue())) return;
+        // 2.更新对应库位库存物料总量
+        List<InvLotLocId> invLotLocIdList = invLotLocIdService.selectInvLotLocIdList(Long.parseLong(qcIntoStorageDTO.getLocationFrom()));
+        Assert.isTrue(CollUtil.isNotEmpty(invLotLocIdList), "质检入库起始点库存未找到");
+        InvLotLocId invLotLocId = invLotLocIdList.stream().findFirst().get();
+        invLotLocId.setTotalAmount(qcIntoStorageDTO.getTotalAmount());
+        int updateINum = invLotLocIdService.updateInvLotLocId(invLotLocId);
+        if (!(updateINum > 0)) throw new ServiceException("质检入库修改库存失败");
+        log.info("质检入库修改库存完成:{}{}-------", qcIntoStorageDTO.getBatchNumber(), qcIntoStorageDTO.getStatus());
+        // 3.质检合格生成质检入库搬运任务
+        if (!StringUtils.equals(qcIntoStorageDTO.getStatus(), Constant.QUALITY_STATUS.BHG.getValue())){
+            this.createQCIntoStorageTask(qcIntoStorageDTO, username, invLotLocId);
+        }
+//        throw new ServiceException("ddd");
+    }
+
+    /**
+     * 创建质检入库任务
+     * @param qcIntoStorageDTO
+     * @param username
+     * @param invLotLocId
+     */
+    private void createQCIntoStorageTask(QcIntoStorageDTO qcIntoStorageDTO, String username, InvLotLocId invLotLocId) {
+        log.info("生成质检入库任务======");
+        // 根据物料类型获取目标库区
+        BaseSku baseSku = baseSkuService.selectBaseSkuByCustomerId(Constants.DEFAULT_CUSTOMER_ID, qcIntoStorageDTO.getSkuCode());
+        Assert.isTrue(ObjectUtil.isNotEmpty(baseSku));
+        String zoneId = Constant.getZoneIdBySkuType(baseSku.getSkuType().toString());
+        // 获取当前库区库位
+        List<BaseLocationInfo> baseLocationToList = baseLocationInfoService.selectSortedLocatinListByZoneId(
+                Long.parseLong(zoneId), Constant.WAREHOUSE_ID, null);
+        List<BaseLocationInfo> baseLocationInfoList = baseLocationToList.stream().filter(item ->
+                StringUtils.equals(item.getStockStatus(), Constant.STOCK_STATUS.STOCK00.getValue())
+                        && StringUtils.equals(item.getIsEmpty(), Constant.IS_YES.Y.name())).collect(Collectors.toList());
+        Assert.isTrue(CollUtil.isNotEmpty(baseLocationInfoList),"对应库区无可用库位");
+        BaseLocationInfo locationTo = baseLocationInfoList.get(0);
+        // 生成移库搬运任务
+        InvMoveDTO invMoveDTO = new InvMoveDTO(invLotLocId.getLocationId(), String.valueOf(locationTo.getId()), qcIntoStorageDTO.getUser());
+        invLotLocIdService.move(invMoveDTO, username);
+        log.info("质检入库任务生成完成======");
+    }
 }

+ 73 - 1
warewms-ams/src/main/java/com/ruoyi/ams/business/BusinessServiceImpl.java

@@ -1,10 +1,19 @@
 package com.ruoyi.ams.business;
 
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.NumberUtil;
+import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.ruoyi.ams.agv.ndc.common.ByteUtil;
 import com.ruoyi.ams.agv.ndc.common.CRC16Util;
 import com.ruoyi.ams.agv.ndc.domain.AmsTask;
 import com.ruoyi.ams.agv.ndc.service.IAmsTaskService;
+import com.ruoyi.ams.bionutrition.doc.dto.BionutritionDocDetailsDTO;
+import com.ruoyi.ams.bionutrition.doc.dto.detail.BionutritionDocDetailsBaseDTO;
+import com.ruoyi.ams.bionutrition.doc.service.BionutritionDocDetailsService;
 import com.ruoyi.ams.box.service.IWmsBoxInfoService;
 import com.ruoyi.ams.config.domain.AsnSoStrategy;
 import com.ruoyi.ams.config.domain.dto.*;
@@ -12,6 +21,8 @@ import com.ruoyi.ams.config.domain.vo.FlowConfigHeaderVO;
 import com.ruoyi.ams.config.mapper.AsnSoStrategyMapper;
 import com.ruoyi.ams.config.service.IFlowConfigHeaderService;
 import com.ruoyi.ams.config.service.LocationAllocationStrategy;
+import com.ruoyi.ams.inv.domain.InvLotAtt;
+import com.ruoyi.ams.inv.domain.InvLotLocId;
 import com.ruoyi.ams.inv.domain.vo.InvLotLocIdLotattVO;
 import com.ruoyi.ams.inv.mapper.InvLotLocIdMapper;
 import com.ruoyi.ams.inv.service.IInvLotAttService;
@@ -33,9 +44,12 @@ import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.redis.RedisCache;
 import com.ruoyi.common.core.redis.RedisKey;
 import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.ConvertUtils;
+import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.uuid.SnowflakeIdWorker;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -78,6 +92,8 @@ public class BusinessServiceImpl implements IBusinessService {
     private IAmsTaskService amsTaskService;
     @Autowired
     private IFlowConfigHeaderService flowConfigHeaderService;
+    @Autowired
+    private BionutritionDocDetailsService bionutritionDocDetailsService;
 
     public static int geniKey(String taskNo) {
         int res = CRC16Util.calcCrc16(ByteUtil.string2byteArray(taskNo));
@@ -173,8 +189,11 @@ public class BusinessServiceImpl implements IBusinessService {
                             , agvCallDTO.getWarehouseId(), hashMap, agvCall.getSku(), "lotatt04 , lotatt06");
                     locationFrom = this.zoneLocationAllocation(locationFromList, "locationFrom", "SO", asnSoStrategy, token);
                     locationTo = this.zoneLocationAllocation(locationToList, "locationTo", "SO", asnSoStrategy, token);
+                    // 记录当前明细已搬运数量
+                    this.recordDetailsTransferedQty(agvCallDTO, locationFrom);
+                    // 更新批次和库存信息(将库位对应的批次绑定出库单号)
+                    this.updateInventoryAndAttInfo(agvCallDTO, locationFrom);
                     wcsTaskList.addAll(this.genTask(locationFrom, locationTo, flowConfigHeaderVO, agvCallDTO, token));
-
                 } else if (flowConfigHeaderVO.getFlowType().equals("MV")) {
                     List<BaseLocationInfo> locationFromList = this.convertLocation(paramLocationFrom, agvCallDTO.getWarehouseId(), null);
                     List<BaseLocationInfo> locationToList = this.convertLocation(paramLocationTo, agvCallDTO.getWarehouseId(), null);
@@ -196,6 +215,21 @@ public class BusinessServiceImpl implements IBusinessService {
         }
     }
 
+    /**
+     * 记录当前明细已搬运数量
+     * @param agvCallDTO
+     * @param locationFrom
+     */
+    private void recordDetailsTransferedQty(AgvCallDTO agvCallDTO, BaseLocationInfo locationFrom) {
+        BionutritionDocDetailsBaseDTO docDetailsBaseDTO = agvCallDTO.getDocDetailsBaseDTO();
+        List<InvLotLocIdLotattVO> invLotLocIdLotattVOS = invLotLocIdService.selectInvLocIdLotattByLocationId(locationFrom.getId());
+        Assert.isTrue(CollUtil.isNotEmpty(invLotLocIdLotattVOS), "未找到对应库位库存信息");
+        InvLotLocIdLotattVO invLotLocIdLotattVO = invLotLocIdLotattVOS.stream().findFirst().orElse(null);
+        BigDecimal transferredQty = NumberUtil.add(docDetailsBaseDTO.getTransferredQty(), String.valueOf(invLotLocIdLotattVO.getQty()));
+        docDetailsBaseDTO.setTransferredQty(transferredQty.toString());
+        bionutritionDocDetailsService.updateDocDetails(ConvertUtils.sourceToTarget(docDetailsBaseDTO, BionutritionDocDetailsDTO.class));
+    }
+
     @Transactional
     @Override
     public BaseLocationInfo inLocationAllocation(InWarehouseDTO inWarehouseDTO, Long token) {
@@ -860,4 +894,42 @@ public class BusinessServiceImpl implements IBusinessService {
         }
         return true;
     }
+
+    @Override
+    public void updateInventoryAndAttInfo(AgvCallDTO agvCallDTO, BaseLocationInfo locationFrom) {
+        // 1.根据库位id查询库存
+        List<InvLotLocIdLotattVO> invLotLocIdLotattVOS = invLotLocIdService.selectInvLocIdLotattByLocationId(locationFrom.getId());
+        Assert.isTrue(CollUtil.isNotEmpty(invLotLocIdLotattVOS), "未找到对应库位库存信息");
+        InvLotLocIdLotattVO invLotLocIdLotattVO = invLotLocIdLotattVOS.stream().findFirst().orElse(null);
+        // 2.找到推荐库存对应批次信息
+        InvLotAtt invLotAtt = iInvLotAttService.selectInvLotAttByLotnum(invLotLocIdLotattVO.getLotnum());
+        String lotnum = invLotAtt.getLotnum();
+        List<AgvCallItemDTO> agvCallItemDTOList = agvCallDTO.getAgvCallItemDTOList();
+        for (AgvCallItemDTO agvCallItemDTO : agvCallItemDTOList) {
+            LotattDTO lotattDTO = new LotattDTO();
+            BeanUtil.copyProperties(invLotAtt, lotattDTO);
+            // 3.当前批次信息绑定出库单头id
+            lotattDTO.setLotatt11(agvCallDTO.getHeaderId());
+            lotattDTO.setLotatt12(agvCallDTO.getDocLineNo());
+            String lotatt19 = invLotLocIdService.buildLotatt19(lotattDTO);
+            InvLotAtt invLotAttSame = iInvLotAttService.selectInvLotAttByLotatt19(lotatt19);
+            String lotnumNew = IdWorker.getIdStr();
+            // 4.不存在相同批次信息则添加 否则不添加
+            if (ObjectUtil.isEmpty(invLotAttSame)) { // 没有相同批次的数据,就添加批次信息;否则只添加库存
+                BeanUtils.copyProperties(lotattDTO, invLotAtt);
+                invLotAtt.setCustomerId(Constant.CUSTOMER_ID);
+                invLotAtt.setSku(agvCallItemDTO.getSku());
+                invLotAtt.setLotnum(lotnumNew);
+                invLotAtt.setLotatt19(lotatt19);
+                invLotAtt.setCreateTime(DateUtils.getNowDate());
+                iInvLotAttService.insertInvLotAtt(invLotAtt);
+            } else {
+                lotnumNew = invLotAttSame.getLotnum();
+            }
+            // 5.将推荐库位库存的lotnum更新为绑定了出库单的批次信息的lotnum
+            // 分配数量设置为推荐库位的全部数量(后续如果需要回库,分配数量需要更新)
+            int updateNum = invLotLocIdService.updateInvLotLocIdByLotNumAndLocationId(lotnum, locationFrom.getId(), lotnumNew, new BigDecimal(invLotLocIdLotattVO.getQty()));
+            if (!(updateNum > 0)) throw new ServiceException("库存信息修改失败");
+        }
+    }
 }

+ 7 - 0
warewms-ams/src/main/java/com/ruoyi/ams/business/IBusinessService.java

@@ -143,4 +143,11 @@ public interface IBusinessService {
      * @return
      */
     boolean taskDispatchCheck(WcsTask wcsTask);
+
+    /**
+     * 修改库存和批次信息
+     * @param agvCallDTO
+     * @param locationFrom
+     */
+    void updateInventoryAndAttInfo(AgvCallDTO agvCallDTO, BaseLocationInfo locationFrom);
 }

+ 5 - 1
warewms-ams/src/main/java/com/ruoyi/ams/config/domain/dto/AgvCallDTO.java

@@ -1,5 +1,6 @@
 package com.ruoyi.ams.config.domain.dto;
 
+import com.ruoyi.ams.bionutrition.doc.dto.detail.BionutritionDocDetailsBaseDTO;
 import lombok.Data;
 
 import java.util.ArrayList;
@@ -16,11 +17,14 @@ public class AgvCallDTO {
     private String palletNo;
     private String extParam;
     private String docNo;
+    private String docType;
     private String docLineNo;
     private String businessType;
-    private String docType;
+    private String headerId;
     private String createUser;
+    private String ifSample;
     private Long warehouseId;
     private String toArea;// 目标区域(货物最终去掉区域)
+    private BionutritionDocDetailsBaseDTO docDetailsBaseDTO; // 单据明细
     private List<AgvCallItemDTO> agvCallItemDTOList = new ArrayList<>();
 }

+ 6 - 0
warewms-ams/src/main/java/com/ruoyi/ams/config/domain/dto/AgvCallItemDTO.java

@@ -2,10 +2,16 @@ package com.ruoyi.ams.config.domain.dto;
 
 import lombok.Data;
 
+import java.math.BigDecimal;
+
 @Data
 public class AgvCallItemDTO {
     private String sku;
     private Double qty;
+    /**
+     * 一托盘的总量(根据qty*物料包装规格计算,单位可能是质量、体积、个数)
+     */
+    private BigDecimal totalAmount;
     private Double weight;
     private String supplier;
     private String extParam;

+ 7 - 1
warewms-ams/src/main/java/com/ruoyi/ams/config/domain/dto/LotattDTO.java

@@ -49,10 +49,16 @@ public class LotattDTO {
      */
     private String lotatt09;
     /**
-     * 明细行号
+     * 入库单明细行号
      */
     private String lotatt10;
+    /**
+     * 出库单头id
+     */
     private String lotatt11;
+    /**
+     * 出库单明细行号
+     */
     private String lotatt12;
     private String lotatt13;
     private String lotatt14;

+ 20 - 13
warewms-ams/src/main/java/com/ruoyi/ams/config/mapper/FlowConfigHeaderMapper.java

@@ -9,15 +9,15 @@ import com.ruoyi.ams.config.domain.vo.LotattConfigVO;
 
 /**
  * 流程配置头Mapper接口
- * 
+ *
  * @author ruoyi
  * @date 2022-02-16
  */
-public interface FlowConfigHeaderMapper 
+public interface FlowConfigHeaderMapper
 {
     /**
      * 查询流程配置头
-     * 
+     *
      * @param id 流程配置头主键
      * @return 流程配置头
      */
@@ -25,7 +25,7 @@ public interface FlowConfigHeaderMapper
 
     /**
      * 查询流程配置头列表
-     * 
+     *
      * @param flowConfigHeader 流程配置头
      * @return 流程配置头集合
      */
@@ -48,7 +48,7 @@ public interface FlowConfigHeaderMapper
 
     /**
      * 新增流程配置头
-     * 
+     *
      * @param flowConfigHeader 流程配置头
      * @return 结果
      */
@@ -56,7 +56,7 @@ public interface FlowConfigHeaderMapper
 
     /**
      * 修改流程配置头
-     * 
+     *
      * @param flowConfigHeader 流程配置头
      * @return 结果
      */
@@ -64,7 +64,7 @@ public interface FlowConfigHeaderMapper
 
     /**
      * 删除流程配置头
-     * 
+     *
      * @param id 流程配置头主键
      * @return 结果
      */
@@ -72,7 +72,7 @@ public interface FlowConfigHeaderMapper
 
     /**
      * 批量删除流程配置头
-     * 
+     *
      * @param ids 需要删除的数据主键集合
      * @return 结果
      */
@@ -80,24 +80,24 @@ public interface FlowConfigHeaderMapper
 
     /**
      * 批量删除流程配置体
-     * 
+     *
      * @param ids 需要删除的数据主键集合
      * @return 结果
      */
      int deleteFlowConfigDetailsByHeaderIds(Long[] ids);
-    
+
     /**
      * 批量新增流程配置体
-     * 
+     *
      * @param flowConfigDetailsList 流程配置体列表
      * @return 结果
      */
      int batchFlowConfigDetails(List<FlowConfigDetails> flowConfigDetailsList);
-    
+
 
     /**
      * 通过流程配置头主键删除流程配置体信息
-     * 
+     *
      * @param id 流程配置头ID
      * @return 结果
      */
@@ -116,4 +116,11 @@ public interface FlowConfigHeaderMapper
      * @return
      */
     List<FlowConfigHeader> selectFlowConfigHeaderRel(Long id);
+
+    /**
+     * 根据idList查询流程
+     * @param flowIds
+     * @return
+     */
+    List<FlowConfigHeaderVO> selectFlowConfigHeaderByIds(List<Long> flowIds);
 }

+ 10 - 8
warewms-ams/src/main/java/com/ruoyi/ams/config/service/IFlowConfigHeaderService.java

@@ -10,15 +10,15 @@ import com.ruoyi.common.core.domain.model.LoginUser;
 
 /**
  * 流程配置头Service接口
- * 
+ *
  * @author ruoyi
  * @date 2022-02-16
  */
-public interface IFlowConfigHeaderService 
+public interface IFlowConfigHeaderService
 {
     /**
      * 查询流程配置头
-     * 
+     *
      * @param id 流程配置头主键
      * @return 流程配置头
      */
@@ -26,7 +26,7 @@ public interface IFlowConfigHeaderService
 
     /**
      * 查询流程配置头列表
-     * 
+     *
      * @param flowConfigHeader 流程配置头
      * @return 流程配置头集合
      */
@@ -41,7 +41,7 @@ public interface IFlowConfigHeaderService
 
     /**
      * 新增流程配置头
-     * 
+     *
      * @param flowConfigHeader 流程配置头
      * @return 结果
      */
@@ -49,7 +49,7 @@ public interface IFlowConfigHeaderService
 
     /**
      * 修改流程配置头
-     * 
+     *
      * @param flowConfigForm 流程配置头
      * @return 结果
      */
@@ -59,7 +59,7 @@ public interface IFlowConfigHeaderService
 
     /**
      * 批量删除流程配置头
-     * 
+     *
      * @param ids 需要删除的流程配置头主键集合
      * @return 结果
      */
@@ -67,7 +67,7 @@ public interface IFlowConfigHeaderService
 
     /**
      * 删除流程配置头信息
-     * 
+     *
      * @param id 流程配置头主键
      * @return 结果
      */
@@ -93,4 +93,6 @@ public interface IFlowConfigHeaderService
      * @return
      */
     List<FlowConfigHeader> sortFlowConfigHeader(Long id);
+
+    List<FlowConfigHeaderVO> selectFlowConfigHeaderByIds(List<Long> flowIds);
 }

+ 5 - 0
warewms-ams/src/main/java/com/ruoyi/ams/config/service/impl/FlowConfigHeaderServiceImpl.java

@@ -335,6 +335,11 @@ public class FlowConfigHeaderServiceImpl implements IFlowConfigHeaderService {
         }
     }
 
+    @Override
+    public List<FlowConfigHeaderVO> selectFlowConfigHeaderByIds(List<Long> flowIds) {
+        return flowConfigHeaderMapper.selectFlowConfigHeaderByIds(flowIds);
+    }
+
     private List<FlowConfigHeader> sortFlow(List<FlowConfigHeader> list, List<FlowConfigHeader> sortList, Long rootId) {
         if (rootId == null) {
             return sortList;

+ 9 - 0
warewms-ams/src/main/java/com/ruoyi/ams/inv/domain/InvLotLocId.java

@@ -43,6 +43,11 @@ public class InvLotLocId extends BaseEntity
     @Excel(name = "库存数量")
     private BigDecimal qtyEach;
 
+    /**
+     * 一托盘的总量(根据qty*物料包装规格计算,单位可能是质量、体积、个数)
+     */
+    private BigDecimal totalAmount;
+
     /** 分配数量 */
     @Excel(name = "分配数量")
     private BigDecimal qtyallocated;
@@ -59,6 +64,10 @@ public class InvLotLocId extends BaseEntity
      * 是否过期
      */
     private String isExpire;
+    /**
+     * 是否为取样库存 Y:是 N:不是
+     */
+    private String ifSample;
 
     /** $column.columnComment */
     @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")

+ 6 - 0
warewms-ams/src/main/java/com/ruoyi/ams/inv/mapper/InvLotLocIdMapper.java

@@ -326,4 +326,10 @@ public interface InvLotLocIdMapper {
     InvLotLocId selectInvLotLocIdByTraceIdAndLocationId(@Param("locationTo")String locationTo, @Param("taskNo")String taskNo);
 
     List<InvLotLocId> selectInvLotLocIdByLotnumList(List<String> lotNumList);
+
+    int updateInvLotLocIdByLotNumAndLocationId(@Param("lotnum")String lotnum, @Param("locationId")Long locationId, @Param("lotnumNew")String lotnumNew, @Param("qtyallocated")BigDecimal qtyallocated);
+
+    int updateInvLotLocIdByLocationId(@Param("lotnum")String lotnum, @Param("locationId")Long locationId, @Param("locationIdNew")String locationIdNew, @Param("qtyallocated")BigDecimal qtyallocated);
+
+    List<InvLotLocIdLotattVO> selectInvLocIdLotattListByLotNum(String lotnum);
 }

+ 6 - 0
warewms-ams/src/main/java/com/ruoyi/ams/inv/service/IInvLotLocIdService.java

@@ -313,4 +313,10 @@ public interface IInvLotLocIdService {
      * @return
      */
     InvLotLocId selectInvLotLocIdByTraceIdAndLocationId(String locationTo, String taskNo);
+
+    int updateInvLotLocIdByLotNumAndLocationId(String lotnum, Long locationId, String lotnumNew, BigDecimal qtyallocated);
+
+    int updateInvLotLocIdByLocationId(String lotnum, Long locationId, String locationIdNew, BigDecimal Qtyallocated);
+
+    List<InvLotLocIdLotattVO> selectInvLocIdLotattListByLotNum(String lotnum);
 }

+ 22 - 13
warewms-ams/src/main/java/com/ruoyi/ams/inv/service/impl/InvLotLocIdServiceImpl.java

@@ -230,6 +230,7 @@ public class InvLotLocIdServiceImpl implements IInvLotLocIdService {
      * @return
      */
     @Override
+    @Transactional(rollbackFor = RuntimeException.class)
     public AjaxResult move(InvMoveDTO invMoveDTO, String updateBy) {
 
         Boolean isEmpty = StringUtils.isEmpty(invMoveDTO.getSourceLocationId()) || StringUtils.isEmpty(invMoveDTO.getTargetLocationId());
@@ -246,19 +247,12 @@ public class InvLotLocIdServiceImpl implements IInvLotLocIdService {
 
         // 验证起始库位
         Boolean isIdleFrom = baseLocationInfoService.verifyLocationIsIdle(locationFrom, warehouseId);
-        if (!isIdleFrom) {
-            return AjaxResult.error("起始库位需要空闲状态!");
-        }
+        Assert.isTrue(isIdleFrom, "起始库位需要空闲状态!");
         // 验证目标库位
         Boolean isIdle = baseLocationInfoService.verifyLocationIsIdle(locationTo, warehouseId);
-        if (!isIdle) {
-            return AjaxResult.error("目标库位需要空闲状态!");
-        }
+        Assert.isTrue(isIdle, "目标库位需要空闲状态!");
         Boolean isInStock = baseLocationInfoService.verifyLocationIsInStock(locationTo, warehouseId);
-        if (isInStock) {
-            return AjaxResult.error("目标库位有货!");
-        }
-
+        Assert.isFalse(isInStock, "目标库位有货!");
 
         // 起始和目标库位
         baseLocationFrom = baseLocationInfoService.selectBaseLocationInfoByIdOrNo(locationFrom, warehouseId);
@@ -575,8 +569,8 @@ public class InvLotLocIdServiceImpl implements IInvLotLocIdService {
             invLotLocId.setCustomerId(customerId);
             invLotLocId.setQty(new BigDecimal(qty));
             invLotLocId.setQtyEach(new BigDecimal(qty));
-            invLotLocId.setQtyallocated(BigDecimal.ZERO);
-            invLotLocId.setQtyallocatedEach(BigDecimal.ZERO);
+            invLotLocId.setTotalAmount(agvCallItemDTO.getTotalAmount());
+            invLotLocId.setIfSample(Constant.IS_YES.N.name());
             invLotLocId.setQtypa(BigDecimal.ZERO);
             invLotLocId.setQtyrpin(BigDecimal.ZERO);
             invLotLocId.setIsExpire(Constant.EXPIRE_STATUS.UNEXPIRED.getValue());
@@ -756,7 +750,7 @@ public class InvLotLocIdServiceImpl implements IInvLotLocIdService {
         lotattVOList = lotattVOList.stream().filter(
                 item->!StringUtils.equals(item.getIsExpire(), Constant.EXPIRE_STATUS.EXPIRED.getValue()))
                 .collect(Collectors.toList());
-        return lotattVOList.stream().allMatch(v -> !v.getLotatt05().equals("FX"));// 是否所有库存都不是放行状态
+        return lotattVOList.stream().allMatch(v -> !v.getLotatt05().equals("FX"));
     }
 
     @Override
@@ -781,4 +775,19 @@ public class InvLotLocIdServiceImpl implements IInvLotLocIdService {
     public InvLotLocId selectInvLotLocIdByTraceIdAndLocationId(String locationTo, String taskNo) {
         return invLotLocIdMapper.selectInvLotLocIdByTraceIdAndLocationId(locationTo, taskNo);
     }
+
+    @Override
+    public int updateInvLotLocIdByLotNumAndLocationId(String lotnum, Long locationId, String lotnumNew, BigDecimal qtyallocated) {
+        return invLotLocIdMapper.updateInvLotLocIdByLotNumAndLocationId(lotnum, locationId, lotnumNew, qtyallocated);
+    }
+
+    @Override
+    public int updateInvLotLocIdByLocationId(String lotnum, Long locationId, String locationIdNew, BigDecimal qtyallocated) {
+        return invLotLocIdMapper.updateInvLotLocIdByLocationId(lotnum, locationId, locationIdNew, qtyallocated);
+    }
+
+    @Override
+    public List<InvLotLocIdLotattVO> selectInvLocIdLotattListByLotNum(String lotnum) {
+        return invLotLocIdMapper.selectInvLocIdLotattListByLotNum(lotnum);
+    }
 }

+ 10 - 6
warewms-ams/src/main/java/com/ruoyi/ams/task/service/impl/WcsTaskServiceImpl.java

@@ -30,7 +30,9 @@ import com.ruoyi.ams.config.domain.FlowConfigEvent;
 import com.ruoyi.ams.config.domain.dto.AgvCallDTO;
 import com.ruoyi.ams.config.domain.dto.AgvCallItemDTO;
 import com.ruoyi.ams.config.domain.dto.LotattDTO;
+import com.ruoyi.ams.config.domain.vo.FlowConfigHeaderVO;
 import com.ruoyi.ams.config.service.IFlowConfigEventService;
+import com.ruoyi.ams.config.service.IFlowConfigHeaderService;
 import com.ruoyi.ams.inv.domain.InvLotAtt;
 import com.ruoyi.ams.inv.domain.InvLotLocId;
 import com.ruoyi.ams.inv.mapper.InvLotLocIdMapper;
@@ -107,6 +109,8 @@ public class WcsTaskServiceImpl implements IWcsTaskService {
 
     @Autowired
     private BionutritionDocDetailsService bionutritionDocDetailsService;
+    @Autowired
+    private IFlowConfigHeaderService flowConfigHeaderService;
 
     //任务状态翻译
     private String codeConvert(int code) {
@@ -644,14 +648,14 @@ public class WcsTaskServiceImpl implements IWcsTaskService {
         Assert.isTrue(NumberUtil.compare(
                 Long.valueOf(docDetailsBaseDTO.getSkuQty()), Long.valueOf(orderAgvCallDTO.getQty())) >= 0
                 , "出库数量超出明细范围");
-        // 记录当前明细已搬运数量
-        BigDecimal transferredQty = NumberUtil.add(docDetailsBaseDTO.getTransferredQty(), orderAgvCallDTO.getQty());
-        docDetailsBaseDTO.setTransferredQty(transferredQty.toString());
-        bionutritionDocDetailsService.updateDocDetails(ConvertUtils.sourceToTarget(docDetailsBaseDTO, BionutritionDocDetailsDTO.class));
         // 3.根据单据类型获取流程id
-        Long flowId = pdaAgvCallService.getFlowIdByDocType(docType);
+        List<Long> flowIds = pdaAgvCallService.getFlowIdByDocTypeOrSkuType(docType, docDetailsBaseDTO.getSkuCode());
+        List<FlowConfigHeaderVO> flowConfigHeaderVOList = flowConfigHeaderService.selectFlowConfigHeaderByIds(flowIds);
+        Long flowId = flowConfigHeaderVOList.stream().filter(f -> StringUtils.equals(Constant.BUSINESS_TYPE.BATCHSO.getValue(), f.getFlowType()))
+                .map(FlowConfigHeaderVO::getId)
+                .findFirst().orElse(null);
         // 4.构建agv呼叫对象
-        AgvCallDTO agvCallDTO = pdaAgvCallService.getOrderAgvCallDTO(orderAgvCallDTO);
+        AgvCallDTO agvCallDTO = pdaAgvCallService.getOrderAgvCallDTO(orderAgvCallDTO, bionutritionDocHeaderBaseDTO, docDetailsBaseDTO);
         return iBusinessService.agvCall(flowId, agvCallDTO);
     }
 

+ 13 - 0
warewms-ams/src/main/resources/mapper/ams/FlowConfigHeaderMapper.xml

@@ -265,4 +265,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <include refid="selectFlowConfigHeaderVo"/>
         where root_flow = #{headerId}
     </select>
+
+    <select id="selectFlowConfigHeaderByIds" resultType="com.ruoyi.ams.config.domain.vo.FlowConfigHeaderVO">
+        select a.id, a.flow_name,a.flow_type, a.sku_type, a.sku_type_flag, a.qty, a.qty_flag, a.weight, a.weight_flag, a.supplier, a.supplier_flag, a.location_from,a.location_from_flag, a.location_from_device, a.location_to,a.location_to_flag, a.location_to_device, a.create_by, a.create_time, a.update_by, a.update_time, a.remark,
+        a.qty_range,a.weight_range,a.supplier_range,b.id as sub_id, b.header_id as sub_header_id, b.lotatt_id as sub_lotatt_id,cf.lotatt_name as sub_lotatt_name, b.lotatt_flag as sub_lotatt_flag, b.create_by as sub_create_by, b.create_time as sub_create_time, b.update_by as sub_update_by, b.update_time as sub_update_time, b.remark as sub_remark,b.default_value as sub_default_value,
+        a.location_from_strategy_flag,a.location_to_strategy_flag,a.rel_flow,a.root_flow
+        from flow_config_header a
+        left join flow_config_details b on b.header_id = a.id
+        left join lotatt_config cf on b.lotatt_id = cf.lotatt_id
+        where a.id in
+        <foreach collection="list" item="flowId" open="(" separator="," close=")">
+            #{flowId}
+        </foreach>
+    </select>
 </mapper>

+ 2 - 2
warewms-ams/src/main/resources/mapper/ams/InvLotAttMapper.xml

@@ -106,8 +106,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <select id="selectInvLotAttListByHeaderIds" resultType="com.ruoyi.ams.inv.domain.InvLotAtt">
         <include refid="selectInvLotAttVo"/>
         where inv_lot_att.lotatt09 in
-        <foreach item="docNo" collection="list" open="(" separator="," close=")">
-            #{docNo}
+        <foreach item="headerId" collection="list" open="(" separator="," close=")">
+            #{headerId}
         </foreach>
     </select>
 

+ 34 - 4
warewms-ams/src/main/resources/mapper/ams/InvLotLocIdMapper.xml

@@ -12,6 +12,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="sku"    column="sku"    />
         <result property="qty"    column="qty"    />
         <result property="qtyEach"    column="qty_each"    />
+        <result property="totalAmount"    column="total_amount"    />
+        <result property="ifSample"    column="if_sample"    />
         <result property="qtyallocated"    column="qtyallocated"    />
         <result property="qtyallocatedEach"    column="qtyallocated_each"    />
         <result property="qtypa"    column="qtypa"    />
@@ -35,7 +37,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="customerId"    column="customer_id"    />
         <result property="sku"    column="sku"    />
         <result property="skuName"    column="sku_name"    />
-        <result property="skuTypeName"    column="sku_type_name"    />
+        <result property="skuTypeName"    column="item_name"    />
         <result property="qty"    column="qty"    />
         <result property="qtyallocated"    column="qtyallocated"    />
         <result property="weight"    column="weight"    />
@@ -121,7 +123,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </resultMap>
 
     <sql id="selectInvLotLocIdVo">
-        select lotnum, location_id, traceid, customer_id, sku, qty, qty_each, qtyallocated, qtyallocated_each, qtypa, qtyrpin, qtyrpout, qtymvin, qtymvout, qtyonhold, create_by, create_time, update_by, update_time, remark from inv_lot_loc_id
+        select lotnum, location_id, traceid, customer_id, sku, qty, qty_each, total_amount, if_sample, qtyallocated, qtyallocated_each, qtypa, qtyrpin, qtyrpout, qtymvin, qtymvout, qtyonhold, create_by, create_time, update_by, update_time, remark from inv_lot_loc_id
     </sql>
 
     <select id="selectInvLotLocIdList" parameterType="InvLotLocId" resultMap="InvLotLocIdResult">
@@ -161,6 +163,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="sku != null">sku,</if>
             <if test="qty != null">qty,</if>
             <if test="qtyEach != null">qty_each,</if>
+            <if test="totalAmount != null">total_amount,</if>
+            <if test="ifSample != null">if_sample,</if>
             <if test="qtyallocated != null">qtyallocated,</if>
             <if test="qtyallocatedEach != null">qtyallocated_each,</if>
             <if test="qtypa != null">qtypa,</if>
@@ -184,6 +188,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="sku != null">#{sku},</if>
             <if test="qty != null">#{qty},</if>
             <if test="qtyEach != null">#{qtyEach},</if>
+            <if test="totalAmount != null">#{totalAmount},</if>
+            <if test="ifSample != null">#{ifSample},</if>
             <if test="qtyallocated != null">#{qtyallocated},</if>
             <if test="qtyallocatedEach != null">#{qtyallocatedEach},</if>
             <if test="qtypa != null">#{qtypa},</if>
@@ -210,6 +216,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="sku != null">sku = #{sku},</if>
             <if test="qty != null">qty = #{qty},</if>
             <if test="qtyEach != null">qty_each = #{qtyEach},</if>
+            <if test="totalAmount != null">total_amount = #{totalAmount},</if>
+            <if test="ifSample != null">if_sample = #{ifSample},</if>
             <if test="qtyallocated != null">qtyallocated = #{qtyallocated},</if>
             <if test="qtyallocatedEach != null">qtyallocated_each = #{qtyallocatedEach},</if>
             <if test="qtypa != null">qtypa = #{qtypa},</if>
@@ -336,7 +344,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <select id="selectInvLocIdLotattList" resultMap="InvLotLocIdLotattResult">
         select
         inv.*,
-        att.lotnum, att.customer_id,z.zone_name
+        att.lotnum, att.customer_id,z.zone_name, sk.sku_name, skt.item_name
         ,lotatt01, lotatt02, lotatt03, lotatt04,lotatt05, lotatt06
         ,lotatt07, lotatt08, lotatt09, lotatt10, lotatt11, lotatt12, lotatt13, lotatt14, lotatt15, lotatt16, lotatt17
         ,lotatt18
@@ -345,9 +353,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         left join inv_lot_att att on inv.lotnum = att.lotnum
         left join base_location_info b on inv.location_id = b.id
         left join base_location_zone z on b.zone_id = z.zone_id
+        left join base_sku sk on sk.sku = inv.sku
+        left join base_sku_type skt on skt.item_code = sk.sku_type
         <where>
+            inv.location_id != '99998'
             <if test="zoneId != null  and zoneId != ''"> and b.zone_id = #{zoneId}</if>
-            <if test="sku != null  and sku != ''"> and (sk.sku like concat('%', #{sku}, '%') or sk.desc1 like concat('%', #{sku}, '%'))</if>
+            <if test="sku != null  and sku != ''"> and sk.sku like concat('%', #{sku}, '%')</if>
             <if test="locationNo != null  and locationNo != ''"> and b.id = #{locationNo}</if>
             <if test="isExpire != null and isExpire != ''"> and inv.is_expire in('1','2')</if>
             <if test="isFull != null  and isFull != ''"> and w.is_full = #{isFull}</if>
@@ -609,6 +620,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         update inv_lot_loc_id set lotnum = #{lotNumNew}, update_time = now()
         where lotnum = #{lotnum}
     </update>
+    <update id="updateInvLotLocIdByLotNumAndLocationId">
+        update inv_lot_loc_id set lotnum = #{lotnumNew}, update_time = now(), qtyallocated = #{qtyallocated}
+        where lotnum = #{lotnum} and location_id = #{locationId}
+    </update>
+    <update id="updateInvLotLocIdByLocationId">
+        update inv_lot_loc_id set location_id = #{locationIdNew}, update_time = now(), qtyallocated = #{qtyallocated}
+        where lotnum = #{lotnum} and location_id = #{locationId}
+    </update>
 
     <select id="querySameTypeByPalletNo" resultMap="InvLotLocIdResult">
         select inv.*
@@ -639,4 +658,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             #{lotNum}
         </foreach>
     </select>
+    <select id="selectInvLocIdLotattListByLotNum" resultType="com.ruoyi.ams.inv.domain.vo.InvLotLocIdLotattVO">
+        select
+            inv.location_id,sk.sku,sk.sku_name,b.location_no,inv.qty,inv.qtyallocated
+            ,att.lotnum, att.customer_id, lotatt01, lotatt02, lotatt03, lotatt04,qua.dict_label lotatt05, lotatt06, lotatt07, lotatt08, lotatt09, lotatt10, lotatt11, lotatt12, lotatt13, lotatt14, lotatt15, lotatt16, lotatt17, lotatt18
+        from inv_lot_loc_id inv
+        left join inv_lot_att att on inv.lotnum = att.lotnum
+        left join base_location_info b on inv.location_id = b.id
+        left join base_sku sk on inv.sku = sk.sku
+        left join base_sku_type skt on sk.sku_type = skt.item_code
+        where inv.lotnum = #{lotnum}
+    </select>
 </mapper>

+ 75 - 2
warewms-base/src/main/java/com/ruoyi/base/constant/Constant.java

@@ -16,9 +16,9 @@ public class Constant {
     public static final Long LOC_STAGE_CACHE = 99997l;
 
     /**
-     * 出库缓存
+     * 出库终点
      */
-    public static final Long LOC_SORTATION_CACHE = 99998l;
+    public static final Long LOC_SORTATION_FINISH = 99998l;
 
     /**
      * 中间缓存位
@@ -693,6 +693,10 @@ public class Constant {
          * 出库单
          */
         ORDER("ORDER"),
+        /**
+         * 出库
+         */
+        BATCHSO("BATCHSO"),
         /**
          * 采购单
          */
@@ -709,4 +713,73 @@ public class Constant {
         }
     }
 
+    /**
+     * 物料类型和库区对照枚举
+     */
+    public enum SKU_TYPE_ZONE_ID{
+        /**
+         * 包材区
+         */
+        PACKAGING_MATERIALS("5", "1"),
+        /**
+         * 原料区
+         */
+        INGREDIENT("1","2"),
+        /**
+         * 原料过敏区
+         */
+        INGREDIENT_ALLERGY("2","3"),
+        /**
+         * 添加剂过敏区
+         */
+        ADDITIVE_ALLERGY("4","4"),
+        /**
+         * 液体区
+         */
+        LIQUID("7","5"),
+        /**
+         * 添加剂区
+         */
+        ADDITIVE("3","6"),
+        /**
+         * 成品区
+         */
+        FINISH_PRODUCT("6","7"),
+        /**
+         * 空拖区
+         */
+        EMPTY_TRAY("8","8");
+
+        private String skuType;
+
+        private String zoneId;
+
+        SKU_TYPE_ZONE_ID(String skuType, String zoneId) {
+            this.skuType = skuType;
+            this.zoneId = zoneId;
+        }
+
+        public String getZoneId() {
+            return zoneId;
+        }
+
+        public String getSkuType() {
+            return skuType;
+        }
+    }
+
+    /**
+     * 根据物料类型获取库区id
+     * @param skuType
+     * @return
+     */
+    public static String getZoneIdBySkuType(String skuType){
+        for (SKU_TYPE_ZONE_ID z : SKU_TYPE_ZONE_ID.values()) {
+            if (z.skuType.equals(skuType)) {
+                return z.zoneId;
+            }
+        }
+        return null;
+    }
+
 }

+ 2 - 0
warewms-base/src/main/java/com/ruoyi/base/constant/type/BizEnum.java

@@ -345,4 +345,6 @@ public class BizEnum {
 
     }
 
+
+
 }