浏览代码

出入库、上架、质检、放行功能,v1.0

dfsfs 1 年之前
父节点
当前提交
74d0ef7255
共有 72 个文件被更改,包括 1738 次插入671 次删除
  1. 54 49
      base/sql/bsl_sql/bsl_ddl_v1.0.0.sql
  2. 18 18
      base/sql/bsl_sql/bsl_dml_v1.0.0.sql
  3. 3 1
      ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java
  4. 10 0
      ruoyi-admin/src/main/java/com/ruoyi/bionutrition/pda/controller/CallBackDTO.java
  5. 26 0
      ruoyi-admin/src/main/java/com/ruoyi/bionutrition/pda/controller/PdaAgvCallController.java
  6. 5 3
      ruoyi-admin/src/main/java/com/ruoyi/bionutrition/pda/controller/PdaDocQcController.java
  7. 1 1
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/warewms/ams/WcsTaskController.java
  8. 5 4
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/warewms/base/BaseLocationInfoController.java
  9. 12 24
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/warewms/doc/BionutritionDocHeaderController.java
  10. 1 1
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/warewms/pda/PdaInvLotLocIdController.java
  11. 8 8
      ruoyi-admin/src/main/resources/logback-test.xml
  12. 8 8
      ruoyi-admin/src/main/resources/logback.xml
  13. 117 0
      ruoyi-admin/src/test/java/com/ruoyi/admin/test/base/WarehouseTest.java
  14. 2 2
      ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java
  15. 1 1
      warewms-ams/src/main/java/com/ruoyi/ams/agv/ndc/AciService.java
  16. 22 6
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/domain/BionutritionDocDetails.java
  17. 8 0
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/domain/BionutritionDocHeader.java
  18. 18 4
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/BionutritionDocDetailsDTO.java
  19. 6 0
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/BionutritionDocHeaderDTO.java
  20. 11 18
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/DocLotattDTO.java
  21. 12 0
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/DocQueryDto.java
  22. 14 0
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/detail/BionutritionDocDetailsBaseDTO.java
  23. 2 2
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/detail/FinishedProductReceiptDetailsDTO.java
  24. 5 6
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/detail/ProductionPickingReceiptDetailsDTO.java
  25. 2 2
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/detail/ProductionReturnOrderDetailsDTO.java
  26. 2 2
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/detail/PurchaseOrderDetailsDTO.java
  27. 2 2
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/detail/PurchaseReceiptDetailsDTO.java
  28. 2 2
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/detail/SaleOutboundOrderDetailsDTO.java
  29. 2 2
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/detail/SaleReturnOrderDetailsDTO.java
  30. 6 0
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/header/BionutritionDocHeaderBaseDTO.java
  31. 2 2
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/excel/detail/FinishedProductReceiptDetailsExcel.java
  32. 5 6
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/excel/detail/ProductionPickingReceiptDetailsExcel.java
  33. 2 2
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/excel/detail/ProductionReturnOrderDetailsExcel.java
  34. 5 2
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/excel/detail/PurchaseOrderDetailsExcel.java
  35. 5 2
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/excel/detail/PurchaseReceiptDetailsExcel.java
  36. 2 2
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/excel/detail/SaleOutboundOrderDetailsExcel.java
  37. 2 2
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/excel/detail/SaleReturnOrderDetailsExcel.java
  38. 0 7
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/factory/BionutritionDocFactory.java
  39. 4 0
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/service/BionutritionDocDetailsService.java
  40. 29 1
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/service/BionutritionDocHeaderService.java
  41. 40 9
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/service/impl/BionutritionDocDetailsServiceImpl.java
  42. 243 8
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/service/impl/BionutritionDocHeaderServiceImpl.java
  43. 14 1
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/dto/AsnAgvCallDTO.java
  44. 6 1
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/dto/DocQcDTO.java
  45. 41 0
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/dto/GroundingDTO.java
  46. 21 0
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/dto/OrderAgvCallDTO.java
  47. 32 0
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/pda/IPdaAgvCallService.java
  48. 170 46
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/pda/impl/PdaAgvCallServiceImpl.java
  49. 81 12
      warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/pda/impl/PdaDocQcServiceImpl.java
  50. 4 13
      warewms-ams/src/main/java/com/ruoyi/ams/business/BusinessServiceImpl.java
  51. 5 0
      warewms-ams/src/main/java/com/ruoyi/ams/config/domain/dto/AgvCallDTO.java
  52. 8 9
      warewms-ams/src/main/java/com/ruoyi/ams/config/domain/dto/LotattDTO.java
  53. 186 157
      warewms-ams/src/main/java/com/ruoyi/ams/inv/domain/InvLotAtt.java
  54. 2 0
      warewms-ams/src/main/java/com/ruoyi/ams/inv/dto/InvMoveDTO.java
  55. 4 0
      warewms-ams/src/main/java/com/ruoyi/ams/inv/mapper/InvLotAttMapper.java
  56. 4 0
      warewms-ams/src/main/java/com/ruoyi/ams/inv/mapper/InvLotLocIdMapper.java
  57. 9 0
      warewms-ams/src/main/java/com/ruoyi/ams/inv/service/IInvLotAttService.java
  58. 22 0
      warewms-ams/src/main/java/com/ruoyi/ams/inv/service/IInvLotLocIdService.java
  59. 11 0
      warewms-ams/src/main/java/com/ruoyi/ams/inv/service/impl/InvLotAttServiceImpl.java
  60. 60 27
      warewms-ams/src/main/java/com/ruoyi/ams/inv/service/impl/InvLotLocIdServiceImpl.java
  61. 17 0
      warewms-ams/src/main/java/com/ruoyi/ams/task/dto/WcsTaskInvLotDTO.java
  62. 10 7
      warewms-ams/src/main/java/com/ruoyi/ams/task/mapper/WcsTaskMapper.java
  63. 8 0
      warewms-ams/src/main/java/com/ruoyi/ams/task/service/IWcsTaskService.java
  64. 154 154
      warewms-ams/src/main/java/com/ruoyi/ams/task/service/impl/WcsTaskServiceImpl.java
  65. 33 4
      warewms-ams/src/main/resources/mapper/ams/InvLotAttMapper.xml
  66. 13 5
      warewms-ams/src/main/resources/mapper/ams/InvLotLocIdMapper.xml
  67. 17 1
      warewms-ams/src/main/resources/mapper/ams/WcsTaskMapper.xml
  68. 4 1
      warewms-ams/src/main/resources/mapper/doc/BionutritionDocHeaderMapper.xml
  69. 72 20
      warewms-base/src/main/java/com/ruoyi/base/constant/Constant.java
  70. 1 1
      warewms-base/src/main/java/com/ruoyi/base/service/IBaseLocationInfoService.java
  71. 2 2
      warewms-base/src/main/java/com/ruoyi/base/service/impl/BaseLocationInfoServiceImpl.java
  72. 3 1
      warewms-base/src/main/resources/mapper/base/BaseLocationInfoMapper.xml

+ 54 - 49
base/sql/bsl_sql/bsl_ddl_v1.0.0.sql

