From 3ca1cefd9bed863131ee3f684ff127bd7ac877aa Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期三, 05 八月 2026 11:35:16 +0800
Subject: [PATCH] feat(ai): 优化AI知识文档处理功能
---
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java | 5
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceServiceImpl.java | 20
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java | 15
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java | 3
yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeSegmentServiceImpl.java | 2
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/quotation/CrmSaleQuotationController.java | 15
yudao-server/src/main/resources/application-test.yaml | 4
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemServiceImpl.java | 5
.playwright-mcp/page-2026-08-04T07-44-38-346Z.yml | 273 ++++++++++++++
yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeDocumentServiceImpl.java | 62 +++
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/request/ErpPurchaseRequestRespVO.java | 3
.playwright-mcp/page-2026-08-04T07-44-03-300Z.yml | 1
yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/wm/warehouse/MesWmWarehouseApi.java | 21 +
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackApproveReqVO.java | 50 ++
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java | 6
yudao-server/src/main/resources/logback-spring.xml | 2
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackBatchCheckRespVO.java | 63 +++
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackService.java | 12
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/service/tender/SrmBidAwardServiceImpl.java | 36 +
yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/wm/warehouse/dto/MesWmWarehouseRespDTO.java | 15
yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/wms/MesWmStockApi.java | 20 +
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/MesProFeedbackController.java | 15
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseRequestServiceImpl.java | 15
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/enums/ErrorCodeConstants.java | 3
yudao-module-ai/pom.xml | 7
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseRequestController.java | 8
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/warehouse/MdmWarehouseController.java | 6
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/api/wm/warehouse/MesWmWarehouseApiImpl.java | 35 +
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/api/wms/MesWmStockApiImpl.java | 37 +
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java | 8
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java | 87 ++++
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java | 1
.playwright-mcp/page-2026-08-04T07-44-19-942Z.yml | 237 ++++++++++++
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java | 19
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceService.java | 5
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/MdmItemController.java | 24
36 files changed, 1,078 insertions(+), 62 deletions(-)
diff --git a/.playwright-mcp/page-2026-08-04T07-44-03-300Z.yml b/.playwright-mcp/page-2026-08-04T07-44-03-300Z.yml
new file mode 100644
index 0000000..6adf37e
--- /dev/null
+++ b/.playwright-mcp/page-2026-08-04T07-44-03-300Z.yml
@@ -0,0 +1 @@
+- generic [active]: 宸ヤ笟AI鏅洪�犲钩鍙�
\ No newline at end of file
diff --git a/.playwright-mcp/page-2026-08-04T07-44-19-942Z.yml b/.playwright-mcp/page-2026-08-04T07-44-19-942Z.yml
new file mode 100644
index 0000000..23f77a5
--- /dev/null
+++ b/.playwright-mcp/page-2026-08-04T07-44-19-942Z.yml
@@ -0,0 +1,237 @@
+- generic [ref=e403]:
+ - banner [ref=e404]:
+ - generic [ref=e408]:
+ - generic [ref=e409]: 鐢熶骇宸ヤ綔鍙�
+ - generic [ref=e410]: 鎷変笣1鍙峰伐浣滅珯
+ - navigation [ref=e411]:
+ - button "宸ュ崟璇︽儏" [ref=e412] [cursor=pointer]
+ - button "鎶ュ伐" [ref=e417] [cursor=pointer]
+ - button "鎶ュ伐璁板綍" [active] [ref=e420] [cursor=pointer]
+ - button "鐢熶骇璁板綍鍙傛暟" [ref=e425] [cursor=pointer]
+ - button "棰嗘枡" [ref=e430] [cursor=pointer]
+ - button "閫�鏂�" [ref=e435] [cursor=pointer]
+ - button "杩斿洖绯荤粺" [ref=e440] [cursor=pointer]
+ - generic [ref=e444]:
+ - complementary [ref=e445]:
+ - generic [ref=e446]:
+ - generic [ref=e447]:
+ - generic [ref=e448]: 宸ヤ綔绔�
+ - button "鍒囨崲" [ref=e454] [cursor=pointer]
+ - generic [ref=e455]:
+ - generic [ref=e456]: WS_002
+ - generic [ref=e457]: 鎷変笣1鍙峰伐浣滅珯
+ - generic [ref=e458]: 鎷変笣
+ - generic [ref=e459]:
+ - generic [ref=e460]:
+ - generic [ref=e461]: 杞﹂棿
+ - generic [ref=e462]: 娴嬭瘯鎷変笣杞﹂棿
+ - generic [ref=e463]:
+ - generic [ref=e464]: 鍦扮偣
+ - generic [ref=e465]: 鈥�
+ - button "涓婂伐" [ref=e467] [cursor=pointer]
+ - generic [ref=e470]:
+ - generic [ref=e471]:
+ - generic [ref=e472]: 宸ュ崟鍒楄〃
+ - generic [ref=e473]: "6"
+ - textbox "璁㈠崟/浜у搧/宸ュ簭" [ref=e475]
+ - generic [ref=e476]:
+ - generic [ref=e479] [cursor=pointer]:
+ - generic [ref=e480]:
+ - generic [ref=e481]: TK_20260729002
+ - generic [ref=e482]: 璐ㄦ
+ - generic [ref=e483]: 鍊掑啿
+ - generic [ref=e484]: 0%
+ - generic [ref=e485]:
+ - generic [ref=e486]: 鎶ュ伐杩涘害
+ - generic [ref=e487]: 0 / 234
+ - generic [ref=e489]:
+ - generic [ref=e490]:
+ - generic [ref=e491]: 璁㈠崟
+ - generic [ref=e492]: WO1784883668267 鐢熶骇宸ュ崟-MPS20260724002
+ - generic [ref=e493]:
+ - generic [ref=e494]: 宸ュ簭
+ - generic [ref=e495]: 鎷変笣
+ - generic [ref=e496]:
+ - generic [ref=e497]: 浜у搧
+ - generic "閾濆崟绾�" [ref=e498]: ITEM_20260716005 閾濆崟绾�
+ - generic [ref=e499]:
+ - generic [ref=e500]: 鍙姤宸�
+ - generic [ref=e501]: 224 鍗冨厠
+ - generic [ref=e504] [cursor=pointer]:
+ - generic [ref=e505]:
+ - generic [ref=e506]: TK_20260729001
+ - generic [ref=e507]: 璐ㄦ
+ - generic [ref=e508]: 鍊掑啿
+ - generic [ref=e509]: 0%
+ - generic [ref=e510]:
+ - generic [ref=e511]: 鎶ュ伐杩涘害
+ - generic [ref=e512]: 0 / 61
+ - generic [ref=e514]:
+ - generic [ref=e515]:
+ - generic [ref=e516]: 璁㈠崟
+ - generic [ref=e517]: WO_20260724003 閰掓硥
+ - generic [ref=e518]:
+ - generic [ref=e519]: 宸ュ簭
+ - generic [ref=e520]: 鎷変笣
+ - generic [ref=e521]:
+ - generic [ref=e522]: 浜у搧
+ - generic "閾濆崟绾�" [ref=e523]: ITEM_20260716005 閾濆崟绾�
+ - generic [ref=e524]:
+ - generic [ref=e525]: 鍙姤宸�
+ - generic [ref=e526]: 61 鍗冨厠
+ - generic [ref=e529] [cursor=pointer]:
+ - generic [ref=e530]:
+ - generic [ref=e531]: TK_20260724001
+ - generic [ref=e532]: 璐ㄦ
+ - generic [ref=e533]: 鍊掑啿
+ - generic [ref=e534]: 0%
+ - generic [ref=e535]:
+ - generic [ref=e536]: 鎶ュ伐杩涘害
+ - generic [ref=e537]: 0 / 1
+ - generic [ref=e539]:
+ - generic [ref=e540]:
+ - generic [ref=e541]: 璁㈠崟
+ - generic [ref=e542]: WO_20260724003 閰掓硥
+ - generic [ref=e543]:
+ - generic [ref=e544]: 宸ュ簭
+ - generic [ref=e545]: 鎷変笣
+ - generic [ref=e546]:
+ - generic [ref=e547]: 浜у搧
+ - generic "閾濆崟绾�" [ref=e548]: ITEM_20260716005 閾濆崟绾�
+ - generic [ref=e549]:
+ - generic [ref=e550]: 鍙姤宸�
+ - generic [ref=e551]: 0 鍗冨厠
+ - generic [ref=e554] [cursor=pointer]:
+ - generic [ref=e555]:
+ - generic [ref=e556]: TK_20260723001
+ - generic [ref=e557]: 璐ㄦ
+ - generic [ref=e558]: 鍊掑啿
+ - generic [ref=e559]: 27%
+ - generic [ref=e560]:
+ - generic [ref=e561]: 鎶ュ伐杩涘害
+ - generic [ref=e562]: 27 / 100
+ - generic [ref=e565]:
+ - generic [ref=e566]:
+ - generic [ref=e567]: 璁㈠崟
+ - generic [ref=e568]: WO_20260722009 閰掓硥
+ - generic [ref=e569]:
+ - generic [ref=e570]: 宸ュ簭
+ - generic [ref=e571]: 鎷変笣
+ - generic [ref=e572]:
+ - generic [ref=e573]: 浜у搧
+ - generic "閾濆崟绾�" [ref=e574]: ITEM_20260716005 閾濆崟绾�
+ - generic [ref=e575]:
+ - generic [ref=e576]: 鍙姤宸�
+ - generic [ref=e577]: 73 鍗冨厠
+ - generic [ref=e580] [cursor=pointer]:
+ - generic [ref=e581]:
+ - generic [ref=e582]: TK_20260717001
+ - generic [ref=e583]: 璐ㄦ
+ - generic [ref=e584]: 鍊掑啿
+ - generic [ref=e585]: 0.6%
+ - generic [ref=e586]:
+ - generic [ref=e587]: 鎶ュ伐杩涘害
+ - generic [ref=e588]: 6 / 1000
+ - generic [ref=e591]:
+ - generic [ref=e592]:
+ - generic [ref=e593]: 璁㈠崟
+ - generic [ref=e594]: WO_20260716050 娴嬭瘯璁㈠崟
+ - generic [ref=e595]:
+ - generic [ref=e596]: 宸ュ簭
+ - generic [ref=e597]: 鎷変笣
+ - generic [ref=e598]:
+ - generic [ref=e599]: 浜у搧
+ - generic "閾濆崟绾�" [ref=e600]: ITEM_20260716005 閾濆崟绾�
+ - generic [ref=e601]:
+ - generic [ref=e602]: 鍙姤宸�
+ - generic [ref=e603]: 994 鍗冨厠
+ - generic [ref=e606] [cursor=pointer]:
+ - generic [ref=e607]:
+ - generic [ref=e608]: TK_20260716001
+ - generic [ref=e609]: 璐ㄦ
+ - generic [ref=e610]: 鍊掑啿
+ - generic [ref=e611]: 0%
+ - generic [ref=e612]:
+ - generic [ref=e613]: 鎶ュ伐杩涘害
+ - generic [ref=e614]: 0 / 12000
+ - generic [ref=e616]:
+ - generic [ref=e617]:
+ - generic [ref=e618]: 璁㈠崟
+ - generic [ref=e619]: WO_20260716050 娴嬭瘯璁㈠崟
+ - generic [ref=e620]:
+ - generic [ref=e621]: 宸ュ簭
+ - generic [ref=e622]: 鎷変笣
+ - generic [ref=e623]:
+ - generic [ref=e624]: 浜у搧
+ - generic "閽㈣姱閾濈粸绾�" [ref=e625]: ITEM_20260716006 閽㈣姱閾濈粸绾�
+ - generic [ref=e626]:
+ - generic [ref=e627]: 鍙姤宸�
+ - generic [ref=e628]: 10000 鍗冨厠
+ - main [ref=e631]:
+ - generic [ref=e632]:
+ - generic [ref=e633]: 鎶ュ伐璁板綍
+ - generic [ref=e634]: 宸ュ崟 TK_20260729002
+ - generic [ref=e725]:
+ - generic [ref=e727]:
+ - generic [ref=e728]: 鎶ュ伐璁板綍
+ - generic [ref=e731]:
+ - button "瞟�" [ref=e732] [cursor=pointer]
+ - button "顪�" [ref=e734] [cursor=pointer]
+ - button "顦�" [ref=e736] [cursor=pointer]
+ - generic [ref=e743]:
+ - generic [ref=e744]:
+ - table [ref=e748]:
+ - rowgroup [ref=e762]:
+ - row [ref=e763]:
+ - columnheader "鎶ヨ鍗曞彿" [ref=e764]
+ - columnheader "浠诲姟缂栫爜" [ref=e769]
+ - columnheader "宸ュ簭" [ref=e774]
+ - columnheader "浜у搧" [ref=e779]
+ - columnheader "鎶ュ伐鏁伴噺" [ref=e784]
+ - columnheader "鍚堟牸鍝�" [ref=e789]
+ - columnheader "涓嶈壇鍝�" [ref=e794]
+ - columnheader "鎶ュ伐浜�" [ref=e799]
+ - columnheader "瀹℃牳浜�" [ref=e804]
+ - columnheader "鐘舵��" [ref=e809]
+ - columnheader "鎶ュ伐鏃堕棿" [ref=e814]
+ - table [ref=e822]:
+ - rowgroup [ref=e836]:
+ - row [ref=e837]:
+ - cell [ref=e838]:
+ - button "FB_20260804006" [ref=e841] [cursor=pointer]
+ - cell "TK_20260729002" [ref=e843]
+ - cell "鎷変笣" [ref=e847]
+ - cell "閾濆崟绾�" [ref=e851]
+ - cell "10" [ref=e855]
+ - cell "0" [ref=e859]
+ - cell "0" [ref=e863]
+ - cell "鑺嬮亾婧愮爜" [ref=e867]
+ - cell "test01" [ref=e871]
+ - cell "瀹℃壒涓�" [ref=e875]
+ - cell "2026-08-04 15:42:04" [ref=e879]
+ - generic [ref=e883]:
+ - table [ref=e886]:
+ - rowgroup [ref=e900]:
+ - row [ref=e901]:
+ - columnheader "鎿嶄綔" [ref=e902]
+ - table [ref=e909]:
+ - rowgroup [ref=e912]:
+ - row [ref=e913]:
+ - cell [ref=e914]:
+ - generic [ref=e917]:
+ - button "鏌ョ湅" [ref=e919] [cursor=pointer]
+ - button "瀹℃壒閫氳繃" [ref=e922] [cursor=pointer]
+ - button "椹冲洖" [ref=e925] [cursor=pointer]
+ - generic [ref=e933]:
+ - generic [ref=e934]: 鍏� 1 鏉¤褰�
+ - generic [ref=e936] [cursor=pointer]:
+ - generic "20鏉�/椤�" [ref=e937]:
+ - textbox "璇烽�夋嫨" [ref=e938]: 20鏉�/椤�
+ - generic [ref=e939]: 睿�
+ - button "飱�" [ref=e942]
+ - button "顧�" [ref=e944]
+ - button "顫�" [ref=e946]
+ - button "1" [ref=e949] [cursor=pointer]
+ - button "顫�" [ref=e950]
+ - button "顧�" [ref=e952]
+ - button "顦�" [ref=e954]
\ No newline at end of file
diff --git a/.playwright-mcp/page-2026-08-04T07-44-38-346Z.yml b/.playwright-mcp/page-2026-08-04T07-44-38-346Z.yml
new file mode 100644
index 0000000..16aaa21
--- /dev/null
+++ b/.playwright-mcp/page-2026-08-04T07-44-38-346Z.yml
@@ -0,0 +1,273 @@
+- generic [ref=e403]:
+ - banner [ref=e404]:
+ - generic [ref=e408]:
+ - generic [ref=e409]: 鐢熶骇宸ヤ綔鍙�
+ - generic [ref=e410]: 鎷変笣1鍙峰伐浣滅珯
+ - navigation [ref=e411]:
+ - button "宸ュ崟璇︽儏" [ref=e412] [cursor=pointer]
+ - button "鎶ュ伐" [active] [ref=e417] [cursor=pointer]
+ - button "鎶ュ伐璁板綍" [ref=e420] [cursor=pointer]
+ - button "鐢熶骇璁板綍鍙傛暟" [ref=e425] [cursor=pointer]
+ - button "棰嗘枡" [ref=e430] [cursor=pointer]
+ - button "閫�鏂�" [ref=e435] [cursor=pointer]
+ - button "杩斿洖绯荤粺" [ref=e440] [cursor=pointer]
+ - generic [ref=e444]:
+ - complementary [ref=e445]:
+ - generic [ref=e446]:
+ - generic [ref=e447]:
+ - generic [ref=e448]: 宸ヤ綔绔�
+ - button "鍒囨崲" [ref=e454] [cursor=pointer]
+ - generic [ref=e455]:
+ - generic [ref=e456]: WS_002
+ - generic [ref=e457]: 鎷変笣1鍙峰伐浣滅珯
+ - generic [ref=e458]: 鎷変笣
+ - generic [ref=e459]:
+ - generic [ref=e460]:
+ - generic [ref=e461]: 杞﹂棿
+ - generic [ref=e462]: 娴嬭瘯鎷変笣杞﹂棿
+ - generic [ref=e463]:
+ - generic [ref=e464]: 鍦扮偣
+ - generic [ref=e465]: 鈥�
+ - button "涓婂伐" [ref=e467] [cursor=pointer]
+ - generic [ref=e470]:
+ - generic [ref=e471]:
+ - generic [ref=e472]: 宸ュ崟鍒楄〃
+ - generic [ref=e473]: "6"
+ - textbox "璁㈠崟/浜у搧/宸ュ簭" [ref=e475]
+ - generic [ref=e476]:
+ - generic [ref=e479] [cursor=pointer]:
+ - generic [ref=e480]:
+ - generic [ref=e481]: TK_20260729002
+ - generic [ref=e482]: 璐ㄦ
+ - generic [ref=e483]: 鍊掑啿
+ - generic [ref=e484]: 0%
+ - generic [ref=e485]:
+ - generic [ref=e486]: 鎶ュ伐杩涘害
+ - generic [ref=e487]: 0 / 234
+ - generic [ref=e489]:
+ - generic [ref=e490]:
+ - generic [ref=e491]: 璁㈠崟
+ - generic [ref=e492]: WO1784883668267 鐢熶骇宸ュ崟-MPS20260724002
+ - generic [ref=e493]:
+ - generic [ref=e494]: 宸ュ簭
+ - generic [ref=e495]: 鎷変笣
+ - generic [ref=e496]:
+ - generic [ref=e497]: 浜у搧
+ - generic "閾濆崟绾�" [ref=e498]: ITEM_20260716005 閾濆崟绾�
+ - generic [ref=e499]:
+ - generic [ref=e500]: 鍙姤宸�
+ - generic [ref=e501]: 224 鍗冨厠
+ - generic [ref=e504] [cursor=pointer]:
+ - generic [ref=e505]:
+ - generic [ref=e506]: TK_20260729001
+ - generic [ref=e507]: 璐ㄦ
+ - generic [ref=e508]: 鍊掑啿
+ - generic [ref=e509]: 0%
+ - generic [ref=e510]:
+ - generic [ref=e511]: 鎶ュ伐杩涘害
+ - generic [ref=e512]: 0 / 61
+ - generic [ref=e514]:
+ - generic [ref=e515]:
+ - generic [ref=e516]: 璁㈠崟
+ - generic [ref=e517]: WO_20260724003 閰掓硥
+ - generic [ref=e518]:
+ - generic [ref=e519]: 宸ュ簭
+ - generic [ref=e520]: 鎷変笣
+ - generic [ref=e521]:
+ - generic [ref=e522]: 浜у搧
+ - generic "閾濆崟绾�" [ref=e523]: ITEM_20260716005 閾濆崟绾�
+ - generic [ref=e524]:
+ - generic [ref=e525]: 鍙姤宸�
+ - generic [ref=e526]: 61 鍗冨厠
+ - generic [ref=e529] [cursor=pointer]:
+ - generic [ref=e530]:
+ - generic [ref=e531]: TK_20260724001
+ - generic [ref=e532]: 璐ㄦ
+ - generic [ref=e533]: 鍊掑啿
+ - generic [ref=e534]: 0%
+ - generic [ref=e535]:
+ - generic [ref=e536]: 鎶ュ伐杩涘害
+ - generic [ref=e537]: 0 / 1
+ - generic [ref=e539]:
+ - generic [ref=e540]:
+ - generic [ref=e541]: 璁㈠崟
+ - generic [ref=e542]: WO_20260724003 閰掓硥
+ - generic [ref=e543]:
+ - generic [ref=e544]: 宸ュ簭
+ - generic [ref=e545]: 鎷変笣
+ - generic [ref=e546]:
+ - generic [ref=e547]: 浜у搧
+ - generic "閾濆崟绾�" [ref=e548]: ITEM_20260716005 閾濆崟绾�
+ - generic [ref=e549]:
+ - generic [ref=e550]: 鍙姤宸�
+ - generic [ref=e551]: 0 鍗冨厠
+ - generic [ref=e554] [cursor=pointer]:
+ - generic [ref=e555]:
+ - generic [ref=e556]: TK_20260723001
+ - generic [ref=e557]: 璐ㄦ
+ - generic [ref=e558]: 鍊掑啿
+ - generic [ref=e559]: 27%
+ - generic [ref=e560]:
+ - generic [ref=e561]: 鎶ュ伐杩涘害
+ - generic [ref=e562]: 27 / 100
+ - generic [ref=e565]:
+ - generic [ref=e566]:
+ - generic [ref=e567]: 璁㈠崟
+ - generic [ref=e568]: WO_20260722009 閰掓硥
+ - generic [ref=e569]:
+ - generic [ref=e570]: 宸ュ簭
+ - generic [ref=e571]: 鎷変笣
+ - generic [ref=e572]:
+ - generic [ref=e573]: 浜у搧
+ - generic "閾濆崟绾�" [ref=e574]: ITEM_20260716005 閾濆崟绾�
+ - generic [ref=e575]:
+ - generic [ref=e576]: 鍙姤宸�
+ - generic [ref=e577]: 73 鍗冨厠
+ - generic [ref=e580] [cursor=pointer]:
+ - generic [ref=e581]:
+ - generic [ref=e582]: TK_20260717001
+ - generic [ref=e583]: 璐ㄦ
+ - generic [ref=e584]: 鍊掑啿
+ - generic [ref=e585]: 0.6%
+ - generic [ref=e586]:
+ - generic [ref=e587]: 鎶ュ伐杩涘害
+ - generic [ref=e588]: 6 / 1000
+ - generic [ref=e591]:
+ - generic [ref=e592]:
+ - generic [ref=e593]: 璁㈠崟
+ - generic [ref=e594]: WO_20260716050 娴嬭瘯璁㈠崟
+ - generic [ref=e595]:
+ - generic [ref=e596]: 宸ュ簭
+ - generic [ref=e597]: 鎷変笣
+ - generic [ref=e598]:
+ - generic [ref=e599]: 浜у搧
+ - generic "閾濆崟绾�" [ref=e600]: ITEM_20260716005 閾濆崟绾�
+ - generic [ref=e601]:
+ - generic [ref=e602]: 鍙姤宸�
+ - generic [ref=e603]: 994 鍗冨厠
+ - generic [ref=e606] [cursor=pointer]:
+ - generic [ref=e607]:
+ - generic [ref=e608]: TK_20260716001
+ - generic [ref=e609]: 璐ㄦ
+ - generic [ref=e610]: 鍊掑啿
+ - generic [ref=e611]: 0%
+ - generic [ref=e612]:
+ - generic [ref=e613]: 鎶ュ伐杩涘害
+ - generic [ref=e614]: 0 / 12000
+ - generic [ref=e616]:
+ - generic [ref=e617]:
+ - generic [ref=e618]: 璁㈠崟
+ - generic [ref=e619]: WO_20260716050 娴嬭瘯璁㈠崟
+ - generic [ref=e620]:
+ - generic [ref=e621]: 宸ュ簭
+ - generic [ref=e622]: 鎷変笣
+ - generic [ref=e623]:
+ - generic [ref=e624]: 浜у搧
+ - generic "閽㈣姱閾濈粸绾�" [ref=e625]: ITEM_20260716006 閽㈣姱閾濈粸绾�
+ - generic [ref=e626]:
+ - generic [ref=e627]: 鍙姤宸�
+ - generic [ref=e628]: 10000 鍗冨厠
+ - main [ref=e631]:
+ - generic [ref=e632]:
+ - generic [ref=e633]: 鎶ュ伐
+ - generic [ref=e634]: 宸ュ崟 TK_20260729002
+ - generic [ref=e956]:
+ - generic [ref=e957]:
+ - heading "鏂板缓鎶ュ伐" [level=3] [ref=e958]
+ - generic [ref=e959]: "宸ュ崟: WO1784883668267 鐢熶骇宸ュ崟-MPS20260724002"
+ - generic [ref=e961]:
+ - generic [ref=e962]:
+ - generic [ref=e963]:
+ - generic [ref=e964]: "*"
+ - text: 鎶ヨ鍗曞彿
+ - generic [ref=e968]:
+ - textbox "* 鎶ヨ鍗曞彿" [ref=e969]:
+ - /placeholder: 璇疯緭鍏ユ姤璁㈠崟鍙�
+ - text: FB_20260804009
+ - button "鐢� 鎴�" [ref=e971] [cursor=pointer]
+ - generic [ref=e973]:
+ - generic [ref=e974]:
+ - generic [ref=e975]: "*"
+ - text: 鎶ュ伐绫诲瀷
+ - generic [ref=e981] [cursor=pointer]:
+ - combobox "* 鎶ュ伐绫诲瀷" [ref=e983]
+ - generic "鑷鎶ュ伐" [ref=e984]
+ - generic [ref=e985]:
+ - generic [ref=e986]:
+ - generic [ref=e987]: "*"
+ - text: 鐢熶骇璁㈠崟
+ - textbox "璇烽�夋嫨璁㈠崟" [ref=e994]: WO1784883668267
+ - generic [ref=e1000]:
+ - generic [ref=e1001]:
+ - generic [ref=e1002]: "*"
+ - text: 鐢熶骇浠诲姟
+ - textbox "璇烽�夋嫨浠诲姟" [ref=e1009]: TK_20260729002
+ - generic [ref=e1015]:
+ - generic [ref=e1016]:
+ - generic [ref=e1017]: "*"
+ - text: 宸ヤ綔绔�
+ - textbox "璇烽�夋嫨宸ヤ綔绔�" [ref=e1024]: 鎷変笣1鍙峰伐浣滅珯
+ - generic [ref=e1030]:
+ - generic [ref=e1031]: 浜у搧缂栫爜
+ - textbox "浜у搧缂栫爜" [disabled] [ref=e1036]:
+ - /placeholder: 璇疯緭鍏�
+ - text: ITEM_20260716005
+ - generic [ref=e1037]:
+ - generic [ref=e1038]: 浜у搧鍚嶇О
+ - textbox "浜у搧鍚嶇О" [disabled] [ref=e1043]:
+ - /placeholder: 璇疯緭鍏�
+ - text: 閾濆崟绾�
+ - generic [ref=e1044]:
+ - generic [ref=e1045]: 鍗曚綅
+ - textbox "鍗曚綅" [disabled] [ref=e1050]:
+ - /placeholder: 璇疯緭鍏�
+ - text: 鍗冨厠
+ - generic [ref=e1051]:
+ - generic [ref=e1052]: 瑙勬牸
+ - textbox "瑙勬牸" [disabled] [ref=e1057]:
+ - /placeholder: 璇疯緭鍏�
+ - text: L-1.72
+ - generic [ref=e1058]:
+ - generic [ref=e1059]:
+ - generic [ref=e1060]: "*"
+ - text: 鎶ュ伐鏁伴噺
+ - generic [ref=e1065]:
+ - generic [ref=e1066]:
+ - button "Increase Value" [ref=e1067] [cursor=pointer]:
+ - img "up" [ref=e1068]
+ - button "Decrease Value" [ref=e1071] [cursor=pointer]:
+ - img "down" [ref=e1072]
+ - spinbutton "* 鎶ュ伐鏁伴噺" [ref=e1076]
+ - generic [ref=e1077]:
+ - generic [ref=e1078]:
+ - generic [ref=e1079]: "*"
+ - text: 鎶ュ伐浜�
+ - generic [ref=e1085] [cursor=pointer]:
+ - combobox "* 鎶ュ伐浜�" [ref=e1087]
+ - generic "鑺嬮亾婧愮爜" [ref=e1088]
+ - generic [ref=e1093]:
+ - generic [ref=e1094]:
+ - generic [ref=e1095]: "*"
+ - text: 鎶ュ伐鏃堕棿
+ - generic [ref=e1101]:
+ - textbox "* 鎶ュ伐鏃堕棿" [ref=e1102]:
+ - /placeholder: 璇烽�夋嫨鎶ュ伐鏃堕棿
+ - text: Invalid Date
+ - generic:
+ - img "calendar"
+ - button [ref=e1103] [cursor=pointer]:
+ - img "close-circle" [ref=e1104]
+ - generic [ref=e1107]:
+ - generic [ref=e1108]:
+ - generic [ref=e1109]: "*"
+ - text: 瀹℃牳浜�
+ - generic [ref=e1115] [cursor=pointer]:
+ - combobox "* 瀹℃牳浜�" [ref=e1117]
+ - generic: 璇烽�夋嫨瀹℃牳浜�
+ - generic [ref=e1118]:
+ - generic [ref=e1119]: 澶囨敞
+ - textbox "澶囨敞" [ref=e1124]:
+ - /placeholder: 璇疯緭鍏ュ娉�
+ - generic [ref=e1125]:
+ - button "淇� 瀛�" [ref=e1126] [cursor=pointer]
+ - button "淇濆瓨骞舵彁浜�" [ref=e1128] [cursor=pointer]
\ No newline at end of file
diff --git a/yudao-module-ai/pom.xml b/yudao-module-ai/pom.xml
index 409a9c3..fda0405 100644
--- a/yudao-module-ai/pom.xml
+++ b/yudao-module-ai/pom.xml
@@ -167,6 +167,13 @@
</exclusions>
</dependency>
+ <!-- Apache POI锛氳礋璐� .doc/.docx 鏂囦欢鍐呭鎻愬彇锛屾瘮 Tika 瀵逛腑鏂囨敮鎸佹洿濂� -->
+ <dependency>
+ <groupId>org.apache.poi</groupId>
+ <artifactId>poi-ooxml</artifactId>
+ <version>5.4.0</version>
+ </dependency>
+
<!-- MCP 鐩稿叧 -->
<!--
鐗规畩璇存槑锛氫笉鑳戒娇鐢� spring-ai-starter-mcp-server-webflux 鎴� spring-ai-starter-mcp-client-webflux 锛侊紒锛�
diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeDocumentServiceImpl.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeDocumentServiceImpl.java
index c11c264..5f671a2 100644
--- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeDocumentServiceImpl.java
+++ b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeDocumentServiceImpl.java
@@ -28,6 +28,10 @@
import org.apache.tika.parser.Parser;
import org.apache.tika.extractor.EmbeddedDocumentExtractor;
import org.apache.tika.sax.BodyContentHandler;
+import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+import org.apache.poi.hwpf.HWPFDocument;
+import org.apache.poi.hwpf.extractor.WordExtractor;
import org.xml.sax.ContentHandler;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
@@ -57,6 +61,8 @@
private AiKnowledgeSegmentService segmentService;
@Resource
private AiModelService modelService;
+ @Resource
+ private cn.iocoder.yudao.module.system.service.storage.SystemStorageBlobService storageBlobService;
@Override
@Transactional(rollbackFor = Exception.class)
@@ -113,11 +119,28 @@
}
}
+ /**
+ * 浠� storage-blob URL 瑙f瀽鍑� fileName 鍜� token
+ */
+ private static java.util.regex.Pattern STORAGE_URL_PATTERN =
+ java.util.regex.Pattern.compile("/storage-blob/(?:preview|download)/([^?]+)\\?.*token=([^&]+)");
+
private byte[] downloadFile(String fileUrl) {
+ // 浼樺厛閫氳繃 storage-blob 鏈湴璇诲彇锛岄伩鍏� HTTP 璁よ瘉闂
+ var matcher = STORAGE_URL_PATTERN.matcher(fileUrl);
+ if (matcher.find()) {
+ String fileName = matcher.group(1);
+ String token = matcher.group(2);
+ try {
+ java.io.File file = storageBlobService.getFileByToken(fileName, token);
+ return java.nio.file.Files.readAllBytes(file.toPath());
+ } catch (Exception e) {
+ log.warn("鏈湴璇诲彇瀛樺偍鏂囦欢澶辫触锛屽洖閫� HTTP 涓嬭浇: {}", e.getMessage());
+ }
+ }
+ // 鍥為�� HTTP 涓嬭浇
try {
- // 鎵嬪姩缂栫爜 URL 璺緞涓殑闈� ASCII 瀛楃锛岄伩鍏� URI 鏋勯�犲嚱鏁版姤閿�
- String encodedUrl = encodeUrlPath(fileUrl);
- URL url = URL.of(new URI(encodedUrl), null);
+ URL url = URL.of(new URI(encodeUrlPath(fileUrl)), null);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(30000);
conn.setReadTimeout(60000);
@@ -184,7 +207,36 @@
if (ArrayUtil.contains(new String[]{"txt", "md", "json", "xml", "csv", "yaml", "yml"}, ext)) {
return new String(fileBytes, StandardCharsets.UTF_8);
}
- // 浣跨敤 AutoDetectParser + EmbeddedDocumentExtractor 璺宠繃宓屽叆鍥剧墖锛岄伩鍏嶆彁鍙栧埌浜岃繘鍒朵贡鐮�
+ // .docx 浼樺厛浣跨敤 POI 鎻愬彇锛屼腑鏂囨敮鎸佹洿濂�
+ if ("docx".equals(ext)) {
+ try (XWPFDocument doc = new XWPFDocument(new java.io.ByteArrayInputStream(fileBytes));
+ XWPFWordExtractor extractor = new XWPFWordExtractor(doc)) {
+ String text = extractor.getText();
+ if (StrUtil.isNotEmpty(text)) return text.trim();
+ } catch (Exception e) {
+ log.warn("POI 瑙f瀽 docx 澶辫触锛屽洖閫� Tika: {}", e.getMessage());
+ }
+ }
+ // .doc 浼樺厛浣跨敤 POI 鎻愬彇
+ if ("doc".equals(ext)) {
+ try (HWPFDocument doc = new HWPFDocument(new java.io.ByteArrayInputStream(fileBytes));
+ WordExtractor extractor = new WordExtractor(doc)) {
+ String text = extractor.getText();
+ if (StrUtil.isNotEmpty(text)) return text.trim();
+ } catch (Exception e) {
+ log.warn("POI 瑙f瀽 doc 澶辫触锛屽洖閫� Tika: {}", e.getMessage());
+ }
+ }
+ // 鍏朵粬鏍煎紡鎴� POI 澶辫触鏃跺洖閫� Tika
+ return extractTextWithTika(fileBytes);
+ } catch (Exception e) {
+ log.warn("鏂囨。鍐呭鎻愬彇澶辫触锛屽皾璇� UTF-8 鏂囨湰璇诲彇: {}", e.getMessage());
+ return "";
+ }
+ }
+
+ private String extractTextWithTika(byte[] fileBytes) {
+ try {
Parser parser = new AutoDetectParser();
ParseContext context = new ParseContext();
context.set(EmbeddedDocumentExtractor.class, new EmbeddedDocumentExtractor() {
@@ -203,7 +255,7 @@
}
return handler.toString().trim();
} catch (Exception e) {
- log.warn("Tika 瑙f瀽鏂囨。澶辫触锛屽皾璇� UTF-8 鏂囨湰璇诲彇: {}", e.getMessage());
+ log.warn("Tika 瑙f瀽澶辫触: {}", e.getMessage());
return "";
}
}
diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeSegmentServiceImpl.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeSegmentServiceImpl.java
index 8763b30..3be25b0 100644
--- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeSegmentServiceImpl.java
+++ b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeSegmentServiceImpl.java
@@ -217,7 +217,7 @@
try {
for (int i = 0; i < documents.size(); i += batchSize) {
int end = Math.min(i + batchSize, documents.size());
- vectorStore.add(documents.subList(i, end));
+ vectorStore.add(new ArrayList<>(documents.subList(i, end)));
}
for (AiKnowledgeSegmentDO segment : segments) {
segment.setVectorId(segment.getId().toString());
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java
index 4098e32..7e8f217 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java
@@ -19,6 +19,8 @@
import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO;
+import cn.iocoder.yudao.module.mdm.api.unit.MdmUnitMeasureApi;
+import cn.iocoder.yudao.module.mdm.api.unit.dto.MdmUnitMeasureRespDTO;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
@@ -63,6 +65,8 @@
private CrmBusinessStatusService businessStatusService;
@Resource
private MdmItemApi mdmItemApi;
+ @Resource
+ private MdmUnitMeasureApi mdmUnitMeasureApi;
@Resource
private AdminUserApi adminUserApi;
@@ -119,10 +123,19 @@
List<CrmBusinessProductDO> businessProducts = businessService.getBusinessProductListByBusinessId(businessVO.getId());
Map<Long, MdmItemRespDTO> itemMap = mdmItemApi.getItemMap(
convertSet(businessProducts, CrmBusinessProductDO::getItemId));
+ Map<Long, MdmUnitMeasureRespDTO> unitMap = mdmUnitMeasureApi.getUnitMeasureMap(
+ convertSet(businessProducts, CrmBusinessProductDO::getItemUnitId));
businessVO.setProducts(BeanUtils.toBean(businessProducts, CrmBusinessRespVO.Product.class, businessProductVO ->
MapUtils.findAndThen(itemMap, businessProductVO.getItemId(),
item -> businessProductVO.setItemName(item.getName())
- .setItemCode(item.getCode()).setItemUnitId(item.getUnitMeasureId()))));
+ .setItemCode(item.getCode())
+ .setBarCode(item.getBarCode())
+ .setItemSpecification(item.getSpecification()))));
+ // 濉厖鍗曚綅鍚嶇О
+ businessVO.getProducts().forEach(product -> {
+ MapUtils.findAndThen(unitMap, product.getItemUnitId(),
+ unit -> product.setItemUnitName(unit.getName()));
+ });
return businessVO;
}
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java
index 83e6578..fb126c2 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java
@@ -132,6 +132,14 @@
private String itemCode;
@Schema(description = "璁¢噺鍗曚綅缂栧彿", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long itemUnitId;
+ @Schema(description = "璁¢噺鍗曚綅鍚嶇О", example = "涓�")
+ private String itemUnitName;
+
+ @Schema(description = "鐗╂枡鏉$爜", example = "12345678")
+ private String barCode;
+
+ @Schema(description = "瑙勬牸鍨嬪彿", example = "M8*20")
+ private String itemSpecification;
@Schema(description = "鐗╂枡鍘熶环", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00")
private BigDecimal itemPrice;
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/quotation/CrmSaleQuotationController.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/quotation/CrmSaleQuotationController.java
index 542f3e0..58b5dba 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/quotation/CrmSaleQuotationController.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/quotation/CrmSaleQuotationController.java
@@ -13,7 +13,9 @@
import cn.iocoder.yudao.module.crm.controller.admin.quotation.vo.CrmSaleQuotationSaveReqVO;
import cn.iocoder.yudao.module.crm.dal.dataobject.quotation.CrmSaleQuotationDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.quotation.CrmSaleQuotationProductDO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
+import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService;
import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
import cn.iocoder.yudao.module.crm.service.quotation.CrmSaleQuotationService;
import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
@@ -66,6 +68,8 @@
private MdmUnitMeasureApi mdmUnitMeasureApi;
@Resource
private CrmCustomerService customerService;
+ @Resource
+ private CrmBusinessService businessService;
@Resource
private StorageAttachmentApi storageAttachmentApi;
@@ -178,6 +182,13 @@
respVO.setCustomerName(customer.getName());
}
}
+ // 2.1 濉厖鍟嗘満鍚嶇О
+ if (saleQuotation.getBusinessId() != null) {
+ CrmBusinessDO business = businessService.getBusiness(saleQuotation.getBusinessId());
+ if (business != null) {
+ respVO.setBusinessName(business.getName());
+ }
+ }
// 3. 濉厖鍏宠仈淇℃伅
fillSaleQuotationRelatedFields(respVO);
// 4. 濉厖闄勪欢鍒楄〃
@@ -204,6 +215,9 @@
// 1.5 閮ㄩ棬淇℃伅
Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(
convertSet(pageResult.getList(), CrmSaleQuotationDO::getOwnerUserId));
+ // 1.6 鍟嗘満淇℃伅锛堣繃婊� null锛宐usinessId 涓哄彲閫夊瓧娈碉級
+ Map<Long, CrmBusinessDO> businessMap = businessService.getBusinessMap(
+ convertSet(pageResult.getList(), CrmSaleQuotationDO::getBusinessId, vo -> vo.getBusinessId() != null));
// 2. 寮�濮嬫嫾鎺�
return BeanUtils.toBean(pageResult, CrmSaleQuotationRespVO.class, vo -> {
@@ -213,6 +227,7 @@
MapUtils.findAndThen(customerMap, vo.getCustomerId(), customer -> vo.setCustomerName(customer.getName()));
MapUtils.findAndThen(userMap, vo.getOwnerUserId(), user -> vo.setOwnerUserName(user.getNickname()));
MapUtils.findAndThen(deptMap, vo.getOwnerUserId(), dept -> vo.setOwnerUserDeptName(dept.getName()));
+ MapUtils.findAndThen(businessMap, vo.getBusinessId(), business -> vo.setBusinessName(business.getName()));
});
}
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java
index 0aaa4ec..65c09cf 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java
@@ -257,6 +257,9 @@
if (product.getItemUnitId() == null) {
product.setItemUnitId(old.getItemUnitId());
}
+ } else {
+ // 鏂颁骇鍝侊細娓呴櫎鍓嶇鐢熸垚鐨勪复鏃� ID锛岃鏁版嵁搴� AUTO_INCREMENT 鎺ョ
+ product.setId(null);
}
// 浼樺厛浣跨敤鍓嶇浼犲叆鐨� totalPrice锛屽惁鍒欓�氳繃 businessPrice * count 璁$畻
if (o.getTotalPrice() != null) {
diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java
index 70128e8..df706ac 100644
--- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java
+++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java
@@ -19,6 +19,8 @@
import cn.iocoder.yudao.module.erp.service.purchase.ErpPurchaseOrderService;
import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO;
+import cn.iocoder.yudao.module.mdm.api.unit.MdmUnitMeasureApi;
+import cn.iocoder.yudao.module.mdm.api.unit.dto.MdmUnitMeasureRespDTO;
import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
@@ -56,6 +58,8 @@
@Resource
private MdmItemApi mdmItemApi;
+ @Resource
+ private MdmUnitMeasureApi mdmUnitMeasureApi;
@Resource
private AdminUserApi adminUserApi;
@Resource
@@ -123,12 +127,16 @@
List<ErpPurchaseOrderItemDO> purchaseOrderItemList = purchaseOrderService.getPurchaseOrderItemListByOrderId(id);
Map<Long, MdmItemRespDTO> itemMap = mdmItemApi.getItemMap(
convertSet(purchaseOrderItemList, ErpPurchaseOrderItemDO::getProductId));
+ Map<Long, MdmUnitMeasureRespDTO> unitMeasureMap = mdmUnitMeasureApi.getUnitMeasureMap(
+ convertSet(purchaseOrderItemList, ErpPurchaseOrderItemDO::getProductUnitId));
return success(BeanUtils.toBean(purchaseOrder, ErpPurchaseOrderRespVO.class, purchaseOrderVO ->
purchaseOrderVO.setItems(BeanUtils.toBean(purchaseOrderItemList, ErpPurchaseOrderRespVO.Item.class, item -> {
// 搴撳瓨淇℃伅鏆備笉鏌ヨ锛堜粨鍌ㄧ墿娴佹ā鍧楋級
item.setStockCount(BigDecimal.ZERO);
MapUtils.findAndThen(itemMap, item.getProductId(), mdmItem -> item.setProductName(mdmItem.getName())
.setProductBarCode(mdmItem.getBarCode()));
+ MapUtils.findAndThen(unitMeasureMap, item.getProductUnitId(), unit ->
+ item.setProductUnitName(unit.getName()));
})).setAttachmentList(storageAttachmentApi.listAttachments("erp_purchase_order", id))
.setSourceTypeName(ErpPurchaseOrderSourceTypeEnum.WORK_ORDER.getType()
.equals(purchaseOrder.getSourceType()) ? "鐢熶骇宸ュ崟" : null)));
@@ -180,11 +188,18 @@
// 1.4 绠$悊鍛樹俊鎭�
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
convertSet(pageResult.getList(), purchaseOrder -> Long.parseLong(purchaseOrder.getCreator())));
+ // 1.5 鍗曚綅淇℃伅
+ Map<Long, MdmUnitMeasureRespDTO> unitMeasureMap = mdmUnitMeasureApi.getUnitMeasureMap(
+ convertSet(purchaseOrderItemList, ErpPurchaseOrderItemDO::getProductUnitId));
// 2. 寮�濮嬫嫾鎺�
return BeanUtils.toBean(pageResult, ErpPurchaseOrderRespVO.class, purchaseOrder -> {
purchaseOrder.setItems(BeanUtils.toBean(purchaseOrderItemMap.get(purchaseOrder.getId()), ErpPurchaseOrderRespVO.Item.class,
- item -> MapUtils.findAndThen(itemMap, item.getProductId(), mdmItem -> item.setProductName(mdmItem.getName())
- .setProductBarCode(mdmItem.getBarCode()))));
+ item -> {
+ MapUtils.findAndThen(itemMap, item.getProductId(), mdmItem -> item.setProductName(mdmItem.getName())
+ .setProductBarCode(mdmItem.getBarCode()));
+ MapUtils.findAndThen(unitMeasureMap, item.getProductUnitId(), unit ->
+ item.setProductUnitName(unit.getName()));
+ }));
purchaseOrder.setProductNames(CollUtil.join(purchaseOrder.getItems(), "锛�", ErpPurchaseOrderRespVO.Item::getProductName));
MapUtils.findAndThen(supplierMap, purchaseOrder.getSupplierId(), supplier -> purchaseOrder.setSupplierName(supplier.getName()));
MapUtils.findAndThen(userMap, Long.parseLong(purchaseOrder.getCreator()), user -> purchaseOrder.setCreatorName(user.getNickname()));
diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseRequestController.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseRequestController.java
index 94881f2..8851644 100644
--- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseRequestController.java
+++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseRequestController.java
@@ -18,6 +18,8 @@
import cn.iocoder.yudao.module.erp.service.purchase.ErpPurchaseRequestService;
import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO;
+import cn.iocoder.yudao.module.mdm.api.unit.MdmUnitMeasureApi;
+import cn.iocoder.yudao.module.mdm.api.unit.dto.MdmUnitMeasureRespDTO;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi;
@@ -56,6 +58,8 @@
@Resource
private MdmItemApi mdmItemApi;
+ @Resource
+ private MdmUnitMeasureApi mdmUnitMeasureApi;
@Resource
private AdminUserApi adminUserApi;
@Resource
@@ -99,10 +103,14 @@
List<ErpPurchaseRequestItemDO> purchaseRequestItemList = purchaseRequestService.getPurchaseRequestItemListByRequestId(id);
Map<Long, MdmItemRespDTO> itemMap = mdmItemApi.getItemMap(
convertSet(purchaseRequestItemList, ErpPurchaseRequestItemDO::getProductId));
+ Map<Long, MdmUnitMeasureRespDTO> unitMeasureMap = mdmUnitMeasureApi.getUnitMeasureMap(
+ convertSet(purchaseRequestItemList, ErpPurchaseRequestItemDO::getProductUnitId));
return success(BeanUtils.toBean(purchaseRequest, ErpPurchaseRequestRespVO.class, purchaseRequestVO ->
purchaseRequestVO.setItems(BeanUtils.toBean(purchaseRequestItemList, ErpPurchaseRequestRespVO.Item.class, item -> {
MapUtils.findAndThen(itemMap, item.getProductId(), mdmItem -> item.setProductName(mdmItem.getName())
.setProductBarCode(mdmItem.getBarCode()));
+ MapUtils.findAndThen(unitMeasureMap, item.getProductUnitId(), unit ->
+ item.setProductUnitName(unit.getName()));
})).setAttachmentList(storageAttachmentApi.listAttachments("erp_purchase_request", id))));
}
diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java
index 448bd6e..e2b3242 100644
--- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java
+++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java
@@ -2,6 +2,9 @@
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
+import cn.iocoder.yudao.module.erp.enums.DictTypeConstants;
import cn.iocoder.yudao.module.system.api.storage.dto.StorageBlobRespDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
@@ -25,7 +28,8 @@
private String no;
@Schema(description = "閲囪喘鐘舵��", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
- @ExcelProperty("閲囪喘鐘舵��")
+ @ExcelProperty(value = "閲囪喘鐘舵��", converter = DictConvert.class)
+ @DictFormat(DictTypeConstants.AUDIT_STATUS)
private Integer status;
@Schema(description = "渚涘簲鍟嗙紪鍙�", requiredMode = Schema.RequiredMode.REQUIRED, example = "1724")
diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/request/ErpPurchaseRequestRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/request/ErpPurchaseRequestRespVO.java
index 0ebadb5..74ff12b 100644
--- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/request/ErpPurchaseRequestRespVO.java
+++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/request/ErpPurchaseRequestRespVO.java
@@ -29,6 +29,9 @@
@ExcelProperty(value = "鐘舵��", converter = cn.iocoder.yudao.module.erp.convert.ErpPurchaseRequestStatusConvert.class)
private Integer status;
+ @Schema(description = "娴佺▼瀹炰緥缂栧彿", example = "1024")
+ private String processInstanceId;
+
@Schema(description = "鐢宠浜虹紪鍙�", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ExcelProperty("鐢宠浜虹紪鍙�")
private Long requestUserId;
diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java
index 018261f..3cacd73 100644
--- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java
+++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java
@@ -24,6 +24,7 @@
import cn.iocoder.yudao.module.mes.api.mps.MesProMpsApi;
import cn.iocoder.yudao.module.mes.api.productsales.MesWmProductSalesLineApi;
import cn.iocoder.yudao.module.mes.api.salesnotice.MesWmSalesNoticeApi;
+import cn.iocoder.yudao.module.mes.api.wms.MesWmStockApi;
import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
@@ -72,6 +73,8 @@
private StorageAttachmentApi storageAttachmentApi;
@Resource
private MdmUnitMeasureApi mdmUnitMeasureApi;
+ @Resource
+ private MesWmStockApi mesWmStockApi;
@PostMapping("/create")
@Operation(summary = "鍒涘缓閿�鍞鍗�")
@@ -158,7 +161,7 @@
convertSet(saleOrderItemList, ErpSaleOrderItemDO::getProductUnitId));
// 3. 杞崲璁㈠崟椤�
List<ErpSaleOrderRespVO.Item> itemVOList = BeanUtils.toBean(saleOrderItemList, ErpSaleOrderRespVO.Item.class, item -> {
- item.setStockCount(BigDecimal.ZERO); // 搴撳瓨淇℃伅鏆備笉鏌ヨ锛堜粨鍌ㄧ墿娴佹ā鍧楋級
+ item.setStockCount(mesWmStockApi.getStockQuantity(item.getProductId()));
item.setBatchCode(batchCodeMap.get(item.getId()));
MapUtils.findAndThen(itemMap, item.getProductId(), mdmItem ->
item.setProductName(mdmItem.getName()).setProductBarCode(mdmItem.getBarCode())
diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseRequestServiceImpl.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseRequestServiceImpl.java
index 540aadc..7f2debd 100644
--- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseRequestServiceImpl.java
+++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseRequestServiceImpl.java
@@ -129,7 +129,7 @@
@Transactional(rollbackFor = Exception.class)
public void updatePurchaseRequest(ErpPurchaseRequestSaveReqVO updateReqVO) {
// 1. 鏍¢獙瀛樺湪 + 鑽夌鐘舵��
- ErpPurchaseRequestDO purchaseRequest = validatePurchaseRequestExistsAndDraft(updateReqVO.getId());
+ ErpPurchaseRequestDO purchaseRequest = validatePurchaseRequestCanModify(updateReqVO.getId());
// 2. 鏍¢獙渚涘簲鍟嗭紙濡傛灉鎸囧畾锛�
if (updateReqVO.getSupplierId() != null) {
supplierService.validateSupplier(updateReqVO.getSupplierId());
@@ -198,8 +198,9 @@
return;
}
purchaseRequests.forEach(purchaseRequest -> {
- // 鍙湁鑽夌鐘舵�佹墠鑳藉垹闄�
- if (!ErpPurchaseRequestStatusEnum.DRAFT.getStatus().equals(purchaseRequest.getStatus())) {
+ Integer status = purchaseRequest.getStatus();
+ if (!ErpPurchaseRequestStatusEnum.DRAFT.getStatus().equals(status)
+ && !ErpPurchaseRequestStatusEnum.REJECT.getStatus().equals(status)) {
throw exception(PURCHASE_REQUEST_DELETE_FAIL_NOT_DRAFT, purchaseRequest.getNo());
}
});
@@ -246,7 +247,7 @@
@Transactional(rollbackFor = Exception.class)
public void submitPurchaseRequest(Long id, String processDefinitionKey, Long userId) {
// 1. 鏍¢獙瀛樺湪 + 鑽夌鐘舵��
- ErpPurchaseRequestDO purchaseRequest = validatePurchaseRequestExistsAndDraft(id);
+ ErpPurchaseRequestDO purchaseRequest = validatePurchaseRequestCanModify(id);
// 2. 鏍¢獙鏄惁鏈夋槑缁�
List<ErpPurchaseRequestItemDO> items = purchaseRequestItemMapper.selectListByRequestId(id);
@@ -455,9 +456,11 @@
return purchaseRequest;
}
- private ErpPurchaseRequestDO validatePurchaseRequestExistsAndDraft(Long id) {
+ private ErpPurchaseRequestDO validatePurchaseRequestCanModify(Long id) {
ErpPurchaseRequestDO purchaseRequest = validatePurchaseRequestExists(id);
- if (!ErpPurchaseRequestStatusEnum.DRAFT.getStatus().equals(purchaseRequest.getStatus())) {
+ Integer status = purchaseRequest.getStatus();
+ if (!ErpPurchaseRequestStatusEnum.DRAFT.getStatus().equals(status)
+ && !ErpPurchaseRequestStatusEnum.REJECT.getStatus().equals(status)) {
throw exception(PURCHASE_REQUEST_UPDATE_FAIL_NOT_DRAFT, purchaseRequest.getNo());
}
return purchaseRequest;
diff --git a/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/MdmItemController.java b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/MdmItemController.java
index 461e65e..d48f4e4 100644
--- a/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/MdmItemController.java
+++ b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/MdmItemController.java
@@ -11,14 +11,14 @@
import cn.iocoder.yudao.module.mdm.dal.dataobject.item.MdmItemBatchConfigDO;
import cn.iocoder.yudao.module.mdm.dal.dataobject.item.MdmItemDO;
import cn.iocoder.yudao.module.mdm.dal.dataobject.unit.MdmUnitMeasureDO;
-import cn.iocoder.yudao.module.mdm.dal.dataobject.warehouse.MdmWarehouseDO;
import cn.iocoder.yudao.module.mdm.service.brand.MdmBrandService;
import cn.iocoder.yudao.module.mdm.service.category.MdmItemCategoryService;
import cn.iocoder.yudao.module.mdm.service.item.MdmItemBatchConfigService;
import cn.iocoder.yudao.module.mdm.service.item.MdmItemService;
import cn.iocoder.yudao.module.mdm.service.unit.MdmUnitMeasureService;
-import cn.iocoder.yudao.module.mdm.service.warehouse.MdmWarehouseService;
import cn.iocoder.yudao.module.mes.api.item.MesMdItemApi;
+import cn.iocoder.yudao.module.mes.api.wm.warehouse.MesWmWarehouseApi;
+import cn.iocoder.yudao.module.mes.api.wm.warehouse.dto.MesWmWarehouseRespDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -51,7 +51,7 @@
@Resource
private MdmUnitMeasureService unitMeasureService;
@Resource
- private MdmWarehouseService warehouseService;
+ private MesWmWarehouseApi mesWmWarehouseApi;
@Resource
private MdmBrandService brandService;
@Resource
@@ -139,14 +139,14 @@
});
Map<Long, MdmUnitMeasureDO> auxUnitMap = unitIds.isEmpty() ?
Collections.emptyMap() : unitMeasureService.getUnitMeasureMap(unitIds);
- // 鎵归噺鍏宠仈鏌ヨ浠撳簱鍚嶇О
+ // 鎵归噺鍏宠仈鏌ヨ浠撳簱鍚嶇О锛堜娇鐢� MES 浠撳簱锛�
Set<Long> warehouseIds = new HashSet<>();
respList.forEach(resp -> {
if (resp.getWarehouseId() != null) warehouseIds.add(resp.getWarehouseId());
});
- Map<Long, MdmWarehouseDO> warehouseMap = warehouseIds.isEmpty() ?
- Collections.emptyMap() : warehouseService.getWarehouseList(warehouseIds).stream()
- .collect(Collectors.toMap(MdmWarehouseDO::getId, w -> w));
+ Map<Long, MesWmWarehouseRespDTO> warehouseMap = warehouseIds.isEmpty() ?
+ Collections.emptyMap() : mesWmWarehouseApi.getWarehouseList(warehouseIds).stream()
+ .collect(Collectors.toMap(MesWmWarehouseRespDTO::getId, w -> w));
// 璧嬪��
respList.forEach(resp -> {
// 鍒嗙被鍚嶇О
@@ -166,7 +166,7 @@
if (auxUnit2 != null) {
resp.setUnitMeasureName3(auxUnit2.getName());
}
- MdmWarehouseDO warehouse = warehouseMap.get(resp.getWarehouseId());
+ MesWmWarehouseRespDTO warehouse = warehouseMap.get(resp.getWarehouseId());
if (warehouse != null) {
resp.setWarehouseName(warehouse.getName());
}
@@ -234,11 +234,11 @@
resp.setUnitMeasureName3(unit3.getName());
}
}
- // 榛樿浠撳簱鍚嶇О
+ // 榛樿浠撳簱鍚嶇О锛堜娇鐢� MES 浠撳簱锛�
if (resp.getWarehouseId() != null) {
- MdmWarehouseDO warehouse = warehouseService.getWarehouse(resp.getWarehouseId());
- if (warehouse != null) {
- resp.setWarehouseName(warehouse.getName());
+ List<MesWmWarehouseRespDTO> warehouses = mesWmWarehouseApi.getWarehouseList(List.of(resp.getWarehouseId()));
+ if (!warehouses.isEmpty()) {
+ resp.setWarehouseName(warehouses.get(0).getName());
}
}
}
diff --git a/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/warehouse/MdmWarehouseController.java b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/warehouse/MdmWarehouseController.java
index 0c15cdf..84da9a1 100644
--- a/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/warehouse/MdmWarehouseController.java
+++ b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/warehouse/MdmWarehouseController.java
@@ -89,9 +89,9 @@
@GetMapping("/list-all-simple")
@Operation(summary = "鑾峰緱鍏ㄩ儴鍚敤鐨勪粨搴撳垪琛�")
public CommonResult<List<MdmWarehouseRespVO>> getSimpleWarehouseList() {
- MdmWarehouseDO query = new MdmWarehouseDO();
- query.setStatus(0);
- List<MdmWarehouseDO> list = warehouseService.getWarehousePage(new MdmWarehousePageReqVO()).getList();
+ MdmWarehousePageReqVO reqVO = new MdmWarehousePageReqVO();
+ reqVO.setStatus(0);
+ List<MdmWarehouseDO> list = warehouseService.getWarehousePage(reqVO).getList();
return success(BeanUtils.toBean(list, MdmWarehouseRespVO.class));
}
diff --git a/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/wm/warehouse/MesWmWarehouseApi.java b/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/wm/warehouse/MesWmWarehouseApi.java
new file mode 100644
index 0000000..9767668
--- /dev/null
+++ b/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/wm/warehouse/MesWmWarehouseApi.java
@@ -0,0 +1,21 @@
+package cn.iocoder.yudao.module.mes.api.wm.warehouse;
+
+import cn.iocoder.yudao.module.mes.api.wm.warehouse.dto.MesWmWarehouseRespDTO;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * MES 浠撳簱 API 鎺ュ彛
+ */
+public interface MesWmWarehouseApi {
+
+ /**
+ * 鑾峰彇浠撳簱鍒楄〃
+ *
+ * @param ids 浠撳簱ID鍒楄〃
+ * @return 浠撳簱鍒楄〃
+ */
+ List<MesWmWarehouseRespDTO> getWarehouseList(Collection<Long> ids);
+
+}
diff --git a/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/wm/warehouse/dto/MesWmWarehouseRespDTO.java b/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/wm/warehouse/dto/MesWmWarehouseRespDTO.java
new file mode 100644
index 0000000..6fc6581
--- /dev/null
+++ b/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/wm/warehouse/dto/MesWmWarehouseRespDTO.java
@@ -0,0 +1,15 @@
+package cn.iocoder.yudao.module.mes.api.wm.warehouse.dto;
+
+import lombok.Data;
+
+/**
+ * MES 浠撳簱 Response DTO
+ */
+@Data
+public class MesWmWarehouseRespDTO {
+
+ private Long id;
+ private String code;
+ private String name;
+
+}
diff --git a/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/wms/MesWmStockApi.java b/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/wms/MesWmStockApi.java
new file mode 100644
index 0000000..62af579
--- /dev/null
+++ b/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/wms/MesWmStockApi.java
@@ -0,0 +1,20 @@
+package cn.iocoder.yudao.module.mes.api.wms;
+
+import java.math.BigDecimal;
+
+/**
+ * WMS 搴撳瓨鏌ヨ API 鎺ュ彛
+ *
+ * 渚涘叾浠栨ā鍧楋紙濡� ERP锛夋煡璇㈢墿鏂欏簱瀛樻暟閲�
+ */
+public interface MesWmStockApi {
+
+ /**
+ * 鑾峰彇鐗╂枡搴撳瓨鎬婚噺锛堟墍鏈変粨搴撴眹鎬伙級
+ *
+ * @param itemId 鐗╂枡ID
+ * @return 搴撳瓨鏁伴噺
+ */
+ BigDecimal getStockQuantity(Long itemId);
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/api/wm/warehouse/MesWmWarehouseApiImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/api/wm/warehouse/MesWmWarehouseApiImpl.java
new file mode 100644
index 0000000..ef7755c
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/api/wm/warehouse/MesWmWarehouseApiImpl.java
@@ -0,0 +1,35 @@
+package cn.iocoder.yudao.module.mes.api.wm.warehouse;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.mes.api.wm.warehouse.dto.MesWmWarehouseRespDTO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO;
+import cn.iocoder.yudao.module.mes.dal.mysql.wm.warehouse.MesWmWarehouseMapper;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * MES 浠撳簱 API 瀹炵幇绫�
+ */
+@Service
+@Validated
+public class MesWmWarehouseApiImpl implements MesWmWarehouseApi {
+
+ @Resource
+ private MesWmWarehouseMapper warehouseMapper;
+
+ @Override
+ public List<MesWmWarehouseRespDTO> getWarehouseList(Collection<Long> ids) {
+ if (CollUtil.isEmpty(ids)) {
+ return Collections.emptyList();
+ }
+ List<MesWmWarehouseDO> list = warehouseMapper.selectListByIds(ids);
+ return BeanUtils.toBean(list, MesWmWarehouseRespDTO.class);
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/api/wms/MesWmStockApiImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/api/wms/MesWmStockApiImpl.java
new file mode 100644
index 0000000..abcccbb
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/api/wms/MesWmStockApiImpl.java
@@ -0,0 +1,37 @@
+package cn.iocoder.yudao.module.mes.api.wms;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO;
+import cn.iocoder.yudao.module.mes.dal.mysql.wm.materialstock.MesWmMaterialStockMapper;
+import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockListReqVO;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * WMS 搴撳瓨 API 瀹炵幇绫�
+ */
+@Service
+@Validated
+public class MesWmStockApiImpl implements MesWmStockApi {
+
+ @Resource
+ private MesWmMaterialStockMapper materialStockMapper;
+
+ @Override
+ public BigDecimal getStockQuantity(Long itemId) {
+ MesWmMaterialStockListReqVO reqVO = new MesWmMaterialStockListReqVO();
+ reqVO.setItemId(itemId);
+ List<MesWmMaterialStockDO> stockList = materialStockMapper.selectList(reqVO);
+ if (CollUtil.isEmpty(stockList)) {
+ return BigDecimal.ZERO;
+ }
+ return stockList.stream()
+ .map(MesWmMaterialStockDO::getQuantity)
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/MesProFeedbackController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/MesProFeedbackController.java
index 010925b..db782f7 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/MesProFeedbackController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/MesProFeedbackController.java
@@ -8,6 +8,8 @@
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.feedback.vo.MesProFeedbackApproveReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.feedback.vo.MesProFeedbackBatchCheckRespVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.feedback.vo.MesProFeedbackBatchCreateReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.feedback.vo.MesProFeedbackBatchCreateRespVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.feedback.vo.MesProFeedbackPageReqVO;
@@ -192,10 +194,17 @@
@PutMapping("/approve")
@Operation(summary = "瀹℃壒鎶ュ伐")
- @Parameter(name = "id", description = "缂栧彿", required = true)
@PreAuthorize("@ss.hasPermission('mes:pro-feedback:approve')")
- public CommonResult<Boolean> approveFeedback(@RequestParam("id") Long id) {
- return success(feedbackService.approveFeedback(id));
+ public CommonResult<Boolean> approveFeedback(@Valid @RequestBody MesProFeedbackApproveReqVO reqVO) {
+ return success(feedbackService.approveFeedback(reqVO));
+ }
+
+ @GetMapping("/batch-requirements")
+ @Operation(summary = "妫�鏌ユ姤宸ュ鎵瑰墠鏄惁闇�瑕佸~鍐欐壒娆″睘鎬�")
+ @Parameter(name = "id", description = "鎶ュ伐鍗曠紪鍙�", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:pro-feedback:approve')")
+ public CommonResult<MesProFeedbackBatchCheckRespVO> getBatchRequirements(@RequestParam("id") Long id) {
+ return success(feedbackService.checkBatchRequirements(id));
}
@PostMapping("/quick-create")
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackApproveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackApproveReqVO.java
new file mode 100644
index 0000000..50cfaa5
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackApproveReqVO.java
@@ -0,0 +1,50 @@
+package cn.iocoder.yudao.module.mes.controller.admin.pro.feedback.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "绠$悊鍚庡彴 - MES 鐢熶骇鎶ュ伐瀹℃壒閫氳繃 Request VO")
+@Data
+public class MesProFeedbackApproveReqVO {
+
+ @Schema(description = "鎶ュ伐鍗曠紪鍙�", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ @NotNull(message = "鎶ュ伐鍗旾D涓嶈兘涓虹┖")
+ private Long id;
+
+ @Schema(description = "鐢熶骇鏃ユ湡")
+ private LocalDateTime produceDate;
+
+ @Schema(description = "杩囨湡鏃ユ湡")
+ private LocalDateTime expireDate;
+
+ @Schema(description = "鍏ュ簱鏃ユ湡")
+ private LocalDateTime receiptDate;
+
+ @Schema(description = "渚涘簲鍟咺D")
+ private Long vendorId;
+
+ @Schema(description = "瀹㈡埛ID")
+ private Long clientId;
+
+ @Schema(description = "閲囪喘璁㈠崟缂栧彿")
+ private String purchaseOrderCode;
+
+ @Schema(description = "閿�鍞鍗曠紪鍙�")
+ private String salesOrderCode;
+
+ @Schema(description = "宸ュ叿ID")
+ private Long toolId;
+
+ @Schema(description = "妯″叿ID")
+ private Long moldId;
+
+ @Schema(description = "鐢熶骇鎵瑰彿")
+ private String lotNumber;
+
+ @Schema(description = "璐ㄩ噺鐘舵��")
+ private Integer qualityStatus;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackBatchCheckRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackBatchCheckRespVO.java
new file mode 100644
index 0000000..146587c
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackBatchCheckRespVO.java
@@ -0,0 +1,63 @@
+package cn.iocoder.yudao.module.mes.controller.admin.pro.feedback.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Schema(description = "绠$悊鍚庡彴 - MES 鐢熶骇鎶ュ伐鎵规闇�姹傛鏌� Response VO")
+@Data
+public class MesProFeedbackBatchCheckRespVO {
+
+ @Schema(description = "鏄惁闇�瑕佹壒娆′俊鎭脊绐�")
+ private Boolean needBatchInput;
+
+ @Schema(description = "鏄惁鍚敤鎵规绠$悊")
+ private Boolean isBatchManaged;
+
+ @Schema(description = "鐢熶骇鏃ユ湡蹇呭~")
+ private Boolean produceDateFlag;
+
+ @Schema(description = "鏈夋晥鏈熷繀濉�")
+ private Boolean expireDateFlag;
+
+ @Schema(description = "鍏ュ簱鏃ユ湡蹇呭~")
+ private Boolean receiptDateFlag;
+
+ @Schema(description = "渚涘簲鍟嗗繀濉�")
+ private Boolean vendorFlag;
+
+ @Schema(description = "瀹㈡埛蹇呭~")
+ private Boolean clientFlag;
+
+ @Schema(description = "閿�鍞鍗曠紪鍙峰繀濉�")
+ private Boolean salesOrderCodeFlag;
+
+ @Schema(description = "閲囪喘璁㈠崟缂栧彿蹇呭~")
+ private Boolean purchaseOrderCodeFlag;
+
+ @Schema(description = "鐢熶骇宸ュ崟蹇呭~")
+ private Boolean workOrderFlag;
+
+ @Schema(description = "鐢熶骇浠诲姟蹇呭~")
+ private Boolean taskFlag;
+
+ @Schema(description = "宸ヤ綔绔欏繀濉�")
+ private Boolean workstationFlag;
+
+ @Schema(description = "宸ュ叿蹇呭~")
+ private Boolean toolFlag;
+
+ @Schema(description = "妯″叿蹇呭~")
+ private Boolean moldFlag;
+
+ @Schema(description = "鐢熶骇鎵瑰彿蹇呭~")
+ private Boolean lotNumberFlag;
+
+ @Schema(description = "璐ㄩ噺鐘舵�佸繀濉�")
+ private Boolean qualityStatusFlag;
+
+ @Schema(description = "宸茶嚜鍔ㄥ~鍏呯殑瀛楁鍚嶅垪琛�")
+ private List<String> autoFilledFields;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
index 5c661bc..81e15c6 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
@@ -18,7 +18,6 @@
ErrorCode MD_ITEM_TYPE_CODE_DUPLICATE = new ErrorCode(1_040_100_005, "鍚屼竴鐖跺垎绫讳笅宸插瓨鍦ㄨ缂栫爜鐨勫垎绫�");
ErrorCode MD_ITEM_TYPE_PARENT_IS_CHILD = new ErrorCode(1_040_100_006, "涓嶈兘璁剧疆鑷繁鐨勫瓙鍒嗙被涓虹埗鍒嗙被");
ErrorCode MD_ITEM_TYPE_EXITS_ITEM = new ErrorCode(1_040_100_007, "璇ュ垎绫讳笅瀛樺湪鐗╂枡锛屾棤娉曞垹闄�");
- ErrorCode MD_ITEM_TYPE_NOT_LEAF = new ErrorCode(1_040_100_008, "鍙兘灏嗙墿鏂欐寕杞藉埌鍙跺瓙鍒嗙被锛堣鍒嗙被涓嬪瓨鍦ㄥ瓙鍒嗙被锛�");
// ========== MES 鍩虹鏁版嵁-璁¢噺鍗曚綅锛�1-040-101-000锛� ==========
ErrorCode MD_UNIT_MEASURE_NOT_EXISTS = new ErrorCode(1_040_101_000, "璁¢噺鍗曚綅涓嶅瓨鍦�");
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemServiceImpl.java
index fcefee0..0899d3a 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemServiceImpl.java
@@ -213,11 +213,6 @@
if (itemTypeService.getItemType(itemTypeId) == null) {
throw exception(MD_ITEM_TYPE_NOT_EXISTS);
}
- // 鏍¢獙蹇呴』鏄彾瀛愬垎绫伙紙娌℃湁瀛愬垎绫伙級
- List<MesMdItemTypeDO> children = itemTypeService.getItemTypeChildrenList(itemTypeId);
- if (CollUtil.isNotEmpty(children)) {
- throw exception(MD_ITEM_TYPE_NOT_LEAF);
- }
}
private void validateUnitMeasureExists(Long unitMeasureId) {
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackService.java
index db97db6..69bc7a5 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackService.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackService.java
@@ -108,10 +108,18 @@
* </li>
* </ol>
*
- * @param id 鎶ュ伐鍗曠紪鍙�
+ * @param reqVO 瀹℃壒璇锋眰锛堝惈鎶ュ伐鍗曠紪鍙峰強鍙�夋壒娆″睘鎬э級
* @return true=宸插畬鎴�, false=寰呮楠岋紙闇�绛夎川妫�鍥炶皟锛�
*/
- boolean approveFeedback(Long id);
+ boolean approveFeedback(@Valid MesProFeedbackApproveReqVO reqVO);
+
+ /**
+ * 妫�鏌ユ姤宸ュ鎵瑰墠鏄惁闇�瑕佸~鍐欐壒娆″睘鎬�
+ *
+ * @param feedbackId 鎶ュ伐鍗曠紪鍙�
+ * @return 鎵规闇�姹傛鏌ョ粨鏋�
+ */
+ MesProFeedbackBatchCheckRespVO checkBatchRequirements(Long feedbackId);
/**
* IPQC 瀹屾垚鍚庡洖璋冿細瀹屾垚鎶ュ伐鍗曞苟鏇存柊浠诲姟/宸ュ崟杩涘害
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java
index 6f36f8c..64d5383 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java
@@ -28,6 +28,10 @@
import cn.iocoder.yudao.module.mes.service.wm.itemconsume.MesWmItemConsumeService;
import cn.iocoder.yudao.module.mes.service.wm.productproduce.MesWmProductProduceLineService;
import cn.iocoder.yudao.module.mes.service.wm.productproduce.MesWmProductProduceService;
+import cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService;
+import cn.iocoder.yudao.module.mes.dal.dataobject.mdm.MesMdmItemDO;
+import cn.iocoder.yudao.module.mdm.api.item.MdmItemBatchConfigApi;
+import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemBatchConfigRespDTO;
import cn.iocoder.yudao.module.mes.api.mps.MesProMpsApi;
import cn.iocoder.yudao.module.mes.api.mps.dto.MesProMpsRespDTO;
import cn.iocoder.yudao.module.mes.api.event.ProductionFinishedEvent;
@@ -40,6 +44,7 @@
import java.math.BigDecimal;
import java.time.LocalDateTime;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -80,6 +85,10 @@
private MesMdAutoCodeRecordService autoCodeRecordService;
@Resource
private ApplicationEventPublisher eventPublisher;
+ @Resource
+ private MesMdmItemService mdmItemService;
+ @Resource
+ private MdmItemBatchConfigApi itemBatchConfigApi;
@Override
public Long createFeedback(MesProFeedbackSaveReqVO createReqVO) {
@@ -161,9 +170,9 @@
@Override
@Transactional(rollbackFor = Exception.class)
- public boolean approveFeedback(Long id) {
+ public boolean approveFeedback(MesProFeedbackApproveReqVO reqVO) {
// 1.1 鏍¢獙瀛樺湪 + 瀹℃壒涓姸鎬�
- MesProFeedbackDO feedback = validateFeedbackStatusApproving(id);
+ MesProFeedbackDO feedback = validateFeedbackStatusApproving(reqVO.getId());
// 1.2 鏍¢獙鎶ュ伐鏁伴噺 > 0
if (feedback.getFeedbackQuantity() == null
|| feedback.getFeedbackQuantity().compareTo(BigDecimal.ZERO) <= 0) {
@@ -201,7 +210,7 @@
}
// 5. 鍏堟洿鏂版姤宸ョ姸鎬佷负宸插畬鎴愶紙纭繚 checkAndFinishMps 妫�鏌ユ椂褰撳墠鎶ュ伐宸叉爣璁板畬鎴愶級
- feedbackMapper.updateById(new MesProFeedbackDO().setId(id)
+ feedbackMapper.updateById(new MesProFeedbackDO().setId(reqVO.getId())
.setStatus(MesProFeedbackStatusEnum.FINISHED.getStatus())
.setUncheckQuantity(BigDecimal.ZERO));
@@ -209,13 +218,13 @@
if (checkFlag) {
// 6.1 闇�瑕佹楠岋細鐢熸垚浜у嚭鍗曪紙璐ㄩ噺鐘舵��=寰呮楠岋級锛屾洿鏂版姤宸ョ姸鎬佷负寰呮楠岋紝绛夎川妫�瀹屾垚鍥炶皟鍚庡啀鍏ュ簱
// 瀹屾垚鏃跺洖璋冭锛歁esQcIpqcServiceImpl#finishIpqc 鈫� splitPendingAndFinishProduce + updateProFeedbackWhenIpqcFinish
- productProduceService.generateProductProduce(feedback, true);
- feedbackMapper.updateById(new MesProFeedbackDO().setId(id)
+ productProduceService.generateProductProduce(feedback, true, reqVO);
+ feedbackMapper.updateById(new MesProFeedbackDO().setId(reqVO.getId())
.setStatus(MesProFeedbackStatusEnum.UNCHECK.getStatus()));
return false;
} else {
// 6.2 鏃犻渶妫�楠岋細鐢熸垚浜у嚭鍗曪紙鎸夊悎鏍�/涓嶅悎鏍兼媶琛岋級锛岀洿鎺ュ畬鎴愬叆搴�
- MesWmProductProduceDO produce = productProduceService.generateProductProduce(feedback, false);
+ MesWmProductProduceDO produce = productProduceService.generateProductProduce(feedback, false, reqVO);
productProduceService.finishProductProduce(produce.getId());
// 鍏抽敭宸ュ簭锛氭洿鏂颁换鍔� + 宸ュ崟鐨勫凡鐢熶骇鏁伴噺锛涢潪鍏抽敭宸ュ簭锛氬彧鏇存柊浠诲姟鐨勫凡鐢熶骇鏁伴噺锛堝伐鍗曞彧鐪嬪叧閿伐搴忎骇鍑猴級
if (keyFlag) {
@@ -480,4 +489,70 @@
updateTaskAndWorkOrderByFeedback(feedback);
}
+ @Override
+ public MesProFeedbackBatchCheckRespVO checkBatchRequirements(Long feedbackId) {
+ MesProFeedbackDO feedback = validateFeedbackExists(feedbackId);
+ MesProFeedbackBatchCheckRespVO respVO = new MesProFeedbackBatchCheckRespVO();
+
+ // 1. 妫�鏌ョ墿鏂欐槸鍚﹀惎鐢ㄦ壒娆$鐞�
+ MesMdmItemDO item = mdmItemService.getItem(feedback.getItemId());
+ if (item == null || Boolean.FALSE.equals(item.getIsBatchManaged())) {
+ respVO.setNeedBatchInput(false);
+ respVO.setIsBatchManaged(false);
+ return respVO;
+ }
+ respVO.setIsBatchManaged(true);
+
+ // 2. 鑾峰彇鎵规閰嶇疆
+ MdmItemBatchConfigRespDTO config = itemBatchConfigApi.getItemBatchConfig(feedback.getItemId());
+ if (config == null) {
+ respVO.setNeedBatchInput(false);
+ return respVO;
+ }
+
+ // 3. 濉厖閰嶇疆鏍囧織
+ respVO.setProduceDateFlag(config.getProduceDateFlag());
+ respVO.setExpireDateFlag(config.getExpireDateFlag());
+ respVO.setReceiptDateFlag(config.getReceiptDateFlag());
+ respVO.setVendorFlag(config.getVendorFlag());
+ respVO.setClientFlag(config.getClientFlag());
+ respVO.setSalesOrderCodeFlag(config.getSalesOrderCodeFlag());
+ respVO.setPurchaseOrderCodeFlag(config.getPurchaseOrderCodeFlag());
+ respVO.setWorkOrderFlag(config.getWorkOrderFlag());
+ respVO.setTaskFlag(config.getTaskFlag());
+ respVO.setWorkstationFlag(config.getWorkstationFlag());
+ respVO.setToolFlag(config.getToolFlag());
+ respVO.setMoldFlag(config.getMoldFlag());
+ respVO.setLotNumberFlag(config.getLotNumberFlag());
+ respVO.setQualityStatusFlag(config.getQualityStatusFlag());
+
+ // 4. 鍒ゆ柇鍝簺瀛楁宸茶嚜鍔ㄥ~鍏咃紙鎶ュ伐鍜岀敓浜ц繃绋嬩腑蹇呯劧鏈夊�肩殑瀛楁锛�
+ List<String> autoFilled = new ArrayList<>();
+ // 鐢熶骇鏃ユ湡锛氬鎵规椂鑷姩鍙栧綋澶�
+ autoFilled.add("produceDate");
+ // 鐢熶骇宸ュ崟锛氫粠鎶ュ伐璁板綍鑾峰彇
+ autoFilled.add("workOrderId");
+ // 鐢熶骇浠诲姟锛氫粠鎶ュ伐璁板綍鑾峰彇
+ autoFilled.add("taskId");
+ // 宸ヤ綔绔欙細浠庢姤宸ヨ褰曡幏鍙�
+ autoFilled.add("workstationId");
+ respVO.setAutoFilledFields(autoFilled);
+
+ // 5. 鍒ゆ柇鏄惁闇�瑕佸脊绐楋細瀛樺湪蹇呭~浣嗘棤娉曡嚜鍔ㄥ~鍏呯殑瀛楁
+ boolean needBatchInput = false;
+ if (Boolean.TRUE.equals(config.getExpireDateFlag())) needBatchInput = true;
+ if (Boolean.TRUE.equals(config.getReceiptDateFlag())) needBatchInput = true;
+ if (Boolean.TRUE.equals(config.getVendorFlag())) needBatchInput = true;
+ if (Boolean.TRUE.equals(config.getClientFlag())) needBatchInput = true;
+ if (Boolean.TRUE.equals(config.getSalesOrderCodeFlag())) needBatchInput = true;
+ if (Boolean.TRUE.equals(config.getPurchaseOrderCodeFlag())) needBatchInput = true;
+ if (Boolean.TRUE.equals(config.getToolFlag())) needBatchInput = true;
+ if (Boolean.TRUE.equals(config.getMoldFlag())) needBatchInput = true;
+ if (Boolean.TRUE.equals(config.getLotNumberFlag())) needBatchInput = true;
+ if (Boolean.TRUE.equals(config.getQualityStatusFlag())) needBatchInput = true;
+ respVO.setNeedBatchInput(needBatchInput);
+
+ return respVO;
+ }
+
}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceService.java
index 76188cf..fe17810 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceService.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceService.java
@@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.mes.service.wm.productproduce;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.feedback.vo.MesProFeedbackApproveReqVO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceDO;
@@ -30,9 +31,11 @@
*
* @param feedback 鎶ュ伐璁板綍
* @param checkFlag 鏄惁闇�瑕佹楠岋紙true=寰呮楠岋紝false=鎸夊悎鏍�/涓嶅悎鏍兼媶鍒嗚锛�
+ * @param approveReqVO 瀹℃壒璇锋眰锛堝惈鍙�夋壒娆″睘鎬э紝鍙负 null锛�
* @return 鐢熸垚鐨勪骇鍝佷骇鍑哄崟
*/
- MesWmProductProduceDO generateProductProduce(MesProFeedbackDO feedback, boolean checkFlag);
+ MesWmProductProduceDO generateProductProduce(MesProFeedbackDO feedback, boolean checkFlag,
+ MesProFeedbackApproveReqVO approveReqVO);
/**
* IPQC 妫�楠屽畬鎴愬洖璋冿細灏嗗緟妫�浜у嚭鎷嗗垎涓哄悎鏍�/涓嶅悎鏍艰銆佺敓鎴愭槑缁嗐�佸畬鎴愬叆搴�
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceServiceImpl.java
index fd6f98a..ef11a06 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceServiceImpl.java
@@ -4,6 +4,7 @@
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.feedback.vo.MesProFeedbackApproveReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchGenerateReqVO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
@@ -110,7 +111,8 @@
@Override
@Transactional(rollbackFor = Exception.class)
- public MesWmProductProduceDO generateProductProduce(MesProFeedbackDO feedback, boolean checkFlag) {
+ public MesWmProductProduceDO generateProductProduce(MesProFeedbackDO feedback, boolean checkFlag,
+ MesProFeedbackApproveReqVO approveReqVO) {
// 0. 鏌ヨ鍏宠仈鐨勫伐鍗曪紙鐢ㄤ簬鑾峰彇 clientId 绛変俊鎭級
MesProWorkOrderDO workOrder = workOrderService.getWorkOrder(feedback.getWorkOrderId());
@@ -122,16 +124,30 @@
.build();
productProduceMapper.insert(produce);
- // 2. 鑾峰彇鎴栫敓鎴愭壒娆�
+ // 2. 鑾峰彇鎴栫敓鎴愭壒娆★紙瀹℃壒璇锋眰涓殑鎵规灞炴�т紭鍏堬級
MesWmBatchGenerateReqVO batchReqVO = new MesWmBatchGenerateReqVO()
.setItemId(feedback.getItemId())
.setProduceDate(LocalDate.now().atStartOfDay()) // 鎴柇鍒板綋澶╅浂鐐癸紝纭繚鍚屼竴澶╃殑鎶ュ伐鐢熸垚鐩稿悓鎵规鍙�
.setExpireDate(feedback.getExpireDate())
.setWorkOrderId(feedback.getWorkOrderId())
+ .setTaskId(feedback.getTaskId())
.setClientId(workOrder != null ? workOrder.getClientId() : null)
.setSalesOrderCode(workOrder != null ? workOrder.getOrderSourceCode() : null)
.setWorkstationId(feedback.getWorkstationId())
.setLotNumber(feedback.getLotNumber());
+ // 鍚堝苟瀹℃壒璇锋眰涓敤鎴峰~鍐欑殑鎵规灞炴�э紙鐢ㄦ埛杈撳叆鍊间紭鍏堬級
+ if (approveReqVO != null) {
+ if (approveReqVO.getExpireDate() != null) batchReqVO.setExpireDate(approveReqVO.getExpireDate());
+ if (approveReqVO.getReceiptDate() != null) batchReqVO.setReceiptDate(approveReqVO.getReceiptDate());
+ if (approveReqVO.getVendorId() != null) batchReqVO.setVendorId(approveReqVO.getVendorId());
+ if (approveReqVO.getClientId() != null) batchReqVO.setClientId(approveReqVO.getClientId());
+ if (approveReqVO.getSalesOrderCode() != null) batchReqVO.setSalesOrderCode(approveReqVO.getSalesOrderCode());
+ if (approveReqVO.getPurchaseOrderCode() != null) batchReqVO.setPurchaseOrderCode(approveReqVO.getPurchaseOrderCode());
+ if (approveReqVO.getToolId() != null) batchReqVO.setToolId(approveReqVO.getToolId());
+ if (approveReqVO.getMoldId() != null) batchReqVO.setMoldId(approveReqVO.getMoldId());
+ if (approveReqVO.getLotNumber() != null) batchReqVO.setLotNumber(approveReqVO.getLotNumber());
+ if (approveReqVO.getQualityStatus() != null) batchReqVO.setQualityStatus(approveReqVO.getQualityStatus());
+ }
MesWmBatchDO batch = batchService.getOrGenerateBatchCode(batchReqVO);
Long batchId = batch != null ? batch.getId() : null;
String batchCode = batch != null ? batch.getCode() : null;
diff --git a/yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/enums/ErrorCodeConstants.java b/yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/enums/ErrorCodeConstants.java
index 106b948..ed09224 100644
--- a/yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/enums/ErrorCodeConstants.java
+++ b/yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/enums/ErrorCodeConstants.java
@@ -58,6 +58,9 @@
ErrorCode TENDER_BID_FORBIDDEN_WITHDRAW = new ErrorCode(1_040_500_028, "褰撳墠鐘舵�佷笉鍏佽鎾ゆ爣");
ErrorCode TENDER_EVALUATION_FORBIDDEN = new ErrorCode(1_040_500_029, "褰撳墠鐘舵�佷笉鍏佽璇勬爣鎿嶄綔");
ErrorCode TENDER_AWARD_FORBIDDEN = new ErrorCode(1_040_500_030, "褰撳墠鐘舵�佷笉鍏佽瀹氭爣鎿嶄綔");
+ ErrorCode AWARD_BID_NOT_IN_PROJECT = new ErrorCode(1_040_500_031, "鎶曟爣璁板綍涓嶅睘浜庡綋鍓嶆嫑鏍囬」鐩�");
+ ErrorCode AWARD_BID_WITHDRAWN = new ErrorCode(1_040_500_032, "鎶曟爣宸叉挙鏍囷紝涓嶅厑璁稿畾鏍�");
+ ErrorCode AWARD_SUPPLIER_NOT_MATCH_BID = new ErrorCode(1_040_500_033, "渚涘簲鍟嗕笌鎶曟爣璁板綍涓嶄竴鑷�");
// ========== 閫氱敤 ==========
ErrorCode QUOTE_MATERIAL_DUPLICATE = new ErrorCode(1_040_900_001, "璇ユ姇鏍囧凡瀛樺湪鐩稿悓鐗╂枡鐨勬姤浠�");
diff --git a/yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/service/tender/SrmBidAwardServiceImpl.java b/yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/service/tender/SrmBidAwardServiceImpl.java
index 6104b97..f005359 100644
--- a/yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/service/tender/SrmBidAwardServiceImpl.java
+++ b/yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/service/tender/SrmBidAwardServiceImpl.java
@@ -22,6 +22,7 @@
import org.springframework.validation.annotation.Validated;
import java.math.BigDecimal;
+import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
@@ -76,17 +77,28 @@
if (existing != null) {
throw ServiceExceptionUtil.exception(ErrorCodeConstants.AWARD_SUPPLIER_EXISTS);
}
+ // 鏍¢獙鎶曟爣璁板綍锛氬繀椤诲睘浜庤椤圭洰銆佹湭琚挙鏍囥�佷笖渚涘簲鍟嗕竴鑷�
+ SrmTenderBidDO bid = tenderBidMapper.selectById(createReqVO.getBidId());
+ if (bid == null) {
+ throw ServiceExceptionUtil.exception(ErrorCodeConstants.BID_NOT_EXISTS);
+ }
+ if (!bid.getTenderProjectId().equals(createReqVO.getTenderProjectId())) {
+ throw ServiceExceptionUtil.exception(ErrorCodeConstants.AWARD_BID_NOT_IN_PROJECT);
+ }
+ if (BidStatusEnum.WITHDRAWN.getCode().equals(bid.getBidStatus())) {
+ throw ServiceExceptionUtil.exception(ErrorCodeConstants.AWARD_BID_WITHDRAWN);
+ }
+ if (!bid.getSupplierId().equals(createReqVO.getSupplierId())) {
+ throw ServiceExceptionUtil.exception(ErrorCodeConstants.AWARD_SUPPLIER_NOT_MATCH_BID);
+ }
SrmBidAwardDO award = BeanUtils.toBean(createReqVO, SrmBidAwardDO.class);
award.setAwardStatus(AwardStatusEnum.PENDING_APPROVAL.getCode());
award.setAwardTime(LocalDateTime.now());
bidAwardMapper.insert(award);
// 鏇存柊鎶曟爣鐘舵�佷负涓爣
- SrmTenderBidDO bid = tenderBidMapper.selectById(createReqVO.getBidId());
- if (bid != null) {
- bid.setBidStatus(BidStatusEnum.WIN.getCode());
- tenderBidMapper.updateById(bid);
- }
+ bid.setBidStatus(BidStatusEnum.WIN.getCode());
+ tenderBidMapper.updateById(bid);
return award.getId();
}
@@ -175,7 +187,15 @@
Map<Long, MdmItemRespDTO> itemMap = mdmItemApi.getItemList(productIds).getCheckedData()
.stream().collect(Collectors.toMap(MdmItemRespDTO::getId, Function.identity()));
- // 6. 鏋勫缓璁㈠崟椤�
+ // 6. 鏋勫缓璁㈠崟椤癸紙鎶ヤ环涓烘�讳环锛岄渶闄や互鏁伴噺寰楀埌鍗曚环锛�
+ BigDecimal totalQuoteAmount = quotes.stream()
+ .map(SrmSupplierQuoteDO::getQuotePrice)
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+ BigDecimal awardAmount = award.getAwardAmount() != null ? award.getAwardAmount() : totalQuoteAmount;
+ BigDecimal ratio = totalQuoteAmount.compareTo(BigDecimal.ZERO) > 0
+ ? awardAmount.divide(totalQuoteAmount, 8, RoundingMode.HALF_UP)
+ : BigDecimal.ONE;
+
List<ErpPurchaseOrderCreateReqDTO.Item> orderItems = new ArrayList<>();
for (SrmTenderMaterialDO material : materials) {
SrmSupplierQuoteDO quote = quoteMap.get(material.getId());
@@ -186,10 +206,12 @@
if (mdmItem == null) {
continue;
}
+ BigDecimal materialTotal = quote.getQuotePrice().multiply(ratio);
+ BigDecimal unitPrice = materialTotal.divide(material.getQuantity(), 4, RoundingMode.HALF_UP);
ErpPurchaseOrderCreateReqDTO.Item item = new ErpPurchaseOrderCreateReqDTO.Item();
item.setProductId(material.getProductId());
item.setProductUnitId(mdmItem.getUnitMeasureId());
- item.setProductPrice(quote.getQuotePrice());
+ item.setProductPrice(unitPrice);
item.setCount(material.getQuantity());
item.setTaxPercent(quote.getTaxRate());
item.setRemark("鎷涙爣缂栧彿: " + award.getAwardNo());
diff --git a/yudao-server/src/main/resources/application-test.yaml b/yudao-server/src/main/resources/application-test.yaml
index ac895f6..aa1ace1 100644
--- a/yudao-server/src/main/resources/application-test.yaml
+++ b/yudao-server/src/main/resources/application-test.yaml
@@ -227,7 +227,7 @@
milvus:
initialize-schema: true
database-name: test
- collection-name: knowledge_segment
+ collection-name: knowledge_segment_test
host: 36.213.180.217
port: 19530
@@ -282,7 +282,7 @@
storage: # 鏂囦欢涓婁紶閰嶇疆
path: /data/javaWork/mom/file # 鏂囦欢瀛樺偍鏍圭洰褰�
url-prefix: /admin-api/system/storage-blob # URL璺緞鍓嶇紑
- domain: https://test.your-domain.com # 鍩熷悕鍓嶇紑锛堟寜瀹為檯鍩熷悕閰嶇疆锛�
+ domain: http://36.213.180.217:9500 # 鍩熷悕鍓嶇紑锛堟寜瀹為檯鍩熷悕閰嶇疆锛夛紝鍓嶇閰嶇疆濂藉儚涓嶅お瀵圭幇鍦ㄦ槸鐩磋繛鍚庣锛屾墍鏈夎鍚庣绔彛
expired: 120 # token杩囨湡鏃堕棿锛堝垎閽燂級
use-limit: 10 # token浣跨敤娆℃暟涓婇檺
jwt-secret: abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG # JWT瀵嗛挜
diff --git a/yudao-server/src/main/resources/logback-spring.xml b/yudao-server/src/main/resources/logback-spring.xml
index 2ad3a66..6f7d8dd 100644
--- a/yudao-server/src/main/resources/logback-spring.xml
+++ b/yudao-server/src/main/resources/logback-spring.xml
@@ -8,7 +8,7 @@
<property name="ERROR_LOG_FILE" value="./logs/error/error.log"/>
<!-- 鎺у埗鍙� Appender -->
- <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">銆�銆�銆�銆�銆�
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
--
Gitblit v1.9.3