瀏覽代碼

质检出入库、物料回库

dfsfs 1 年之前
父節點
當前提交
b1cb6c8e4a
共有 38 個文件被更改,包括 930 次插入222 次删除
  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;
 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.AsnAgvCallDTO;
 import com.ruoyi.ams.bionutrition.dto.GroundingDTO;
 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.bionutrition.pda.IPdaAgvCallService;
 import com.ruoyi.ams.business.IBusinessService;
 import com.ruoyi.ams.business.IBusinessService;
 import com.ruoyi.ams.task.service.IWcsTaskService;
 import com.ruoyi.ams.task.service.IWcsTaskService;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.domain.AjaxResult;
-import com.ruoyi.common.utils.StringUtils;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 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;
 import javax.validation.Valid;
 
 
@@ -38,12 +40,19 @@ public class PdaAgvCallController {
         return AjaxResult.success("入库任务下发成功");
         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")
     @PostMapping("/grounding")
     public AjaxResult grounding(@RequestBody @Valid GroundingDTO groundingDTO) {
     public AjaxResult grounding(@RequestBody @Valid GroundingDTO groundingDTO) {
         pdaAgvCallService.grounding(groundingDTO);
         pdaAgvCallService.grounding(groundingDTO);
         return AjaxResult.success("上架成功");
         return AjaxResult.success("上架成功");
-    }
+    }*/
 
 
     @PostMapping("/testCallBack")
     @PostMapping("/testCallBack")
     public AjaxResult testCallBack(@RequestBody CallBackDTO callBackDTO){
     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.AsnAgvCallDTO;
 import com.ruoyi.ams.bionutrition.dto.DocQcDTO;
 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.IPdaAgvCallService;
 import com.ruoyi.ams.bionutrition.pda.IPdaDocQcService;
 import com.ruoyi.ams.bionutrition.pda.IPdaDocQcService;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.controller.BaseController;
@@ -41,14 +43,26 @@ public class PdaDocQcController extends BaseController {
     }
     }
 
 
     /**
     /**
-     * 质检提交
-     * @param docQcDTO
+     * 质检出库
+     * @param qcOutboundDTO
      * @return
      * @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();
         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);
         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
     @Test
     public void testInsertBaseLocationInfo(){
     public void testInsertBaseLocationInfo(){
         String s = "[\n" +
         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);
         JSONArray jsonArray = JSONUtil.parseArray(s);
         List<Dict> dicts = JSONUtil.toList(jsonArray, Dict.class);
         List<Dict> dicts = JSONUtil.toList(jsonArray, Dict.class);
@@ -437,7 +437,7 @@ public class WarehouseTest {
                 baseLocationInfo.setColIndex(Long.parseLong(split[1]));
                 baseLocationInfo.setColIndex(Long.parseLong(split[1]));
                 System.out.println(baseLocationInfo);
                 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
     @Override
     public void insertFill(MetaObject metaObject) {
     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) {
         } 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, 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());
         strictInsertFill(metaObject, UPDATE_DATE, Date.class, DateUtil.date());
     }
     }
 
 
     @Override
     @Override
     public void updateFill(MetaObject metaObject) {
     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());
         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 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;
     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
     @Override
     public synchronized void confirmAnalysis(String taskNo, Integer aciIndex, String type, Integer carNo) {
     public synchronized void confirmAnalysis(String taskNo, Integer aciIndex, String type, Integer carNo) {
+
+        // todo 读取plc信号 1.12
         AmsTask amsTask = new AmsTask();
         AmsTask amsTask = new AmsTask();
         amsTask.setTaskNo(taskNo);
         amsTask.setTaskNo(taskNo);
         amsTask = amsTaskService.selectAmsTaskByModel(amsTask);
         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("已搬运数量")
     @ApiModelProperty("已搬运数量")
     private String transferredQty;
     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("已搬运数量")
     @ApiModelProperty("已搬运数量")
     private String transferredQty;
     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);
     void updateDocStatus(WcsTask wcsTask);
 
 
     List<BionutritionDocBaseDTO> buildBionutritionDocBaseDTOByIdList(String docNo, String docType);
     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
     @Override
     public List<BionutritionDocBaseDTO> selectDetailsByDocNoAndDocType(String docNo, String docType) {
     public List<BionutritionDocBaseDTO> selectDetailsByDocNoAndDocType(String docNo, String docType) {
         List<BionutritionDocBaseDTO> docBaseDTOList = bionutritionDocHeaderService.buildBionutritionDocBaseDTOByIdList(docNo, 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) {
     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.github.pagehelper.PageInfo;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Lists;
 import com.ruoyi.ams.bionutrition.doc.domain.BionutritionDocHeader;
 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.detail.BionutritionDocDetailsBaseDTO;
 import com.ruoyi.ams.bionutrition.doc.dto.header.BionutritionDocHeaderBaseDTO;
 import com.ruoyi.ams.bionutrition.doc.dto.header.BionutritionDocHeaderBaseDTO;
 import com.ruoyi.ams.bionutrition.doc.dto.header.FinishedProductReceiptHeaderDTO;
 import com.ruoyi.ams.bionutrition.doc.dto.header.FinishedProductReceiptHeaderDTO;
@@ -517,7 +514,19 @@ public class BionutritionDocHeaderServiceImpl extends CrudServiceImpl<Bionutriti
      * @return
      * @return
      */
      */
     public List<BionutritionDocBaseDTO> buildBionutritionDocBaseDTOByIdList(String docNo, String docType) {
     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());
         List<String> docTypeList = bionutritionDocHeaderDTOList.stream().map(item -> item.getDocType()).distinct().collect(Collectors.toList());
         return NumberUtil.isGreater(BigDecimal.valueOf(docTypeList.size()), BigDecimal.ONE) ?
         return NumberUtil.isGreater(BigDecimal.valueOf(docTypeList.size()), BigDecimal.ONE) ?
                 buildBionutritionDocDifferentTypeList(bionutritionDocHeaderDTOList) : buildBionutritionDocSameTypeList(bionutritionDocHeaderDTOList);
                 buildBionutritionDocDifferentTypeList(bionutritionDocHeaderDTOList) : buildBionutritionDocSameTypeList(bionutritionDocHeaderDTOList);
@@ -626,7 +635,6 @@ public class BionutritionDocHeaderServiceImpl extends CrudServiceImpl<Bionutriti
     public void updateDocStatus(WcsTask wcsTask) {
     public void updateDocStatus(WcsTask wcsTask) {
         // 不是出入库任务直接返回
         // 不是出入库任务直接返回
         if (StringUtils.isEmpty(wcsTask.getExt5())) return;
         if (StringUtils.isEmpty(wcsTask.getExt5())) return;
-
         String ext5 = wcsTask.getExt5();
         String ext5 = wcsTask.getExt5();
         String docNo = null;
         String docNo = null;
         String docLineNo = null;
         String docLineNo = null;
@@ -669,6 +677,7 @@ public class BionutritionDocHeaderServiceImpl extends CrudServiceImpl<Bionutriti
         log.info("===更改出库单据状态,单号{},明细行号{},单头状态更改为{},明细状态更改为{}",
         log.info("===更改出库单据状态,单号{},明细行号{},单头状态更改为{},明细状态更改为{}",
                 bionutritionDocHeaderBaseDTO.getDocNo(), docDetails.getDocLineNo()
                 bionutritionDocHeaderBaseDTO.getDocNo(), docDetails.getDocLineNo()
                 , bionutritionDocHeaderBaseDTO.getDocStatus(), docDetails.getLineStatus());
                 , bionutritionDocHeaderBaseDTO.getDocStatus(), docDetails.getLineStatus());
+
     }
     }
 
 
     /**
     /**
@@ -794,10 +803,11 @@ public class BionutritionDocHeaderServiceImpl extends CrudServiceImpl<Bionutriti
         return getBionutritionDocHeaderDTOList(null, null, docType);
         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()
         List<BionutritionDocHeader> bionutritionDocHeaderList = baseDao.selectList(Wrappers.<BionutritionDocHeader>lambdaQuery()
                 .like(StringUtils.isNotEmpty(docNo), BionutritionDocHeader::getDocNo, docNo)
                 .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);
         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 = "请填写明细行号")
     @NotBlank(message = "请填写明细行号")
     private String lineNo;
     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.AsnAgvCallDTO;
 import com.ruoyi.ams.bionutrition.dto.GroundingDTO;
 import com.ruoyi.ams.bionutrition.dto.GroundingDTO;
 import com.ruoyi.ams.bionutrition.dto.OrderAgvCallDTO;
 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.AgvCallDTO;
 import com.ruoyi.ams.config.domain.dto.LotattDTO;
 import com.ruoyi.ams.config.domain.dto.LotattDTO;
 import com.ruoyi.base.domain.BaseSku;
 import com.ruoyi.base.domain.BaseSku;
 
 
+import java.util.List;
+
 /**
 /**
  * 佰穗莱pda呼叫AGV生成搬运任务
  * 佰穗莱pda呼叫AGV生成搬运任务
  */
  */
@@ -24,14 +27,14 @@ public interface IPdaAgvCallService {
      * 上架
      * 上架
      * @param groundingDTO
      * @param groundingDTO
      */
      */
-    void grounding(GroundingDTO groundingDTO);
+//    void grounding(GroundingDTO groundingDTO);
 
 
     /**
     /**
      * 根据单据类型获取流程id
      * 根据单据类型获取流程id
      * @param docType
      * @param docType
      * @return
      * @return
      */
      */
-    Long getFlowIdByDocType(String docType);
+    List<Long> getFlowIdByDocTypeOrSkuType(String docType, String skuType);
 
 
     /**
     /**
      * 构建批次属性对象
      * 构建批次属性对象
@@ -40,7 +43,13 @@ public interface IPdaAgvCallService {
      * @param baseSku
      * @param baseSku
      * @return
      * @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;
 package com.ruoyi.ams.bionutrition.pda;
 
 
 import com.ruoyi.ams.bionutrition.dto.DocQcDTO;
 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;
 import java.util.List;
 
 
@@ -9,15 +11,23 @@ import java.util.List;
  */
  */
 public interface IPdaDocQcService {
 public interface IPdaDocQcService {
 
 
-    /**
-     * 质检提交
-     * @param docQcDTO
-     */
-    void docQcSubmit(DocQcDTO docQcDTO, String updateBy);
-
     /**
     /**
      * 获取质检列表
      * 获取质检列表
      * @return
      * @return
      */
      */
     List<DocQcDTO> getQcList(String sku);
     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.JSONObject;
 import cn.hutool.json.JSONUtil;
 import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 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.agv.ndc.common.Aci;
 import com.ruoyi.ams.bionutrition.doc.domain.BionutritionDocDetails;
 import com.ruoyi.ams.bionutrition.doc.domain.BionutritionDocDetails;
 import com.ruoyi.ams.bionutrition.doc.domain.BionutritionDocHeader;
 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.AsnAgvCallDTO;
 import com.ruoyi.ams.bionutrition.dto.GroundingDTO;
 import com.ruoyi.ams.bionutrition.dto.GroundingDTO;
 import com.ruoyi.ams.bionutrition.dto.OrderAgvCallDTO;
 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.bionutrition.pda.IPdaAgvCallService;
 import com.ruoyi.ams.business.IBusinessService;
 import com.ruoyi.ams.business.IBusinessService;
 import com.ruoyi.ams.config.domain.dto.AgvCallDTO;
 import com.ruoyi.ams.config.domain.dto.AgvCallDTO;
 import com.ruoyi.ams.config.domain.dto.AgvCallItemDTO;
 import com.ruoyi.ams.config.domain.dto.AgvCallItemDTO;
 import com.ruoyi.ams.config.domain.dto.LotattDTO;
 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.Constant;
 import com.ruoyi.base.constant.type.BizEnum;
 import com.ruoyi.base.constant.type.BizEnum;
 import com.ruoyi.base.domain.BaseSku;
 import com.ruoyi.base.domain.BaseSku;
 import com.ruoyi.base.service.IBaseSkuService;
 import com.ruoyi.base.service.IBaseSkuService;
+import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.constant.base.EnumUtils;
 import com.ruoyi.common.constant.base.EnumUtils;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.ConvertUtils;
 import com.ruoyi.common.utils.ConvertUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.system.service.ISysConfigService;
 import com.ruoyi.system.service.ISysConfigService;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.annotation.Transactional;
 
 
+import javax.validation.constraints.NotEmpty;
 import java.math.BigDecimal;
 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
 @Slf4j
 @Service
 @Service
@@ -68,6 +82,12 @@ public class PdaAgvCallServiceImpl implements IPdaAgvCallService {
     private ISysConfigService iSysConfigService;
     private ISysConfigService iSysConfigService;
     @Autowired
     @Autowired
     private IBaseSkuService skuService;
     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), "该单据不存在");
         Assert.isTrue(ObjectUtil.isNotNull(bionutritionDocBaseDTO), "该单据不存在");
         BionutritionDocHeaderBaseDTO bionutritionDocHeaderBaseDTO = bionutritionDocBaseDTO.getBionutritionDocHeaderBaseDTO();
         BionutritionDocHeaderBaseDTO bionutritionDocHeaderBaseDTO = bionutritionDocBaseDTO.getBionutritionDocHeaderBaseDTO();
         String docType = bionutritionDocHeaderBaseDTO.getDocType();
         String docType = bionutritionDocHeaderBaseDTO.getDocType();
-        Assert.isTrue(StringUtils.isNotEmpty(docType), "单据信息中单据类型为空");
         Assert.isTrue(StringUtils.equals(bionutritionDocHeaderBaseDTO.getBusinessType(),Constant.BUSINESS_TYPE.ASN.getValue())
         Assert.isTrue(StringUtils.equals(bionutritionDocHeaderBaseDTO.getBusinessType(),Constant.BUSINESS_TYPE.ASN.getValue())
                 || StringUtils.equals(bionutritionDocHeaderBaseDTO.getBusinessType(),Constant.BUSINESS_TYPE.PO.getValue())
                 || StringUtils.equals(bionutritionDocHeaderBaseDTO.getBusinessType(),Constant.BUSINESS_TYPE.PO.getValue())
                 , "该单据不是入库单据");
                 , "该单据不是入库单据");
-        List<BionutritionDocDetailsBaseDTO> docDetailsList = bionutritionDocBaseDTO.getBionutritionDocDetailsBaseDTOList();
-        Assert.isTrue(CollUtil.isNotEmpty(docDetailsList), "单据明细数据为空");
         // 2.根据明细行号筛选明细信息
         // 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.判断数量是否超出范围
         // 3.判断数量是否超出范围
         // 记录当前明细已搬运数量
         // 记录当前明细已搬运数量
         BigDecimal transferredQty = NumberUtil.add(docDetailsBaseDTO.getTransferredQty(), asnAgvCallDTO.getQty());
         BigDecimal transferredQty = NumberUtil.add(docDetailsBaseDTO.getTransferredQty(), asnAgvCallDTO.getQty());
@@ -102,57 +117,65 @@ public class PdaAgvCallServiceImpl implements IPdaAgvCallService {
                 , "入库数量超出范围,剩余数量"+NumberUtil.sub(docDetailsBaseDTO.getSkuQty(), docDetailsBaseDTO.getTransferredQty()));
                 , "入库数量超出范围,剩余数量"+NumberUtil.sub(docDetailsBaseDTO.getSkuQty(), docDetailsBaseDTO.getTransferredQty()));
         docDetailsBaseDTO.setTransferredQty(transferredQty.toString());
         docDetailsBaseDTO.setTransferredQty(transferredQty.toString());
         bionutritionDocDetailsService.updateDocDetails(ConvertUtils.sourceToTarget(docDetailsBaseDTO, BionutritionDocDetailsDTO.class));
         bionutritionDocDetailsService.updateDocDetails(ConvertUtils.sourceToTarget(docDetailsBaseDTO, BionutritionDocDetailsDTO.class));
-
         // 如果是采购入库 需要根据采购单生成采购入库单
         // 如果是采购入库 需要根据采购单生成采购入库单
         if (StringUtils.equals(docType, BizEnum.BionutritionExcelDocTitleEnum.PURCHASE_ORDER.getDocType())) {
         if (StringUtils.equals(docType, BizEnum.BionutritionExcelDocTitleEnum.PURCHASE_ORDER.getDocType())) {
             this.addPurchaseReceiptDoc(bionutritionDocBaseDTO, docDetailsBaseDTO, asnAgvCallDTO);
             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任务
         // 5.生成agv呼叫对象,生成对应wcs任务
-        AgvCallDTO agvCallDTO = this.getASNAgvCallDTO(asnAgvCallDTO, bionutritionDocHeaderBaseDTO, docDetailsBaseDTO);
+        AgvCallDTO agvCallDTO = this.getASNAgvCallDTO(asnAgvCallDTO, bionutritionDocHeaderBaseDTO, docDetailsBaseDTO, null);
         businessService.agvCall(flowId, agvCallDTO);
         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();
         List<BionutritionDocDetailsBaseDTO> docDetailsList = bionutritionDocBaseDTO.getBionutritionDocDetailsBaseDTOList();
         Assert.isTrue(CollUtil.isNotEmpty(docDetailsList), "单据明细数据为空");
         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);
                 .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
      * @param docType
      * @return
      * @return
      */
      */
     @NotNull
     @NotNull
-    public Long getFlowIdByDocType(String docType) {
+    public List<Long> getFlowIdByDocTypeOrSkuType(String docType, String skuCode) {
         JSONArray docTypeFlowObjects = JSONUtil.parseArray(iSysConfigService.selectConfigByKey("sys.docType.corresponding.business"));
         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 bionutritionDocBaseDTO
      * @param docDetailsBaseDTO
      * @param docDetailsBaseDTO
      */
      */
@@ -219,56 +242,79 @@ public class PdaAgvCallServiceImpl implements IPdaAgvCallService {
      * @param asnAgvCallDTO
      * @param asnAgvCallDTO
      * @return
      * @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);
         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), "物料信息未找到");
         Assert.isTrue(ObjectUtil.isNotEmpty(baseSku), "物料信息未找到");
         List<AgvCallItemDTO> agvCallItemDTOList = new ArrayList<>();
         List<AgvCallItemDTO> agvCallItemDTOList = new ArrayList<>();
         AgvCallItemDTO agvCallItemDTO = new AgvCallItemDTO();
         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.setSku(asnAgvCallDTO.getSkuCode());
         agvCallItemDTO.setQty(Double.valueOf(asnAgvCallDTO.getQty()));
         agvCallItemDTO.setQty(Double.valueOf(asnAgvCallDTO.getQty()));
+        // 计算一托盘总量
+        if (ObjectUtil.isEmpty(totalAmount)) totalAmount = this.buildTotalAmount(baseSku, asnAgvCallDTO.getQty());
+        agvCallItemDTO.setTotalAmount(totalAmount);
         agvCallItemDTO.setLotattDTO(lotattDTO);
         agvCallItemDTO.setLotattDTO(lotattDTO);
         agvCallItemDTOList.add(agvCallItemDTO);
         agvCallItemDTOList.add(agvCallItemDTO);
         AgvCallDTO agvCallDTO = new AgvCallDTO();
         AgvCallDTO agvCallDTO = new AgvCallDTO();
+        if (StringUtils.isNotBlank(asnAgvCallDTO.getIfSample())) agvCallDTO.setIfSample(asnAgvCallDTO.getIfSample());
         agvCallDTO.setLocationFrom(asnAgvCallDTO.getLocationFrom());
         agvCallDTO.setLocationFrom(asnAgvCallDTO.getLocationFrom());
+        agvCallDTO.setDocNo(asnAgvCallDTO.getDocNo());
+        agvCallDTO.setDocType(asnAgvCallDTO.getDocType());
         agvCallDTO.setAgvCallItemDTOList(agvCallItemDTOList);
         agvCallDTO.setAgvCallItemDTOList(agvCallItemDTOList);
-        agvCallDTO.setDocNo(asnAgvCallDTO.getDocNo());// 设置单号
+        agvCallDTO.setHeaderId(docHeaderBaseDTO.getId());// 设置单头id
         agvCallDTO.setDocLineNo(asnAgvCallDTO.getLineNo()); // 设置明细行号
         agvCallDTO.setDocLineNo(asnAgvCallDTO.getLineNo()); // 设置明细行号
         agvCallDTO.setBusinessType(Constant.BUSINESS_TYPE.ASN.getValue()); // 设置单据业务类型 -- 入库
         agvCallDTO.setBusinessType(Constant.BUSINESS_TYPE.ASN.getValue()); // 设置单据业务类型 -- 入库
-        agvCallDTO.setDocType(asnAgvCallDTO.getDocType()); // 设置单据类型
         agvCallDTO.setCreateUser(asnAgvCallDTO.getUser()); // 设置操作人
         agvCallDTO.setCreateUser(asnAgvCallDTO.getUser()); // 设置操作人
         return agvCallDTO;
         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 docHeaderBaseDTO
      * @param docLotattDTO
      * @param docLotattDTO
      * @param baseSku
      * @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 lotattDTO = new LotattDTO();
         lotattDTO.setLotatt01(docLotattDTO.getVendorCode());// 供应商编码
         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 {
         } else {
-            lotattDTO.setLotatt02(docLotattDTO.getProductLotNumber()); // 生产退库:进厂批号
+            lotattDTO.setLotatt02(docLotattDTO.getProductLotNumber()); // 成品入库、销售退库:产品批号
         }
         }
         String manufactureDate = DateUtil.format(docLotattDTO.getManufactureDate(), "yyyy-MM-dd");
         String manufactureDate = DateUtil.format(docLotattDTO.getManufactureDate(), "yyyy-MM-dd");
         lotattDTO.setLotatt03(manufactureDate);// 生产日期
         lotattDTO.setLotatt03(manufactureDate);// 生产日期
         // 计算有效截止日期:生产日期加上有效期(天)
         // 计算有效截止日期:生产日期加上有效期(天)
         DateTime dateTime = DateUtil.offsetDay(DateUtil.parse(manufactureDate), baseSku.getSkuShelflife());
         DateTime dateTime = DateUtil.offsetDay(DateUtil.parse(manufactureDate), baseSku.getSkuShelflife());
         lotattDTO.setLotatt04(DateUtil.format(dateTime,"yyyy-MM-dd"));// 有效截止日期
         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.setLotatt06(DateUtil.format(new Date(), "yyyy-MM-dd"));// 入库日期
         lotattDTO.setLotatt07(docLotattDTO.getIncomeLotNumber());// 进厂批号
         lotattDTO.setLotatt07(docLotattDTO.getIncomeLotNumber());// 进厂批号
-        lotattDTO.setLotatt08(docLotattDTO.getProductLotNumber());// 产批号
+        lotattDTO.setLotatt08(docLotattDTO.getProductLotNumber());// 产批号
         lotattDTO.setLotatt09(docHeaderBaseDTO.getId());// 入库单头id
         lotattDTO.setLotatt09(docHeaderBaseDTO.getId());// 入库单头id
         lotattDTO.setLotatt10(docDetailsBaseDTO.getDocLineNo()); // 明细行号
         lotattDTO.setLotatt10(docDetailsBaseDTO.getDocLineNo()); // 明细行号
         return lotattDTO;
         return lotattDTO;
@@ -280,24 +326,119 @@ public class PdaAgvCallServiceImpl implements IPdaAgvCallService {
      * @return
      * @return
      */
      */
     @Override
     @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), "物料信息未找到");
         Assert.isTrue(ObjectUtil.isNotEmpty(baseSku), "物料信息未找到");
         List<AgvCallItemDTO> agvCallItemDTOList = new ArrayList<>();
         List<AgvCallItemDTO> agvCallItemDTOList = new ArrayList<>();
         AgvCallItemDTO agvCallItemDTO = new AgvCallItemDTO();
         AgvCallItemDTO agvCallItemDTO = new AgvCallItemDTO();
 
 
         agvCallItemDTO.setSku(orderAgvCallDTO.getSkuCode());
         agvCallItemDTO.setSku(orderAgvCallDTO.getSkuCode());
         agvCallItemDTO.setQty(Double.valueOf(orderAgvCallDTO.getQty()));
         agvCallItemDTO.setQty(Double.valueOf(orderAgvCallDTO.getQty()));
+        LotattDTO lotattDTO = new LotattDTO();
+        lotattDTO.setLotatt02(orderAgvCallDTO.getBatchNumber());
+        agvCallItemDTO.setLotattDTO(lotattDTO);
         agvCallItemDTOList.add(agvCallItemDTO);
         agvCallItemDTOList.add(agvCallItemDTO);
         AgvCallDTO agvCallDTO = new AgvCallDTO();
         AgvCallDTO agvCallDTO = new AgvCallDTO();
+        agvCallDTO.setDocDetailsBaseDTO(docDetailsBaseDTO);
         agvCallDTO.setLocationFrom(orderAgvCallDTO.getLocationTo());
         agvCallDTO.setLocationFrom(orderAgvCallDTO.getLocationTo());
         agvCallDTO.setAgvCallItemDTOList(agvCallItemDTOList);
         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.setDocLineNo(orderAgvCallDTO.getLineNo()); // 设置明细行号
         agvCallDTO.setBusinessType(Constant.BUSINESS_TYPE.ORDER.getValue()); // 设置单据业务类型 -- 出库
         agvCallDTO.setBusinessType(Constant.BUSINESS_TYPE.ORDER.getValue()); // 设置单据业务类型 -- 出库
         agvCallDTO.setDocType(orderAgvCallDTO.getDocType()); // 设置单据类型
         agvCallDTO.setDocType(orderAgvCallDTO.getDocType()); // 设置单据类型
         agvCallDTO.setCreateUser(orderAgvCallDTO.getUser()); // 设置操作人
         agvCallDTO.setCreateUser(orderAgvCallDTO.getUser()); // 设置操作人
         return agvCallDTO;
         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.BionutritionDocDetailsService;
 import com.ruoyi.ams.bionutrition.doc.service.BionutritionDocHeaderService;
 import com.ruoyi.ams.bionutrition.doc.service.BionutritionDocHeaderService;
 import com.ruoyi.ams.bionutrition.dto.DocQcDTO;
 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.pda.IPdaDocQcService;
+import com.ruoyi.ams.bionutrition.sku.service.ISkuService;
 import com.ruoyi.ams.business.IBusinessService;
 import com.ruoyi.ams.business.IBusinessService;
 import com.ruoyi.ams.config.domain.dto.LotattDTO;
 import com.ruoyi.ams.config.domain.dto.LotattDTO;
 import com.ruoyi.ams.inv.domain.InvLotAtt;
 import com.ruoyi.ams.inv.domain.InvLotAtt;
 import com.ruoyi.ams.inv.domain.InvLotLocId;
 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.dto.InvMoveDTO;
 import com.ruoyi.ams.inv.service.IInvLotAttService;
 import com.ruoyi.ams.inv.service.IInvLotAttService;
 import com.ruoyi.ams.inv.service.IInvLotLocIdService;
 import com.ruoyi.ams.inv.service.IInvLotLocIdService;
 import com.ruoyi.base.constant.Constant;
 import com.ruoyi.base.constant.Constant;
 import com.ruoyi.base.domain.BaseLocationInfo;
 import com.ruoyi.base.domain.BaseLocationInfo;
+import com.ruoyi.base.domain.BaseSku;
 import com.ruoyi.base.service.IBaseLocationInfoService;
 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.core.redis.RedisKey;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.DateUtils;
@@ -54,13 +63,15 @@ public class PdaDocQcServiceImpl implements IPdaDocQcService {
     private BionutritionDocHeaderService bionutritionDocHeaderService;
     private BionutritionDocHeaderService bionutritionDocHeaderService;
     @Autowired
     @Autowired
     private BionutritionDocDetailsService bionutritionDocDetailsService;
     private BionutritionDocDetailsService bionutritionDocDetailsService;
+    @Autowired
+    private IBaseSkuService baseSkuService;
 
 
     /**
     /**
      * PDA质检
      * PDA质检
      * @param docQcDTO
      * @param docQcDTO
      * @param updateBy
      * @param updateBy
      */
      */
-    @Override
+    /*@Override
     @Transactional(rollbackFor = RuntimeException.class)
     @Transactional(rollbackFor = RuntimeException.class)
     public void docQcSubmit(DocQcDTO docQcDTO, String updateBy) {
     public void docQcSubmit(DocQcDTO docQcDTO, String updateBy) {
         // 根据物料编码和批号查询批次信息
         // 根据物料编码和批号查询批次信息
@@ -98,7 +109,7 @@ public class PdaDocQcServiceImpl implements IPdaDocQcService {
                 createConveyTaskToBHGZone(updateBy, lotNumNew, docQcDTO);
                 createConveyTaskToBHGZone(updateBy, lotNumNew, docQcDTO);
             }
             }
         }
         }
-    }
+    }*/
 
 
     /**
     /**
      * 生成搬运任务到不合格区
      * 生成搬运任务到不合格区
@@ -106,16 +117,16 @@ public class PdaDocQcServiceImpl implements IPdaDocQcService {
      * @param updateBy
      * @param updateBy
      * @param lotNumNew
      * @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);
         List<InvLotLocId> invLotLocIdList = invLotLocIdService.selectInvLotLocIdByLotnum(lotNumNew);
         Assert.isTrue(CollUtil.isNotEmpty(invLotLocIdList), "未找到批号对应库存");
         Assert.isTrue(CollUtil.isNotEmpty(invLotLocIdList), "未找到批号对应库存");
         int availableLocNumber = 0;
         int availableLocNumber = 0;
         // 同一批次多个库位库存都需要搬运至不合格区
         // 同一批次多个库位库存都需要搬运至不合格区
         for (InvLotLocId invLotLocId : invLotLocIdList) {
         for (InvLotLocId invLotLocId : invLotLocIdList) {
+            BaseLocationInfo locationInfo = null;
             // 获取所有不合格区库位
             // 获取所有不合格区库位
             List<BaseLocationInfo> baseLocationToList = baseLocationInfoService.selectSortedLocatinListByZoneId(
             List<BaseLocationInfo> baseLocationToList = baseLocationInfoService.selectSortedLocatinListByZoneId(
                     Long.parseLong(Constant.LOCATION_ZONE.BHG_ZONE.getValue()), Constant.WAREHOUSE_ID, null);
                     Long.parseLong(Constant.LOCATION_ZONE.BHG_ZONE.getValue()), Constant.WAREHOUSE_ID, null);
-            BaseLocationInfo locationInfo = null;
             for (BaseLocationInfo b : baseLocationToList) {
             for (BaseLocationInfo b : baseLocationToList) {
                 // 获取一个没有任务且为空的库位
                 // 获取一个没有任务且为空的库位
                 if (StringUtils.equals(b.getStockStatus(), Constant.STOCK_STATUS.STOCK00.getValue())
                 if (StringUtils.equals(b.getStockStatus(), Constant.STOCK_STATUS.STOCK00.getValue())
@@ -129,15 +140,20 @@ public class PdaDocQcServiceImpl implements IPdaDocQcService {
             if (locationInfo == null) {
             if (locationInfo == null) {
                 throw new ServiceException("当前批次库存有" + invLotLocIdList.size() + "托,不合格区可用库位有"+availableLocNumber+"个");
                 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);
             invLotLocIdService.move(invMoveDTO, updateBy);
         }
         }
     }
     }
 
 
+    /**
+     * 获取质检列表
+     * @param sku
+     * @return
+     */
     @Override
     @Override
     public List<DocQcDTO> getQcList(String sku) {
     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), "没有状态为上架的信息");
         Assert.isTrue(CollUtil.isNotEmpty(docDetailsDTOList), "没有状态为上架的信息");
         //2. 查出单据 List<Header>
         //2. 查出单据 List<Header>
         List<String> headerIdList = docDetailsDTOList.stream().filter(item->StringUtils.isNotBlank(item.getDocHeaderId()))
         List<String> headerIdList = docDetailsDTOList.stream().filter(item->StringUtils.isNotBlank(item.getDocHeaderId()))
@@ -155,29 +171,129 @@ public class PdaDocQcServiceImpl implements IPdaDocQcService {
 
 
         //对每一个库存: 找到对应的批次 根据批次的lot10 找到对应的明细
         //对每一个库存: 找到对应的批次 根据批次的lot10 找到对应的明细
         List<String> lotNumListHasLoc = invLotLocIds.stream().map(InvLotLocId::getLotnum).distinct().collect(Collectors.toList());
         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<String> lineNoList = docDetailsDTOList.stream().map(item -> item.getDocLineNo()).collect(Collectors.toList());
         List<DocQcDTO> docQcDTOList = invLotAttList.stream().filter(item -> CollUtil.contains(lotNumListHasLoc, item.getLotnum()))
         List<DocQcDTO> docQcDTOList = invLotAttList.stream().filter(item -> CollUtil.contains(lotNumListHasLoc, item.getLotnum()))
                 .filter(item -> CollUtil.contains(lineNoList, item.getLotatt10()))
                 .filter(item -> CollUtil.contains(lineNoList, item.getLotatt10()))
+                .filter(item->StringUtils.equals(item.getLotatt05(), Constant.QUALITY_STATUS.HG.getValue()))
                 .map(item -> {
                 .map(item -> {
                     DocQcDTO docQcDTO = new DocQcDTO();
                     DocQcDTO docQcDTO = new DocQcDTO();
                     docQcDTO.setBatchNumber(item.getLotatt02());
                     docQcDTO.setBatchNumber(item.getLotatt02());
                     docQcDTO.setSkuCode(item.getSku());
                     docQcDTO.setSkuCode(item.getSku());
                     docQcDTO.setDocNo(map.get(item.getLotatt09()));
                     docQcDTO.setDocNo(map.get(item.getLotatt09()));
-                    docQcDTO.setStatus(Constant.ASN_STS.STS60.getValue());
+                    docQcDTO.setStatus(item.getLotatt05());
                     return docQcDTO;
                     return docQcDTO;
-                }).collect(Collectors.toList());
+                }).distinct().collect(Collectors.toList());
 //        invLotAttService.selectInvLotAttByLotnum()
 //        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;
         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;
 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.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.ByteUtil;
 import com.ruoyi.ams.agv.ndc.common.CRC16Util;
 import com.ruoyi.ams.agv.ndc.common.CRC16Util;
 import com.ruoyi.ams.agv.ndc.domain.AmsTask;
 import com.ruoyi.ams.agv.ndc.domain.AmsTask;
 import com.ruoyi.ams.agv.ndc.service.IAmsTaskService;
 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.box.service.IWmsBoxInfoService;
 import com.ruoyi.ams.config.domain.AsnSoStrategy;
 import com.ruoyi.ams.config.domain.AsnSoStrategy;
 import com.ruoyi.ams.config.domain.dto.*;
 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.mapper.AsnSoStrategyMapper;
 import com.ruoyi.ams.config.service.IFlowConfigHeaderService;
 import com.ruoyi.ams.config.service.IFlowConfigHeaderService;
 import com.ruoyi.ams.config.service.LocationAllocationStrategy;
 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.domain.vo.InvLotLocIdLotattVO;
 import com.ruoyi.ams.inv.mapper.InvLotLocIdMapper;
 import com.ruoyi.ams.inv.mapper.InvLotLocIdMapper;
 import com.ruoyi.ams.inv.service.IInvLotAttService;
 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.RedisCache;
 import com.ruoyi.common.core.redis.RedisKey;
 import com.ruoyi.common.core.redis.RedisKey;
 import com.ruoyi.common.exception.ServiceException;
 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.StringUtils;
 import com.ruoyi.common.utils.uuid.SnowflakeIdWorker;
 import com.ruoyi.common.utils.uuid.SnowflakeIdWorker;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.annotation.Transactional;
@@ -78,6 +92,8 @@ public class BusinessServiceImpl implements IBusinessService {
     private IAmsTaskService amsTaskService;
     private IAmsTaskService amsTaskService;
     @Autowired
     @Autowired
     private IFlowConfigHeaderService flowConfigHeaderService;
     private IFlowConfigHeaderService flowConfigHeaderService;
+    @Autowired
+    private BionutritionDocDetailsService bionutritionDocDetailsService;
 
 
     public static int geniKey(String taskNo) {
     public static int geniKey(String taskNo) {
         int res = CRC16Util.calcCrc16(ByteUtil.string2byteArray(taskNo));
         int res = CRC16Util.calcCrc16(ByteUtil.string2byteArray(taskNo));
@@ -173,8 +189,11 @@ public class BusinessServiceImpl implements IBusinessService {
                             , agvCallDTO.getWarehouseId(), hashMap, agvCall.getSku(), "lotatt04 , lotatt06");
                             , agvCallDTO.getWarehouseId(), hashMap, agvCall.getSku(), "lotatt04 , lotatt06");
                     locationFrom = this.zoneLocationAllocation(locationFromList, "locationFrom", "SO", asnSoStrategy, token);
                     locationFrom = this.zoneLocationAllocation(locationFromList, "locationFrom", "SO", asnSoStrategy, token);
                     locationTo = this.zoneLocationAllocation(locationToList, "locationTo", "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));
                     wcsTaskList.addAll(this.genTask(locationFrom, locationTo, flowConfigHeaderVO, agvCallDTO, token));
-
                 } else if (flowConfigHeaderVO.getFlowType().equals("MV")) {
                 } else if (flowConfigHeaderVO.getFlowType().equals("MV")) {
                     List<BaseLocationInfo> locationFromList = this.convertLocation(paramLocationFrom, agvCallDTO.getWarehouseId(), null);
                     List<BaseLocationInfo> locationFromList = this.convertLocation(paramLocationFrom, agvCallDTO.getWarehouseId(), null);
                     List<BaseLocationInfo> locationToList = this.convertLocation(paramLocationTo, 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
     @Transactional
     @Override
     @Override
     public BaseLocationInfo inLocationAllocation(InWarehouseDTO inWarehouseDTO, Long token) {
     public BaseLocationInfo inLocationAllocation(InWarehouseDTO inWarehouseDTO, Long token) {
@@ -860,4 +894,42 @@ public class BusinessServiceImpl implements IBusinessService {
         }
         }
         return true;
         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
      * @return
      */
      */
     boolean taskDispatchCheck(WcsTask wcsTask);
     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;
 package com.ruoyi.ams.config.domain.dto;
 
 
+import com.ruoyi.ams.bionutrition.doc.dto.detail.BionutritionDocDetailsBaseDTO;
 import lombok.Data;
 import lombok.Data;
 
 
 import java.util.ArrayList;
 import java.util.ArrayList;
@@ -16,11 +17,14 @@ public class AgvCallDTO {
     private String palletNo;
     private String palletNo;
     private String extParam;
     private String extParam;
     private String docNo;
     private String docNo;
+    private String docType;
     private String docLineNo;
     private String docLineNo;
     private String businessType;
     private String businessType;
-    private String docType;
+    private String headerId;
     private String createUser;
     private String createUser;
+    private String ifSample;
     private Long warehouseId;
     private Long warehouseId;
     private String toArea;// 目标区域(货物最终去掉区域)
     private String toArea;// 目标区域(货物最终去掉区域)
+    private BionutritionDocDetailsBaseDTO docDetailsBaseDTO; // 单据明细
     private List<AgvCallItemDTO> agvCallItemDTOList = new ArrayList<>();
     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 lombok.Data;
 
 
+import java.math.BigDecimal;
+
 @Data
 @Data
 public class AgvCallItemDTO {
 public class AgvCallItemDTO {
     private String sku;
     private String sku;
     private Double qty;
     private Double qty;
+    /**
+     * 一托盘的总量(根据qty*物料包装规格计算,单位可能是质量、体积、个数)
+     */
+    private BigDecimal totalAmount;
     private Double weight;
     private Double weight;
     private String supplier;
     private String supplier;
     private String extParam;
     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 lotatt09;
     /**
     /**
-     * 明细行号
+     * 入库单明细行号
      */
      */
     private String lotatt10;
     private String lotatt10;
+    /**
+     * 出库单头id
+     */
     private String lotatt11;
     private String lotatt11;
+    /**
+     * 出库单明细行号
+     */
     private String lotatt12;
     private String lotatt12;
     private String lotatt13;
     private String lotatt13;
     private String lotatt14;
     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接口
  * 流程配置头Mapper接口
- * 
+ *
  * @author ruoyi
  * @author ruoyi
  * @date 2022-02-16
  * @date 2022-02-16
  */
  */
-public interface FlowConfigHeaderMapper 
+public interface FlowConfigHeaderMapper
 {
 {
     /**
     /**
      * 查询流程配置头
      * 查询流程配置头
-     * 
+     *
      * @param id 流程配置头主键
      * @param id 流程配置头主键
      * @return 流程配置头
      * @return 流程配置头
      */
      */
@@ -25,7 +25,7 @@ public interface FlowConfigHeaderMapper
 
 
     /**
     /**
      * 查询流程配置头列表
      * 查询流程配置头列表
-     * 
+     *
      * @param flowConfigHeader 流程配置头
      * @param flowConfigHeader 流程配置头
      * @return 流程配置头集合
      * @return 流程配置头集合
      */
      */
@@ -48,7 +48,7 @@ public interface FlowConfigHeaderMapper
 
 
     /**
     /**
      * 新增流程配置头
      * 新增流程配置头
-     * 
+     *
      * @param flowConfigHeader 流程配置头
      * @param flowConfigHeader 流程配置头
      * @return 结果
      * @return 结果
      */
      */
@@ -56,7 +56,7 @@ public interface FlowConfigHeaderMapper
 
 
     /**
     /**
      * 修改流程配置头
      * 修改流程配置头
-     * 
+     *
      * @param flowConfigHeader 流程配置头
      * @param flowConfigHeader 流程配置头
      * @return 结果
      * @return 结果
      */
      */
@@ -64,7 +64,7 @@ public interface FlowConfigHeaderMapper
 
 
     /**
     /**
      * 删除流程配置头
      * 删除流程配置头
-     * 
+     *
      * @param id 流程配置头主键
      * @param id 流程配置头主键
      * @return 结果
      * @return 结果
      */
      */
@@ -72,7 +72,7 @@ public interface FlowConfigHeaderMapper
 
 
     /**
     /**
      * 批量删除流程配置头
      * 批量删除流程配置头
-     * 
+     *
      * @param ids 需要删除的数据主键集合
      * @param ids 需要删除的数据主键集合
      * @return 结果
      * @return 结果
      */
      */
@@ -80,24 +80,24 @@ public interface FlowConfigHeaderMapper
 
 
     /**
     /**
      * 批量删除流程配置体
      * 批量删除流程配置体
-     * 
+     *
      * @param ids 需要删除的数据主键集合
      * @param ids 需要删除的数据主键集合
      * @return 结果
      * @return 结果
      */
      */
      int deleteFlowConfigDetailsByHeaderIds(Long[] ids);
      int deleteFlowConfigDetailsByHeaderIds(Long[] ids);
-    
+
     /**
     /**
      * 批量新增流程配置体
      * 批量新增流程配置体
-     * 
+     *
      * @param flowConfigDetailsList 流程配置体列表
      * @param flowConfigDetailsList 流程配置体列表
      * @return 结果
      * @return 结果
      */
      */
      int batchFlowConfigDetails(List<FlowConfigDetails> flowConfigDetailsList);
      int batchFlowConfigDetails(List<FlowConfigDetails> flowConfigDetailsList);
-    
+
 
 
     /**
     /**
      * 通过流程配置头主键删除流程配置体信息
      * 通过流程配置头主键删除流程配置体信息
-     * 
+     *
      * @param id 流程配置头ID
      * @param id 流程配置头ID
      * @return 结果
      * @return 结果
      */
      */
@@ -116,4 +116,11 @@ public interface FlowConfigHeaderMapper
      * @return
      * @return
      */
      */
     List<FlowConfigHeader> selectFlowConfigHeaderRel(Long id);
     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接口
  * 流程配置头Service接口
- * 
+ *
  * @author ruoyi
  * @author ruoyi
  * @date 2022-02-16
  * @date 2022-02-16
  */
  */
-public interface IFlowConfigHeaderService 
+public interface IFlowConfigHeaderService
 {
 {
     /**
     /**
      * 查询流程配置头
      * 查询流程配置头
-     * 
+     *
      * @param id 流程配置头主键
      * @param id 流程配置头主键
      * @return 流程配置头
      * @return 流程配置头
      */
      */
@@ -26,7 +26,7 @@ public interface IFlowConfigHeaderService
 
 
     /**
     /**
      * 查询流程配置头列表
      * 查询流程配置头列表
-     * 
+     *
      * @param flowConfigHeader 流程配置头
      * @param flowConfigHeader 流程配置头
      * @return 流程配置头集合
      * @return 流程配置头集合
      */
      */
@@ -41,7 +41,7 @@ public interface IFlowConfigHeaderService
 
 
     /**
     /**
      * 新增流程配置头
      * 新增流程配置头
-     * 
+     *
      * @param flowConfigHeader 流程配置头
      * @param flowConfigHeader 流程配置头
      * @return 结果
      * @return 结果
      */
      */
@@ -49,7 +49,7 @@ public interface IFlowConfigHeaderService
 
 
     /**
     /**
      * 修改流程配置头
      * 修改流程配置头
-     * 
+     *
      * @param flowConfigForm 流程配置头
      * @param flowConfigForm 流程配置头
      * @return 结果
      * @return 结果
      */
      */
@@ -59,7 +59,7 @@ public interface IFlowConfigHeaderService
 
 
     /**
     /**
      * 批量删除流程配置头
      * 批量删除流程配置头
-     * 
+     *
      * @param ids 需要删除的流程配置头主键集合
      * @param ids 需要删除的流程配置头主键集合
      * @return 结果
      * @return 结果
      */
      */
@@ -67,7 +67,7 @@ public interface IFlowConfigHeaderService
 
 
     /**
     /**
      * 删除流程配置头信息
      * 删除流程配置头信息
-     * 
+     *
      * @param id 流程配置头主键
      * @param id 流程配置头主键
      * @return 结果
      * @return 结果
      */
      */
@@ -93,4 +93,6 @@ public interface IFlowConfigHeaderService
      * @return
      * @return
      */
      */
     List<FlowConfigHeader> sortFlowConfigHeader(Long id);
     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) {
     private List<FlowConfigHeader> sortFlow(List<FlowConfigHeader> list, List<FlowConfigHeader> sortList, Long rootId) {
         if (rootId == null) {
         if (rootId == null) {
             return sortList;
             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 = "库存数量")
     @Excel(name = "库存数量")
     private BigDecimal qtyEach;
     private BigDecimal qtyEach;
 
 
+    /**
+     * 一托盘的总量(根据qty*物料包装规格计算,单位可能是质量、体积、个数)
+     */
+    private BigDecimal totalAmount;
+
     /** 分配数量 */
     /** 分配数量 */
     @Excel(name = "分配数量")
     @Excel(name = "分配数量")
     private BigDecimal qtyallocated;
     private BigDecimal qtyallocated;
@@ -59,6 +64,10 @@ public class InvLotLocId extends BaseEntity
      * 是否过期
      * 是否过期
      */
      */
     private String isExpire;
     private String isExpire;
+    /**
+     * 是否为取样库存 Y:是 N:不是
+     */
+    private String ifSample;
 
 
     /** $column.columnComment */
     /** $column.columnComment */
     @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
     @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);
     InvLotLocId selectInvLotLocIdByTraceIdAndLocationId(@Param("locationTo")String locationTo, @Param("taskNo")String taskNo);
 
 
     List<InvLotLocId> selectInvLotLocIdByLotnumList(List<String> lotNumList);
     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
      * @return
      */
      */
     InvLotLocId selectInvLotLocIdByTraceIdAndLocationId(String locationTo, String taskNo);
     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
      * @return
      */
      */
     @Override
     @Override
+    @Transactional(rollbackFor = RuntimeException.class)
     public AjaxResult move(InvMoveDTO invMoveDTO, String updateBy) {
     public AjaxResult move(InvMoveDTO invMoveDTO, String updateBy) {
 
 
         Boolean isEmpty = StringUtils.isEmpty(invMoveDTO.getSourceLocationId()) || StringUtils.isEmpty(invMoveDTO.getTargetLocationId());
         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);
         Boolean isIdleFrom = baseLocationInfoService.verifyLocationIsIdle(locationFrom, warehouseId);
-        if (!isIdleFrom) {
-            return AjaxResult.error("起始库位需要空闲状态!");
-        }
+        Assert.isTrue(isIdleFrom, "起始库位需要空闲状态!");
         // 验证目标库位
         // 验证目标库位
         Boolean isIdle = baseLocationInfoService.verifyLocationIsIdle(locationTo, warehouseId);
         Boolean isIdle = baseLocationInfoService.verifyLocationIsIdle(locationTo, warehouseId);
-        if (!isIdle) {
-            return AjaxResult.error("目标库位需要空闲状态!");
-        }
+        Assert.isTrue(isIdle, "目标库位需要空闲状态!");
         Boolean isInStock = baseLocationInfoService.verifyLocationIsInStock(locationTo, warehouseId);
         Boolean isInStock = baseLocationInfoService.verifyLocationIsInStock(locationTo, warehouseId);
-        if (isInStock) {
-            return AjaxResult.error("目标库位有货!");
-        }
-
+        Assert.isFalse(isInStock, "目标库位有货!");
 
 
         // 起始和目标库位
         // 起始和目标库位
         baseLocationFrom = baseLocationInfoService.selectBaseLocationInfoByIdOrNo(locationFrom, warehouseId);
         baseLocationFrom = baseLocationInfoService.selectBaseLocationInfoByIdOrNo(locationFrom, warehouseId);
@@ -575,8 +569,8 @@ public class InvLotLocIdServiceImpl implements IInvLotLocIdService {
             invLotLocId.setCustomerId(customerId);
             invLotLocId.setCustomerId(customerId);
             invLotLocId.setQty(new BigDecimal(qty));
             invLotLocId.setQty(new BigDecimal(qty));
             invLotLocId.setQtyEach(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.setQtypa(BigDecimal.ZERO);
             invLotLocId.setQtyrpin(BigDecimal.ZERO);
             invLotLocId.setQtyrpin(BigDecimal.ZERO);
             invLotLocId.setIsExpire(Constant.EXPIRE_STATUS.UNEXPIRED.getValue());
             invLotLocId.setIsExpire(Constant.EXPIRE_STATUS.UNEXPIRED.getValue());
@@ -756,7 +750,7 @@ public class InvLotLocIdServiceImpl implements IInvLotLocIdService {
         lotattVOList = lotattVOList.stream().filter(
         lotattVOList = lotattVOList.stream().filter(
                 item->!StringUtils.equals(item.getIsExpire(), Constant.EXPIRE_STATUS.EXPIRED.getValue()))
                 item->!StringUtils.equals(item.getIsExpire(), Constant.EXPIRE_STATUS.EXPIRED.getValue()))
                 .collect(Collectors.toList());
                 .collect(Collectors.toList());
-        return lotattVOList.stream().allMatch(v -> !v.getLotatt05().equals("FX"));// 是否所有库存都不是放行状态
+        return lotattVOList.stream().allMatch(v -> !v.getLotatt05().equals("FX"));
     }
     }
 
 
     @Override
     @Override
@@ -781,4 +775,19 @@ public class InvLotLocIdServiceImpl implements IInvLotLocIdService {
     public InvLotLocId selectInvLotLocIdByTraceIdAndLocationId(String locationTo, String taskNo) {
     public InvLotLocId selectInvLotLocIdByTraceIdAndLocationId(String locationTo, String taskNo) {
         return invLotLocIdMapper.selectInvLotLocIdByTraceIdAndLocationId(locationTo, 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.AgvCallDTO;
 import com.ruoyi.ams.config.domain.dto.AgvCallItemDTO;
 import com.ruoyi.ams.config.domain.dto.AgvCallItemDTO;
 import com.ruoyi.ams.config.domain.dto.LotattDTO;
 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.IFlowConfigEventService;
+import com.ruoyi.ams.config.service.IFlowConfigHeaderService;
 import com.ruoyi.ams.inv.domain.InvLotAtt;
 import com.ruoyi.ams.inv.domain.InvLotAtt;
 import com.ruoyi.ams.inv.domain.InvLotLocId;
 import com.ruoyi.ams.inv.domain.InvLotLocId;
 import com.ruoyi.ams.inv.mapper.InvLotLocIdMapper;
 import com.ruoyi.ams.inv.mapper.InvLotLocIdMapper;
@@ -107,6 +109,8 @@ public class WcsTaskServiceImpl implements IWcsTaskService {
 
 
     @Autowired
     @Autowired
     private BionutritionDocDetailsService bionutritionDocDetailsService;
     private BionutritionDocDetailsService bionutritionDocDetailsService;
+    @Autowired
+    private IFlowConfigHeaderService flowConfigHeaderService;
 
 
     //任务状态翻译
     //任务状态翻译
     private String codeConvert(int code) {
     private String codeConvert(int code) {
@@ -644,14 +648,14 @@ public class WcsTaskServiceImpl implements IWcsTaskService {
         Assert.isTrue(NumberUtil.compare(
         Assert.isTrue(NumberUtil.compare(
                 Long.valueOf(docDetailsBaseDTO.getSkuQty()), Long.valueOf(orderAgvCallDTO.getQty())) >= 0
                 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
         // 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呼叫对象
         // 4.构建agv呼叫对象
-        AgvCallDTO agvCallDTO = pdaAgvCallService.getOrderAgvCallDTO(orderAgvCallDTO);
+        AgvCallDTO agvCallDTO = pdaAgvCallService.getOrderAgvCallDTO(orderAgvCallDTO, bionutritionDocHeaderBaseDTO, docDetailsBaseDTO);
         return iBusinessService.agvCall(flowId, agvCallDTO);
         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"/>
         <include refid="selectFlowConfigHeaderVo"/>
         where root_flow = #{headerId}
         where root_flow = #{headerId}
     </select>
     </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>
 </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">
     <select id="selectInvLotAttListByHeaderIds" resultType="com.ruoyi.ams.inv.domain.InvLotAtt">
         <include refid="selectInvLotAttVo"/>
         <include refid="selectInvLotAttVo"/>
         where inv_lot_att.lotatt09 in
         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>
         </foreach>
     </select>
     </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="sku"    column="sku"    />
         <result property="qty"    column="qty"    />
         <result property="qty"    column="qty"    />
         <result property="qtyEach"    column="qty_each"    />
         <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="qtyallocated"    column="qtyallocated"    />
         <result property="qtyallocatedEach"    column="qtyallocated_each"    />
         <result property="qtyallocatedEach"    column="qtyallocated_each"    />
         <result property="qtypa"    column="qtypa"    />
         <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="customerId"    column="customer_id"    />
         <result property="sku"    column="sku"    />
         <result property="sku"    column="sku"    />
         <result property="skuName"    column="sku_name"    />
         <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="qty"    column="qty"    />
         <result property="qtyallocated"    column="qtyallocated"    />
         <result property="qtyallocated"    column="qtyallocated"    />
         <result property="weight"    column="weight"    />
         <result property="weight"    column="weight"    />
@@ -121,7 +123,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </resultMap>
     </resultMap>
 
 
     <sql id="selectInvLotLocIdVo">
     <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>
     </sql>
 
 
     <select id="selectInvLotLocIdList" parameterType="InvLotLocId" resultMap="InvLotLocIdResult">
     <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="sku != null">sku,</if>
             <if test="qty != null">qty,</if>
             <if test="qty != null">qty,</if>
             <if test="qtyEach != null">qty_each,</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="qtyallocated != null">qtyallocated,</if>
             <if test="qtyallocatedEach != null">qtyallocated_each,</if>
             <if test="qtyallocatedEach != null">qtyallocated_each,</if>
             <if test="qtypa != null">qtypa,</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="sku != null">#{sku},</if>
             <if test="qty != null">#{qty},</if>
             <if test="qty != null">#{qty},</if>
             <if test="qtyEach != null">#{qtyEach},</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="qtyallocated != null">#{qtyallocated},</if>
             <if test="qtyallocatedEach != null">#{qtyallocatedEach},</if>
             <if test="qtyallocatedEach != null">#{qtyallocatedEach},</if>
             <if test="qtypa != null">#{qtypa},</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="sku != null">sku = #{sku},</if>
             <if test="qty != null">qty = #{qty},</if>
             <if test="qty != null">qty = #{qty},</if>
             <if test="qtyEach != null">qty_each = #{qtyEach},</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="qtyallocated != null">qtyallocated = #{qtyallocated},</if>
             <if test="qtyallocatedEach != null">qtyallocated_each = #{qtyallocatedEach},</if>
             <if test="qtyallocatedEach != null">qtyallocated_each = #{qtyallocatedEach},</if>
             <if test="qtypa != null">qtypa = #{qtypa},</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 id="selectInvLocIdLotattList" resultMap="InvLotLocIdLotattResult">
         select
         select
         inv.*,
         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
         ,lotatt01, lotatt02, lotatt03, lotatt04,lotatt05, lotatt06
         ,lotatt07, lotatt08, lotatt09, lotatt10, lotatt11, lotatt12, lotatt13, lotatt14, lotatt15, lotatt16, lotatt17
         ,lotatt07, lotatt08, lotatt09, lotatt10, lotatt11, lotatt12, lotatt13, lotatt14, lotatt15, lotatt16, lotatt17
         ,lotatt18
         ,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 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_info b on inv.location_id = b.id
         left join base_location_zone z on b.zone_id = z.zone_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>
         <where>
+            inv.location_id != '99998'
             <if test="zoneId != null  and zoneId != ''"> and b.zone_id = #{zoneId}</if>
             <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="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="isExpire != null and isExpire != ''"> and inv.is_expire in('1','2')</if>
             <if test="isFull != null  and isFull != ''"> and w.is_full = #{isFull}</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()
         update inv_lot_loc_id set lotnum = #{lotNumNew}, update_time = now()
         where lotnum = #{lotnum}
         where lotnum = #{lotnum}
     </update>
     </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 id="querySameTypeByPalletNo" resultMap="InvLotLocIdResult">
         select inv.*
         select inv.*
@@ -639,4 +658,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             #{lotNum}
             #{lotNum}
         </foreach>
         </foreach>
     </select>
     </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>
 </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_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"),
         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 {
 
 
     }
     }
 
 
+
+
 }
 }