@@ -430,10 +430,12 @@ CREATE TABLE `bsl_doc_details` (
   `doc_header_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '单据头id',
   `doc_line_no` int(64) DEFAULT NULL COMMENT '明细行号',
   `sku_code` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '物料编码',
+  `line_status` varchar(20) DEFAULT NULL COMMENT '明细行状态',
   `sku_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '物料名称',
   `sku_qty` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '物料数量',
   `original_lot_number` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '原厂批号',
-  `batch_number` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '批号',
+  `income_lot_number` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '进厂批号',
+  `product_lot_number` varchar(255) DEFAULT NULL COMMENT '产品批号',
   `product_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '产品名称',
   `measure_unit` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '计量单位',
   `manufacture_date` datetime DEFAULT NULL COMMENT '生产日期',
@@ -444,6 +446,7 @@ CREATE TABLE `bsl_doc_details` (
   `price_include_tax` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '含税价',
   `warehouse_person` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '入库人',
   `reviewer_next` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '复审人',
+  `belong_details_id` varchar(255) DEFAULT NULL COMMENT '对应采购单明细id,只有采购入库单有值',
   `remark` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '备注',
   `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '创建者',
   `create_date` datetime DEFAULT NULL COMMENT '创建时间',
@@ -564,63 +567,65 @@ CREATE TABLE `flow_config_header`  (
 -- ----------------------------
 -- Table structure for inv_lot_att
 -- ----------------------------
+DROP TABLE IF EXISTS `inv_lot_att`;
 CREATE TABLE `inv_lot_att` (
-  `lotnum` varchar(50) CHARACTER SET utf8 NOT NULL COMMENT '主键',
-  `customer_id` varchar(30) CHARACTER SET utf8 DEFAULT NULL COMMENT '货主代码',
-  `sku` varchar(50) CHARACTER SET utf8 NOT NULL COMMENT '物料编码',
-  `lotatt01` varchar(20) CHARACTER SET utf8 DEFAULT NULL COMMENT '客户编码',
-  `lotatt02` varchar(20) CHARACTER SET utf8 DEFAULT NULL COMMENT '批号',
-  `lotatt03` varchar(20) CHARACTER SET utf8 DEFAULT NULL COMMENT '生产日期',
-  `lotatt04` varchar(100) CHARACTER SET utf8 DEFAULT NULL COMMENT '有效期',
-  `lotatt05` varchar(100) CHARACTER SET utf8 DEFAULT NULL COMMENT '检验状态',
-  `lotatt06` varchar(100) CHARACTER SET utf8 DEFAULT NULL COMMENT '入库日期',
-  `lotatt07` varchar(100) CHARACTER SET utf8 DEFAULT NULL COMMENT '规格型号',
-  `lotatt08` varchar(100) CHARACTER SET utf8 DEFAULT NULL COMMENT '收货日期',
-  `lotatt09` varchar(100) CHARACTER SET utf8 DEFAULT NULL COMMENT '总净重',
-  `lotatt10` varchar(100) CHARACTER SET utf8 DEFAULT NULL COMMENT '总毛重',
-  `lotatt11` varchar(100) CHARACTER SET utf8 DEFAULT NULL COMMENT '总皮重',
-  `lotatt12` varchar(100) CHARACTER SET utf8 DEFAULT NULL,
-  `lotatt13` varchar(100) CHARACTER SET utf8 DEFAULT NULL,
-  `lotatt14` varchar(100) CHARACTER SET utf8 DEFAULT NULL,
-  `lotatt15` varchar(100) CHARACTER SET utf8 DEFAULT NULL,
-  `lotatt16` varchar(100) CHARACTER SET utf8 DEFAULT NULL,
-  `lotatt17` varchar(100) CHARACTER SET utf8 DEFAULT NULL,
-  `lotatt18` varchar(100) CHARACTER SET utf8 DEFAULT NULL,
-  `create_by` varchar(64) DEFAULT '' COMMENT '创建者',
+  `lotnum` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键',
+  `customer_id` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '货主代码',
+  `sku` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '物料编码',
+  `lotatt01` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '客户编码',
+  `lotatt02` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '原厂批号',
+  `lotatt03` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '生产日期',
+  `lotatt04` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '有效期(有效截止日)',
+  `lotatt05` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '检验状态',
+  `lotatt06` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '入库日期',
+  `lotatt07` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '进厂批号',
+  `lotatt08` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '生产批号',
+  `lotatt09` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '入库单号',
+  `lotatt10` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
+  `lotatt11` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
+  `lotatt12` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
+  `lotatt13` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
+  `lotatt14` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
+  `lotatt15` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
+  `lotatt16` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
+  `lotatt17` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
+  `lotatt18` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
+  `create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '创建者',
   `create_time` datetime DEFAULT NULL COMMENT '创建时间',
-  `update_by` varchar(64) DEFAULT '' COMMENT '更新者',
+  `update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '更新者',
   `update_time` datetime DEFAULT NULL COMMENT '更新时间',
-  `remark` varchar(500) DEFAULT NULL COMMENT '备注',
+  `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
   PRIMARY KEY (`lotnum`) USING BTREE
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='批次属性';
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='批次属性';
 
 -- ----------------------------
 -- Table structure for inv_lot_loc_id
 -- ----------------------------
 DROP TABLE IF EXISTS `inv_lot_loc_id`;
-CREATE TABLE `inv_lot_loc_id`  (
-  `lotnum` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '批次号',
-  `location_id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '库位',
-  `traceid` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '跟踪号',
-  `customer_id` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '客户',
-  `sku` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '产品',
-  `qty` decimal(18, 8) NULL DEFAULT NULL COMMENT '数量',
-  `qty_each` decimal(18, 8) NULL DEFAULT NULL,
-  `qtyallocated` decimal(18, 8) NULL DEFAULT NULL COMMENT '分配数量',
-  `qtyallocated_each` decimal(18, 8) NULL DEFAULT NULL,
-  `qtypa` decimal(18, 8) NULL DEFAULT NULL COMMENT '上架数量',
-  `qtyrpin` decimal(18, 3) NULL DEFAULT NULL,
-  `qtyrpout` decimal(18, 3) NULL DEFAULT NULL,
-  `qtymvin` decimal(18, 3) NULL DEFAULT NULL,
-  `qtymvout` decimal(19, 4) NULL DEFAULT NULL,
-  `qtyonhold` decimal(18, 3) NULL DEFAULT NULL,
-  `create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '创建者',
-  `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
-  `update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '更新者',
-  `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
-  `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
-  PRIMARY KEY (`lotnum`, `location_id`, `customer_id`, `sku`) USING BTREE
-) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '库位库存信息' ROW_FORMAT = Dynamic;
+CREATE TABLE `inv_lot_loc_id` (
+  `lotnum` varchar(50) CHARACTER SET utf8 NOT NULL COMMENT '批次号',
+  `location_id` varchar(20) CHARACTER SET utf8 NOT NULL COMMENT '库位',
+  `traceid` varchar(30) CHARACTER SET utf8 DEFAULT NULL COMMENT '跟踪号',
+  `customer_id` varchar(30) CHARACTER SET utf8 NOT NULL COMMENT '客户',
+  `sku` varchar(50) CHARACTER SET utf8 NOT NULL COMMENT '产品',
+  `qty` decimal(18,8) DEFAULT NULL COMMENT '数量',
+  `qty_each` decimal(18,8) DEFAULT NULL,
+  `qtyallocated` decimal(18,8) DEFAULT NULL COMMENT '分配数量',
+  `qtyallocated_each` decimal(18,8) DEFAULT NULL,
+  `qtypa` decimal(18,8) DEFAULT NULL COMMENT '上架数量',
+  `qtyrpin` decimal(18,3) DEFAULT NULL,
+  `qtyrpout` decimal(18,3) DEFAULT NULL,
+  `qtymvin` decimal(18,3) DEFAULT NULL,
+  `qtymvout` decimal(19,4) DEFAULT NULL,
+  `qtyonhold` decimal(18,3) DEFAULT NULL,
+  `is_expire` varchar(10) DEFAULT NULL COMMENT '是否过期',
+  `create_by` varchar(64) DEFAULT '' COMMENT '创建者',
+  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+  `update_by` varchar(64) DEFAULT '' COMMENT '更新者',
+  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+  `remark` varchar(500) DEFAULT NULL COMMENT '备注',
+  PRIMARY KEY (`lotnum`,`location_id`,`customer_id`,`sku`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='库位库存信息';
 
 -- ----------------------------
 -- Table structure for location_priority_details

+ 18 - 18
base/sql/bsl_sql/bsl_dml_v1.0.0.sql

@@ -255,21 +255,21 @@ UPDATE `sys_menu` SET `menu_name` = '系统工具', `parent_id` = 0, `order_num`
 DELETE FROM sys_menu WHERE menu_id = 4
 
 /*批次配置数据*/
-INSERT INTO `lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2, 'lotatt01', '客户编码', 'Choice', 'Text', NULL, NULL, '0', '', NULL, '', '2022-04-07 22:05:09', NULL);
-INSERT INTO `lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (3, 'lotatt02', '批号', 'Choice', 'Text', NULL, NULL, '0', '', NULL, '', '2022-08-29 17:34:02', NULL);
-INSERT INTO `lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (4, 'lotatt03', '生产日期', 'Choice', 'DateBox', '', '', '0', '', NULL, '', NULL, NULL);
-INSERT INTO `lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (5, 'lotatt04', '有效期', 'Choice', 'DateBox', NULL, NULL, '0', '', NULL, '', NULL, NULL);
-INSERT INTO `lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (6, 'lotatt05', '收货日期', 'Choice', 'ComboBox', 'ams_inv_quality', '90', '0', '', NULL, '', '2022-12-22 16:58:33', NULL);
-INSERT INTO `lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (7, 'lotatt06', '入库日期', 'Choice', 'Text', NULL, NULL, '0', '', NULL, '', '2022-12-22 16:58:43', NULL);
-INSERT INTO `lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (8, 'lotatt07', '规格型号', 'Choice', 'Text', NULL, NULL, '0', '', NULL, '', '2022-12-22 16:59:45', NULL);
-INSERT INTO `lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (9, 'lotatt08', '检验状态', 'Choice', 'Text', NULL, NULL, '0', '', NULL, '', '2022-12-22 16:59:52', NULL);
-INSERT INTO `lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (10, 'lotatt09', '总净重', 'Choice', 'Text', NULL, NULL, '0', '', NULL, '', '2022-12-22 16:58:55', NULL);
-INSERT INTO `lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (11, 'lotatt10', '总毛重', 'Choice', 'Text', NULL, NULL, '0', '', NULL, '', '2022-12-22 17:00:00', NULL);
-INSERT INTO `lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (12, 'lotatt11', '总皮重', 'Choice', 'Text', NULL, NULL, '0', '', NULL, '', '2022-12-22 16:58:20', NULL);
-INSERT INTO `lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (13, 'lotatt12', '自定义', 'Choice', 'ComboBox', 'sys_yes_no', NULL, '0', '', NULL, '', NULL, NULL);
-INSERT INTO `lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (14, 'lotatt13', '自定义', 'Choice', 'DateBox', NULL, NULL, '0', '', NULL, '', '2022-12-22 16:58:13', NULL);
-INSERT INTO `lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (15, 'lotatt14', '自定义', 'Choice', 'Text', NULL, NULL, '0', '', NULL, '', '2022-03-31 15:35:42', NULL);
-INSERT INTO `lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (16, 'lotatt15', '自定义', 'Choice', 'ComboBox', 'qc_status', NULL, '0', '', NULL, '', '2022-12-16 10:46:53', NULL);
-INSERT INTO `lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (17, 'lotatt16', '自定义', 'Choice', 'Text', NULL, NULL, '0', '', NULL, '', '2022-12-22 16:58:03', NULL);
-INSERT INTO `lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (18, 'lotatt17', '自定义批次17', 'Choice', 'Text', NULL, NULL, '0', '', NULL, '', '2022-12-22 16:57:54', NULL);
-INSERT INTO `lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (19, 'lotatt18', '自定义批次18', 'Choice', 'Text', NULL, NULL, '0', '', NULL, '', '2022-04-12 19:35:11', NULL);
+INSERT INTO `baisuilai_test`.`lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2, 'lotatt01', '客户编码', 'Choice', 'Text', NULL, NULL, '0', '', NULL, '', '2022-04-07 22:05:09', NULL);
+INSERT INTO `baisuilai_test`.`lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (3, 'lotatt02', '原厂批号', 'Choice', 'Text', NULL, NULL, '0', '', NULL, '', '2022-08-29 17:34:02', NULL);
+INSERT INTO `baisuilai_test`.`lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (4, 'lotatt03', '生产日期', 'Choice', 'DateBox', '', '', '0', '', NULL, '', NULL, NULL);
+INSERT INTO `baisuilai_test`.`lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (5, 'lotatt04', '有效期', 'Choice', 'DateBox', NULL, NULL, '0', '', NULL, '', NULL, NULL);
+INSERT INTO `baisuilai_test`.`lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (6, 'lotatt05', '检验状态', 'Choice', 'ComboBox', 'ams_inv_quality', '90', '0', '', NULL, '', '2022-12-22 16:58:33', NULL);
+INSERT INTO `baisuilai_test`.`lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (7, 'lotatt06', '入库日期', 'Choice', 'Text', NULL, NULL, '0', '', NULL, '', '2022-12-22 16:58:43', NULL);
+INSERT INTO `baisuilai_test`.`lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (8, 'lotatt07', '进厂批号', 'Choice', 'Text', NULL, NULL, '0', '', NULL, '', '2022-12-22 16:59:45', NULL);
+INSERT INTO `baisuilai_test`.`lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (9, 'lotatt08', '生产批号', 'Choice', 'Text', NULL, NULL, '0', '', NULL, '', '2022-12-22 16:59:52', NULL);
+INSERT INTO `baisuilai_test`.`lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (10, 'lotatt09', '入库单号', 'Choice', 'Text', NULL, NULL, '0', '', NULL, '', '2022-12-22 16:58:55', NULL);
+INSERT INTO `baisuilai_test`.`lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (11, 'lotatt10', '自定义', 'Choice', 'Text', NULL, NULL, '0', '', NULL, '', '2022-12-22 17:00:00', NULL);
+INSERT INTO `baisuilai_test`.`lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (12, 'lotatt11', '自定义', 'Choice', 'Text', NULL, NULL, '0', '', NULL, '', '2022-12-22 16:58:20', NULL);
+INSERT INTO `baisuilai_test`.`lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (13, 'lotatt12', '自定义', 'Choice', 'ComboBox', 'sys_yes_no', NULL, '0', '', NULL, '', NULL, NULL);
+INSERT INTO `baisuilai_test`.`lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (14, 'lotatt13', '自定义', 'Choice', 'DateBox', NULL, NULL, '0', '', NULL, '', '2022-12-22 16:58:13', NULL);
+INSERT INTO `baisuilai_test`.`lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (15, 'lotatt14', '自定义', 'Choice', 'Text', NULL, NULL, '0', '', NULL, '', '2022-03-31 15:35:42', NULL);
+INSERT INTO `baisuilai_test`.`lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (16, 'lotatt15', '自定义', 'Choice', 'ComboBox', 'qc_status', NULL, '0', '', NULL, '', '2022-12-16 10:46:53', NULL);
+INSERT INTO `baisuilai_test`.`lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (17, 'lotatt16', '自定义', 'Choice', 'Text', NULL, NULL, '0', '', NULL, '', '2022-12-22 16:58:03', NULL);
+INSERT INTO `baisuilai_test`.`lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (18, 'lotatt17', '自定义批次17', 'Choice', 'Text', NULL, NULL, '0', '', NULL, '', '2022-12-22 16:57:54', NULL);
+INSERT INTO `baisuilai_test`.`lotatt_config`(`id`, `lotatt_id`, `lotatt_name`, `required_tag`, `input_type`, `input_scope`, `default_value`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (19, 'lotatt18', '自定义批次18', 'Choice', 'Text', NULL, NULL, '0', '', NULL, '', '2022-04-12 19:35:11', NULL);

+ 3 - 1
ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java

@@ -3,13 +3,15 @@ package com.ruoyi;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.scheduling.annotation.EnableScheduling;
 
 /**
  * 启动程序
- * 
+ *
  * @author ruoyi
  */
 @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
+@EnableScheduling
 public class RuoYiApplication
 {
     public static void main(String[] args)

+ 10 - 0
ruoyi-admin/src/main/java/com/ruoyi/bionutrition/pda/controller/CallBackDTO.java

@@ -0,0 +1,10 @@
+package com.ruoyi.bionutrition.pda.controller;
+
+import lombok.Data;
+
+@Data
+public class CallBackDTO {
+    private String taskNo;
+    private Integer state;
+
+}

+ 26 - 0
ruoyi-admin/src/main/java/com/ruoyi/bionutrition/pda/controller/PdaAgvCallController.java

@@ -2,7 +2,10 @@ package com.ruoyi.bionutrition.pda.controller;
 
 import cn.hutool.core.lang.Assert;
 import com.ruoyi.ams.bionutrition.dto.AsnAgvCallDTO;
+import com.ruoyi.ams.bionutrition.dto.GroundingDTO;
 import com.ruoyi.ams.bionutrition.pda.IPdaAgvCallService;
+import com.ruoyi.ams.business.IBusinessService;
+import com.ruoyi.ams.task.service.IWcsTaskService;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.utils.StringUtils;
 import io.swagger.annotations.ApiOperation;
@@ -23,6 +26,10 @@ public class PdaAgvCallController {
 
     @Autowired
     private IPdaAgvCallService pdaAgvCallService;
+    @Autowired
+    private IWcsTaskService wcsTaskService;
+    @Autowired
+    private IBusinessService businessService;
 
     @ApiOperation("pda入库任务")
     @PostMapping("/intoStorage")
@@ -31,4 +38,23 @@ public class PdaAgvCallController {
         return AjaxResult.success("入库任务下发成功");
     }
 
+    @ApiOperation("pda上架入库")
+    @PostMapping("/grounding")
+    public AjaxResult grounding(@RequestBody @Valid GroundingDTO groundingDTO) {
+        pdaAgvCallService.grounding(groundingDTO);
+        return AjaxResult.success("上架成功");
+    }
+
+    @PostMapping("/testCallBack")
+    public AjaxResult testCallBack(@RequestBody CallBackDTO callBackDTO){
+        wcsTaskService.callBack(callBackDTO.getTaskNo(), callBackDTO.getState(), 1);
+        return AjaxResult.success("任务回调完成");
+    }
+
+    @PostMapping("/testAutoSend")
+    public AjaxResult testAutoSend(){
+        businessService.autoSend();
+        return AjaxResult.success("任务下发完成");
+    }
+
 }

+ 5 - 3
ruoyi-admin/src/main/java/com/ruoyi/bionutrition/pda/controller/PdaDocQcController.java

@@ -6,6 +6,7 @@ import com.ruoyi.ams.bionutrition.pda.IPdaAgvCallService;
 import com.ruoyi.ams.bionutrition.pda.IPdaDocQcService;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.utils.StringUtils;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
@@ -33,9 +34,10 @@ public class PdaDocQcController extends BaseController {
      * @return
      */
     @GetMapping("/getQcList")
-    public AjaxResult getQcList(@RequestParam String sku) {
+    public TableDataInfo getQcList(@RequestParam String sku) {
+        startPage();
         List<DocQcDTO> qcList = pdaDocQcService.getQcList(sku);
-        return AjaxResult.success("获取成功!", qcList);
+        return getDataTable(qcList);
     }
 
     /**
@@ -46,7 +48,7 @@ public class PdaDocQcController extends BaseController {
     @ApiOperation("pda质检")
     @PostMapping("/submit")
     public AjaxResult docQcSubmit(@RequestBody @Valid DocQcDTO docQcDTO) {
-        pdaDocQcService.docQcSubmit(docQcDTO, "111");
+        pdaDocQcService.docQcSubmit(docQcDTO, getUsername());
         return AjaxResult.success();
     }
 

+ 1 - 1
ruoyi-admin/src/main/java/com/ruoyi/web/controller/warewms/ams/WcsTaskController.java

@@ -205,7 +205,7 @@ public class WcsTaskController extends BaseController {
     }
 
     /**
-     * 根据单号创建出库任务
+     * 根据单号盒类型创建出库任务
      *
      * @param orderAgvCallDTO
      * @return

+ 5 - 4
ruoyi-admin/src/main/java/com/ruoyi/web/controller/warewms/base/BaseLocationInfoController.java

@@ -109,9 +109,10 @@ public class BaseLocationInfoController extends BaseController {
      * 获取库位字典
      */
     @GetMapping("/queryDict/{zoneId}")
-    public AjaxResult queryDict(@PathVariable("zoneId") Long zoneId) {
+    public TableDataInfo queryDict(@PathVariable("zoneId") Long zoneId) {
+        startPage();
         List<BaseLocationInfo> locationInfoList = baseLocationInfoService.selectSortedLocatinListByZoneId(zoneId, 1L,null);
-        return AjaxResult.success("", locationInfoList);
+        return getDataTable( locationInfoList);
     }
 
     /**
@@ -122,7 +123,7 @@ public class BaseLocationInfoController extends BaseController {
         return AjaxResult.success(baseLocationInfoService.buildLocationTreeSelect());
     }
 
-    @Log(title = "库位导入", businessType = BusinessType.IMPORT)
+    /*@Log(title = "库位导入", businessType = BusinessType.IMPORT)
     @PreAuthorize("@ss.hasPermi('base:locationInfo:edit')")
     @PostMapping("/importData")
     public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
@@ -131,7 +132,7 @@ public class BaseLocationInfoController extends BaseController {
         List<BaseLocationInfo> list = util.importExcel(file.getInputStream());
         String operName = getUsername();
         return baseLocationInfoService.importLocation(list, updateSupport, operName);
-    }
+    }*/
 
     @PostMapping("/importTemplate")
     public void importTemplate(HttpServletResponse response)

+ 12 - 24
ruoyi-admin/src/main/java/com/ruoyi/web/controller/warewms/doc/BionutritionDocHeaderController.java

@@ -1,25 +1,15 @@
 package com.ruoyi.web.controller.warewms.doc;
 
-import cn.hutool.core.lang.Assert;
 import com.github.pagehelper.PageInfo;
-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.excel.BionutritionDocBaseExcel;
-import com.ruoyi.ams.bionutrition.doc.excel.header.BionutritionDocHeaderBaseExcel;
+import com.ruoyi.ams.bionutrition.doc.dto.*;
 import com.ruoyi.ams.bionutrition.doc.service.BionutritionDocDetailsService;
 import com.ruoyi.ams.bionutrition.doc.service.BionutritionDocHeaderService;
-import com.ruoyi.ams.bionutrition.doc.util.BionutritionDocUtil;
-import com.ruoyi.base.constant.type.BizEnum;
 import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.common.utils.PageUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.poi.ExcelUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -27,10 +17,8 @@ import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletResponse;
 import javax.validation.Valid;
-import java.lang.reflect.Field;
 import java.util.Arrays;
 import java.util.List;
-import java.util.stream.Collectors;
 
 @Slf4j
 @RestController
@@ -105,22 +93,22 @@ public class BionutritionDocHeaderController extends BaseController {
     @Log(title = "导出单据", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
     public void export(HttpServletResponse response, @Valid DocExcelQueryDTO docExcelQueryDTO) throws ClassNotFoundException {
-
-/*        docBaseExcels.forEach(item->{
-            Class<? extends BionutritionDocHeaderBaseExcel> aClass = item.getBionutritionDocHeaderBaseExcelDTO().getClass();
-            System.out.println(aClass.getCanonicalName());
-            Field[] declaredFields = aClass.getDeclaredFields();
-            for (Field declaredField : declaredFields) {
-                System.out.println("===="+declaredField+"====");
-            }
-        });*/
         bionutritionDocHeaderService.exportExcel(response,docExcelQueryDTO);
-        /*ExcelUtil<BionutritionDocBaseExcel> util = new ExcelUtil<BionutritionDocBaseExcel>(BionutritionDocBaseExcel.class);
-        util.exportExcel(response, docBaseExcels, "单据", docExcelQueryDTO.getDocType());*/
     }
 
     /********************************** 单据明细 *********************************************/
 
+    /**
+     * 根据单号和单据类型获取单据信息
+     */
+    @PreAuthorize("@ss.hasPermi('docAsn:docAsn:query')")
+    @GetMapping("/getInfo")
+    public AjaxResult getInfoByDocNoAndDocType(DocQueryDto docQueryDto)
+    {
+        List<BionutritionDocBaseDTO> docBaseDTOList = bionutritionDocDetailsService.selectDetailsByDocNoAndDocType(docQueryDto.getDocNo(), docQueryDto.getDocType());
+        return AjaxResult.success(docBaseDTOList);
+    }
+
     /**
      * 新增单据明细
      */

+ 1 - 1
ruoyi-admin/src/main/java/com/ruoyi/web/controller/warewms/pda/PdaInvLotLocIdController.java

@@ -114,7 +114,7 @@ public class PdaInvLotLocIdController extends BaseController {
         // 判断是否叫车
         if (invLotLocIdMoveForm.getIsCallCar() == null
                 || invLotLocIdMoveForm.getIsCallCar().equals(Constant.IS_YES.Y.getValue())) {
-            InvMoveDTO invMoveDTO = new InvMoveDTO(invLotLocIdMoveForm.getLocationFrom(), invLotLocIdMoveForm.getLocationTo());
+            InvMoveDTO invMoveDTO = new InvMoveDTO(invLotLocIdMoveForm.getLocationFrom(), invLotLocIdMoveForm.getLocationTo(), invLotLocIdMoveForm.getUpdateBy());
             return invLotLocIdService.move(invMoveDTO, getUsername());
         } else {
             return invLotLocIdService.moveDirect(invLotLocIdMoveForm);

+ 8 - 8
ruoyi-admin/src/main/resources/logback-test.xml

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <configuration>
     <!-- 日志存放路径 -->
-	<property name="log.path" value="/Users/gizmo/JavaProjectsFiles/Logs/ruoyi/logs" />
+	<property name="log.path" value="../logs" />
     <!-- 日志输出格式 -->
 	<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
 
@@ -11,7 +11,7 @@
 			<pattern>${log.pattern}</pattern>
 		</encoder>
 	</appender>
-	
+
 	<!-- 系统日志输出 -->
 	<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
 	    <file>${log.path}/sys-info.log</file>
@@ -34,7 +34,7 @@
             <onMismatch>DENY</onMismatch>
         </filter>
 	</appender>
-	
+
 	<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
 	    <file>${log.path}/sys-error.log</file>
         <!-- 循环政策:基于时间创建日志文件 -->
@@ -56,7 +56,7 @@
             <onMismatch>DENY</onMismatch>
         </filter>
     </appender>
-	
+
 	<!-- 用户访问日志输出  -->
     <appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
 		<file>${log.path}/sys-user.log</file>
@@ -70,7 +70,7 @@
             <pattern>${log.pattern}</pattern>
         </encoder>
     </appender>
-	
+
 	<!-- 系统模块日志级别控制  -->
 	<logger name="com.ruoyi" level="info" />
 	<!-- Spring日志级别控制  -->
@@ -79,15 +79,15 @@
 	<root level="info">
 		<appender-ref ref="console" />
 	</root>
-	
+
 	<!--系统操作日志-->
     <root level="info">
         <appender-ref ref="file_info" />
         <appender-ref ref="file_error" />
     </root>
-	
+
 	<!--系统用户操作日志-->
     <logger name="sys-user" level="info">
         <appender-ref ref="sys-user"/>
     </logger>
-</configuration> 
+</configuration>

+ 8 - 8
ruoyi-admin/src/main/resources/logback.xml

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <configuration>
     <!-- 日志存放路径 -->
-	<property name="log.path" value="../../../warewms/logs" />
+	<property name="log.path" value="../logs" />
     <!-- 日志输出格式 -->
 	<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
 
@@ -11,7 +11,7 @@
 			<pattern>${log.pattern}</pattern>
 		</encoder>
 	</appender>
-	
+
 	<!-- 系统日志输出 -->
 	<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
 	    <file>${log.path}/sys-info.log</file>
@@ -34,7 +34,7 @@
             <onMismatch>DENY</onMismatch>
         </filter>
 	</appender>
-	
+
 	<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
 	    <file>${log.path}/sys-error.log</file>
         <!-- 循环政策:基于时间创建日志文件 -->
@@ -56,7 +56,7 @@
             <onMismatch>DENY</onMismatch>
         </filter>
     </appender>
-	
+
 	<!-- 用户访问日志输出  -->
     <appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
 		<file>${log.path}/sys-user.log</file>
@@ -70,7 +70,7 @@
             <pattern>${log.pattern}</pattern>
         </encoder>
     </appender>
-	
+
 	<!-- 系统模块日志级别控制  -->
 	<logger name="com.ruoyi" level="info" />
 	<!-- Spring日志级别控制  -->
@@ -79,15 +79,15 @@
 	<root level="info">
 		<appender-ref ref="console" />
 	</root>
-	
+
 	<!--系统操作日志-->
     <root level="info">
         <appender-ref ref="file_info" />
         <appender-ref ref="file_error" />
     </root>
-	
+
 	<!--系统用户操作日志-->
     <logger name="sys-user" level="info">
         <appender-ref ref="sys-user"/>
     </logger>
-</configuration> 
+</configuration>

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

@@ -1,5 +1,9 @@
 package com.ruoyi.admin.test.base;
 
+import cn.hutool.core.lang.Dict;
+import cn.hutool.json.JSONArray;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
 import com.ruoyi.RuoYiApplication;
 import com.ruoyi.ams.agv.ndc.domain.AmsHexdefineDetail;
@@ -9,6 +13,7 @@ import com.ruoyi.ams.agv.ndc.service.IAmsTaskService;
 import com.ruoyi.ams.asn.domain.WmsDocAsnDetails;
 import com.ruoyi.ams.asn.domain.WmsDocAsnHeader;
 import com.ruoyi.ams.asn.service.IWmsDocAsnHeaderService;
+import com.ruoyi.ams.bionutrition.doc.service.BionutritionDocHeaderService;
 import com.ruoyi.ams.bionutrition.dto.AsnAgvCallDTO;
 import com.ruoyi.ams.bionutrition.pda.IPdaAgvCallService;
 import com.ruoyi.ams.bionutrition.pda.impl.PdaAgvCallServiceImpl;
@@ -32,6 +37,7 @@ import com.ruoyi.ams.order.domain.WmsDocOrderHeader;
 import com.ruoyi.ams.order.mapper.WmsDocOrderDetailsMapper;
 import com.ruoyi.ams.order.service.IWmsDocOrderHeaderService;
 import com.ruoyi.ams.order.vo.StockOrderVO;
+import com.ruoyi.ams.task.domain.WcsTask;
 import com.ruoyi.ams.task.service.IWcsTaskService;
 import com.ruoyi.base.constant.Constant;
 import com.ruoyi.base.domain.BaseLocationInfo;
@@ -43,11 +49,14 @@ import com.ruoyi.base.service.IBaseIdsequenceService;
 import com.ruoyi.base.service.IBaseLocationInfoService;
 import com.ruoyi.base.service.IBaseWarehouseService;
 import com.ruoyi.base.utils.IdSequenceUtils;
+import com.ruoyi.common.utils.StringUtils;
+import lombok.extern.slf4j.Slf4j;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
 import java.util.ArrayList;
@@ -59,6 +68,7 @@ import java.util.List;
  * User: andy.qu
  * Date: 2022/2/9
  */
+@Slf4j
 @RunWith(SpringRunner.class)
 @SpringBootTest(classes = RuoYiApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
 public class WarehouseTest {
@@ -331,4 +341,111 @@ public class WarehouseTest {
         pdaAgvCallService.createIntoStorageTask(asnAgvCallDTO);
     }
 
+    @Autowired
+    private BionutritionDocHeaderService bionutritionDocHeaderService;
+    @Test
+    public void testUpdateDocStatus(){
+        WcsTask wcsTask = wcsTaskService.selectWcsTaskByTaskNo("1702869769911");
+        bionutritionDocHeaderService.updateDocStatus(wcsTask);
+    }
+
+    @Test
+    public void testCallBack(){
+        wcsTaskService.callBack("1703144270275", 6, 1);
+    }
+
+    @Test
+    public void testInsertBaseLocationInfo(){
+        String s = "[\n" +
+                "{\"第1层\":\"G01-01\",\"站点编号1\":901,\"第2层\":\"G02-01\",\"站点编号2\":902,\"第3层\":\"G03-01\",\"站点编号3\":903,\"第4层\":\"G04-01\",\"站点编号4\":904},\n" +
+                "{\"第1层\":\"G01-02\",\"站点编号1\":905,\"第2层\":\"G02-02\",\"站点编号2\":906,\"第3层\":\"G03-02\",\"站点编号3\":907,\"第4层\":\"G04-02\",\"站点编号4\":908},\n" +
+                "{\"第1层\":\"G01-03\",\"站点编号1\":909,\"第2层\":\"G02-03\",\"站点编号2\":910,\"第3层\":\"G03-03\",\"站点编号3\":911,\"第4层\":\"G04-03\",\"站点编号4\":912},\n" +
+                "{\"第1层\":\"G01-04\",\"站点编号1\":913,\"第2层\":\"G02-04\",\"站点编号2\":914,\"第3层\":\"G03-04\",\"站点编号3\":915,\"第4层\":\"G04-04\",\"站点编号4\":916},\n" +
+                "{\"第1层\":\"G01-05\",\"站点编号1\":917,\"第2层\":\"G02-05\",\"站点编号2\":918,\"第3层\":\"G03-05\",\"站点编号3\":919,\"第4层\":\"G04-05\",\"站点编号4\":920},\n" +
+                "{\"第1层\":\"G01-06\",\"站点编号1\":921,\"第2层\":\"G02-06\",\"站点编号2\":922,\"第3层\":\"G03-06\",\"站点编号3\":923,\"第4层\":\"G04-06\",\"站点编号4\":924},\n" +
+                "{\"第1层\":\"G01-07\",\"站点编号1\":925,\"第2层\":\"G02-07\",\"站点编号2\":926,\"第3层\":\"G03-07\",\"站点编号3\":927,\"第4层\":\"G04-07\",\"站点编号4\":928},\n" +
+                "{\"第1层\":\"G01-08\",\"站点编号1\":929,\"第2层\":\"G02-08\",\"站点编号2\":930,\"第3层\":\"G03-08\",\"站点编号3\":931,\"第4层\":\"G04-08\",\"站点编号4\":932},\n" +
+                "{\"第1层\":\"G01-09\",\"站点编号1\":933,\"第2层\":\"G02-09\",\"站点编号2\":934,\"第3层\":\"G03-09\",\"站点编号3\":935,\"第4层\":\"G04-09\",\"站点编号4\":936},\n" +
+                "{\"第1层\":\"G01-10\",\"站点编号1\":937,\"第2层\":\"G02-10\",\"站点编号2\":938,\"第3层\":\"G03-10\",\"站点编号3\":939,\"第4层\":\"G04-10\",\"站点编号4\":940},\n" +
+                "{\"第1层\":\"G01-11\",\"站点编号1\":941,\"第2层\":\"G02-11\",\"站点编号2\":942,\"第3层\":\"G03-11\",\"站点编号3\":943,\"第4层\":\"G04-11\",\"站点编号4\":944},\n" +
+                "{\"第1层\":\"G01-12\",\"站点编号1\":945,\"第2层\":\"G02-12\",\"站点编号2\":946,\"第3层\":\"G03-12\",\"站点编号3\":947,\"第4层\":\"G04-12\",\"站点编号4\":948},\n" +
+                "{\"第1层\":\"G01-13\",\"站点编号1\":949,\"第2层\":\"G02-13\",\"站点编号2\":950,\"第3层\":\"G03-13\",\"站点编号3\":951,\"第4层\":\"G04-13\",\"站点编号4\":952},\n" +
+                "{\"第1层\":\"G01-14\",\"站点编号1\":953,\"第2层\":\"G02-14\",\"站点编号2\":954,\"第3层\":\"G03-14\",\"站点编号3\":955,\"第4层\":\"G04-14\",\"站点编号4\":956},\n" +
+                "{\"第1层\":\"G01-15\",\"站点编号1\":957,\"第2层\":\"G02-15\",\"站点编号2\":958,\"第3层\":\"G03-15\",\"站点编号3\":959,\"第4层\":\"G04-15\",\"站点编号4\":960},\n" +
+                "{\"第1层\":\"G01-16\",\"站点编号1\":961,\"第2层\":\"G02-16\",\"站点编号2\":962,\"第3层\":\"G03-16\",\"站点编号3\":963,\"第4层\":\"G04-16\",\"站点编号4\":964},\n" +
+                "{\"第1层\":\"G01-17\",\"站点编号1\":965,\"第2层\":\"G02-17\",\"站点编号2\":966,\"第3层\":\"G03-17\",\"站点编号3\":967,\"第4层\":\"G04-17\",\"站点编号4\":968},\n" +
+                "{\"第1层\":\"G01-18\",\"站点编号1\":969,\"第2层\":\"G02-18\",\"站点编号2\":970,\"第3层\":\"G03-18\",\"站点编号3\":971,\"第4层\":\"G04-18\",\"站点编号4\":972},\n" +
+                "{\"第1层\":\"G01-19\",\"站点编号1\":973,\"第2层\":\"G02-19\",\"站点编号2\":974,\"第3层\":\"G03-19\",\"站点编号3\":975,\"第4层\":\"G04-19\",\"站点编号4\":976},\n" +
+                "{\"第1层\":\"G01-20\",\"站点编号1\":977,\"第2层\":\"G02-20\",\"站点编号2\":978,\"第3层\":\"G03-20\",\"站点编号3\":979,\"第4层\":\"G04-20\",\"站点编号4\":980},\n" +
+                "{\"第1层\":\"G01-21\",\"站点编号1\":981,\"第2层\":\"G02-21\",\"站点编号2\":982,\"第3层\":\"G03-21\",\"站点编号3\":983,\"第4层\":\"G04-21\",\"站点编号4\":984},\n" +
+                "{\"第1层\":\"G01-22\",\"站点编号1\":985,\"第2层\":\"G02-22\",\"站点编号2\":986,\"第3层\":\"G03-22\",\"站点编号3\":987,\"第4层\":\"G04-22\",\"站点编号4\":988},\n" +
+                "{\"第1层\":\"G01-23\",\"站点编号1\":989,\"第2层\":\"G02-23\",\"站点编号2\":990,\"第3层\":\"G03-23\",\"站点编号3\":991,\"第4层\":\"G04-23\",\"站点编号4\":992},\n" +
+                "{\"第1层\":\"G01-24\",\"站点编号1\":993,\"第2层\":\"G02-24\",\"站点编号2\":994,\"第3层\":\"G03-24\",\"站点编号3\":995,\"第4层\":\"G04-24\",\"站点编号4\":996},\n" +
+                "{\"第1层\":\"G01-25\",\"站点编号1\":997,\"第2层\":\"G02-25\",\"站点编号2\":998,\"第3层\":\"G03-25\",\"站点编号3\":999,\"第4层\":\"G04-25\",\"站点编号4\":1000},\n" +
+                "{\"第1层\":\"G01-26\",\"站点编号1\":1001,\"第2层\":\"G02-26\",\"站点编号2\":1002,\"第3层\":\"G03-26\",\"站点编号3\":1003,\"第4层\":\"G04-26\",\"站点编号4\":1004},\n" +
+                "{\"第1层\":\"G01-27\",\"站点编号1\":1005,\"第2层\":\"G02-27\",\"站点编号2\":1006,\"第3层\":\"G03-27\",\"站点编号3\":1007,\"第4层\":\"G04-27\",\"站点编号4\":1008},\n" +
+                "{\"第1层\":\"G01-28\",\"站点编号1\":1009,\"第2层\":\"G02-28\",\"站点编号2\":1010,\"第3层\":\"G03-28\",\"站点编号3\":1011,\"第4层\":\"G04-28\",\"站点编号4\":1012},\n" +
+                "{\"第1层\":\"G01-29\",\"站点编号1\":1013,\"第2层\":\"G02-29\",\"站点编号2\":1014,\"第3层\":\"G03-29\",\"站点编号3\":1015,\"第4层\":\"G04-29\",\"站点编号4\":1016},\n" +
+                "{\"第1层\":\"G01-30\",\"站点编号1\":1017,\"第2层\":\"G02-30\",\"站点编号2\":1018,\"第3层\":\"G03-30\",\"站点编号3\":1019,\"第4层\":\"G04-30\",\"站点编号4\":1020},\n" +
+                "{\"第1层\":\"G01-31\",\"站点编号1\":1021,\"第2层\":\"G02-31\",\"站点编号2\":1022,\"第3层\":\"G03-31\",\"站点编号3\":1023,\"第4层\":\"G04-31\",\"站点编号4\":1024},\n" +
+                "{\"第1层\":\"G01-32\",\"站点编号1\":1025,\"第2层\":\"G02-32\",\"站点编号2\":1026,\"第3层\":\"G03-32\",\"站点编号3\":1027,\"第4层\":\"G04-32\",\"站点编号4\":1028},\n" +
+                "{\"第1层\":\"G01-33\",\"站点编号1\":1029,\"第2层\":\"G02-33\",\"站点编号2\":1030,\"第3层\":\"G03-33\",\"站点编号3\":1031,\"第4层\":\"G04-33\",\"站点编号4\":1032},\n" +
+                "{\"第1层\":\"G01-34\",\"站点编号1\":1033,\"第2层\":\"G02-34\",\"站点编号2\":1034,\"第3层\":\"G03-34\",\"站点编号3\":1035,\"第4层\":\"G04-34\",\"站点编号4\":1036},\n" +
+                "{\"第1层\":\"G01-35\",\"站点编号1\":1037,\"第2层\":\"G02-35\",\"站点编号2\":1038,\"第3层\":\"G03-35\",\"站点编号3\":1039,\"第4层\":\"G04-35\",\"站点编号4\":1040},\n" +
+                "{\"第1层\":\"G01-36\",\"站点编号1\":1041,\"第2层\":\"G02-36\",\"站点编号2\":1042,\"第3层\":\"G03-36\",\"站点编号3\":1043,\"第4层\":\"G04-36\",\"站点编号4\":1044},\n" +
+                "{\"第1层\":\"G01-37\",\"站点编号1\":1045,\"第2层\":\"G02-37\",\"站点编号2\":1046,\"第3层\":\"G03-37\",\"站点编号3\":1047,\"第4层\":\"G04-37\",\"站点编号4\":1048},\n" +
+                "{\"第1层\":\"G01-38\",\"站点编号1\":1049,\"第2层\":\"G02-38\",\"站点编号2\":1050,\"第3层\":\"G03-38\",\"站点编号3\":1051,\"第4层\":\"G04-38\",\"站点编号4\":1052}\n" +
+                "]";
+        JSONArray jsonArray = JSONUtil.parseArray(s);
+        List<Dict> dicts = JSONUtil.toList(jsonArray, Dict.class);
+        int totalSize = 848;// 已插入总数量
+        int currentSize = 0;// 本次插入数量
+        for (int i = 0; i < dicts.size(); i++) {
+            Dict dict = dicts.get(i);
+            int size = 4;
+            if (StringUtils.isEmpty(dict.getStr("站点编号4"))){
+                size = 3;
+            }
+            for (int j = 1; j <=size; j++) {
+                currentSize++;
+                totalSize++;
+                String formatTotalSize = String.format("%04d", totalSize);
+
+                BaseLocationInfo baseLocationInfo = new BaseLocationInfo();
+                baseLocationInfo.setWarehouseId(1L);
+                baseLocationInfo.setZoneId(2L);// 库区编号
+                baseLocationInfo.setIsEmpty("Y");
+                baseLocationInfo.setZoneName("原料区");// 库区名称
+                baseLocationInfo.setRowNo("07");// 排编号
+                baseLocationInfo.setRowIndex(7L);// 排号
+                baseLocationInfo.setStockStatus("00");
+                baseLocationInfo.setLocationType("1");
+                baseLocationInfo.setFoldedCount(0L);
+                baseLocationInfo.setFoldedTag("0");
+                baseLocationInfo.setHeightLimit(0d);
+                baseLocationInfo.setWeightLimit(0d);
+                baseLocationInfo.setId(Long.valueOf("10"+formatTotalSize));// 库位id
+
+                baseLocationInfo.setShiftIndex(Long.valueOf(j));
+                baseLocationInfo.setShiftNo(String.valueOf(j));
+                String locationNo = dict.getStr("第" + j + "层");
+                baseLocationInfo.setLocationNo(locationNo);
+                String agvStation = dict.getStr("站点编号" + j);
+                baseLocationInfo.setAgvStation(Long.valueOf(agvStation));
+                String[] split = locationNo.split("-");
+                baseLocationInfo.setColNo(split[1]);
+                baseLocationInfo.setColIndex(Long.parseLong(split[1]));
+                System.out.println(baseLocationInfo);
+
+                baseLocationInfoService.insertBaseLocationInfo(baseLocationInfo);
+            }
+
+        }
+
+        log.info("==本次导入数量:{}",currentSize);
+        log.info("==已导入总数量:{}",totalSize);
+
+    }
+
+
 }

+ 2 - 2
ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java

@@ -4,7 +4,7 @@ import com.ruoyi.common.utils.StringUtils;
 
 /**
  * 分页数据
- * 
+ *
  * @author ruoyi
  */
 public class PageDomain
@@ -89,7 +89,7 @@ public class PageDomain
     {
         if (StringUtils.isNull(reasonable))
         {
-            return Boolean.TRUE;
+            return Boolean.FALSE;
         }
         return reasonable;
     }

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

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

+ 22 - 6
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/domain/BionutritionDocDetails.java

@@ -2,6 +2,7 @@ package com.ruoyi.ams.bionutrition.doc.domain;
 
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.base.constant.Constant;
 import com.ruoyi.common.core.bean.entity.WarewmsExtEntity;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
@@ -32,12 +33,11 @@ public class BionutritionDocDetails extends WarewmsExtEntity {
     @ApiModelProperty("原厂批号")
     private String originalLotNumber;
 
-    /*    @ApiModelProperty("进厂批号")
-        private String incomeLotNumber;
-        @ApiModelProperty("产品批号")
-        private String productLotNumber;*/
-    @ApiModelProperty("批号")
-    private String batchNumber;
+    @ApiModelProperty("进厂批号")
+    private String incomeLotNumber;
+
+    @ApiModelProperty("产品批号")
+    private String productLotNumber;
 
     @ApiModelProperty("产品名称")
     private String productName;
@@ -70,4 +70,20 @@ public class BionutritionDocDetails extends WarewmsExtEntity {
     @ApiModelProperty("复审人")
     private String reviewerNext;
 
+    /**
+     * {@link Constant.ASN_STS}
+     * {@link Constant.ORDER_STS}
+     */
+    @ApiModelProperty("明细行状态")
+    private String lineStatus;
+
+    /**
+     * 只有采购收货单有 表示采购收货单的明细属于那一条采购单明细
+     */
+    @ApiModelProperty("所属明细id")
+    private String belongDetailsId;
+
+    @ApiModelProperty("已搬运数量")
+    private String transferredQty;
+
 }

+ 8 - 0
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/domain/BionutritionDocHeader.java

@@ -1,6 +1,7 @@
 package com.ruoyi.ams.bionutrition.doc.domain;
 
 import com.baomidou.mybatisplus.annotation.TableName;
+import com.ruoyi.base.constant.Constant;
 import com.ruoyi.common.core.bean.entity.WarewmsExtEntity;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
@@ -71,4 +72,11 @@ public class BionutritionDocHeader extends WarewmsExtEntity {
     @ApiModelProperty("仓库类别")
     private String warehouseType;
 
+    /**
+     * {@link Constant.ASN_STS}
+     * {@link Constant.ORDER_STS}
+     */
+    @ApiModelProperty("单据状态")
+    private String docStatus;
+
 }

+ 18 - 4
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/BionutritionDocDetailsDTO.java

@@ -28,12 +28,11 @@ public class BionutritionDocDetailsDTO extends WarewmsExtDTO {
     @ApiModelProperty("原厂批号")
     private String originalLotNumber;
 
-/*    @ApiModelProperty("进厂批号")
+    @ApiModelProperty("进厂批号")
     private String incomeLotNumber;
+
     @ApiModelProperty("产品批号")
-    private String productLotNumber;*/
-    @ApiModelProperty("批号")
-    private String batchNumber;
+    private String productLotNumber;
 
     @ApiModelProperty("产品名称")
     private String productName;
@@ -68,4 +67,19 @@ public class BionutritionDocDetailsDTO extends WarewmsExtDTO {
 
     @ApiModelProperty("备注")
     private String remark;
+    /**
+     * {@link com.ruoyi.base.constant.Constant.ASN_STS}
+     * {@link com.ruoyi.base.constant.Constant.ORDER_STS}
+     */
+    @ApiModelProperty("明细行状态")
+    private String lineStatus;
+
+    /**
+     * 只有采购收货单有 表示采购收货单的明细属于那一条采购单明细
+     */
+    @ApiModelProperty("所属明细id")
+    private String belongDetailsId;
+
+    @ApiModelProperty("已搬运数量")
+    private String transferredQty;
 }

+ 6 - 0
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/BionutritionDocHeaderDTO.java

@@ -71,5 +71,11 @@ public class BionutritionDocHeaderDTO extends WarewmsExtDTO {
 
     @ApiModelProperty("备注")
     private String remark;
+    /**
+     * {@link com.ruoyi.base.constant.Constant.ASN_STS}
+     * {@link com.ruoyi.base.constant.Constant.ORDER_STS}
+     */
+    @ApiModelProperty("单据状态")
+    private String docStatus;
 
 }

+ 11 - 18
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/DocLotattDTO.java

@@ -1,5 +1,6 @@
 package com.ruoyi.ams.bionutrition.doc.dto;
 
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import java.io.Serializable;
@@ -18,32 +19,24 @@ public class DocLotattDTO implements Serializable {
      */
     private String vendorCode;
     /**
-     * 批号
+     * 原厂批号
      */
-    private String batchNumber;
+    private String originalLotNumber;
     /**
-     * 规格
+     * 有效期截止日
      */
-    private String specification;
+    private String skuShelflife;
     /**
-     * 有效期
-     */
-    private Integer skuShelflife;
-    /**
-     * 皮重
-     */
-    private BigDecimal skuTare;
-    /**
-     * 毛重
+     * 生产日期
      */
-    private BigDecimal skuGrossweight;
+    private Date manufactureDate;
     /**
-     * 净重
+     * 进厂批号
      */
-    private BigDecimal skuNetweight;
+    private String incomeLotNumber;
     /**
-     * 生产日期
+     * 产品批号
      */
-    private Date manufactureDate;
+    private String productLotNumber;
 
 }

+ 12 - 0
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/DocQueryDto.java

@@ -0,0 +1,12 @@
+package com.ruoyi.ams.bionutrition.doc.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class DocQueryDto implements Serializable {
+    private static final long serialVersionUID = 1372260678875020454L;
+    private String docNo;
+    private String docType;
+}

+ 14 - 0
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/detail/BionutritionDocDetailsBaseDTO.java

@@ -26,4 +26,18 @@ public class BionutritionDocDetailsBaseDTO extends WarewmsExtDTO {
 
     @ApiModelProperty("备注")
     private String remark;
+    /**
+     * {@link com.ruoyi.base.constant.Constant.ASN_STS}
+     * {@link com.ruoyi.base.constant.Constant.ORDER_STS}
+     */
+    @ApiModelProperty("明细行状态")
+    private String lineStatus;
+    /**
+     * 只有采购收货单有 表示采购收货单的明细属于那一条采购单明细
+     */
+    @ApiModelProperty("所属明细id")
+    private String belongDetailsId;
+
+    @ApiModelProperty("已搬运数量")
+    private String transferredQty;
 }

+ 2 - 2
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/detail/FinishedProductReceiptDetailsDTO.java

@@ -10,8 +10,8 @@ import lombok.Data;
 @Data
 public class FinishedProductReceiptDetailsDTO extends BionutritionDocDetailsBaseDTO {
 
-    @ApiModelProperty("批号")
-    private String batchNumber;
+    @ApiModelProperty("产品批号")
+    private String productLotNumber;
 
     @ApiModelProperty("收货人")
     private String receiver;

+ 5 - 6
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/detail/ProductionPickingReceiptDetailsDTO.java

@@ -12,12 +12,11 @@ import java.util.Date;
 @Data
 public class ProductionPickingReceiptDetailsDTO extends BionutritionDocDetailsBaseDTO {
 
-    /*    @ApiModelProperty("进厂批号")
-     private String incomeLotNumber;
-     @ApiModelProperty("产品批号")
-     private String productLotNumber;*/
-    @ApiModelProperty("批号")
-    private String batchNumber;
+    @ApiModelProperty("进厂批号")
+    private String incomeLotNumber;
+
+    @ApiModelProperty("产品批号")
+    private String productLotNumber;
 
     @ApiModelProperty("计量单位")
     private String measureUnit;

+ 2 - 2
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/detail/ProductionReturnOrderDetailsDTO.java

@@ -10,8 +10,8 @@ import lombok.Data;
 @Data
 public class ProductionReturnOrderDetailsDTO extends BionutritionDocDetailsBaseDTO {
 
-    @ApiModelProperty("批号")
-    private String batchNumber;
+    @ApiModelProperty("进厂批号")
+    private String incomeLotNumber;
 
     @ApiModelProperty("计量单位")
     private String measureUnit;

+ 2 - 2
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/detail/PurchaseOrderDetailsDTO.java

@@ -15,8 +15,8 @@ public class PurchaseOrderDetailsDTO extends BionutritionDocDetailsBaseDTO {
     @ApiModelProperty("原厂批号")
     private String originalLotNumber;
 
-    @ApiModelProperty("批号")
-    private String batchNumber;
+    @ApiModelProperty("进厂批号")
+    private String incomeLotNumber;
 
     @ApiModelProperty("计量单位")
     private String measureUnit;

+ 2 - 2
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/detail/PurchaseReceiptDetailsDTO.java

@@ -16,8 +16,8 @@ public class PurchaseReceiptDetailsDTO extends BionutritionDocDetailsBaseDTO {
     @ApiModelProperty("原厂批号")
     private String originalLotNumber;
 
-    @ApiModelProperty("批号")
-    private String batchNumber;
+    @ApiModelProperty("进厂批号")
+    private String incomeLotNumber;
 
     @ApiModelProperty("计量单位")
     private String measureUnit;

+ 2 - 2
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/detail/SaleOutboundOrderDetailsDTO.java

@@ -13,8 +13,8 @@ public class SaleOutboundOrderDetailsDTO extends BionutritionDocDetailsBaseDTO {
     @ApiModelProperty("产品名称")
     private String productName;
 
-    @ApiModelProperty("批号")
-    private String batchNumber;
+    @ApiModelProperty("产品批号")
+    private String productLotNumber;
 
     @ApiModelProperty("计量单位")
     private String measureUnit;

+ 2 - 2
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/detail/SaleReturnOrderDetailsDTO.java

@@ -10,8 +10,8 @@ import lombok.Data;
 @Data
 public class SaleReturnOrderDetailsDTO extends BionutritionDocDetailsBaseDTO {
 
-    @ApiModelProperty("批号")
-    private String batchNumber;
+    @ApiModelProperty("产品批号")
+    private String productLotNumber;
 
     @ApiModelProperty("计量单位")
     private String measureUnit;

+ 6 - 0
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/dto/header/BionutritionDocHeaderBaseDTO.java

@@ -18,4 +18,10 @@ public class BionutritionDocHeaderBaseDTO extends WarewmsExtDTO {
 
     @ApiModelProperty("备注")
     private String remark;
+    /**
+     * {@link com.ruoyi.base.constant.Constant.ASN_STS}
+     * {@link com.ruoyi.base.constant.Constant.ORDER_STS}
+     */
+    @ApiModelProperty("单据状态")
+    private String docStatus;
 }

+ 2 - 2
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/excel/detail/FinishedProductReceiptDetailsExcel.java

@@ -16,8 +16,8 @@ import java.util.Map;
 @Data
 public class FinishedProductReceiptDetailsExcel extends BionutritionDocDetailsBaseExcel {
 
-    @Excel(name = "批号")
-    private String batchNumber;
+    @Excel(name = "产品批号")
+    private String productLotNumber;
 
     @Excel(name = "收货人")
     private String receiver;

+ 5 - 6
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/excel/detail/ProductionPickingReceiptDetailsExcel.java

@@ -16,12 +16,11 @@ import java.util.Map;
 @Data
 public class ProductionPickingReceiptDetailsExcel extends BionutritionDocDetailsBaseExcel {
 
-    /*    @ApiModelProperty("进厂批号")
-        private String incomeLotNumber;
-        @ApiModelProperty("产品批号")
-        private String productLotNumber;*/
-    @Excel(name = "批号")
-    private String batchNumber;
+    @Excel(name = "进厂批号")
+    private String incomeLotNumber;
+
+    @Excel(name = "产品批号")
+    private String productLotNumber;
 
     @Excel(name = "计量单位")
     private String measureUnit;

+ 2 - 2
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/excel/detail/ProductionReturnOrderDetailsExcel.java

@@ -16,8 +16,8 @@ import java.util.Map;
 @Data
 public class ProductionReturnOrderDetailsExcel extends BionutritionDocDetailsBaseExcel {
 
-    @Excel(name = "批号")
-    private String batchNumber;
+    @Excel(name = "进厂批号")
+    private String incomeLotNumber;
 
     @Excel(name = "计量单位")
     private String measureUnit;

+ 5 - 2
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/excel/detail/PurchaseOrderDetailsExcel.java

@@ -16,8 +16,11 @@ import java.util.Map;
 @Data
 public class PurchaseOrderDetailsExcel extends BionutritionDocDetailsBaseExcel {
 
-    @Excel(name = "批号")
-    private String batchNumber;
+    @Excel(name = "原厂批号")
+    private String originalLotNumber;
+
+    @Excel(name = "进厂批号")
+    private String incomeLotNumber;
 
     @Excel(name = "计量单位")
     private String measureUnit;

+ 5 - 2
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/excel/detail/PurchaseReceiptDetailsExcel.java

@@ -17,8 +17,11 @@ import java.util.Map;
 @Data
 public class PurchaseReceiptDetailsExcel extends BionutritionDocDetailsBaseExcel {
 
-    @Excel(name = "批号")
-    private String batchNumber;
+    @Excel(name = "原厂批号")
+    private String originalLotNumber;
+
+    @Excel(name = "进厂批号")
+    private String incomeLotNumber;
 
     @Excel(name = "计量单位")
     private String measureUnit;

+ 2 - 2
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/excel/detail/SaleOutboundOrderDetailsExcel.java

@@ -19,8 +19,8 @@ public class SaleOutboundOrderDetailsExcel extends BionutritionDocDetailsBaseExc
     @Excel(name = "产品名称")
     private String productName;
 
-    @Excel(name = "批号")
-    private String batchNumber;
+    @Excel(name = "产品批号")
+    private String productLotNumber;
 
     @Excel(name = "计量单位")
     private String measureUnit;

+ 2 - 2
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/excel/detail/SaleReturnOrderDetailsExcel.java

@@ -16,8 +16,8 @@ import java.util.Map;
 @Data
 public class SaleReturnOrderDetailsExcel extends BionutritionDocDetailsBaseExcel {
 
-    @Excel(name = "批号")
-    private String batchNumber;
+    @Excel(name = "产品批号")
+    private String productLotNumber;
 
     @Excel(name = "计量单位")
     private String measureUnit;

+ 0 - 7
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/factory/BionutritionDocFactory.java

@@ -1,7 +0,0 @@
-package com.ruoyi.ams.bionutrition.doc.factory;
-
-public class BionutritionDocFactory {
-    public void test(String type){
-
-    }
-}

+ 4 - 0
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/service/BionutritionDocDetailsService.java

@@ -3,6 +3,7 @@ package com.ruoyi.ams.bionutrition.doc.service;
 import cn.hutool.core.lang.Assert;
 import com.ruoyi.ams.bionutrition.doc.domain.BionutritionDocDetails;
 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.common.utils.ConvertUtils;
@@ -22,6 +23,7 @@ public interface BionutritionDocDetailsService extends CrudService<BionutritionD
 
     List<BionutritionDocDetailsDTO> getBionutritionDocDetailsDTOList(List<String> docHeaderIdList);
 
+    List<BionutritionDocDetailsDTO> getBionutritionDocDetailsDTOListByLineStatus(String lineStatus);
     /**
      * 根据物料编码和批号获取明细信息
      * @param skuCode
@@ -54,4 +56,6 @@ public interface BionutritionDocDetailsService extends CrudService<BionutritionD
     BionutritionDocDetailsDTO selectDocDetailsByLineNo(String docHeaderId, String docLineNo);
 
     int deleteByHeaderIds(String[] ids);
+
+    List<BionutritionDocBaseDTO> selectDetailsByDocNoAndDocType(String docNo, String docType);
 }

+ 29 - 1
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/doc/service/BionutritionDocHeaderService.java

@@ -6,6 +6,7 @@ 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.task.domain.WcsTask;
 import com.ruoyi.framework.service.CrudService;
 
 import javax.servlet.http.HttpServletResponse;
@@ -66,7 +67,9 @@ public interface BionutritionDocHeaderService extends CrudService<BionutritionDo
      * @param ids
      * @return
      */
-    List<BionutritionDocBaseDTO> getDicListByIds(String[] ids);
+    List<BionutritionDocBaseDTO> getDicListByIds(List<String> ids);
+
+    List<BionutritionDocHeaderDTO> getBionutritionDocHeaderDTOList(List<String> idList);
 
     /**
      * 导出单据excel方法
@@ -81,4 +84,29 @@ public interface BionutritionDocHeaderService extends CrudService<BionutritionDo
      * @return
      */
     BionutritionDocBaseDTO selectDocBySkuAndBatchNumber(String skuCode, String batchNumber, String docType);
+
+    /**
+     * 根据单据号和单据类型获取单据信息
+     * @param docNo
+     * @param docType
+     * @return
+     */
+    BionutritionDocBaseDTO selectDocByDocNoAndDocType(String docNo, String docType);
+
+    List<BionutritionDocHeaderDTO> selectDocBaseByDocNoAndDocType(String docNo, String docType);
+    /**
+     * 根据单据号和单据类型获取单据信息 未找到返回null
+     * @param docNo
+     * @param docType
+     * @return
+     */
+    BionutritionDocHeaderDTO getDocHeaderDTOListByDocNoAndDocType(String docNo, String docType);
+
+    /**
+     * 卸货完成后修改单据状态
+     * @param wcsTask
+     */
+    void updateDocStatus(WcsTask wcsTask);
+
+    List<BionutritionDocBaseDTO> buildBionutritionDocBaseDTOByIdList(String docNo, String docType);
 }

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

@@ -1,5 +1,6 @@
 package com.ruoyi.ams.bionutrition.doc.service.impl;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.lang.Assert;
 import cn.hutool.core.util.ArrayUtil;
@@ -10,11 +11,15 @@ import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.google.common.collect.Lists;
 import com.ruoyi.ams.bionutrition.doc.domain.BionutritionDocDetails;
+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.detail.BionutritionDocDetailsBaseDTO;
 import com.ruoyi.ams.bionutrition.doc.mapper.BionutritionDocDetailsMapper;
 import com.ruoyi.ams.bionutrition.doc.service.BionutritionDocDetailsService;
 import com.ruoyi.ams.bionutrition.doc.service.BionutritionDocHeaderService;
 import com.ruoyi.base.constant.Constant;
+import com.ruoyi.base.constant.type.BizEnum;
 import com.ruoyi.common.utils.ConvertUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.framework.service.impl.CrudServiceImpl;
@@ -24,6 +29,7 @@ import org.springframework.stereotype.Service;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * 分配查询Service业务层处理
@@ -34,19 +40,21 @@ import java.util.Map;
 @Service
 public class BionutritionDocDetailsServiceImpl extends CrudServiceImpl<BionutritionDocDetailsMapper, BionutritionDocDetails, BionutritionDocDetailsDTO> implements BionutritionDocDetailsService {
 
+    @Autowired
+    private BionutritionDocHeaderService bionutritionDocHeaderService;
 
     @Override
     public List<BionutritionDocDetailsDTO> getBionutritionDocDetailsDTOList(String docHeaderId) {
-        return getBionutritionDocDetailsDTOList(Lists.newArrayList(docHeaderId), Lists.newArrayList());
+        return getBionutritionDocDetailsDTOList(Lists.newArrayList(docHeaderId), Lists.newArrayList(), Lists.newArrayList());
     }
 
     @Override
     public List<BionutritionDocDetailsDTO> getBionutritionDocDetailsDTOList(List<String> docHeaderIdList) {
-        return getBionutritionDocDetailsDTOList(docHeaderIdList, Lists.newArrayList());
+        return getBionutritionDocDetailsDTOList(docHeaderIdList, Lists.newArrayList(), Lists.newArrayList());
     }
 
     /**
-     * 根据物料和批号查询单据明细信息
+     * 根据物料和原厂批号查询单据明细信息(只适用于采购入库)
      * @param skuCode
      * @param batchNumber
      * @return
@@ -57,7 +65,7 @@ public class BionutritionDocDetailsServiceImpl extends CrudServiceImpl<Bionutrit
         Assert.isTrue(StringUtils.isNotBlank(batchNumber), "批号为空");
         List<BionutritionDocDetails> docDetailsList = baseDao.selectList(Wrappers.<BionutritionDocDetails>lambdaQuery()
                 .eq(BionutritionDocDetails::getSkuCode, skuCode)
-                .eq(BionutritionDocDetails::getBatchNumber, batchNumber));
+                .eq(BionutritionDocDetails::getOriginalLotNumber, batchNumber));
         return ConvertUtils.sourceToTarget(docDetailsList, BionutritionDocDetailsDTO.class);
     }
 
@@ -140,22 +148,45 @@ public class BionutritionDocDetailsServiceImpl extends CrudServiceImpl<Bionutrit
                 .in(ArrayUtil.isNotEmpty(ids), BionutritionDocDetails::getDocHeaderId, Arrays.asList(ids)));
     }
 
+    @Override
+    public List<BionutritionDocBaseDTO> selectDetailsByDocNoAndDocType(String docNo, String docType) {
+        List<BionutritionDocBaseDTO> docBaseDTOList = bionutritionDocHeaderService.buildBionutritionDocBaseDTOByIdList(docNo, docType);
+        if (StringUtils.isNotBlank(docType)) return docBaseDTOList;
+        // 上架入库
+        return docBaseDTOList.stream().map(item->{
+            BionutritionDocBaseDTO bionutritionDocBaseDTO = item;
+            // 只返回完全入库的明细
+            List<BionutritionDocDetailsBaseDTO> docBaseDTOFilterList = item.getBionutritionDocDetailsBaseDTOList().stream().filter(
+                        details -> StringUtils.equals(details.getLineStatus(), Constant.ASN_STS.STS40.getValue()))
+                        .collect(Collectors.toList());
+            bionutritionDocBaseDTO.setBionutritionDocDetailsBaseDTOList(docBaseDTOFilterList);
+            return bionutritionDocBaseDTO;
+            }).filter(item->CollUtil.isNotEmpty(item.getBionutritionDocDetailsBaseDTOList())
+                && !StringUtils.equals(item.getBionutritionDocHeaderBaseDTO().getDocType(), BizEnum.BionutritionHeaderDocTypeEnum.PURCHASE_RECEIPT.getDocType()))
+                .collect(Collectors.toList());
+    }
+
     public List<BionutritionDocDetailsDTO> getBionutritionDocDetailsDTOList(List<String> docHeaderIdList, String skuCode) {
-        return getBionutritionDocDetailsDTOList(docHeaderIdList, Lists.newArrayList(skuCode));
+        return getBionutritionDocDetailsDTOList(docHeaderIdList, Lists.newArrayList(skuCode), Lists.newArrayList());
     }
 
     public List<BionutritionDocDetailsDTO> getBionutritionDocDetailsDTOList(String docHeaderId, String skuCode) {
-        return getBionutritionDocDetailsDTOList(Lists.newArrayList(docHeaderId), Lists.newArrayList(skuCode));
+        return getBionutritionDocDetailsDTOList(Lists.newArrayList(docHeaderId), Lists.newArrayList(skuCode), Lists.newArrayList());
     }
 
     public List<BionutritionDocDetailsDTO> getBionutritionDocDetailsDTOList(String docHeaderId, List<String> skuCodeList) {
-        return getBionutritionDocDetailsDTOList(Lists.newArrayList(docHeaderId), skuCodeList);
+        return getBionutritionDocDetailsDTOList(Lists.newArrayList(docHeaderId), skuCodeList, Lists.newArrayList());
+    }
+
+    public List<BionutritionDocDetailsDTO> getBionutritionDocDetailsDTOListByLineStatus(String lineStatus) {
+        return getBionutritionDocDetailsDTOList(Lists.newArrayList(), Lists.newArrayList(), Lists.newArrayList(lineStatus));
     }
 
-    public List<BionutritionDocDetailsDTO> getBionutritionDocDetailsDTOList(List<String> docHeaderIdList, List<String> skuCodeList) {
+    public List<BionutritionDocDetailsDTO> getBionutritionDocDetailsDTOList(List<String> docHeaderIdList, List<String> skuCodeList, List<String> lineStatusList) {
         List<BionutritionDocDetails> bionutritionDocDetailsList = baseDao.selectList(Wrappers.<BionutritionDocDetails>lambdaQuery()
                 .in(CollectionUtil.isNotEmpty(docHeaderIdList), BionutritionDocDetails::getDocHeaderId, docHeaderIdList)
-                .in(CollectionUtil.isNotEmpty(skuCodeList), BionutritionDocDetails::getSkuCode, skuCodeList));
+                .in(CollectionUtil.isNotEmpty(skuCodeList), BionutritionDocDetails::getSkuCode, skuCodeList)
+                .in(CollectionUtil.isNotEmpty(lineStatusList), BionutritionDocDetails::getLineStatus, lineStatusList));
         return ConvertUtils.sourceToTarget(bionutritionDocDetailsList, BionutritionDocDetailsDTO.class);
     }
 

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

@@ -12,6 +12,7 @@ import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.github.pagehelper.Page;
 import com.github.pagehelper.PageInfo;
@@ -31,6 +32,11 @@ import com.ruoyi.ams.bionutrition.doc.mapper.BionutritionDocHeaderMapper;
 import com.ruoyi.ams.bionutrition.doc.service.BionutritionDocDetailsService;
 import com.ruoyi.ams.bionutrition.doc.service.BionutritionDocHeaderService;
 import com.ruoyi.ams.bionutrition.doc.util.BionutritionDocUtil;
+import com.ruoyi.ams.inv.domain.InvLotLocId;
+import com.ruoyi.ams.inv.service.IInvLotLocIdService;
+import com.ruoyi.ams.task.domain.WcsTask;
+import com.ruoyi.ams.task.dto.WcsTaskInvLotDTO;
+import com.ruoyi.ams.task.service.IWcsTaskService;
 import com.ruoyi.base.constant.Constant;
 import com.ruoyi.base.constant.type.BizEnum;
 import com.ruoyi.common.constant.base.EnumUtils;
@@ -50,6 +56,7 @@ import org.apache.poi.xssf.streaming.SXSSFSheet;
 import org.apache.poi.xssf.streaming.SXSSFWorkbook;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
@@ -69,6 +76,10 @@ public class BionutritionDocHeaderServiceImpl extends CrudServiceImpl<Bionutriti
     private BionutritionDocDetailsService bionutritionDocDetailsService;
     @Autowired
     private ISysConfigService sysConfigService;
+    @Autowired
+    private IInvLotLocIdService invLotLocIdService;
+    @Autowired
+    private IWcsTaskService wcsTaskService;
 
     /**
      * 查询单据头分页数据
@@ -99,6 +110,7 @@ public class BionutritionDocHeaderServiceImpl extends CrudServiceImpl<Bionutriti
      * @param docHeaderDTO
      * @return
      */
+    @Transactional(rollbackFor = RuntimeException.class)
     @Override
     public String insertDocHeader(BionutritionDocHeaderDTO docHeaderDTO) {
         Assert.notNull(docHeaderDTO, "不允许插入空数据");
@@ -113,6 +125,7 @@ public class BionutritionDocHeaderServiceImpl extends CrudServiceImpl<Bionutriti
      * @param docHeaderDTO
      * @return
      */
+    @Transactional(rollbackFor = RuntimeException.class)
     @Override
     public int updateDoc(BionutritionDocHeaderDTO docHeaderDTO) {
         UpdateWrapper<BionutritionDocHeader> updateWrapper = new UpdateWrapper<>();
@@ -126,6 +139,7 @@ public class BionutritionDocHeaderServiceImpl extends CrudServiceImpl<Bionutriti
      * @param ids
      * @return
      */
+    @Transactional(rollbackFor = RuntimeException.class)
     @Override
     public int deleteDocByIds(String[] ids) {
         bionutritionDocDetailsService.deleteByHeaderIds(ids);
@@ -145,9 +159,9 @@ public class BionutritionDocHeaderServiceImpl extends CrudServiceImpl<Bionutriti
      * @return
      */
     @Override
-    public List<BionutritionDocBaseDTO> getDicListByIds(String[] ids) {
+    public List<BionutritionDocBaseDTO> getDicListByIds(List<String> ids) {
         List<BionutritionDocHeaderDTO> docHeaderDTOList = ArrayUtil.isNotEmpty(ids) ?
-                getBionutritionDocHeaderDTOList(Arrays.asList(ids)) :
+                getBionutritionDocHeaderDTOList(ids) :
                 ConvertUtils.sourceToTarget(baseDao.selectList(Wrappers.emptyWrapper()), BionutritionDocHeaderDTO.class);
         return buildBionutritionDocDifferentTypeList(docHeaderDTOList);
     }
@@ -162,15 +176,30 @@ public class BionutritionDocHeaderServiceImpl extends CrudServiceImpl<Bionutriti
     @Override
     public BionutritionDocBaseDTO selectDocBySkuAndBatchNumber(String skuCode, String batchNumber, String docType) {
         List<BionutritionDocDetailsDTO> docDetailsDTOList = bionutritionDocDetailsService.selectDocDetailsDTOList(skuCode, batchNumber);
-        Assert.isTrue(CollUtil.isNotEmpty(docDetailsDTOList), "对应单据明细不存在");
-        List<String> headerIds = docDetailsDTOList.stream().map(item -> item.getDocHeaderId()).collect(Collectors.toList());
-        Assert.isTrue(CollUtil.isNotEmpty(headerIds), "明细对应单据头id不存在");
-        BionutritionDocHeaderDTO bionutritionDocHeaderDTO = getBionutritionDocHeaderDTOList(headerIds).stream()
-                .filter(docHeaderDTO -> StringUtils.equals(docHeaderDTO.getDocType(), docType)).findFirst().orElse(null);
+        Assert.isTrue(CollUtil.isNotEmpty(docDetailsDTOList), "原厂批号对应单据明细不存在");
+        String headerId = docDetailsDTOList.stream().map(item -> item.getDocHeaderId())
+                .distinct().findFirst().orElse(null);
+        Assert.isTrue(StringUtils.isNotBlank(headerId), "明细对应单据头id不存在");
+        BionutritionDocHeaderDTO bionutritionDocHeaderDTO = getBionutritionDocHeaderDTOListById(headerId);
         Assert.isTrue(ObjectUtil.isNotEmpty(bionutritionDocHeaderDTO), "明细对应单据头不存在或单据类型不对应");
         return buildBionutritionDocBaseDTO(bionutritionDocHeaderDTO);
     }
 
+    @Override
+    public BionutritionDocBaseDTO selectDocByDocNoAndDocType(String docNo, String docType) {
+        return buildDocBaseDTOByDocNoAndDocType(docNo, docType);
+    }
+
+    @Override
+    public List<BionutritionDocHeaderDTO> selectDocBaseByDocNoAndDocType(String docNo, String docType) {
+        return getBionutritionDocHeaderDTOList(null,  Lists.newArrayList(docNo), docType);
+    }
+
+    private BionutritionDocBaseDTO buildDocBaseDTOByDocNoAndDocType(String docNo, String docType) {
+        BionutritionDocHeaderDTO bionutritionDocHeaderDTO = getBionutritionDocHeaderDTOListByDocNoAndDocType(docNo, docType);
+        return buildBionutritionDocBaseDTO(bionutritionDocHeaderDTO);
+    }
+
     /**
      * 单据导出excel
      *
@@ -273,7 +302,6 @@ public class BionutritionDocHeaderServiceImpl extends CrudServiceImpl<Bionutriti
             cell.setCellValue(docFieldRemarkMap.get(totalFields[i].getName()));
         }
 
-
         startRow = 3;
         try {
             // 4.设置数据
@@ -482,6 +510,19 @@ public class BionutritionDocHeaderServiceImpl extends CrudServiceImpl<Bionutriti
                 buildBionutritionDocDifferentTypeList(bionutritionDocHeaderDTOList) : buildBionutritionDocSameTypeList(bionutritionDocHeaderDTOList);
     }
 
+    /**
+     * 构建类型单据内容(多个)
+     * @param docNo
+     * @param docType
+     * @return
+     */
+    public List<BionutritionDocBaseDTO> buildBionutritionDocBaseDTOByIdList(String docNo, String docType) {
+        List<BionutritionDocHeaderDTO> bionutritionDocHeaderDTOList = getLikeBionutritionDocHeaderDTOList(docNo, docType);
+        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);
+    }
+
     /**
      * 构建类型单据内容(单个)
      *
@@ -544,6 +585,17 @@ public class BionutritionDocHeaderServiceImpl extends CrudServiceImpl<Bionutriti
         }).collect(Collectors.toList());
     }
 
+    /**
+     * 未查到返回对象
+     * @param docNo
+     * @param docType
+     * @return
+     */
+    public BionutritionDocHeaderDTO getBionutritionDocHeaderDTOListByDocNoAndDocType(String docNo, String docType) {
+        return getBionutritionDocHeaderDTOList(null, Lists.newArrayList(docNo), docType)
+                .stream().findFirst().orElseGet(() -> new BionutritionDocHeaderDTO());
+    }
+
     public BionutritionDocHeaderDTO getBionutritionDocHeaderDTOListByDocNo(String docNo) {
         return getBionutritionDocHeaderDTOList(null, Lists.newArrayList(docNo), null)
                 .stream().findFirst().orElseGet(() -> new BionutritionDocHeaderDTO());
@@ -554,6 +606,182 @@ public class BionutritionDocHeaderServiceImpl extends CrudServiceImpl<Bionutriti
                 .stream().findFirst().orElseGet(() -> new BionutritionDocHeaderDTO());
     }
 
+    /**
+     * 未查到返回null
+     * @param docNo
+     * @param docType
+     * @return
+     */
+    public BionutritionDocHeaderDTO getDocHeaderDTOListByDocNoAndDocType(String docNo, String docType) {
+        return getBionutritionDocHeaderDTOList(null, Lists.newArrayList(docNo), docType)
+                .stream().findFirst().orElse(null);
+    }
+
+    /**
+     * 任务回调修改单据状态
+     * @param wcsTask
+     * @return
+     */
+    @Override
+    public void updateDocStatus(WcsTask wcsTask) {
+        // 不是出入库任务直接返回
+        if (StringUtils.isEmpty(wcsTask.getExt5())) return;
+
+        String ext5 = wcsTask.getExt5();
+        String docNo = null;
+        String docLineNo = null;
+        String businessType = null;
+        String docType = null;
+
+        if (StringUtils.isNotEmpty(ext5)){
+            String[] docParams = ext5.split(",");
+            docNo = docParams[0];
+            docLineNo = docParams[1];
+            businessType = docParams[2];
+            docType = docParams[3];
+        }
+        //根据单号和类型获取单据信息
+        BionutritionDocBaseDTO bionutritionDocBaseDTO = this.selectDocByDocNoAndDocType(docNo, docType);
+        BionutritionDocHeaderBaseDTO bionutritionDocHeaderBaseDTO = bionutritionDocBaseDTO.getBionutritionDocHeaderBaseDTO();
+        BionutritionDocDetailsDTO docDetails = bionutritionDocDetailsService.selectDocDetailsByLineNo(bionutritionDocHeaderBaseDTO.getId(), docLineNo);
+        // 根据单据业务类型修改单据状态
+        if (StringUtils.equals(businessType, Constant.BUSINESS_TYPE.ASN.getValue())) {
+            this.updateASNDocStatus(wcsTask, docNo, docType, bionutritionDocHeaderBaseDTO, docDetails);
+        }else {
+            this.updateSODocStatus(wcsTask, docNo, docType, bionutritionDocHeaderBaseDTO, docDetails);
+        }
+    }
+
+    /**
+     * 修改出库单状态
+     * @param bionutritionDocHeaderBaseDTO
+     * @param docDetails
+     */
+    private void updateSODocStatus(WcsTask wcsTask, String docNo, String docType, BionutritionDocHeaderBaseDTO bionutritionDocHeaderBaseDTO, BionutritionDocDetailsDTO docDetails) {
+        // 1.修改明细
+        // 比较明细已搬运数量和需搬运数量大小
+        BigDecimal sub = NumberUtil.sub(docDetails.getSkuQty(), docDetails.getTransferredQty());
+        // 明细中需搬运数量大于任务已搬运数量,状态为部分出库,否则为完全出库
+        docDetails.setLineStatus(sub.compareTo(BigDecimal.ZERO) > 0 ? Constant.ORDER_STS.STS10.getValue() : Constant.ORDER_STS.STS20.getValue());
+        bionutritionDocDetailsService.updateDocDetails(docDetails);
+        // 2.修改单头
+        this.updateDocHeaderStatus(bionutritionDocHeaderBaseDTO);
+        log.info("===更改出库单据状态,单号{},明细行号{},单头状态更改为{},明细状态更改为{}",
+                bionutritionDocHeaderBaseDTO.getDocNo(), docDetails.getDocLineNo()
+                , bionutritionDocHeaderBaseDTO.getDocStatus(), docDetails.getLineStatus());
+    }
+
+    /**
+     * 修改入库单状态
+     * @param docNo
+     * @param docType
+     * @param bionutritionDocHeaderBaseDTO
+     * @param docDetails
+     */
+    private void updateASNDocStatus(WcsTask wcsTask, String docNo, String docType, BionutritionDocHeaderBaseDTO bionutritionDocHeaderBaseDTO, BionutritionDocDetailsDTO docDetails) {
+        // 1.设置明细状态
+        // 比较明细已搬运数量和需搬运数量大小
+        BigDecimal sub = NumberUtil.sub(docDetails.getSkuQty(), docDetails.getTransferredQty());
+        // 需搬运数量大于已搬运数量,设置单据为部分入库,否则为全部入库
+        docDetails.setLineStatus(sub.compareTo(BigDecimal.ZERO) > 0 ? Constant.ASN_STS.STS30.getValue() : Constant.ASN_STS.STS40.getValue());
+        // 如果采购单的一条明细完全收货
+        if (StringUtils.equals(docType, BizEnum.BionutritionHeaderDocTypeEnum.PURCHASE_ORDER.getDocType())
+                && StringUtils.equals(docDetails.getLineStatus(), Constant.ASN_STS.STS40.getValue())){
+            // 修改采购入库单状态
+            this.updatePurchaseReceiptDocStatus(docNo, docDetails);
+        }
+        bionutritionDocDetailsService.updateDocDetails(docDetails);
+        // 2.设置单头状态
+        this.updateDocHeaderStatus(bionutritionDocHeaderBaseDTO);
+        log.info("===更改入库单据状态,单号{},明细行号{},单头状态更改为{},明细状态更改为{}",
+                bionutritionDocHeaderBaseDTO.getDocNo(), docDetails.getDocLineNo()
+                , bionutritionDocHeaderBaseDTO.getDocStatus(), docDetails.getLineStatus());
+    }
+
+    public static void main(String[] args) {
+        BigDecimal sub = NumberUtil.sub("35", "26");
+        // 需搬运数量大于已搬运数量,设置单据为部分入库,否则为全部入库
+        boolean b = sub.compareTo(BigDecimal.ZERO) > 0;
+        System.out.println(b);
+
+    }
+
+    /**
+     * 比较单据的一条明细已生成任务的搬运总数量和明细需要搬运总数量大小
+     * @param wcsTask
+     * @param docDetails
+     * @return
+     */
+    private int getQtyCompare(WcsTask wcsTask, BionutritionDocDetailsDTO docDetails) {
+        // 查询同单号同明细中未取消的任务
+        List<WcsTaskInvLotDTO> wcsTaskInvLots = wcsTaskService.selectWcsTaskListByExt5(wcsTask.getExt5());
+        long sum = wcsTaskInvLots.stream().filter(item -> StringUtils.isNotBlank(item.getQty()))
+                .mapToLong(item -> Long.parseLong(NumberUtil.roundStr(item.getQty(), 0))).sum();
+        int compare = NumberUtil.compare(Long.valueOf(docDetails.getSkuQty()), sum);
+        return compare;
+    }
+
+    /**
+     * 修改单头状态
+     * @param bionutritionDocHeaderBaseDTO
+     */
+    private void updateDocHeaderStatus(BionutritionDocHeaderBaseDTO bionutritionDocHeaderBaseDTO) {
+        List<BionutritionDocDetailsDTO> docDetailsDTOList = bionutritionDocDetailsService.getBionutritionDocDetailsDTOList(bionutritionDocHeaderBaseDTO.getId());
+        // 出库 过滤掉不是完全出库状态的明细
+        if (StringUtils.equals(bionutritionDocHeaderBaseDTO.getBusinessType(), Constant.BUSINESS_TYPE.ORDER.getValue())){
+            List<BionutritionDocDetailsDTO> collect = docDetailsDTOList.stream()
+                    .filter(item -> !StringUtils.equals(item.getLineStatus(), Constant.ORDER_STS.STS20.getValue())).collect(Collectors.toList());
+            // 如果存在不是完全出库状态的明细 单头设置为部分出库; 否则设置为完全出库
+            bionutritionDocHeaderBaseDTO.setDocStatus(CollUtil.isNotEmpty(collect) ?
+                    Constant.ORDER_STS.STS10.getValue() : Constant.ORDER_STS.STS20.getValue());
+        } else { // 入库 过滤掉不是完全入库状态的明细
+            List<BionutritionDocDetailsDTO> collect = docDetailsDTOList.stream()
+                    .filter(item -> !StringUtils.equals(item.getLineStatus(), Constant.ASN_STS.STS40.getValue())).collect(Collectors.toList());
+            // 如果存在不是完全收货状态的明细 单头设置为部分收货; 否则设置为完全收货
+            bionutritionDocHeaderBaseDTO.setDocStatus(CollUtil.isNotEmpty(collect) ?
+                    Constant.ASN_STS.STS30.getValue() : Constant.ASN_STS.STS40.getValue());
+        }
+        this.updateDoc(ConvertUtils.sourceToTarget(bionutritionDocHeaderBaseDTO, BionutritionDocHeaderDTO.class));
+    }
+
+    /**
+     * 判断单据的一条明细是否完全搬运
+     * @param docDetails
+     * @param docDetailsDTOList
+     * @return
+     */
+    private boolean ifLessEqualQty(BionutritionDocDetailsDTO docDetails, List<BionutritionDocDetailsBaseDTO> docDetailsDTOList) {
+        long qty = docDetailsDTOList.stream().filter(item -> StringUtils.isNotBlank(item.getSkuQty()))
+                .mapToLong(item -> Long.parseLong(item.getSkuQty())).sum();
+        // 判断已搬运的数量是否小于采购单对应明细的总数量
+        long qtySupposed = Long.parseLong(docDetails.getSkuQty());
+        log.info("当前已搬运数量{},剩余未搬运数量{}", qty, qtySupposed - qty);
+        boolean ifLessEqualQty = qtySupposed - qty > 0;
+        return ifLessEqualQty;
+    }
+
+    /**
+     * 修改采购入库单状态
+     * @param docNo
+     */
+    private void updatePurchaseReceiptDocStatus(String docNo, BionutritionDocDetailsDTO docDetails) {
+        BionutritionDocBaseDTO purchaseReceiptDoc = this.selectDocByDocNoAndDocType(docNo, BizEnum.BionutritionHeaderDocTypeEnum.PURCHASE_RECEIPT.getDocType());
+        List<BionutritionDocDetailsBaseDTO> docDetailsDTOList = purchaseReceiptDoc.getBionutritionDocDetailsBaseDTOList();
+        // 将对应的采购收货单改为完全收货
+        /*docDetailsDTOList.forEach(item->{
+            item.setLineStatus(Constant.ASN_STS.STS40.getValue());
+            bionutritionDocDetailsService.updateDocDetails(ConvertUtils.sourceToTarget(item, BionutritionDocDetailsDTO.class));
+        });*/
+        // 修改明细
+        docDetailsDTOList.stream().filter(item->StringUtils.equals(item.getBelongDetailsId(), docDetails.getId())).collect(Collectors.toList())
+                .forEach(item->{
+            item.setLineStatus(Constant.ASN_STS.STS40.getValue());
+            bionutritionDocDetailsService.updateDocDetails(ConvertUtils.sourceToTarget(item, BionutritionDocDetailsDTO.class));
+        });
+        // 修改单头
+        this.updateDocHeaderStatus(purchaseReceiptDoc.getBionutritionDocHeaderBaseDTO());
+    }
+
     public List<BionutritionDocHeaderDTO> getBionutritionDocHeaderDTOListByDocNo(List<String> docNoList) {
         return getBionutritionDocHeaderDTOList(null, docNoList, null);
     }
@@ -566,6 +794,13 @@ public class BionutritionDocHeaderServiceImpl extends CrudServiceImpl<Bionutriti
         return getBionutritionDocHeaderDTOList(null, null, docType);
     }
 
+    private List<BionutritionDocHeaderDTO> getLikeBionutritionDocHeaderDTOList(String docNo, String docType) {
+        List<BionutritionDocHeader> bionutritionDocHeaderList = baseDao.selectList(Wrappers.<BionutritionDocHeader>lambdaQuery()
+                .like(StringUtils.isNotEmpty(docNo), BionutritionDocHeader::getDocNo, docNo)
+                .eq(StringUtils.isNotBlank(docType), BionutritionDocHeader::getDocType, docType));
+        return ConvertUtils.sourceToTarget(bionutritionDocHeaderList, BionutritionDocHeaderDTO.class);
+    }
+
     private List<BionutritionDocHeaderDTO> getBionutritionDocHeaderDTOList(List<String> idList, List<String> docNoList, String docType) {
         List<BionutritionDocHeader> bionutritionDocHeaderList = baseDao.selectList(Wrappers.<BionutritionDocHeader>lambdaQuery()
                 .in(CollectionUtil.isNotEmpty(idList), BionutritionDocHeader::getId, idList)

+ 14 - 1
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/dto/AsnAgvCallDTO.java

@@ -12,6 +12,7 @@ public class AsnAgvCallDTO implements Serializable {
     /**
      * 单据号
      */
+    @NotBlank(message = "请填写单据号")
     private String docNo ;
     /**
      * 起始库位
@@ -26,10 +27,11 @@ public class AsnAgvCallDTO implements Serializable {
      * 产品批号
      */
     @NotBlank(message = "请填写产品批号")
-    private String batchNumber ;
+    private String batchNumber;
     /**
      * 数量
      */
+    @NotBlank(message = "请填写数量")
     private String qty;
     /**
      * 物料编号
@@ -41,4 +43,15 @@ public class AsnAgvCallDTO implements Serializable {
      */
     @NotBlank(message = "单据类型不确定")
     private String docType;
+    /**
+     * 明细行号
+     */
+    @NotBlank(message = "请填写明细行号")
+    private String lineNo;
+
+    /**
+     * 操作人
+     */
+    private String user;
+
 }

+ 6 - 1
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/dto/DocQcDTO.java

@@ -20,7 +20,7 @@ public class DocQcDTO implements Serializable {
     private String skuCode;
     /**
      * 批次状态
-     * HG:合格 BHG:不合格 DJ:待检{@link com.ruoyi.base.constant.Constant.QUALITY_STATUS}
+     * HG:合格 BHG:不合格 DJ:待检 FX:放行{@link com.ruoyi.base.constant.Constant.QUALITY_STATUS}
      */
     @NotBlank(message = "状态不能为空")
     private String status;
@@ -29,5 +29,10 @@ public class DocQcDTO implements Serializable {
      */
     @NotBlank(message = "批次号不能为空")
     private String batchNumber;
+    /**
+     * 单据号
+     */
+    private String docNo;
 
+    private String user;
 }

+ 41 - 0
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/dto/GroundingDTO.java

@@ -0,0 +1,41 @@
+package com.ruoyi.ams.bionutrition.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import java.io.Serializable;
+
+@Data
+public class GroundingDTO implements Serializable {
+
+    private static final long serialVersionUID = -3507477864537906270L;
+    /**
+     * 单据号
+     */
+    @NotBlank(message = "请填写单据号")
+    private String docNo ;
+    /**
+     * 产品批号
+     */
+    @NotBlank(message = "请填写产品批号")
+    private String batchNumber;
+    /**
+     * 数量
+     */
+    @NotBlank(message = "请填写数量")
+    private String qty;
+    /**
+     * 物料编号
+     */
+    @NotBlank(message = "请填写物料信息")
+    private String skuCode;
+    /**
+     * 单据类型
+     */
+    private String docType;
+    /**
+     * 明细行号
+     */
+    @NotBlank(message = "请填写明细行号")
+    private String lineNo;
+}

+ 21 - 0
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/dto/OrderAgvCallDTO.java

@@ -22,6 +22,7 @@ public class OrderAgvCallDTO implements Serializable {
     /**
      * 数量
      */
+    @NotBlank(message = "请填写数量")
     private String qty;
     /**
      * 物料编号
@@ -33,4 +34,24 @@ public class OrderAgvCallDTO implements Serializable {
      */
     @NotBlank(message = "单据类型不确定")
     private String docType;
+    /**
+     * 单据号
+     */
+    @NotBlank(message = "请填写单据号")
+    private String docNo;
+    /**
+     * 明细行号
+     */
+    @NotBlank(message = "请填写明细行号")
+    private String lineNo;
+    /**
+     * 明细id
+     */
+    private String detailsId;
+
+    /**
+     * 操作人
+     */
+    private String user;
+
 }

+ 32 - 0
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/pda/IPdaAgvCallService.java

@@ -1,6 +1,14 @@
 package com.ruoyi.ams.bionutrition.pda;
 
+import com.ruoyi.ams.bionutrition.doc.dto.DocLotattDTO;
+import com.ruoyi.ams.bionutrition.doc.dto.detail.BionutritionDocDetailsBaseDTO;
+import com.ruoyi.ams.bionutrition.doc.dto.header.BionutritionDocHeaderBaseDTO;
 import com.ruoyi.ams.bionutrition.dto.AsnAgvCallDTO;
+import com.ruoyi.ams.bionutrition.dto.GroundingDTO;
+import com.ruoyi.ams.bionutrition.dto.OrderAgvCallDTO;
+import com.ruoyi.ams.config.domain.dto.AgvCallDTO;
+import com.ruoyi.ams.config.domain.dto.LotattDTO;
+import com.ruoyi.base.domain.BaseSku;
 
 /**
  * 佰穗莱pda呼叫AGV生成搬运任务
@@ -11,4 +19,28 @@ public interface IPdaAgvCallService {
      * @param asnAgvCallDTO
      */
     void createIntoStorageTask(AsnAgvCallDTO asnAgvCallDTO);
+
+    /**
+     * 上架
+     * @param groundingDTO
+     */
+    void grounding(GroundingDTO groundingDTO);
+
+    /**
+     * 根据单据类型获取流程id
+     * @param docType
+     * @return
+     */
+    Long getFlowIdByDocType(String docType);
+
+    /**
+     * 构建批次属性对象
+     * @param docHeaderBaseDTO
+     * @param docLotattDTO
+     * @param baseSku
+     * @return
+     */
+    LotattDTO buildLotattArgument(BionutritionDocHeaderBaseDTO docHeaderBaseDTO,BionutritionDocDetailsBaseDTO docDetailsBaseDTO, DocLotattDTO docLotattDTO, BaseSku baseSku);
+
+    AgvCallDTO getOrderAgvCallDTO(OrderAgvCallDTO orderAgvCallDTO);
 }

+ 170 - 46
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/pda/impl/PdaAgvCallServiceImpl.java

@@ -1,13 +1,17 @@
 package com.ruoyi.ams.bionutrition.pda.impl;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.NumberUtil;
 import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONArray;
 import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+import com.ruoyi.ams.agv.ndc.common.Aci;
 import com.ruoyi.ams.bionutrition.doc.domain.BionutritionDocDetails;
 import com.ruoyi.ams.bionutrition.doc.domain.BionutritionDocHeader;
 import com.ruoyi.ams.bionutrition.doc.dto.BionutritionDocBaseDTO;
@@ -21,6 +25,8 @@ import com.ruoyi.ams.bionutrition.doc.dto.header.BionutritionDocHeaderBaseDTO;
 import com.ruoyi.ams.bionutrition.doc.service.BionutritionDocDetailsService;
 import com.ruoyi.ams.bionutrition.doc.service.BionutritionDocHeaderService;
 import com.ruoyi.ams.bionutrition.dto.AsnAgvCallDTO;
+import com.ruoyi.ams.bionutrition.dto.GroundingDTO;
+import com.ruoyi.ams.bionutrition.dto.OrderAgvCallDTO;
 import com.ruoyi.ams.bionutrition.pda.IPdaAgvCallService;
 import com.ruoyi.ams.business.IBusinessService;
 import com.ruoyi.ams.config.domain.dto.AgvCallDTO;
@@ -42,6 +48,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
@@ -63,46 +70,78 @@ public class PdaAgvCallServiceImpl implements IPdaAgvCallService {
     private IBaseSkuService skuService;
 
     /**
-     * 入库单据类型
-     */
-    private final List<String> IntoStorageDocTypeList = Arrays.asList("FinishedProductReceipt", "ProductionReturnOrder", "PurchaseOrder", "SaleReturnOrder");
-
-    /**
-     * 入库
+     * 根据单号和单据类型生成入库任务
      * @param asnAgvCallDTO
      */
     @Override
     @Transactional(rollbackFor = RuntimeException.class)
     public void createIntoStorageTask(AsnAgvCallDTO asnAgvCallDTO) {
-        // 根据单号查询单据 || 根据物料编码和批次号查询单据信息
-//        BionutritionDocBaseDTO bionutritionDocBaseDTO = bionutritionDocHeaderService.selectDocByDocNo(asnAgvCallDTO.getDocNo());
-        BionutritionDocBaseDTO bionutritionDocBaseDTO = bionutritionDocHeaderService.selectDocBySkuAndBatchNumber(
-                asnAgvCallDTO.getSkuCode(),asnAgvCallDTO.getBatchNumber(), asnAgvCallDTO.getDocType());
-        // 校验参数
+        // 1.校验参数
+        Assert.isFalse(StringUtils.equals(asnAgvCallDTO.getQty(), "0"), "入库数量不能为0");
+        // 根据单号和单据类型查询单据信息
+        BionutritionDocBaseDTO bionutritionDocBaseDTO =
+                bionutritionDocHeaderService.selectDocByDocNoAndDocType(asnAgvCallDTO.getDocNo(), asnAgvCallDTO.getDocType());
         Assert.isTrue(ObjectUtil.isNotNull(bionutritionDocBaseDTO), "该单据不存在");
-        String docType = bionutritionDocBaseDTO.getBionutritionDocHeaderBaseDTO().getDocType();
-        Assert.isTrue(StringUtils.isNotEmpty(docType), "单据信息中物料类型为空");
-        Assert.isTrue(IntoStorageDocTypeList.contains(docType), "该单据不是入库单据");
+        BionutritionDocHeaderBaseDTO bionutritionDocHeaderBaseDTO = bionutritionDocBaseDTO.getBionutritionDocHeaderBaseDTO();
+        String docType = bionutritionDocHeaderBaseDTO.getDocType();
+        Assert.isTrue(StringUtils.isNotEmpty(docType), "单据信息中单据类型为空");
+        Assert.isTrue(StringUtils.equals(bionutritionDocHeaderBaseDTO.getBusinessType(),Constant.BUSINESS_TYPE.ASN.getValue())
+                || StringUtils.equals(bionutritionDocHeaderBaseDTO.getBusinessType(),Constant.BUSINESS_TYPE.PO.getValue())
+                , "该单据不是入库单据");
         List<BionutritionDocDetailsBaseDTO> docDetailsList = bionutritionDocBaseDTO.getBionutritionDocDetailsBaseDTOList();
         Assert.isTrue(CollUtil.isNotEmpty(docDetailsList), "单据明细数据为空");
+        // 2.根据明细行号筛选明细信息
+        BionutritionDocDetailsBaseDTO docDetailsBaseDTO = docDetailsList.stream().filter(item -> StringUtils.equals(item.getDocLineNo(), asnAgvCallDTO.getLineNo()))
+                .findFirst().orElse(null);
+        Assert.isTrue(ObjectUtil.isNotEmpty(docDetailsBaseDTO), "对应明细行号数据未找到");
+        // 3.判断数量是否超出范围
+        // 记录当前明细已搬运数量
+        BigDecimal transferredQty = NumberUtil.add(docDetailsBaseDTO.getTransferredQty(), asnAgvCallDTO.getQty());
+        Assert.isTrue(NumberUtil.compare(
+                Long.valueOf(docDetailsBaseDTO.getSkuQty()), Long.valueOf(transferredQty.toString())) >= 0
+                , "入库数量超出范围,剩余数量"+NumberUtil.sub(docDetailsBaseDTO.getSkuQty(), docDetailsBaseDTO.getTransferredQty()));
+        docDetailsBaseDTO.setTransferredQty(transferredQty.toString());
+        bionutritionDocDetailsService.updateDocDetails(ConvertUtils.sourceToTarget(docDetailsBaseDTO, BionutritionDocDetailsDTO.class));
+
         // 如果是采购入库 需要根据采购单生成采购入库单
         if (StringUtils.equals(docType, BizEnum.BionutritionExcelDocTitleEnum.PURCHASE_ORDER.getDocType())) {
-            addPurchaseReceiptDoc(bionutritionDocBaseDTO, docDetailsList);
+            this.addPurchaseReceiptDoc(bionutritionDocBaseDTO, docDetailsBaseDTO, asnAgvCallDTO);
         }
-        // 获取配置信息单据类型对应流程id
-        Long flowId = getFlowIdByDocType(docType);
-        // 生成agv呼叫对象,生成对应wcs任务
-        AgvCallDTO agvCallDTO = getAgvCallDTO(asnAgvCallDTO, docDetailsList.get(0));
+        // 4.获取配置信息单据类型对应流程id
+        Long flowId = this.getFlowIdByDocType(docType);
+        // 5.生成agv呼叫对象,生成对应wcs任务
+        AgvCallDTO agvCallDTO = this.getASNAgvCallDTO(asnAgvCallDTO, bionutritionDocHeaderBaseDTO, docDetailsBaseDTO);
         businessService.agvCall(flowId, agvCallDTO);
     }
 
+    /**
+     * 上架
+     * @param groundingDTO
+     */
+    @Override
+    @Transactional(rollbackFor = RuntimeException.class)
+    public void grounding(GroundingDTO groundingDTO) {
+        // 根据单号和单据类型查询单据信息
+        BionutritionDocBaseDTO bionutritionDocBaseDTO =
+                bionutritionDocHeaderService.selectDocByDocNoAndDocType(groundingDTO.getDocNo(), groundingDTO.getDocType());
+        Assert.isTrue(ObjectUtil.isNotNull(bionutritionDocBaseDTO), "该单据不存在");
+        List<BionutritionDocDetailsBaseDTO> docDetailsList = bionutritionDocBaseDTO.getBionutritionDocDetailsBaseDTOList();
+        Assert.isTrue(CollUtil.isNotEmpty(docDetailsList), "单据明细数据为空");
+        BionutritionDocDetailsBaseDTO docDetailsBaseDTO = docDetailsList.stream().filter(item -> StringUtils.equals(item.getDocLineNo(), groundingDTO.getLineNo()))
+                .findFirst().orElse(null);
+        Assert.isTrue(ObjectUtil.isNotEmpty(docDetailsBaseDTO), "行号对应明细数据未找到");
+        // 修改单据明细状态为完全上架
+        docDetailsBaseDTO.setLineStatus(Constant.ASN_STS.STS60.getValue());
+        bionutritionDocDetailsService.updateDocDetails(ConvertUtils.sourceToTarget(docDetailsBaseDTO, BionutritionDocDetailsDTO.class));
+    }
+
     /**
      * 根据单据类型获取流程id
      * @param docType
      * @return
      */
     @NotNull
-    private Long getFlowIdByDocType(String docType) {
+    public Long getFlowIdByDocType(String docType) {
         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);
@@ -115,65 +154,150 @@ public class PdaAgvCallServiceImpl implements IPdaAgvCallService {
     /**
      * 添加采购入库单
      * @param bionutritionDocBaseDTO
-     * @param docDetailsList
+     * @param docDetailsBaseDTO
      */
-    private void addPurchaseReceiptDoc(BionutritionDocBaseDTO bionutritionDocBaseDTO, List<BionutritionDocDetailsBaseDTO> docDetailsList) {
-        // 单头、明细设置新id主键
+    private void addPurchaseReceiptDoc(BionutritionDocBaseDTO bionutritionDocBaseDTO, BionutritionDocDetailsBaseDTO docDetailsBaseDTO, AsnAgvCallDTO asnAgvCallDTO) {
+        BionutritionDocDetailsDTO docDetailsDTO = ConvertUtils.sourceToTarget(docDetailsBaseDTO, BionutritionDocDetailsDTO.class);
         BionutritionDocHeaderBaseDTO docHeaderBaseDTO = bionutritionDocBaseDTO.getBionutritionDocHeaderBaseDTO();
-        String headerId = IdWorker.getIdStr();
-        docHeaderBaseDTO.setId(headerId);
-        docDetailsList.stream().forEach(detail->{
-            detail.setDocHeaderId(headerId);
-            detail.setId(IdWorker.getIdStr());
-        });
+        // 根据单号和单据类型查询采购入库单头
+        BionutritionDocHeaderDTO purchaseReceiptDocHeader = bionutritionDocHeaderService.getDocHeaderDTOListByDocNoAndDocType(
+                asnAgvCallDTO.getDocNo(), BizEnum.BionutritionHeaderDocTypeEnum.PURCHASE_RECEIPT.getDocType());
+        // 如果没有同单号的采购入库单,则新生成单头 如果有同单号的采购入库单则新生成的明细关联当前单头
+        if (ObjectUtil.isEmpty(purchaseReceiptDocHeader)){
+            // 单头新id主键
+            String headerId = IdWorker.getIdStr();
+            docHeaderBaseDTO.setId(headerId);
+            docDetailsDTO.setDocHeaderId(docHeaderBaseDTO.getId());
+            BionutritionDocHeaderDTO bionutritionDocHeaderDTO = ConvertUtils.sourceToTarget(docHeaderBaseDTO, BionutritionDocHeaderDTO.class);
+            // 设置单据类型为采购入库单
+            bionutritionDocHeaderDTO.setDocType(BizEnum.BionutritionExcelDocTitleEnum.PURCHASE_RECEIPT.getDocType());
+            bionutritionDocHeaderDTO.setBusinessType(Constant.BUSINESS_TYPE.ASN.getValue());
+            bionutritionDocHeaderService.insertDocHeader(bionutritionDocHeaderDTO);
+        }else {
+            BionutritionDocBaseDTO purchaseReceiptDoc = bionutritionDocHeaderService.selectDocByDocNoAndDocType(
+                    asnAgvCallDTO.getDocNo(), BizEnum.BionutritionHeaderDocTypeEnum.PURCHASE_RECEIPT.getDocType());
+            docDetailsDTO.setDocHeaderId(purchaseReceiptDocHeader.getId());
+            // 计算采购入库搬运数量是否合理
+            List<BionutritionDocDetailsBaseDTO> detailsBaseDTOList = purchaseReceiptDoc.getBionutritionDocDetailsBaseDTOList();
+            this.calculateQuantityIfReasonable(detailsBaseDTOList, docDetailsBaseDTO, asnAgvCallDTO);
+        }
+        // 设置属于那条采购单明细
+        docDetailsDTO.setBelongDetailsId(docDetailsDTO.getId());
+        docDetailsDTO.setId(IdWorker.getIdStr());
+        docDetailsDTO.setSkuQty(asnAgvCallDTO.getQty());
+        docDetailsDTO.setTransferredQty(asnAgvCallDTO.getQty());
         // 生成采购入库单
-        bionutritionDocDetailsService.insertBatch(ConvertUtils.sourceToTarget(docDetailsList, BionutritionDocDetails.class));
-        BionutritionDocHeaderDTO bionutritionDocHeaderDTO = ConvertUtils.sourceToTarget(docHeaderBaseDTO, BionutritionDocHeaderDTO.class);
-        bionutritionDocHeaderDTO.setDocType(BizEnum.BionutritionExcelDocTitleEnum.PURCHASE_RECEIPT.getDocType());
-        bionutritionDocHeaderService.insertDocHeader(bionutritionDocHeaderDTO);
+        bionutritionDocDetailsService.insertDocDetails(docDetailsDTO);
+    }
+
+    /**
+     * 计算采购入库搬运数量是否合理
+     * @param docDetailsBaseDTOList
+     * @param docDetailsBaseDTO
+     * @param asnAgvCallDTO
+     */
+    private void calculateQuantityIfReasonable(List<BionutritionDocDetailsBaseDTO> docDetailsBaseDTOList, BionutritionDocDetailsBaseDTO docDetailsBaseDTO, AsnAgvCallDTO asnAgvCallDTO) {
+        /*Assert.isTrue(CollUtil.isNotEmpty(docDetailsBaseDTOList), "采购入库单明细为空");
+        long qty = docDetailsBaseDTOList.stream()
+                .filter(item -> StringUtils.equals(item.getSkuCode(), asnAgvCallDTO.getSkuCode()))
+                .filter(item -> StringUtils.isNotBlank(item.getSkuQty()))
+                .mapToLong(item -> Long.parseLong(item.getSkuQty())).sum();*/
+        // 计算当前明细的总数量
+        /*long qty = docDetailsBaseDTOList.stream().filter(item -> StringUtils.isNotBlank(item.getSkuQty()))
+                .mapToLong(item -> Long.parseLong(item.getSkuQty())).sum();*/
+        // 判断已搬运的数量加上当前搬运数量是否小于采购单对应明细的总数量
+        long qty = StrUtil.isBlank(docDetailsBaseDTO.getTransferredQty()) ? 0 : Long.valueOf(docDetailsBaseDTO.getTransferredQty());
+        long qtySupposed = Long.parseLong(docDetailsBaseDTO.getSkuQty());
+        long qtyRemain = qtySupposed - qty;
+        boolean ifLessEqualQty = qty <= qtySupposed;
+        log.info("当前搬运数量{},剩余未搬运数量{}",asnAgvCallDTO.getQty(), qtyRemain);
+        Assert.isTrue(ifLessEqualQty, "搬运数量超出范围,剩余数量为"+qtyRemain);
     }
 
     /**
-     * 生成agv呼叫对象
+     * 生成入库agv呼叫对象
      * @param asnAgvCallDTO
      * @return
      */
-    private AgvCallDTO getAgvCallDTO(AsnAgvCallDTO asnAgvCallDTO, BionutritionDocDetailsBaseDTO docDetailsBaseDTO) {
+    private AgvCallDTO getASNAgvCallDTO(AsnAgvCallDTO asnAgvCallDTO, BionutritionDocHeaderBaseDTO docHeaderBaseDTO, BionutritionDocDetailsBaseDTO docDetailsBaseDTO) {
         DocLotattDTO docLotattDTO = ConvertUtils.sourceToTarget(docDetailsBaseDTO, DocLotattDTO.class);
         // 根据物料编码查询物料信息
-        BaseSku baseSku = skuService.selectBaseSkuByCustomerId("default", docDetailsBaseDTO.getSkuCode());
+        BaseSku baseSku = skuService.selectBaseSkuByCustomerId("default", asnAgvCallDTO.getSkuCode());
         Assert.isTrue(ObjectUtil.isNotEmpty(baseSku), "物料信息未找到");
         List<AgvCallItemDTO> agvCallItemDTOList = new ArrayList<>();
         AgvCallItemDTO agvCallItemDTO = new AgvCallItemDTO();
         // 构建批次属性
-        LotattDTO lotattDTO = buildLotattArgument(docDetailsBaseDTO, docLotattDTO, baseSku);
+        LotattDTO lotattDTO = this.buildLotattArgument(docHeaderBaseDTO, docDetailsBaseDTO, docLotattDTO, baseSku);
 
         agvCallItemDTO.setSku(asnAgvCallDTO.getSkuCode());
+        agvCallItemDTO.setQty(Double.valueOf(asnAgvCallDTO.getQty()));
         agvCallItemDTO.setLotattDTO(lotattDTO);
         agvCallItemDTOList.add(agvCallItemDTO);
         AgvCallDTO agvCallDTO = new AgvCallDTO();
         agvCallDTO.setLocationFrom(asnAgvCallDTO.getLocationFrom());
         agvCallDTO.setAgvCallItemDTOList(agvCallItemDTOList);
+        agvCallDTO.setDocNo(asnAgvCallDTO.getDocNo());// 设置单号
+        agvCallDTO.setDocLineNo(asnAgvCallDTO.getLineNo()); // 设置明细行号
+        agvCallDTO.setBusinessType(Constant.BUSINESS_TYPE.ASN.getValue()); // 设置单据业务类型 -- 入库
+        agvCallDTO.setDocType(asnAgvCallDTO.getDocType()); // 设置单据类型
+        agvCallDTO.setCreateUser(asnAgvCallDTO.getUser()); // 设置操作人
         return agvCallDTO;
     }
 
     /**
      * 构建批次属性
-     * @param docDetailsBaseDTO
+     * @param docHeaderBaseDTO
      * @param docLotattDTO
      * @param baseSku
      */
-    private LotattDTO buildLotattArgument(BionutritionDocDetailsBaseDTO docDetailsBaseDTO, DocLotattDTO docLotattDTO, BaseSku baseSku) {
+    public LotattDTO buildLotattArgument(BionutritionDocHeaderBaseDTO docHeaderBaseDTO, BionutritionDocDetailsBaseDTO docDetailsBaseDTO, DocLotattDTO docLotattDTO, BaseSku baseSku) {
         LotattDTO lotattDTO = new LotattDTO();
         lotattDTO.setLotatt01(docLotattDTO.getVendorCode());// 供应商编码
-        lotattDTO.setLotatt02(docLotattDTO.getBatchNumber());// 批号
-        lotattDTO.setLotatt03(DateUtil.format(docLotattDTO.getManufactureDate(), "yyyy-MM-dd"));// 生产日期
-        lotattDTO.setLotatt04(String.valueOf(baseSku.getSkuShelflife()));// 有效期
-        lotattDTO.setLotatt05(Constant.QUALITY_STATUS.DJ.getValue());// 质检状态
+        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()); // 成品入库、销售退库:产品批号
+        } else {
+            lotattDTO.setLotatt02(docLotattDTO.getProductLotNumber()); // 生产退库:进厂批号
+        }
+        String manufactureDate = DateUtil.format(docLotattDTO.getManufactureDate(), "yyyy-MM-dd");
+        lotattDTO.setLotatt03(manufactureDate);// 生产日期
+        // 计算有效截止日期:生产日期加上有效期(天)
+        DateTime dateTime = DateUtil.offsetDay(DateUtil.parse(manufactureDate), baseSku.getSkuShelflife());
+        lotattDTO.setLotatt04(DateUtil.format(dateTime,"yyyy-MM-dd"));// 有效截止日期
+        lotattDTO.setLotatt05(Constant.QUALITY_STATUS.DJ.getValue());// 质检状态 默认待检
         lotattDTO.setLotatt06(DateUtil.format(new Date(), "yyyy-MM-dd"));// 入库日期
-        lotattDTO.setLotatt07(StringUtils.isNotEmpty(docLotattDTO.getSpecification())
-                ? docLotattDTO.getSpecification() : baseSku.getSkuSpecs());// 规格型号
-        lotattDTO.setLotatt08(DateUtil.format(docDetailsBaseDTO.getCreateDate(), "yyyy-MM-dd"));// 收货日期
+        lotattDTO.setLotatt07(docLotattDTO.getIncomeLotNumber());// 进厂批号
+        lotattDTO.setLotatt08(docLotattDTO.getProductLotNumber());// 生产批号
+        lotattDTO.setLotatt09(docHeaderBaseDTO.getId());// 入库单头id
+        lotattDTO.setLotatt10(docDetailsBaseDTO.getDocLineNo()); // 明细行号
         return lotattDTO;
     }
+
+    /**
+     * 构建出库agv呼叫对象
+     * @param orderAgvCallDTO
+     * @return
+     */
+    @Override
+    public AgvCallDTO getOrderAgvCallDTO(OrderAgvCallDTO orderAgvCallDTO) {
+        // 根据物料编码查询物料信息
+        BaseSku baseSku = skuService.selectBaseSkuByCustomerId("default", orderAgvCallDTO.getSkuCode());
+        Assert.isTrue(ObjectUtil.isNotEmpty(baseSku), "物料信息未找到");
+        List<AgvCallItemDTO> agvCallItemDTOList = new ArrayList<>();
+        AgvCallItemDTO agvCallItemDTO = new AgvCallItemDTO();
+
+        agvCallItemDTO.setSku(orderAgvCallDTO.getSkuCode());
+        agvCallItemDTO.setQty(Double.valueOf(orderAgvCallDTO.getQty()));
+        agvCallItemDTOList.add(agvCallItemDTO);
+        AgvCallDTO agvCallDTO = new AgvCallDTO();
+        agvCallDTO.setLocationFrom(orderAgvCallDTO.getLocationTo());
+        agvCallDTO.setAgvCallItemDTOList(agvCallItemDTOList);
+        agvCallDTO.setDocNo(orderAgvCallDTO.getDocNo());// 设置单号
+        agvCallDTO.setDocLineNo(orderAgvCallDTO.getLineNo()); // 设置明细行号
+        agvCallDTO.setBusinessType(Constant.BUSINESS_TYPE.ORDER.getValue()); // 设置单据业务类型 -- 出库
+        agvCallDTO.setDocType(orderAgvCallDTO.getDocType()); // 设置单据类型
+        agvCallDTO.setCreateUser(orderAgvCallDTO.getUser()); // 设置操作人
+        return agvCallDTO;
+    }
 }

+ 81 - 12
warewms-ams/src/main/java/com/ruoyi/ams/bionutrition/pda/impl/PdaDocQcServiceImpl.java

@@ -1,14 +1,21 @@
 package com.ruoyi.ams.bionutrition.pda.impl;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.ListUtil;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.lang.Assert;
 import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.google.common.collect.Lists;
+import com.ruoyi.ams.bionutrition.doc.dto.BionutritionDocDetailsDTO;
+import com.ruoyi.ams.bionutrition.doc.dto.BionutritionDocHeaderDTO;
+import com.ruoyi.ams.bionutrition.doc.service.BionutritionDocDetailsService;
+import com.ruoyi.ams.bionutrition.doc.service.BionutritionDocHeaderService;
 import com.ruoyi.ams.bionutrition.dto.DocQcDTO;
 import com.ruoyi.ams.bionutrition.pda.IPdaDocQcService;
 import com.ruoyi.ams.business.IBusinessService;
+import com.ruoyi.ams.config.domain.dto.LotattDTO;
 import com.ruoyi.ams.inv.domain.InvLotAtt;
 import com.ruoyi.ams.inv.domain.InvLotLocId;
 import com.ruoyi.ams.inv.dto.InvMoveDTO;
@@ -19,13 +26,17 @@ import com.ruoyi.base.domain.BaseLocationInfo;
 import com.ruoyi.base.service.IBaseLocationInfoService;
 import com.ruoyi.common.core.redis.RedisKey;
 import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.DateUtils;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 @Slf4j
 @Service
@@ -39,6 +50,10 @@ public class PdaDocQcServiceImpl implements IPdaDocQcService {
     private IBusinessService businessService;
     @Autowired
     private IBaseLocationInfoService baseLocationInfoService;
+    @Autowired
+    private BionutritionDocHeaderService bionutritionDocHeaderService;
+    @Autowired
+    private BionutritionDocDetailsService bionutritionDocDetailsService;
 
     /**
      * PDA质检
@@ -51,24 +66,36 @@ public class PdaDocQcServiceImpl implements IPdaDocQcService {
         // 根据物料编码和批号查询批次信息
         List<InvLotAtt> invLotAttList = invLotAttService.selectInvLotAttByBatchNum(docQcDTO.getBatchNumber(), docQcDTO.getSkuCode());
         Assert.isTrue(CollUtil.isNotEmpty(invLotAttList), "所属批次信息未找到");
+        String lotNumNew = "";
         for (InvLotAtt invLotAtt : invLotAttList) {
             String lotnum = invLotAtt.getLotnum();
             // 根据批次号查询库存信息
             List<InvLotLocId> invLotLocIds = invLotLocIdService.selectInvLotLocIdByLotnum(lotnum);
             // 如果没有对应的库存信息,遍历下一条批次数据 因为根据物料和批号会匹配到多条仅仅是质检状态不同批次数据
-            if (CollUtil.isNotEmpty(invLotLocIds)) continue;
-            // 设置状态
+            if (CollUtil.isEmpty(invLotLocIds)) continue;
             invLotAtt.setLotatt05(docQcDTO.getStatus());
-            String lotNumNew = IdWorker.getIdStr();
-            // 更新批次号
-            invLotAtt.setLotnum(lotNumNew);
-            // 插入一条批次信息
-            invLotAttService.insertInvLotAtt(invLotAtt);
+            // 构建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)){ // 没有相同批次的数据,就添加批次信息
+                BeanUtils.copyProperties(lotattDTO, invLotAtt);
+                // 更新批次号
+                invLotAtt.setLotnum(lotNumNew);
+                invLotAtt.setLotatt19(lotatt19);
+                invLotAtt.setCreateTime(DateUtils.getNowDate());
+                invLotAttService.insertInvLotAtt(invLotAtt);
+            }else {
+                lotNumNew = invLotAttSame.getLotnum();
+            }
             // 修改库存表对应的批次号
             invLotLocIdService.updateInvLotLocIdByLotNum(lotnum, lotNumNew);
             // 如果是不合格 生成搬运任务到不合格区
             if (StringUtils.equals(docQcDTO.getStatus(), Constant.QUALITY_STATUS.BHG.getValue())) {
-                createConveyTaskToBHGZone(updateBy, lotNumNew);
+                createConveyTaskToBHGZone(updateBy, lotNumNew, docQcDTO);
             }
         }
     }
@@ -79,7 +106,7 @@ public class PdaDocQcServiceImpl implements IPdaDocQcService {
      * @param updateBy
      * @param lotNumNew
      */
-    private void createConveyTaskToBHGZone(String updateBy, String lotNumNew) {
+    private void createConveyTaskToBHGZone(String updateBy, String lotNumNew, DocQcDTO docQcDTO) {
         List<InvLotLocId> invLotLocIdList = invLotLocIdService.selectInvLotLocIdByLotnum(lotNumNew);
         Assert.isTrue(CollUtil.isNotEmpty(invLotLocIdList), "未找到批号对应库存");
         int availableLocNumber = 0;
@@ -98,17 +125,59 @@ public class PdaDocQcServiceImpl implements IPdaDocQcService {
                     break;
                 }
             }
-            //没有可分配库位 后续不合格库存暂时不生成任务
+            //没有可分配库位
             if (locationInfo == null) {
                 throw new ServiceException("当前批次库存有" + invLotLocIdList.size() + "托,不合格区可用库位有"+availableLocNumber+"个");
             }
-            InvMoveDTO invMoveDTO = new InvMoveDTO(invLotLocId.getLocationId(), String.valueOf(locationInfo.getId()));
+            InvMoveDTO invMoveDTO = new InvMoveDTO(invLotLocId.getLocationId(), String.valueOf(locationInfo.getId()), docQcDTO.getUser());
             invLotLocIdService.move(invMoveDTO, updateBy);
         }
     }
 
     @Override
     public List<DocQcDTO> getQcList(String sku) {
-        return invLotAttService.getQcList(sku);
+        //1.查出所有状态为60的明细 List<Details>
+        List<BionutritionDocDetailsDTO> docDetailsDTOList = bionutritionDocDetailsService.getBionutritionDocDetailsDTOListByLineStatus(Constant.ASN_STS.STS60.getValue());
+        Assert.isTrue(CollUtil.isNotEmpty(docDetailsDTOList), "没有状态为上架的信息");
+        //2. 查出单据 List<Header>
+        List<String> headerIdList = docDetailsDTOList.stream().filter(item->StringUtils.isNotBlank(item.getDocHeaderId()))
+                .map(BionutritionDocDetailsDTO::getDocHeaderId).collect(Collectors.toList());
+        List<BionutritionDocHeaderDTO> docHeaderDTOList = bionutritionDocHeaderService.getBionutritionDocHeaderDTOList(headerIdList);
+        //3. 查出所有绑定这些单据的批次 List<Attr>
+        Assert.isTrue(CollUtil.isNotEmpty(docHeaderDTOList), "对应单头未找到");
+        //key: docId  value: docNo
+        Map<String, String> map = docHeaderDTOList.stream().collect(Collectors.toMap(BionutritionDocHeaderDTO::getId, BionutritionDocHeaderDTO::getDocNo));
+        List<InvLotAtt> invLotAttList = invLotAttService.selectInvLotAttListByHeaderIds(headerIdList);
+        //4. 根据查出来的批次list stream.map(Attr::getLotnum)... 根据这个list获取所有库存
+        Assert.isTrue(CollUtil.isNotEmpty(invLotAttList), " 对应批次未找到");
+        List<String> lotNumList = invLotAttList.stream().map(InvLotAtt::getLotnum).collect(Collectors.toList());
+        List<InvLotLocId> invLotLocIds = invLotLocIdService.selectInvLotLocIdByLotnumList(lotNumList);
+
+        //对每一个库存: 找到对应的批次 根据批次的lot10 找到对应的明细
+        List<String> lotNumListHasLoc = invLotLocIds.stream().map(InvLotLocId::getLotnum).distinct().collect(Collectors.toList());
+        // 所有状态为60的明细行号
+        List<String> lineNoList = docDetailsDTOList.stream().map(item -> item.getDocLineNo()).collect(Collectors.toList());
+        List<DocQcDTO> docQcDTOList = invLotAttList.stream().filter(item -> CollUtil.contains(lotNumListHasLoc, item.getLotnum()))
+                .filter(item -> CollUtil.contains(lineNoList, item.getLotatt10()))
+                .map(item -> {
+                    DocQcDTO docQcDTO = new DocQcDTO();
+                    docQcDTO.setBatchNumber(item.getLotatt02());
+                    docQcDTO.setSkuCode(item.getSku());
+                    docQcDTO.setDocNo(map.get(item.getLotatt09()));
+                    docQcDTO.setStatus(Constant.ASN_STS.STS60.getValue());
+                    return docQcDTO;
+                }).collect(Collectors.toList());
+//        invLotAttService.selectInvLotAttByLotnum()
+        // 5. 构建质检列表
+        /*List<DocQcDTO> docQcDTOList = docDetailsDTOList.stream().filter().map(item -> {
+            DocQcDTO docQcDTO = new DocQcDTO();
+            docQcDTO.setBatchNumber(item.getOriginalLotNumber());
+            docQcDTO.setSkuCode(item.getSkuCode());
+            docQcDTO.setDocNo(map.get(item.getDocHeaderId()));
+            docQcDTO.setStatus(Constant.ASN_STS.STS60.getValue());
+            return docQcDTO;
+        }).collect(Collectors.toList());invLotAttService.getQcList(sku)
+        */
+        return docQcDTOList;
     }
 }

+ 4 - 13
warewms-ams/src/main/java/com/ruoyi/ams/business/BusinessServiceImpl.java

@@ -170,7 +170,7 @@ public class BusinessServiceImpl implements IBusinessService {
                     List<BaseLocationInfo> locationToList = this.convertLocation(paramLocationTo, agvCallDTO.getWarehouseId(), null);
                     HashMap<String, String> hashMap = JSON.parseObject(JSON.toJSONString(agvCall.getLotattDTO()), HashMap.class);
                     List<BaseLocationInfo> locationFromList = baseLocationInfoMapper.selectSortedLocationLotattListByZoneIdListOrderBy(zoneIdList
-                            , agvCallDTO.getWarehouseId(), hashMap, agvCall.getSku(), "lotatt04 - DATEDIFF (NOW() ,att.lotatt03)  , lotatt07");
+                            , agvCallDTO.getWarehouseId(), hashMap, agvCall.getSku(), "lotatt04 , lotatt06");
                     locationFrom = this.zoneLocationAllocation(locationFromList, "locationFrom", "SO", asnSoStrategy, token);
                     locationTo = this.zoneLocationAllocation(locationToList, "locationTo", "SO", asnSoStrategy, token);
                     wcsTaskList.addAll(this.genTask(locationFrom, locationTo, flowConfigHeaderVO, agvCallDTO, token));
@@ -347,7 +347,7 @@ public class BusinessServiceImpl implements IBusinessService {
                     }
                     // 判断起始库位上的库存质检状态是否可以出库
                     boolean con = invLotLocIdService.verifyInventoryCanOutbound(b.getId().toString());
-                    if (!con) {
+                    if (con) {
                         continue;
                     }
                     locationInfo = b;
@@ -463,20 +463,11 @@ public class BusinessServiceImpl implements IBusinessService {
             wcsTask.setCreateDate(new Date());
             wcsTask.setBusinessType("01");
             wcsTask.setTaskType(Constant.TASK_TYPE.FORWARD.getValue());
+            wcsTask.setExt5(agvCallDTO.getDocNo()+","+agvCallDTO.getDocLineNo()+","+agvCallDTO.getBusinessType()+","+agvCallDTO.getDocType());
+            wcsTask.setCreateUser(agvCallDTO.getCreateUser());
             wcsTask.setExt8(token.toString());
             wcsTask.setExt7(flowConfigHeaderVO.getId().toString());
             wcsTask.setExt6(StringUtils.isNotEmpty(agvCallDTO.getToArea()) ? agvCallDTO.getToArea() : "");
-            // 三向车叉尺方向(货叉朝左1,朝右2,中位或其他0)
-            // 如果起始点是仓储区,左1,右2,我们系统A是靠马路也就是叉尺的右边
-            /*if (locationFrom.getZoneId() != null
-                    && Objects.equals(locationFrom.getZoneId(), Constant.ZONE_TYPE.STORAGE.getValue())) {
-                wcsTask.setExt4(locationFrom.getRowNo().equals("A") ? "2" : "1");
-            }
-            // 如果起始点是接驳位,默认给1
-            if (locationFrom.getZoneId() != null
-                    && Objects.equals(locationFrom.getZoneId(), Constant.ZONE_TYPE.TRANSIT.getValue())) {
-                wcsTask.setExt4("1");
-            }*/
             wcsTask.setExtParam(agvCallDTO.getExtParam());
             wcsTaskList.add(wcsTask);
             businessService.addTask(wcsTask);

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

@@ -15,6 +15,11 @@ public class AgvCallDTO {
     private String locationTo;
     private String palletNo;
     private String extParam;
+    private String docNo;
+    private String docLineNo;
+    private String businessType;
+    private String docType;
+    private String createUser;
     private Long warehouseId;
     private String toArea;// 目标区域(货物最终去掉区域)
     private List<AgvCallItemDTO> agvCallItemDTOList = new ArrayList<>();

+ 8 - 9
warewms-ams/src/main/java/com/ruoyi/ams/config/domain/dto/LotattDTO.java

@@ -1,6 +1,7 @@
 package com.ruoyi.ams.config.domain.dto;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.Data;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -8,6 +9,7 @@ import java.util.Map;
 /**
  * 批次属性业务
  */
+@Data
 public class LotattDTO {
 
     /**
@@ -15,7 +17,7 @@ public class LotattDTO {
      */
     private String lotatt01;
     /**
-     * 批号
+     * 批号: 所有批号匹配根据这个字段
      */
     private String lotatt02;
     /**
@@ -23,7 +25,7 @@ public class LotattDTO {
      */
     private String lotatt03;
     /**
-     * 有效期
+     * 有效期截止日 格式yyyy-mm-dd
      */
     private String lotatt04;
     /**
@@ -35,24 +37,21 @@ public class LotattDTO {
      */
     private String lotatt06;
     /**
-     * 规格型
+     * 进厂批
      */
     private String lotatt07;
     /**
-     * 收货日期
+     * 生产批号
      */
     private String lotatt08;
     /**
-     * 总净重
+     * 入库单头id
      */
     private String lotatt09;
     /**
-     * 总毛重
+     * 明细行号
      */
     private String lotatt10;
-    /**
-     * 总皮重
-     */
     private String lotatt11;
     private String lotatt12;
     private String lotatt13;

+ 186 - 157
warewms-ams/src/main/java/com/ruoyi/ams/inv/domain/InvLotAtt.java

@@ -7,316 +7,345 @@ import com.ruoyi.common.core.domain.BaseEntity;
 
 /**
  * 批次属性对象 inv_lot_att
- * 
+ *
  * @author andy
  * @date 2022-03-09
  */
-public class InvLotAtt extends BaseEntity
-{
+public class InvLotAtt extends BaseEntity {
     private static final long serialVersionUID = 1L;
 
-    /** 主键 */
+    /**
+     * 主键
+     */
     private String lotnum;
 
-    /** 货主代码 */
+    /**
+     * 货主代码
+     */
     @Excel(name = "货主代码")
     private String customerId;
 
-    /** 物料编码 */
+    /**
+     * 物料编码
+     */
     @Excel(name = "物料编码")
     private String sku;
 
-    /** $column.columnComment */
+    /**
+     * $column.columnComment
+     */
     @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
     private String lotatt01;
 
-    /** $column.columnComment */
+    /**
+     * $column.columnComment
+     */
     @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
     private String lotatt02;
 
-    /** $column.columnComment */
+    /**
+     * $column.columnComment
+     */
     @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
     private String lotatt03;
 
-    /** $column.columnComment */
+    /**
+     * $column.columnComment
+     */
     @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
     private String lotatt04;
 
-    /** $column.columnComment */
+    /**
+     * $column.columnComment
+     */
     @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
     private String lotatt05;
 
-    /** $column.columnComment */
+    /**
+     * $column.columnComment
+     */
     @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
     private String lotatt06;
 
-    /** $column.columnComment */
+    /**
+     * $column.columnComment
+     */
     @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
     private String lotatt07;
 
-    /** $column.columnComment */
+    /**
+     * $column.columnComment
+     */
     @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
     private String lotatt08;
 
-    /** $column.columnComment */
+    /**
+     * $column.columnComment
+     */
     @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
     private String lotatt09;
 
-    /** $column.columnComment */
+    /**
+     * $column.columnComment
+     */
     @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
     private String lotatt10;
 
-    /** $column.columnComment */
+    /**
+     * $column.columnComment
+     */
     @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
     private String lotatt11;
 
-    /** $column.columnComment */
+    /**
+     * $column.columnComment
+     */
     @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
     private String lotatt12;
 
-    /** $column.columnComment */
+    /**
+     * $column.columnComment
+     */
     @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
     private String lotatt13;
 
-    /** $column.columnComment */
+    /**
+     * $column.columnComment
+     */
     @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
     private String lotatt14;
 
-    /** $column.columnComment */
+    /**
+     * $column.columnComment
+     */
     @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
     private String lotatt15;
 
-    /** $column.columnComment */
+    /**
+     * $column.columnComment
+     */
     @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
     private String lotatt16;
 
-    /** $column.columnComment */
+    /**
+     * $column.columnComment
+     */
     @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
     private String lotatt17;
 
-    /** $column.columnComment */
+    /**
+     * $column.columnComment
+     */
     @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
     private String lotatt18;
 
-    public void setLotnum(String lotnum) 
-    {
+    /**
+     * $column.columnComment
+     */
+    @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+    private String lotatt19;
+
+    public String getLotnum() {
+        return lotnum;
+    }
+
+    public void setLotnum(String lotnum) {
         this.lotnum = lotnum;
     }
 
-    public String getLotnum() 
-    {
-        return lotnum;
+    public String getCustomerId() {
+        return customerId;
     }
-    public void setCustomerId(String customerId) 
-    {
+
+    public void setCustomerId(String customerId) {
         this.customerId = customerId;
     }
 
-    public String getCustomerId() 
-    {
-        return customerId;
+    public String getSku() {
+        return sku;
     }
-    public void setSku(String sku) 
-    {
+
+    public void setSku(String sku) {
         this.sku = sku;
     }
 
-    public String getSku() 
-    {
-        return sku;
+    public String getLotatt01() {
+        return lotatt01;
     }
-    public void setLotatt01(String lotatt01) 
-    {
+
+    public void setLotatt01(String lotatt01) {
         this.lotatt01 = lotatt01;
     }
 
-    public String getLotatt01() 
-    {
-        return lotatt01;
+    public String getLotatt02() {
+        return lotatt02;
     }
-    public void setLotatt02(String lotatt02) 
-    {
+
+    public void setLotatt02(String lotatt02) {
         this.lotatt02 = lotatt02;
     }
 
-    public String getLotatt02() 
-    {
-        return lotatt02;
+    public String getLotatt03() {
+        return lotatt03;
     }
-    public void setLotatt03(String lotatt03) 
-    {
+
+    public void setLotatt03(String lotatt03) {
         this.lotatt03 = lotatt03;
     }
 
-    public String getLotatt03() 
-    {
-        return lotatt03;
+    public String getLotatt04() {
+        return lotatt04;
     }
-    public void setLotatt04(String lotatt04) 
-    {
+
+    public void setLotatt04(String lotatt04) {
         this.lotatt04 = lotatt04;
     }
 
-    public String getLotatt04() 
-    {
-        return lotatt04;
+    public String getLotatt05() {
+        return lotatt05;
     }
-    public void setLotatt05(String lotatt05) 
-    {
+
+    public void setLotatt05(String lotatt05) {
         this.lotatt05 = lotatt05;
     }
 
-    public String getLotatt05() 
-    {
-        return lotatt05;
+    public String getLotatt06() {
+        return lotatt06;
     }
-    public void setLotatt06(String lotatt06) 
-    {
+
+    public void setLotatt06(String lotatt06) {
         this.lotatt06 = lotatt06;
     }
 
-    public String getLotatt06() 
-    {
-        return lotatt06;
+    public String getLotatt07() {
+        return lotatt07;
     }
-    public void setLotatt07(String lotatt07) 
-    {
+
+    public void setLotatt07(String lotatt07) {
         this.lotatt07 = lotatt07;
     }
 
-    public String getLotatt07() 
-    {
-        return lotatt07;
+    public String getLotatt08() {
+        return lotatt08;
     }
-    public void setLotatt08(String lotatt08) 
-    {
+
+    public void setLotatt08(String lotatt08) {
         this.lotatt08 = lotatt08;
     }
 
-    public String getLotatt08() 
-    {
-        return lotatt08;
+    public String getLotatt09() {
+        return lotatt09;
     }
-    public void setLotatt09(String lotatt09) 
-    {
+
+    public void setLotatt09(String lotatt09) {
         this.lotatt09 = lotatt09;
     }
 
-    public String getLotatt09() 
-    {
-        return lotatt09;
+    public String getLotatt10() {
+        return lotatt10;
     }
-    public void setLotatt10(String lotatt10) 
-    {
+
+    public void setLotatt10(String lotatt10) {
         this.lotatt10 = lotatt10;
     }
 
-    public String getLotatt10() 
-    {
-        return lotatt10;
+    public String getLotatt11() {
+        return lotatt11;
     }
-    public void setLotatt11(String lotatt11) 
-    {
+
+    public void setLotatt11(String lotatt11) {
         this.lotatt11 = lotatt11;
     }
 
-    public String getLotatt11() 
-    {
-        return lotatt11;
+    public String getLotatt12() {
+        return lotatt12;
     }
-    public void setLotatt12(String lotatt12) 
-    {
+
+    public void setLotatt12(String lotatt12) {
         this.lotatt12 = lotatt12;
     }
 
-    public String getLotatt12() 
-    {
-        return lotatt12;
+    public String getLotatt13() {
+        return lotatt13;
     }
-    public void setLotatt13(String lotatt13) 
-    {
+
+    public void setLotatt13(String lotatt13) {
         this.lotatt13 = lotatt13;
     }
 
-    public String getLotatt13() 
-    {
-        return lotatt13;
+    public String getLotatt14() {
+        return lotatt14;
     }
-    public void setLotatt14(String lotatt14) 
-    {
+
+    public void setLotatt14(String lotatt14) {
         this.lotatt14 = lotatt14;
     }
 
-    public String getLotatt14() 
-    {
-        return lotatt14;
+    public String getLotatt15() {
+        return lotatt15;
     }
-    public void setLotatt15(String lotatt15) 
-    {
+
+    public void setLotatt15(String lotatt15) {
         this.lotatt15 = lotatt15;
     }
 
-    public String getLotatt15() 
-    {
-        return lotatt15;
+    public String getLotatt16() {
+        return lotatt16;
     }
-    public void setLotatt16(String lotatt16) 
-    {
+
+    public void setLotatt16(String lotatt16) {
         this.lotatt16 = lotatt16;
     }
 
-    public String getLotatt16() 
-    {
-        return lotatt16;
+    public String getLotatt17() {
+        return lotatt17;
     }
-    public void setLotatt17(String lotatt17) 
-    {
+
+    public void setLotatt17(String lotatt17) {
         this.lotatt17 = lotatt17;
     }
 
-    public String getLotatt17() 
-    {
-        return lotatt17;
+    public String getLotatt18() {
+        return lotatt18;
     }
-    public void setLotatt18(String lotatt18) 
-    {
+
+    public void setLotatt18(String lotatt18) {
         this.lotatt18 = lotatt18;
     }
 
-    public String getLotatt18() 
-    {
-        return lotatt18;
+    public String getLotatt19() {
+        return lotatt19;
+    }
+
+    public void setLotatt19(String lotatt19) {
+        this.lotatt19 = lotatt19;
     }
 
     @Override
     public String toString() {
-        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
-            .append("lotnum", getLotnum())
-            .append("customerId", getCustomerId())
-            .append("sku", getSku())
-            .append("lotatt01", getLotatt01())
-            .append("lotatt02", getLotatt02())
-            .append("lotatt03", getLotatt03())
-            .append("lotatt04", getLotatt04())
-            .append("lotatt05", getLotatt05())
-            .append("lotatt06", getLotatt06())
-            .append("lotatt07", getLotatt07())
-            .append("lotatt08", getLotatt08())
-            .append("lotatt09", getLotatt09())
-            .append("lotatt10", getLotatt10())
-            .append("lotatt11", getLotatt11())
-            .append("lotatt12", getLotatt12())
-            .append("lotatt13", getLotatt13())
-            .append("lotatt14", getLotatt14())
-            .append("lotatt15", getLotatt15())
-            .append("lotatt16", getLotatt16())
-            .append("lotatt17", getLotatt17())
-            .append("lotatt18", getLotatt18())
-            .append("createBy", getCreateBy())
-            .append("createTime", getCreateTime())
-            .append("updateBy", getUpdateBy())
-            .append("updateTime", getUpdateTime())
-            .append("remark", getRemark())
-            .toString();
+        return "InvLotAtt{" +
+                "lotnum='" + lotnum + '\'' +
+                ", customerId='" + customerId + '\'' +
+                ", sku='" + sku + '\'' +
+                ", lotatt01='" + lotatt01 + '\'' +
+                ", lotatt02='" + lotatt02 + '\'' +
+                ", lotatt03='" + lotatt03 + '\'' +
+                ", lotatt04='" + lotatt04 + '\'' +
+                ", lotatt05='" + lotatt05 + '\'' +
+                ", lotatt06='" + lotatt06 + '\'' +
+                ", lotatt07='" + lotatt07 + '\'' +
+                ", lotatt08='" + lotatt08 + '\'' +
+                ", lotatt09='" + lotatt09 + '\'' +
+                ", lotatt10='" + lotatt10 + '\'' +
+                ", lotatt11='" + lotatt11 + '\'' +
+                ", lotatt12='" + lotatt12 + '\'' +
+                ", lotatt13='" + lotatt13 + '\'' +
+                ", lotatt14='" + lotatt14 + '\'' +
+                ", lotatt15='" + lotatt15 + '\'' +
+                ", lotatt16='" + lotatt16 + '\'' +
+                ", lotatt17='" + lotatt17 + '\'' +
+                ", lotatt18='" + lotatt18 + '\'' +
+                ", lotatt19='" + lotatt19 + '\'' +
+                '}';
     }
 }

+ 2 - 0
warewms-ams/src/main/java/com/ruoyi/ams/inv/dto/InvMoveDTO.java

@@ -22,4 +22,6 @@ public class InvMoveDTO implements Serializable {
      * 目标点
      */
     private String targetLocationId;
+
+    private String user;
 }

+ 4 - 0
warewms-ams/src/main/java/com/ruoyi/ams/inv/mapper/InvLotAttMapper.java

@@ -78,4 +78,8 @@ public interface InvLotAttMapper {
     List<InvLotAtt> selectInvLotAttBySkuAndBatchNumber(@Param("sku") String sku, @Param("batchNumber") String batchNumber);
 
     List<DocQcDTO> getQcList(@Param("sku") String sku);
+
+    InvLotAtt selectInvLotAttByLotatt19(String lotatt19);
+
+    List<InvLotAtt> selectInvLotAttListByHeaderIds(List<String> headerIds);
 }

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

@@ -322,4 +322,8 @@ public interface InvLotLocIdMapper {
      * @return
      */
     int updateInvLotLocIdByLotNum(@Param("lotnum")String lotnum, @Param("lotNumNew")String lotNumNew);
+
+    InvLotLocId selectInvLotLocIdByTraceIdAndLocationId(@Param("locationTo")String locationTo, @Param("taskNo")String taskNo);
+
+    List<InvLotLocId> selectInvLotLocIdByLotnumList(List<String> lotNumList);
 }

+ 9 - 0
warewms-ams/src/main/java/com/ruoyi/ams/inv/service/IInvLotAttService.java

@@ -88,4 +88,13 @@ public interface IInvLotAttService {
      * @return
      */
     List<DocQcDTO> getQcList(String sku);
+
+    /**
+     * 根据lotatt19获取批次信息
+     * @param lotatt19
+     * @return
+     */
+    InvLotAtt selectInvLotAttByLotatt19(String lotatt19);
+
+    List<InvLotAtt> selectInvLotAttListByHeaderIds(List<String> headerIds);
 }

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

@@ -34,6 +34,14 @@ public interface IInvLotLocIdService {
      */
     List<InvLotLocId> selectInvLotLocIdByLotnum(String lotnum);
 
+    /**
+     * 查询库位库存信息
+     *
+     * @param lotNumList 批次号列表
+     * @return 库位库存信息
+     */
+    List<InvLotLocId> selectInvLotLocIdByLotnumList(List<String> lotNumList);
+
     /**
      * 根据主键查询
      *
@@ -184,6 +192,12 @@ public interface IInvLotLocIdService {
      */
     String initInv(String locationId, AgvCallDTO agvCallDTO);
 
+    /**
+     * 构建lotatt19属性
+     * @param lotattDTO
+     * @return
+     */
+    String buildLotatt19(LotattDTO lotattDTO);
     /**
      * 根据库位id查询库位库存包含批次属性
      *
@@ -291,4 +305,12 @@ public interface IInvLotLocIdService {
      * @return
      */
     String getInvLocIfExpire();
+
+    /**
+     * 根据任务号和库位id查询库存
+     * @param locationTo
+     * @param taskNo
+     * @return
+     */
+    InvLotLocId selectInvLotLocIdByTraceIdAndLocationId(String locationTo, String taskNo);
 }

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

@@ -112,4 +112,15 @@ public class InvLotAttServiceImpl implements IInvLotAttService {
     public List<DocQcDTO> getQcList(String sku) {
         return invLotAttMapper.getQcList(sku);
     }
+
+    @Override
+    public InvLotAtt selectInvLotAttByLotatt19(String lotatt19) {
+        return invLotAttMapper.selectInvLotAttByLotatt19(lotatt19);
+    }
+
+    @Override
+    public List<InvLotAtt> selectInvLotAttListByHeaderIds(List<String> headerIds) {
+        return invLotAttMapper.selectInvLotAttListByHeaderIds(headerIds);
+    }
+
 }

+ 60 - 27
warewms-ams/src/main/java/com/ruoyi/ams/inv/service/impl/InvLotLocIdServiceImpl.java

@@ -5,6 +5,7 @@ import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUnit;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.ruoyi.ams.box.domain.WmsBoxInfo;
 import com.ruoyi.ams.box.service.IWmsBoxInfoService;
@@ -36,14 +37,12 @@ import com.ruoyi.common.utils.StringUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.Objects;
+import java.util.*;
 import java.util.stream.Collector;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -86,6 +85,11 @@ public class InvLotLocIdServiceImpl implements IInvLotLocIdService {
         return invLotLocIdMapper.selectInvLotLocIdByLotnum(lotnum);
     }
 
+    @Override
+    public List<InvLotLocId> selectInvLotLocIdByLotnumList(List<String> lotNumList) {
+        return invLotLocIdMapper.selectInvLotLocIdByLotnumList(lotNumList);
+    }
+
     @Override
     public InvLotLocId selectInvLotLocIdById(String locationId, String customerId, String sku, String lotnum) {
         InvLotLocId invLotLocId = new InvLotLocId();
@@ -127,37 +131,35 @@ public class InvLotLocIdServiceImpl implements IInvLotLocIdService {
 
     @Override
     public List<InvLotLocIdLotattVO> selectInvLocIdLotattList(InvLocIdSearchFrom invLocIdSearchFrom) {
-        List<InvLotLocIdLotattVO> invLotLocIdLotattVOS = invLotLocIdMapper.selectInvLocIdLotattList(invLocIdSearchFrom);
-        // 检查更新库位过期状态
-        return refreshExpireStatus(invLotLocIdLotattVOS);
+        return invLotLocIdMapper.selectInvLocIdLotattList(invLocIdSearchFrom);
     }
 
     /**
-     * 更新库存过期状态
-     *
-     * @param invLotLocIdLotattVOS
+     * 定时更新库存过期状态
      */
-    private List<InvLotLocIdLotattVO> refreshExpireStatus(List<InvLotLocIdLotattVO> invLotLocIdLotattVOS) {
-        List<InvLotLocIdLotattVO> lotLocIdLotattVOS = invLotLocIdLotattVOS.stream().map(item -> {
-            Long shelfLife = Long.valueOf(item.getLotatt04());// 有效期
-            DateTime manufactureDate = DateUtil.parse(item.getLotatt03());// 生产日期
+    @Scheduled(cron = "0 0 0 * * ?")
+    private void refreshExpireStatus() {
+        List<InvLotLocIdLotattVO> invLotLocIdLotattVOS = invLotLocIdMapper.selectInvLocIdLotattList(new InvLocIdSearchFrom());
+        String msg = null;
+        invLotLocIdLotattVOS.stream().forEach(item -> {
+            log.info("库位{}上的库存过期状态为{}", item.getLocationId(), item.getIsExpire());
+            DateTime shelfLife = DateUtil.parse(item.getLotatt04());// 有效期截止日 格式给为yyyy-mm-dd
             DateTime now = DateUtil.date();
-            // 剩余有效期
-            Long validityDay = shelfLife - DateUtil.between(now, manufactureDate, DateUnit.DAY);
+            long validityDay = DateUtil.between(now, shelfLife, DateUnit.DAY,false);
             // 有效期大于30天
             if (validityDay > 30) {
                 item.setIsExpire(Constant.EXPIRE_STATUS.UNEXPIRED.getValue());
-            } else if (validityDay < 30 && validityDay > 0) { // 有效期在30天以内
+            } else if (validityDay < 30 && validityDay > 1) { // 有效期在30天以内
                 item.setIsExpire(Constant.EXPIRE_STATUS.WITHIN_THIRTY_DAYS.getValue());
             } else { // 已过期
                 item.setIsExpire(Constant.EXPIRE_STATUS.EXPIRED.getValue());
             }
             InvLotLocId invLotLocId = new InvLotLocId();
+            invLotLocId.setLocationId(String.valueOf(item.getLocationId()));
             BeanUtils.copyProperties(item, invLotLocId);
             invLotLocIdMapper.updateInvLotLocId(invLotLocId);
-            return item;
-        }).collect(Collectors.toList());
-        return lotLocIdLotattVOS;
+            log.info("修改库位{}上的库存过期状态为{}", item.getLocationId(), item.getIsExpire());
+        });
     }
 
     /**
@@ -277,7 +279,9 @@ public class InvLotLocIdServiceImpl implements IInvLotLocIdService {
         wcsTask.setState(9L);
         wcsTask.setPriority(1L);
         wcsTask.setShopId(Constant.WAREHOUSE_ID.toString());
+
         wcsTask.setCreateDate(new Date());
+        wcsTask.setCreateUser(invMoveDTO.getUser());
         wcsTask.setBusinessType("01");
         // 设置为移库任务类型
         wcsTask.setTaskType(Constant.TASK_TYPE.MV.getValue());
@@ -549,12 +553,20 @@ public class InvLotLocIdServiceImpl implements IInvLotLocIdService {
             String lotnum = IdWorker.getIdStr();
             LotattDTO lotattDTO = agvCallItemDTO.getLotattDTO();
             InvLotAtt invLotAtt = new InvLotAtt();
-            BeanUtils.copyProperties(lotattDTO, invLotAtt);
-            invLotAtt.setCustomerId(customerId);
-            invLotAtt.setSku(sku);
-            invLotAtt.setLotnum(lotnum);
-            invLotAtt.setCreateTime(DateUtils.getNowDate());
-            invLotAttMapper.insertInvLotAtt(invLotAtt);
+            // 判断是否存在相同批次的数据
+            String lotatt19 = this.buildLotatt19(lotattDTO);
+            InvLotAtt invLotAttSame = invLotAttMapper.selectInvLotAttByLotatt19(lotatt19);
+            if (ObjectUtil.isEmpty(invLotAttSame)){ // 没有相同批次的数据,就添加批次信息;否则只添加库存
+                BeanUtils.copyProperties(lotattDTO, invLotAtt);
+                invLotAtt.setCustomerId(customerId);
+                invLotAtt.setSku(sku);
+                invLotAtt.setLotnum(lotnum);
+                invLotAtt.setLotatt19(lotatt19);
+                invLotAtt.setCreateTime(DateUtils.getNowDate());
+                invLotAttMapper.insertInvLotAtt(invLotAtt);
+            }else {
+                lotnum = invLotAttSame.getLotnum();
+            }
             // 库存表
             InvLotLocId invLotLocId = new InvLotLocId();
             invLotLocId.setLotnum(lotnum);
@@ -578,6 +590,18 @@ public class InvLotLocIdServiceImpl implements IInvLotLocIdService {
         return "";
     }
 
+    /**
+     * 构建lotatt19
+     * @param lotattDTO
+     */
+    public String buildLotatt19(LotattDTO lotattDTO) {
+        // 拼接lotatt01-lotatt18批次属性,存在相同的批次数据,就不添加
+        Map<String, Object> lotattMap = BeanUtil.beanToMap(lotattDTO);
+        Collection<Object> values = lotattMap.values();
+        String lotatt19 = values.stream().map(String::valueOf).collect(Collectors.joining(","));
+        return lotatt19;
+    }
+
     @Override
     public List<InvLotLocIdLotattVO> selectInvLocIdLotattByLocationId(Long locationId) {
         return invLotLocIdMapper.selectInvLocIdLotattByLocationId(locationId);
@@ -728,7 +752,11 @@ public class InvLotLocIdServiceImpl implements IInvLotLocIdService {
         InvLocIdSearchFrom invLocIdSearchFrom = new InvLocIdSearchFrom();
         invLocIdSearchFrom.setLocationNo(locationNo);
         List<InvLotLocIdLotattVO> lotattVOList = selectInvLocIdLotattList(invLocIdSearchFrom);
-        return lotattVOList.stream().allMatch(v -> !v.getLotatt05().equals("DJ"));
+        // 过滤掉已经过期的
+        lotattVOList = lotattVOList.stream().filter(
+                item->!StringUtils.equals(item.getIsExpire(), Constant.EXPIRE_STATUS.EXPIRED.getValue()))
+                .collect(Collectors.toList());
+        return lotattVOList.stream().allMatch(v -> !v.getLotatt05().equals("FX"));// 是否所有库存都不是放行状态
     }
 
     @Override
@@ -748,4 +776,9 @@ public class InvLotLocIdServiceImpl implements IInvLotLocIdService {
         List<InvLotLocIdLotattVO> invLotLocIdLotattVOS = invLotLocIdMapper.selectInvLocIdLotattList(invLocIdSearchFrom);
         return invLotLocIdLotattVOS.size() > 0 ? "存在即将过期的库存" : StringUtils.EMPTY;
     }
+
+    @Override
+    public InvLotLocId selectInvLotLocIdByTraceIdAndLocationId(String locationTo, String taskNo) {
+        return invLotLocIdMapper.selectInvLotLocIdByTraceIdAndLocationId(locationTo, taskNo);
+    }
 }

+ 17 - 0
warewms-ams/src/main/java/com/ruoyi/ams/task/dto/WcsTaskInvLotDTO.java

@@ -0,0 +1,17 @@
+package com.ruoyi.ams.task.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+@Data
+public class WcsTaskInvLotDTO implements Serializable {
+
+    private String taskNo;
+    private String qty;
+    private String locationFrom;
+    private String locationTo;
+    private String state;
+    private String ext5;
+}

+ 10 - 7
warewms-ams/src/main/java/com/ruoyi/ams/task/mapper/WcsTaskMapper.java

@@ -2,6 +2,7 @@ package com.ruoyi.ams.task.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.ruoyi.ams.task.domain.WcsTask;
+import com.ruoyi.ams.task.dto.WcsTaskInvLotDTO;
 import com.ruoyi.ams.task.dto.WcsTaskLocationDTO;
 import org.apache.ibatis.annotations.Param;
 
@@ -9,7 +10,7 @@ import java.util.List;
 
 /**
  * AGV任务Mapper接口
- * 
+ *
  * @author andy
  * @date 2022-03-10
  */
@@ -17,7 +18,7 @@ public interface WcsTaskMapper extends BaseMapper<WcsTask>
 {
     /**
      * 查询AGV任务
-     * 
+     *
      * @param taskNo AGV任务主键
      * @return AGV任务
      */
@@ -25,7 +26,7 @@ public interface WcsTaskMapper extends BaseMapper<WcsTask>
 
     /**
      * 查询AGV任务列表
-     * 
+     *
      * @param wcsTask AGV任务
      * @return AGV任务集合
      */
@@ -40,7 +41,7 @@ public interface WcsTaskMapper extends BaseMapper<WcsTask>
 
     /**
      * 新增AGV任务
-     * 
+     *
      * @param wcsTask AGV任务
      * @return 结果
      */
@@ -48,7 +49,7 @@ public interface WcsTaskMapper extends BaseMapper<WcsTask>
 
     /**
      * 修改AGV任务
-     * 
+     *
      * @param wcsTask AGV任务
      * @return 结果
      */
@@ -56,7 +57,7 @@ public interface WcsTaskMapper extends BaseMapper<WcsTask>
 
     /**
      * 删除AGV任务
-     * 
+     *
      * @param taskNo AGV任务主键
      * @return 结果
      */
@@ -64,7 +65,7 @@ public interface WcsTaskMapper extends BaseMapper<WcsTask>
 
     /**
      * 批量删除AGV任务
-     * 
+     *
      * @param taskNos 需要删除的数据主键集合
      * @return 结果
      */
@@ -109,4 +110,6 @@ public interface WcsTaskMapper extends BaseMapper<WcsTask>
      * @return
      */
      List<WcsTask> selectBeforeTask(@Param("taskNo") String taskNo);
+
+     List<WcsTaskInvLotDTO> selectWcsTaskListByExt5(String ext5);
 }

+ 8 - 0
warewms-ams/src/main/java/com/ruoyi/ams/task/service/IWcsTaskService.java

@@ -5,6 +5,7 @@ import java.util.List;
 import com.ruoyi.ams.agv.ndc.entity.CallbackResult;
 import com.ruoyi.ams.bionutrition.dto.OrderAgvCallDTO;
 import com.ruoyi.ams.task.domain.WcsTask;
+import com.ruoyi.ams.task.dto.WcsTaskInvLotDTO;
 import com.ruoyi.ams.task.dto.WcsTaskLocationDTO;
 import com.ruoyi.common.core.domain.AjaxResult;
 
@@ -183,4 +184,11 @@ public interface IWcsTaskService {
      * @return
      */
     AjaxResult createOutboundTaskByDoc(OrderAgvCallDTO orderAgvCallDTO);
+
+    /**
+     * 根据ext5查询未取消的任务
+     * @param ext5
+     * @return
+     */
+    List<WcsTaskInvLotDTO> selectWcsTaskListByExt5(String ext5);
 }

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

@@ -1,11 +1,14 @@
 package com.ruoyi.ams.task.service.impl;
 
 import java.lang.reflect.Method;
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
 
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.NumberUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.json.JSON;
 import cn.hutool.json.JSONObject;
@@ -14,9 +17,13 @@ import com.ruoyi.ams.agv.ndc.domain.AmsTask;
 import com.ruoyi.ams.agv.ndc.entity.CallbackResult;
 import com.ruoyi.ams.agv.ndc.service.IAmsTaskService;
 import com.ruoyi.ams.bionutrition.doc.dto.BionutritionDocBaseDTO;
+import com.ruoyi.ams.bionutrition.doc.dto.BionutritionDocDetailsDTO;
 import com.ruoyi.ams.bionutrition.doc.dto.detail.BionutritionDocDetailsBaseDTO;
+import com.ruoyi.ams.bionutrition.doc.dto.header.BionutritionDocHeaderBaseDTO;
+import com.ruoyi.ams.bionutrition.doc.service.BionutritionDocDetailsService;
 import com.ruoyi.ams.bionutrition.doc.service.BionutritionDocHeaderService;
 import com.ruoyi.ams.bionutrition.dto.OrderAgvCallDTO;
+import com.ruoyi.ams.bionutrition.pda.IPdaAgvCallService;
 import com.ruoyi.ams.box.service.IWmsBoxInfoService;
 import com.ruoyi.ams.business.IBusinessService;
 import com.ruoyi.ams.config.domain.FlowConfigEvent;
@@ -29,6 +36,7 @@ import com.ruoyi.ams.inv.domain.InvLotLocId;
 import com.ruoyi.ams.inv.mapper.InvLotLocIdMapper;
 import com.ruoyi.ams.inv.service.IInvLotAttService;
 import com.ruoyi.ams.inv.service.IInvLotLocIdService;
+import com.ruoyi.ams.task.dto.WcsTaskInvLotDTO;
 import com.ruoyi.ams.task.dto.WcsTaskLocationDTO;
 import com.ruoyi.base.constant.Constant;
 import com.ruoyi.base.domain.BaseLocationInfo;
@@ -38,6 +46,7 @@ import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.domain.BaseEntity;
 import com.ruoyi.common.core.redis.RedisCache;
 import com.ruoyi.common.exception.base.BaseException;
+import com.ruoyi.common.utils.ConvertUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.spring.SpringUtils;
 import com.ruoyi.common.utils.uuid.SnowflakeIdWorker;
@@ -83,9 +92,10 @@ public class WcsTaskServiceImpl implements IWcsTaskService {
     private IAmsTaskService iAmsTaskService;
     @Autowired
     private AutoDoorClient autoDoorClient;
-
     @Autowired
     private BionutritionDocHeaderService bionutritionDocHeaderService;
+    @Autowired
+    private IPdaAgvCallService pdaAgvCallService;
 
     private List<String> outboundDocTypeList  = Arrays.asList("SaleOutboundOrder","ProductionPickingReceipt");
 
@@ -95,6 +105,9 @@ public class WcsTaskServiceImpl implements IWcsTaskService {
     @Autowired
     private IBusinessService iBusinessService;
 
+    @Autowired
+    private BionutritionDocDetailsService bionutritionDocDetailsService;
+
     //任务状态翻译
     private String codeConvert(int code) {
         switch (code) {
@@ -397,127 +410,118 @@ public class WcsTaskServiceImpl implements IWcsTaskService {
             log.info("已取消的任务无需重复取消");
             return AjaxResult.error("已取消的任务无需重复取消");
         }
-        //转发类型任务才回调
-        if (wcsTask.getTaskType().equals(Constant.TASK_TYPE.FORWARD.getValue())) {
-            try {
-                switch (state) {
-                    case 1:
-                        wcsTask.setStartTime(new Date());
-                        break;
-                    case 2://完成
-                        if (wcsTask.getState() != 4
-                                && (StringUtils.isEmpty(wcsTask.getBeforeTask()) || !wcsTask.getBeforeTask().equals("1"))) {
-                            log.info("任务未取货,不能直接完成!" + taskNo);
-                            return AjaxResult.error("任务未取货,不能直接完成!" + taskNo);
-                        }
-                        if (wcsTask.getState() == 2) {
-                            log.info("不能重复放货," + taskNo);
-                            return AjaxResult.error("不能重复放货," + taskNo);
-                        }
-                        if (wcsTask.getState() == 6) {
-                            // 修改任务状态
-                            wcsTask.setState(state.longValue());
-                            wcsTask.setUpdateDate(new Date());
-                            wcsTaskService.updateWcsTask(wcsTask);
-                            return AjaxResult.error("不能重复放货," + taskNo);
-                        }
-                        wcsTask.setEndTime(new Date());
+
+        try {
+            switch (state) {
+                case 1:
+                    wcsTask.setStartTime(new Date());
+                    break;
+                case 2://完成
+                    if (wcsTask.getState() != 4
+                            && (StringUtils.isEmpty(wcsTask.getBeforeTask()) || !wcsTask.getBeforeTask().equals("1"))) {
+                        log.info("任务未取货,不能直接完成!" + taskNo);
+                        return AjaxResult.error("任务未取货,不能直接完成!" + taskNo);
+                    }
+                    if (wcsTask.getState() == 2) {
+                        log.info("不能重复放货," + taskNo);
+                        return AjaxResult.error("不能重复放货," + taskNo);
+                    }
+                    wcsTask.setEndTime(new Date());
+                    // 解锁终点库位
+                    baseLocationInfoService.unLockLocationStockStatus(Long.parseLong(wcsTask.getLocationTo())
+                            , Constant.WAREHOUSE_ID, updateBy);
+                    // 将中间缓存位库存移动到终点
+                    moveMiddleCacheToDestination(wcsTask);
+                    //释放redis锁
+                    if (!StringUtils.isEmpty(wcsTask.getExt8())) {
+                        redisCache.unlockCacheObject(Long.parseLong(wcsTask.getExt8()));
+                    }
+                    break;
+                case 3:
+                    break;
+                case 4:
+                    if (wcsTask.getState() == 4) {
+                        log.info("不能重复取货," + taskNo);
+                        return AjaxResult.error("不能重复取货," + taskNo);
+                    }
+                    if (wcsTask.getBeforeTask() != null && wcsTask.getBeforeTask().equals("1")) {
+                        log.info("不能重复取货," + taskNo);
+                        return AjaxResult.error("不能重复取货," + taskNo);
+                    }
+                    // 标记已经取货完成
+                    wcsTask.setBeforeTask("1");
+                    // 解锁起始库位
+                    baseLocationInfoService.unLockLocationStockStatus(Long.parseLong(wcsTask.getLocationFrom())
+                            , Constant.WAREHOUSE_ID, updateBy);
+                    // 将起始点库存移动到中间缓存位
+                    moveStartingPointToMiddleCache(wcsTask);
+
+                    //释放redis锁
+                    if (!StringUtils.isEmpty(wcsTask.getExt8())) {
+                        redisCache.unlockCacheObject(Long.parseLong(wcsTask.getExt8()), wcsTask.getLocationFrom());
+                    }
+                    break;
+                case 5:
+                    break;
+                case 6://卸货
+                    if (wcsTask.getState() != 4
+                            && (StringUtils.isEmpty(wcsTask.getBeforeTask())|| !wcsTask.getBeforeTask().equals("1"))) {
+                        log.info("任务未取货,不能直接完成!" + taskNo);
+                        return AjaxResult.error("任务未取货,不能直接完成!" + taskNo);
+                    }
+                    if (wcsTask.getState() == 2) {
+                        log.info("不能重复放货," + taskNo);
+                        return AjaxResult.error("不能重复放货," + taskNo);
+                    }
+                    if (wcsTask.getState() == 6) {
+                        return AjaxResult.error("不能重复放货," + taskNo);
+                    }
+                    wcsTask.setEndTime(new Date());
+                    // 解锁终点库位
+                    baseLocationInfoService.unLockLocationStockStatus(Long.parseLong(wcsTask.getLocationTo())
+                            , Constant.WAREHOUSE_ID, updateBy);
+                    // 将中间缓存位库存移动到终点
+                    moveMiddleCacheToDestination(wcsTask);
+                    // 修改单据状态
+                    bionutritionDocHeaderService.updateDocStatus(wcsTask);
+                    //释放redis锁
+                    if (!StringUtils.isEmpty(wcsTask.getExt8())) {
+                        redisCache.unlockCacheObject(Long.parseLong(wcsTask.getExt8()));
+                    }
+                    break;
+                case 7://取消
+                    wcsTask.setEndTime(new Date());
+                    //如果取到货就只解锁终点库位
+                    if (wcsTask.getState() == 4 || wcsTask.getState() == 5) {
                         // 解锁终点库位
                         baseLocationInfoService.unLockLocationStockStatus(Long.parseLong(wcsTask.getLocationTo())
                                 , Constant.WAREHOUSE_ID, updateBy);
-                        // 将中间缓存位库存移动到终点
-                        moveMiddleCacheToDestination(wcsTask);
-                        //释放redis锁
-                        if (!StringUtils.isEmpty(wcsTask.getExt8())) {
-                            redisCache.unlockCacheObject(Long.parseLong(wcsTask.getExt8()));
-                        }
-                        break;
-                    case 3:
-                        break;
-                    case 4:
-                        if (wcsTask.getState() == 4) {
-                            log.info("不能重复取货," + taskNo);
-                            return AjaxResult.error("不能重复取货," + taskNo);
-                        }
-                        if (wcsTask.getBeforeTask() != null && wcsTask.getBeforeTask().equals("1")) {
-                            log.info("不能重复取货," + taskNo);
-                            return AjaxResult.error("不能重复取货," + taskNo);
-                        }
-                        // 标记已经取货完成
-                        wcsTask.setBeforeTask("1");
-                        // 解锁起始库位
-                        baseLocationInfoService.unLockLocationStockStatus(Long.parseLong(wcsTask.getLocationFrom())
-                                , Constant.WAREHOUSE_ID, updateBy);
-                        // 将起始点库存移动到中间缓存位
-                        moveStartingPointToMiddleCache(wcsTask);
-
-                        //释放redis锁
-                        if (!StringUtils.isEmpty(wcsTask.getExt8())) {
-                            redisCache.unlockCacheObject(Long.parseLong(wcsTask.getExt8()), wcsTask.getLocationFrom());
-                        }
-                        break;
-                    case 5:
-                        break;
-                    case 6://卸货
-                        if (wcsTask.getState() != 4
-                                && (StringUtils.isEmpty(wcsTask.getBeforeTask())|| !wcsTask.getBeforeTask().equals("1"))) {
-                            log.info("任务未取货,不能直接完成!" + taskNo);
-                            return AjaxResult.error("任务未取货,不能直接完成!" + taskNo);
-                        }
-                        if (wcsTask.getState() == 2) {
-                            log.info("不能重复放货," + taskNo);
-                            return AjaxResult.error("不能重复放货," + taskNo);
-                        }
-                        if (wcsTask.getState() == 6) {
-                            return AjaxResult.error("不能重复放货," + taskNo);
-                        }
-                        wcsTask.setEndTime(new Date());
-                        // 解锁终点库位
-                        baseLocationInfoService.unLockLocationStockStatus(Long.parseLong(wcsTask.getLocationTo())
+                    } else {
+                        // 解锁终点和起始库位
+                        baseLocationInfoService.unLockLocationStockStatus(Long.parseLong(wcsTask.getLocationFrom()), Long.parseLong(wcsTask.getLocationTo())
                                 , Constant.WAREHOUSE_ID, updateBy);
-                        // 将中间缓存位库存移动到终点
-                        moveMiddleCacheToDestination(wcsTask);
-                        //释放redis锁
-                        if (!StringUtils.isEmpty(wcsTask.getExt8())) {
-                            redisCache.unlockCacheObject(Long.parseLong(wcsTask.getExt8()));
-                        }
-                        break;
-                    case 7://取消
-                        wcsTask.setEndTime(new Date());
-                        //如果取到货就只解锁终点库位
-                        if (wcsTask.getState() == 4 || wcsTask.getState() == 5) {
-                            // 解锁终点库位
-                            baseLocationInfoService.unLockLocationStockStatus(Long.parseLong(wcsTask.getLocationTo())
-                                    , Constant.WAREHOUSE_ID, updateBy);
-                        } else {
-                            // 解锁终点和起始库位
-                            baseLocationInfoService.unLockLocationStockStatus(Long.parseLong(wcsTask.getLocationFrom()), Long.parseLong(wcsTask.getLocationTo())
-                                    , Constant.WAREHOUSE_ID, updateBy);
-                        }
-                        //释放redis锁
-                        if (!StringUtils.isEmpty(wcsTask.getExt8())) {
-                            redisCache.unlockCacheObject(Long.parseLong(wcsTask.getExt8()));
-                        }
-                        // 取消任务删除中间缓存库存
-//                        cancelTaskDelMiddleCache(wcsTask);
-                        break;
-                    case 8:
-                        log.error("任务异常状态------------" + wcsTask.getTaskNo());
-                        break;
-                    default:
-                        break;
-                }
-            } catch (Exception e) {
-                log.info(wcsTask.getTaskNo() + "-----" + "回调状态:" + state + "异常", e);
-                wcsTask.setRemark("回调状态:" + state + "异常");
-                //释放redis锁
-                if (!StringUtils.isEmpty(wcsTask.getExt8())) {
-                    redisCache.unlockCacheObject(Long.parseLong(wcsTask.getExt8()));
-                }
-                throw new RuntimeException();
+                    }
+                    //释放redis锁
+                    if (!StringUtils.isEmpty(wcsTask.getExt8())) {
+                        redisCache.unlockCacheObject(Long.parseLong(wcsTask.getExt8()));
+                    }
+                    // 取消任务删除中间缓存库存
+//                    cancelTaskDelMiddleCache(wcsTask);
+                    break;
+                case 8:
+                    log.error("任务异常状态------------" + wcsTask.getTaskNo());
+                    break;
+                default:
+                    break;
             }
-        } else {
-
+        } catch (Exception e) {
+            log.info(wcsTask.getTaskNo() + "-----" + "回调状态:" + state + "异常", e);
+            wcsTask.setRemark("回调状态:" + state + "异常");
+            //释放redis锁
+            if (!StringUtils.isEmpty(wcsTask.getExt8())) {
+                redisCache.unlockCacheObject(Long.parseLong(wcsTask.getExt8()));
+            }
+            throw new RuntimeException();
         }
         wcsTask.setState(state.longValue());
         wcsTask.setUpdateDate(new Date());
@@ -615,51 +619,47 @@ public class WcsTaskServiceImpl implements IWcsTaskService {
     }
 
     /**
-     * 根据单号生成AGV出库任务
+     * 根据单号和单据类型生成AGV出库任务
      * @param orderAgvCallDTO
      * @return
      */
     @Override
     public synchronized AjaxResult createOutboundTaskByDoc(OrderAgvCallDTO orderAgvCallDTO) {
-        //校验单号
-        BionutritionDocBaseDTO bionutritionDocBaseDTO = bionutritionDocHeaderService.selectDocBySkuAndBatchNumber(
-                orderAgvCallDTO.getSkuCode(),orderAgvCallDTO.getBatchNumber(), orderAgvCallDTO.getDocType());
-        if (ObjectUtil.isEmpty(bionutritionDocBaseDTO)){
-           return AjaxResult.error("单据不存在");
-        }
-        if(!outboundDocTypeList.contains(bionutritionDocBaseDTO.getBionutritionDocHeaderBaseDTO().getDocType())){
-            return AjaxResult.error("该单据不是出库单据");
-        }
-        String skuCode = null;
-        for (BionutritionDocDetailsBaseDTO bionutritionDocDetailsBaseDTO : bionutritionDocBaseDTO.getBionutritionDocDetailsBaseDTOList()) {
-           if(StringUtils.equals(orderAgvCallDTO.getSkuCode(), bionutritionDocDetailsBaseDTO.getSkuCode())){
-               skuCode = bionutritionDocDetailsBaseDTO.getSkuCode();
-           }
-        }
-        if (StringUtils.isEmpty(skuCode)){
-            return AjaxResult.error("该单据不存在该物料信息!");
-        }
-
-        Long flowId = 0L;
-        for (Object o : JSONUtil.parseArray(iSysConfigService.selectConfigByKey("sys.docType.corresponding.business"))) {
-            JSONObject entries = JSONUtil.parseObj(o.toString());
-            if (bionutritionDocBaseDTO.getBionutritionDocHeaderBaseDTO().getDocType().equals(entries.get("docType"))){
-                flowId = Long.parseLong(entries.get("flowId").toString());
-            }
-        }
-        if (flowId==0){
-            return AjaxResult.error("未找到对应的任务下发流程!");
-        }
-        List<AgvCallItemDTO> agvCallItemDTOList = new ArrayList<>();
-        AgvCallItemDTO agvCallItemDTO = new AgvCallItemDTO();
-        agvCallItemDTO.setSku(orderAgvCallDTO.getSkuCode());
-        agvCallItemDTOList.add(agvCallItemDTO);
-        AgvCallDTO agvCallDTO = new AgvCallDTO();
-        agvCallDTO.setLocationTo(orderAgvCallDTO.getLocationTo());
-        agvCallDTO.setAgvCallItemDTOList(agvCallItemDTOList);
+        // 根据单号和单据类型查询单据信息
+        BionutritionDocBaseDTO bionutritionDocBaseDTO =
+                bionutritionDocHeaderService.selectDocByDocNoAndDocType(orderAgvCallDTO.getDocNo(), orderAgvCallDTO.getDocType());
+        // 1.校验信息
+        Assert.isTrue(ObjectUtil.isNotEmpty(bionutritionDocBaseDTO), "单据不存在");
+        BionutritionDocHeaderBaseDTO bionutritionDocHeaderBaseDTO = bionutritionDocBaseDTO.getBionutritionDocHeaderBaseDTO();
+        String docType = bionutritionDocHeaderBaseDTO.getDocType();
+        Assert.isTrue(StringUtils.isNotEmpty(docType), "单据信息中物料类型为空");
+        Assert.isTrue(StringUtils.equals(bionutritionDocHeaderBaseDTO.getBusinessType()
+                ,Constant.BUSINESS_TYPE.ORDER.getValue()), "该单据不是出库单据");
+        // 2.根据明细行号筛选明细信息
+        List<BionutritionDocDetailsBaseDTO> docDetailsList = bionutritionDocBaseDTO.getBionutritionDocDetailsBaseDTOList();
+        BionutritionDocDetailsBaseDTO docDetailsBaseDTO = docDetailsList.stream().filter(item -> StringUtils.equals(item.getDocLineNo(), orderAgvCallDTO.getLineNo()))
+                .findFirst().orElse(null);
+        Assert.isTrue(ObjectUtil.isNotEmpty(docDetailsBaseDTO), "对应明细行号数据未找到");
+        // 判断数量是否超出范围
+        Assert.isTrue(NumberUtil.compare(
+                Long.valueOf(docDetailsBaseDTO.getSkuQty()), Long.valueOf(orderAgvCallDTO.getQty())) >= 0
+                , "出库数量超出明细范围");
+        // 记录当前明细已搬运数量
+        BigDecimal transferredQty = NumberUtil.add(docDetailsBaseDTO.getTransferredQty(), orderAgvCallDTO.getQty());
+        docDetailsBaseDTO.setTransferredQty(transferredQty.toString());
+        bionutritionDocDetailsService.updateDocDetails(ConvertUtils.sourceToTarget(docDetailsBaseDTO, BionutritionDocDetailsDTO.class));
+        // 3.根据单据类型获取流程id
+        Long flowId = pdaAgvCallService.getFlowIdByDocType(docType);
+        // 4.构建agv呼叫对象
+        AgvCallDTO agvCallDTO = pdaAgvCallService.getOrderAgvCallDTO(orderAgvCallDTO);
         return iBusinessService.agvCall(flowId, agvCallDTO);
     }
 
+    @Override
+    public List<WcsTaskInvLotDTO> selectWcsTaskListByExt5(String ext5) {
+        return wcsTaskMapper.selectWcsTaskListByExt5(ext5);
+    }
+
     /**
      * 修改库存出入库标记
      *

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

@@ -26,6 +26,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="lotatt16"    column="lotatt16"    />
         <result property="lotatt17"    column="lotatt17"    />
         <result property="lotatt18"    column="lotatt18"    />
+        <result property="lotatt19"    column="lotatt19"    />
         <result property="createBy"    column="create_by"    />
         <result property="createTime"    column="create_time"    />
         <result property="updateBy"    column="update_by"    />
@@ -34,7 +35,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </resultMap>
 
     <sql id="selectInvLotAttVo">
-        select lotnum, customer_id, sku, lotatt01, lotatt02, lotatt03, lotatt04, lotatt05, lotatt06, lotatt07, lotatt08, lotatt09, lotatt10, lotatt11, lotatt12, lotatt13, lotatt14, lotatt15, lotatt16, lotatt17, lotatt18, create_by, create_time, update_by, update_time, remark from inv_lot_att
+        select lotnum, customer_id, sku, lotatt01, lotatt02, lotatt03, lotatt04, lotatt05, lotatt06, lotatt07, lotatt08, lotatt09, lotatt10, lotatt11, lotatt12, lotatt13, lotatt14, lotatt15, lotatt16, lotatt17, lotatt18, lotatt19, create_by, create_time, update_by, update_time, remark from inv_lot_att
     </sql>
 
     <select id="selectInvLotAttList" parameterType="InvLotAtt" resultMap="InvLotAttResult">
@@ -60,6 +61,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="lotatt16 != null  and lotatt16 != ''"> and lotatt16 = #{lotatt16}</if>
             <if test="lotatt17 != null  and lotatt17 != ''"> and lotatt17 = #{lotatt17}</if>
             <if test="lotatt18 != null  and lotatt18 != ''"> and lotatt18 = #{lotatt18}</if>
+            <if test="lotatt19 != null  and lotatt19 != ''"> and lotatt19 = #{lotatt19}</if>
         </where>
     </select>
 
@@ -72,19 +74,43 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         where sku = #{sku} and lotatt02 = #{batchNumber}
     </select>
 
-    <select id="getQcList" resultMap="InvLotAttResult">
-        select att.sku, att.lotatt02 from inv_lot_att att
-        left join inv_lot_loc_id lot on att.lotnum = lot.lotnum
+    <resultMap type="com.ruoyi.ams.bionutrition.dto.DocQcDTO" id="DocQcResult">
+        <result property="skuCode"    column="sku"    />
+        <result property="status"    column="line_status"    />
+        <result property="batchNumber"    column="lotatt02"    />
+        <result property="docNo"    column="doc_no"    />
+    </resultMap>
+
+    <select id="getQcList" resultMap="DocQcResult">
+        select att.sku, att.lotatt02, bdh.doc_no, bdd.line_status
+        from bsl_doc_details bdd
+        left join bsl_doc_header bdh on bdh.id = bdd.doc_header_id
+        left join inv_lot_att att on att.lotatt09 = bdh.doc_no
+        left join inv_lot_loc_id lot on lot.lotnum = att.lotnum
         <where>
             lot.lotnum = att.lotnum
             <if test="sku != null  and sku != ''">
              and att.sku like concat('%', #{sku}, '%')
             </if>
+            and bdd.line_status = '60'
         </where>
         group by att.lotatt02
         order by att.lotatt06
     </select>
 
+    <select id="selectInvLotAttByLotatt19" resultType="com.ruoyi.ams.inv.domain.InvLotAtt">
+        <include refid="selectInvLotAttVo"/>
+        where lotatt19 = #{lotatt19}
+    </select>
+
+    <select id="selectInvLotAttListByHeaderIds" resultType="com.ruoyi.ams.inv.domain.InvLotAtt">
+        <include refid="selectInvLotAttVo"/>
+        where inv_lot_att.lotatt09 in
+        <foreach item="docNo" collection="list" open="(" separator="," close=")">
+            #{docNo}
+        </foreach>
+    </select>
+
     <insert id="insertInvLotAtt" parameterType="InvLotAtt">
         insert into inv_lot_att
         <trim prefix="(" suffix=")" suffixOverrides=",">
@@ -109,6 +135,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="lotatt16 != null">lotatt16,</if>
             <if test="lotatt17 != null">lotatt17,</if>
             <if test="lotatt18 != null">lotatt18,</if>
+            <if test="lotatt19 != null">lotatt19,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createTime != null">create_time,</if>
             <if test="updateBy != null">update_by,</if>
@@ -137,6 +164,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="lotatt16 != null">#{lotatt16},</if>
             <if test="lotatt17 != null">#{lotatt17},</if>
             <if test="lotatt18 != null">#{lotatt18},</if>
+            <if test="lotatt19 != null">#{lotatt19},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null">#{updateBy},</if>
@@ -168,6 +196,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="lotatt16 != null">lotatt16 = #{lotatt16},</if>
             <if test="lotatt17 != null">lotatt17 = #{lotatt17},</if>
             <if test="lotatt18 != null">lotatt18 = #{lotatt18},</if>
+            <if test="lotatt19 != null">lotatt18 = #{lotatt19},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
             <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>

+ 13 - 5
warewms-ams/src/main/resources/mapper/ams/InvLotLocIdMapper.xml

@@ -149,8 +149,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <include refid="selectInvLotLocIdVo"/>
         where lotnum = #{lotnum}
         and location_id = #{location}
-        and customer_id = #{customerId}
-        and sku = #{sku}
     </select>
 
     <insert id="insertInvLotLocId" parameterType="InvLotLocId">
@@ -229,8 +227,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </trim>
         where lotnum = #{lotnum}
         and location_id = #{locationId}
-        and customer_id = #{customerId}
-        and sku = #{sku}
     </update>
 
     <delete id="deleteInvLotLocIdByLotnum" parameterType="String">
@@ -610,7 +606,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         where lotnum = #{lotnum} and location_id = #{locationId}
     </update>
     <update id="updateInvLotLocIdByLotNum">
-        update inv_lot_loc_id set lotnum = #{lotNumNew}
+        update inv_lot_loc_id set lotnum = #{lotNumNew}, update_time = now()
         where lotnum = #{lotnum}
     </update>
 
@@ -631,4 +627,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </where>
         order by (qtyallocated - qty)
     </select>
+
+    <select id="selectInvLotLocIdByTraceIdAndLocationId" resultMap="InvLotLocIdResult">
+        select * from inv_lot_loc_id where trace_id = #{taskNo} and location_id = #{locationTo}
+    </select>
+
+    <select id="selectInvLotLocIdByLotnumList" resultMap="InvLotLocIdResult">
+        <include refid="selectInvLotLocIdVo"/>
+        where inv_lot_loc_id.lotnum in
+        <foreach item="lotNum" collection="list" open="(" separator="," close=")">
+            #{lotNum}
+        </foreach>
+    </select>
 </mapper>

+ 17 - 1
warewms-ams/src/main/resources/mapper/ams/WcsTaskMapper.xml

@@ -111,7 +111,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
     <select id="selectWcsTaskListVO" parameterType="WcsTask" resultMap="WcsTaskResult">
         select t.task_no, t.business_type,bf.location_no location_from,fz.zone_name area_from,bt.location_no location_to,tz.zone_name area_to,
-        t.state,t.create_date,t.task_type, t.start_time, t.end_time,t.remark
+        t.state,t.create_date,t.task_type, t.start_time, t.end_time,t.remark, t.create_user
         from wcs_task t
         left join base_location_info bf on t.location_from = bf.id
         left join base_location_info bt on t.location_to = bt.id
@@ -337,4 +337,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         select * from wcs_task
         where task_no = #{taskNo} and state not in (2,7,4,11,12)
     </select>
+
+    <resultMap type="com.ruoyi.ams.task.dto.WcsTaskInvLotDTO" id="WcsTaskInvDTOResult">
+        <result property="taskNo"    column="task_no"/>
+        <result property="qty"    column="qty"/>
+        <result property="locationFrom"    column="location_from"/>
+        <result property="locationTo"    column="location_to"/>
+        <result property="state"    column="state"/>
+        <result property="ext5"    column="ext5"/>
+    </resultMap>
+
+    <select id="selectWcsTaskListByExt5" resultMap="WcsTaskInvDTOResult">
+        select wt.task_no, wt.ext5, wt.location_from, wt.location_to, wt.state, inv.qty from wcs_task wt
+        left join inv_lot_loc_id inv on inv.traceid = wt.task_no
+        left join inv_lot_att att on att.lotnum = inv.lotnum
+        where ext5 = #{ext5} and state not in (7,8)
+    </select>
 </mapper>

+ 4 - 1
warewms-ams/src/main/resources/mapper/doc/BionutritionDocHeaderMapper.xml

@@ -8,6 +8,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result column="id"  property="id"/>
         <result column="doc_no"  property="docNo"/>
         <result column="doc_type"  property="docType"/>
+        <result column="doc_status"  property="docStatus"/>
         <result column="doc_creator"  property="docCreator"/>
         <result column="business_type"  property="businessType"/>
         <result column="vendor_code"  property="vendorCode"/>
@@ -37,6 +38,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         select  id,
                 doc_no,
                 doc_type,
+                doc_status,
                 doc_creator,
                 business_type,
                 vendor_code,
@@ -67,8 +69,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <include refid="selectDocHeaderResultVo"/>
         <where>
             <if test="docType != null and docType != ''"> and doc_type = #{docType}</if>
-            <if test="docNo != null and docNo != ''"> and doc_no = #{docNo}</if>
+            <if test="docNo != null and docNo != ''"> and doc_no like concat('%', #{docNo}, '%')</if>
             <if test="businessType != null and businessType != ''"> and business_type = #{businessType} </if>
+            <if test="docStatus != null and docStatus != ''"> and doc_status = #{docStatus} </if>
             <if test="createDate != null"><!-- 开始时间检索 -->
                 AND date_format(create_date,'%y%m%d') = date_format(#{createDate},'%y%m%d')
             </if>

+ 72 - 20
warewms-base/src/main/java/com/ruoyi/base/constant/Constant.java

@@ -248,21 +248,13 @@ public class Constant {
          */
         STS00("00"),
         /**
-         * 部分分配
+         * 部分出库
          */
         STS10("10"),
         /**
-         * 完全分配
+         * 完全出库
          */
         STS20("20"),
-        /**
-         * 部分拣货
-         */
-        STS30("30"),
-        /**
-         * 拣货完成
-         */
-        STS40("40"),
         /**
          * 取消
          */
@@ -288,25 +280,53 @@ public class Constant {
      */
     public enum LOCATION_ZONE {
         /**
-         * 立体库一层
+         * 包材区
          */
-        INV_1("1"),
+        PACKAGING_MATERIALS("1"),
         /**
-         * 立体库二层
+         * 原料区
          */
-        INV_2("2"),
+        INGREDIENT("2"),
         /**
-         * 立体库三层
+         * 原料过敏区
          */
-        INV_3("3"),
+        INGREDIENT_ALLERGY("3"),
         /**
-         * 桶装入库缓存
+         * 添加剂过敏
          */
-        TZ_ASN_CACHE("4"),
+        ADDITIVE_ALLERGY("4"),
+        /**
+         * 液体区
+         */
+        LIQUID("5"),
+        /**
+         * 添加剂区
+         */
+        ADDITIVE("6"),
+        /**
+         * 成品区
+         */
+        FINISH_PRODUCT("7"),
+        /**
+         * 空拖区
+         */
+        EMPTY_TRAY("8"),
+        /**
+         * 退货区
+         */
+        RETURNED_GOODS("9"),
         /**
          * 不合格区
          */
-        BHG_ZONE("5");
+        BHG_ZONE("10"),
+        /**
+         * 其他区
+         */
+        OTHER_ZONE("11"),
+        /**
+         * 添加剂过敏区
+         */
+        DOCKING_ZONE("12");
         private String value;
 
         LOCATION_ZONE(String value) {
@@ -616,7 +636,11 @@ public class Constant {
         /***
          * 待检
          */
-        DJ("DJ");
+        DJ("DJ"),
+        /**
+         * 放行
+         */
+        FX("FX");
 
         private String value;
 
@@ -657,4 +681,32 @@ public class Constant {
         }
     }
 
+    /**
+     * 单据业务类型
+     */
+    public enum BUSINESS_TYPE {
+        /***
+         * 入库单
+         */
+        ASN("ASN"),
+        /***
+         * 出库单
+         */
+        ORDER("ORDER"),
+        /**
+         * 采购单
+         */
+        PO("PO");
+
+        private String value;
+
+        BUSINESS_TYPE(String value) {
+            this.value = value;
+        }
+
+        public String getValue() {
+            return value;
+        }
+    }
+
 }

+ 1 - 1
warewms-base/src/main/java/com/ruoyi/base/service/IBaseLocationInfoService.java

@@ -298,5 +298,5 @@ public interface IBaseLocationInfoService {
      * @param opname
      * @return
      */
-    AjaxResult importLocation(List<BaseLocationInfo> list, boolean updateSupport, String opname);
+    /*AjaxResult importLocation(List<BaseLocationInfo> list, boolean updateSupport, String opname);*/
 }

+ 2 - 2
warewms-base/src/main/java/com/ruoyi/base/service/impl/BaseLocationInfoServiceImpl.java

@@ -363,7 +363,7 @@ public class BaseLocationInfoServiceImpl implements IBaseLocationInfoService {
         return this.updateBaseLocationInfo(locationInfoFromUpdate) > 0;
     }
 
-    @Override
+    /*@Override
     public AjaxResult importLocation(List<BaseLocationInfo> list, boolean updateSupport, String opname) {
         if (StringUtils.isNull(list) || list.size() == 0) {
             throw new ServiceException("导入库位基本信息数据不能为空!");
@@ -421,5 +421,5 @@ public class BaseLocationInfoServiceImpl implements IBaseLocationInfoService {
             successMsg.insert(0, "数据已全部导入成功!共 " + successNum + " 条,数据如下:");
         }
         return AjaxResult.success(successMsg);
-    }
+    }*/
 }

+ 3 - 1
warewms-base/src/main/resources/mapper/base/BaseLocationInfoMapper.xml

@@ -198,6 +198,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <insert id="insertBaseLocationInfo" parameterType="BaseLocationInfo" useGeneratedKeys="true" keyProperty="id">
         insert into base_location_info
         <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
             <if test="warehouseId != null">warehouse_id,</if>
             <if test="zoneId != null">zone_id,</if>
             <if test="locationNo != null">location_no,</if>
@@ -235,6 +236,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="remark != null">remark,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
             <if test="warehouseId != null">#{warehouseId},</if>
             <if test="zoneId != null">#{zoneId},</if>
             <if test="locationNo != null">#{locationNo},</if>
@@ -661,7 +663,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                 ORDER BY t1.col_no + 0,t1.location_no
             </when >
             <otherwise>
-                ORDER BY ${sort}
+                ORDER BY #{sort}
             </otherwise>
         </choose>
     </select>