From be5783c8a7e13bbc76d33c95643d75779cce21db Mon Sep 17 00:00:00 2001
From: liyong <18434998025@163.com>
Date: 星期六, 18 七月 2026 15:39:05 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_business' into dev_business

---
 yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java                         |    8 
 yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java                                    |   30 
 TODO.md                                                                                                                              |  164 ++
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/MesQcIqcController.java                           |   13 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnvendor/MesWmReturnVendorDO.java                   |    3 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/mps/MesProMpsMergeItemMapper.java                           |   25 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImpl.java                                   |   80 +
 yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/api/customer/CrmCustomerApi.java                                          |    9 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/MesProTaskController.java                       |   13 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptDO.java                     |    3 
 yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/sale/listener/ErpSaleOrderStatusListener.java                     |  160 ++
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/mps/MesProMpsController.java                         |  156 ++
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorServiceImpl.java                 |    6 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemServiceImpl.java                                 |   17 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/MesProWorkOrderController.java             |   27 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/pendinginspect/MesQcPendingInspectController.java     |   19 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/arrivalnotice/MesWmArrivalNoticeDO.java                 |    3 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/MesWmOutsourceIssueController.java     |   13 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/batch/MesWmBatchMapper.java                                  |   32 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/packages/MesWmPackageMapper.java                             |   22 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeServiceImpl.java                   |   20 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/mps/MesProMpsService.java                                     |  148 ++
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/MesWmProductIssueController.java         |   11 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/mps/vo/MesProMpsRespVO.java                          |  125 ++
 .claude/rules/powershell-commands.md                                                                                                 |   35 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesServiceImpl.java                   |    9 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workorder/MesProWorkOrderMapper.java                        |   25 
 yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/mps/dto/MesProMpsRespDTO.java                                     |   69 +
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImpl.java                                   |   16 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdItemMapper.java                                    |    4 
 yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java                              |    5 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/salesnotice/MesWmSalesNoticeDO.java                     |    1 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesDO.java                   |    1 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueServiceImpl.java             |    6 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/mps/MesProMpsMergeItemDO.java                          |   62 +
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageServiceImpl.java                          |    6 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/packages/MesWmPackageDO.java                            |    3 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java                                             |   11 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProMpsStatusEnum.java                                        |   52 
 docs/mps_integration.md                                                                                                              |  224 +++
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/mps/MesProMpsMapper.java                                    |   96 +
 yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java                    |   13 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/MesWmOutsourceReceiptController.java |   11 
 yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderSaveReqVO.java                 |    3 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/api/salesnotice/MesWmSalesNoticeApiImpl.java                              |   41 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/iqc/MesQcIqcDO.java                                     |    3 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/DictTypeConstants.java                                              |    1 
 yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/mps/dto/MesProMpsCreateReqDTO.java                                |   44 
 yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/salesnotice/MesWmSalesNoticeApi.java                              |   21 
 yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java                                  |    7 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/batch/MesWmBatchController.java                       |   23 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderServiceImpl.java                     |    7 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java                 |   35 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptServiceImpl.java         |    6 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineServiceImpl.java             |   39 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/mps/MesProMpsServiceImpl.java                                 |  433 +++++++
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskDO.java                                 |    3 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnsales/MesWmReturnSalesMapper.java                      |   24 
 yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/quotation/CrmSaleQuotationServiceImpl.java                        |    7 
 yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java                                 |   21 
 yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/quotation/CrmSaleQuotationMapper.java                           |   21 
 yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java                              |    9 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/MesWmReturnVendorController.java         |   13 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourcereceipt/MesWmOutsourceReceiptDO.java           |    3 
 docs/sql/mes_pro_mps.sql                                                                                                             |   92 +
 yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java                                 |    3 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/mps/vo/MesProMpsPageReqVO.java                       |   46 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/api/mps/MesProMpsApiImpl.java                                             |   63 +
 yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderItemDO.java                               |   14 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueDO.java               |    3 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/salesnotice/MesWmSalesNoticeMapper.java                      |   39 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchServiceImpl.java                               |    7 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/oqc/MesQcOqcMapper.java                                      |   23 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/MesWmPackageController.java                  |   11 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workorder/MesProWorkOrderDO.java                       |    6 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productsales/MesWmProductSalesMapper.java                    |   21 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/MesQcOqcController.java                           |   11 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/mps/MesProMpsDO.java                                   |  148 ++
 yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/api/customer/CrmCustomerApiImpl.java                                      |  164 ++
 /dev/null                                                                                                                            |  229 ---
 yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/mps/MesProMpsApi.java                                             |   49 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/mps/vo/MesProMpsSaveReqVO.java                       |   58 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcService.java                                       |   12 
 yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/api/customer/CrmCustomerApi.java                                      |    9 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/materialstock/MesWmMaterialStockDO.java                 |    3 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/batch/MesWmBatchDO.java                                 |    6 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemService.java                                     |   17 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/MesWmMaterialStockController.java       |   11 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/oqc/MesQcOqcDO.java                                     |    3 
 .claude/worktrees/agent-a1e034d925913c04a                                                                                            |    1 
 90 files changed, 3,166 insertions(+), 403 deletions(-)

diff --git a/.claude/rules/powershell-commands.md b/.claude/rules/powershell-commands.md
new file mode 100644
index 0000000..04a9b69
--- /dev/null
+++ b/.claude/rules/powershell-commands.md
@@ -0,0 +1,35 @@
+# PowerShell 鍛戒护瑙勫垯
+
+## 瑙勫垯
+
+鐢变簬椤圭洰杩愯鍦� Windows 鐜涓嬶紝鐢ㄦ埛缁堢榛樿浣跨敤 PowerShell 鑰岄潪 bash銆傚湪鎻愪緵鍛戒护琛屾寚瀵兼椂锛屽繀椤讳娇鐢� PowerShell 璇硶銆�
+
+## 甯哥敤鍛戒护瀵圭収
+
+| 鎿嶄綔 | Bash | PowerShell |
+|------|------|-------------|
+| 鍒犻櫎鐩綍 | `rm -rf <path>` | `Remove-Item -Recurse -Force <path>` 鎴栫畝鍐� `ri -r -fo <path>` |
+| 澶嶅埗鏂囦欢 | `cp <src> <dest>` | `Copy-Item <src> <dest>` 鎴栫畝鍐� `cp <src> <dest>` |
+| 绉诲姩鏂囦欢 | `mv <src> <dest>` | `Move-Item <src> <dest>` 鎴栫畝鍐� `mv <src> <dest>` |
+| 鍒涘缓鐩綍 | `mkdir -p <path>` | `New-Item -ItemType Directory -Path <path>` 鎴栫畝鍐� `md <path>` |
+| 鏌ョ湅鏂囦欢 | `cat <file>` | `Get-Content <file>` 鎴栫畝鍐� `gc <file>` |
+| 鍒楀嚭鏂囦欢 | `ls` | `Get-ChildItem` 鎴栫畝鍐� `ls`/`dir` |
+| 鏌ユ壘鏂囦欢 | `find . -name "*.java"` | `Get-ChildItem -Recurse -Filter "*.java"` 鎴栫畝鍐� `gci -r -fi "*.java"` |
+| 鏌ユ壘鍐呭 | `grep -r "pattern" .` | `Select-String -Path "*.java" -Pattern "pattern"` 鎴栫畝鍐� `sls "pattern" *.java -r` |
+
+## 鍒犻櫎鐩綍绀轰緥
+
+```powershell
+# 鎺ㄨ崘锛氫娇鐢� Remove-Item 瀹屾暣鍛戒护
+Remove-Item -Recurse -Force yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/client
+
+# 绠�鍐欏舰寮�
+ri -r -fo yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/client
+```
+
+## 娉ㄦ剰浜嬮」
+
+- PowerShell 鍙傛暟浣跨敤 `-` 鍓嶇紑锛屽 `-Recurse`銆乣-Force`
+- 鍙傛暟鍙互绠�鍐欓瀛楁瘝锛屽 `-r`銆乣-fo`
+- 璺緞鍒嗛殧绗﹀湪 PowerShell 涓彲浠ヤ娇鐢� `/` 鎴� `\`锛屾帹鑽愪娇鐢� `/` 浠ヤ繚鎸佽法骞冲彴鍏煎
+- 閬垮厤 `-rf` 杩欐牱鐨� bash 椋庢牸鍙傛暟缁勫悎锛孭owerShell 涓嶆敮鎸�
\ No newline at end of file
diff --git a/.claude/worktrees/agent-a1e034d925913c04a b/.claude/worktrees/agent-a1e034d925913c04a
new file mode 160000
index 0000000..a26b31c
--- /dev/null
+++ b/.claude/worktrees/agent-a1e034d925913c04a
@@ -0,0 +1 @@
+Subproject commit a26b31cc9f3ee9b21b1a754e80fa7359e8a7a8f8
diff --git a/TODO.md b/TODO.md
new file mode 100644
index 0000000..e0f6741
--- /dev/null
+++ b/TODO.md
@@ -0,0 +1,164 @@
+# 鍒犻櫎 MES 瀹㈡埛鍜屼緵搴斿晢妯″潡 - 杩涘害璺熻釜
+
+## 浠诲姟姒傝堪
+鍒犻櫎 MES 妯″潡涓嫭绔嬬殑瀹㈡埛锛圡esMdClient锛夊拰渚涘簲鍟嗭紙MesMdVendor锛夌鐞嗗姛鑳斤紝鏀逛负澶嶇敤锛�
+- **瀹㈡埛**锛氫娇鐢� CRM 鐨勫鎴风鐞嗭紙CrmCustomerApi锛�
+- **渚涘簲鍟�**锛氫娇鐢ㄩ噰璐ā鍧楃殑渚涘簲鍟嗙鐞嗭紙ErpSupplierApi锛�
+
+---
+
+## 宸插畬鎴� 鉁�
+
+### Step 1: 鎵╁睍 CRM 鍜� ERP API
+- [x] CrmCustomerApi 宸叉湁 `validateCustomer` 鏂规硶锛屽彲鐩存帴浣跨敤
+- [x] ErpSupplierApi 宸叉湁 `validateSupplier` 鏂规硶锛堝凡鏍¢獙瀛樺湪+鍚敤锛夛紝鍙洿鎺ヤ娇鐢�
+
+### Step 2: 鏇挎崲 Service 灞傚紩鐢�
+
+**瀹㈡埛鏍¢獙鏇挎崲锛�4涓枃浠讹級锛�**
+- [x] MesWmProductSalesServiceImpl.java
+- [x] MesWmSalesNoticeServiceImpl.java
+- [x] MesWmReturnSalesServiceImpl.java
+- [x] MesQcOqcServiceImpl.java
+
+**渚涘簲鍟嗘牎楠屾浛鎹紙5涓枃浠讹級锛�**
+- [x] MesWmReturnVendorServiceImpl.java
+- [x] MesWmOutsourceReceiptServiceImpl.java
+- [x] MesWmOutsourceIssueServiceImpl.java
+- [x] MesQcIqcServiceImpl.java
+
+### Step 3: 鏇挎崲 Controller 灞傚紩鐢�
+
+**瀹㈡埛淇℃伅鎷兼帴锛堝凡瀹屾垚锛夛細**
+- [x] MesProTaskController.java
+- [x] MesProMpsController.java
+- [x] MesQcOqcController.java
+- [x] MesQcPendingInspectController.java
+- [x] MesWmProductIssueController.java
+- [x] MesWmBatchController.java
+- [x] MesWmPackageController.java
+
+**渚涘簲鍟嗕俊鎭嫾鎺ワ紙宸插畬鎴愶級锛�**
+- [x] MesWmMaterialStockController.java
+- [x] MesWmBatchController.java
+- [x] MesWmReturnVendorController.java
+- [x] MesWmOutsourceReceiptController.java
+- [x] MesWmOutsourceIssueController.java
+- [x] MesQcIqcController.java
+- [x] MesQcPendingInspectController.java
+- [x] MesProWorkOrderController.java
+
+### Step 4: 鏇存柊 DO 娉ㄩ噴
+
+**瀹㈡埛锛�6涓枃浠讹級锛�**
+- [x] MesProWorkOrderDO
+- [x] MesProTaskDO
+- [x] MesProMpsDO
+- [x] MesQcOqcDO
+- [x] MesWmBatchDO
+- [x] MesWmPackageDO
+
+**渚涘簲鍟嗭紙7涓枃浠讹級锛�**
+- [x] MesWmReturnVendorDO
+- [x] MesWmOutsourceReceiptDO
+- [x] MesWmOutsourceIssueDO
+- [x] MesWmMaterialStockDO
+- [x] MesWmBatchDO
+- [x] MesQcIqcDO
+- [x] MesProWorkOrderDO
+
+**鍏朵粬鐩稿叧 DO 鏂囦欢锛�**
+- [x] MesWmArrivalNoticeDO
+- [x] MesWmItemReceiptDO
+- [x] MesWmProductSalesDO
+- [x] MesWmSalesNoticeDO
+
+### Step 5: 娓呯悊鏃犵敤 import
+
+- [x] 鍒犻櫎鎵�鏈� DO 鏂囦欢涓殑 `MesMdClientDO` 鍜� `MesMdVendorDO` import 璇彞
+
+### Step 6: 鍒犻櫎 MES 瀹㈡埛/渚涘簲鍟嗘ā鍧楁枃浠�
+
+**寰呭垹闄ょ洰褰曪紙闇�鎵嬪姩鎵ц锛夛細**
+```
+yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/
+yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/
+yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/client/
+yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/vendor/
+yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/client/
+yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/vendor/
+yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/client/
+yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/vendor/
+```
+
+### Step 7: 鍒犻櫎鏁版嵁搴撹〃
+
+- [x] `DROP TABLE IF EXISTS mes_md_client;` 鉁� 宸叉墽琛�
+- [x] `DROP TABLE IF EXISTS mes_md_vendor;` 鉁� 宸叉墽琛�
+
+### 缂栬瘧楠岃瘉
+- [x] `mvn compile -pl yudao-module-mes -am -q` 缂栬瘧閫氳繃 鉁�
+
+### Step 8: 瀹㈡埛鏉冮檺杩囨护锛堜富鏌ヨ锛�
+
+**宸叉坊鍔� CRM API 鏂规硶锛�**
+- [x] CrmCustomerApi.getPermittedCustomerIds() - 鑾峰彇鐢ㄦ埛鏈夋潈闄愮殑瀹㈡埛 ID 鍒楄〃
+
+**宸叉坊鍔犲鎴锋潈闄愯繃婊ょ殑 Mapper 鍜� Service锛�**
+- [x] MesWmSalesNoticeMapper + MesWmSalesNoticeService - 鍙戣揣閫氱煡鍗�
+- [x] MesWmReturnSalesMapper + MesWmReturnSalesService - 閿�鍞��璐у崟
+- [x] MesWmProductSalesMapper + MesWmProductSalesService - 閿�鍞嚭搴撳崟
+- [x] MesWmPackageMapper + MesWmPackageService - 瑁呯鍗�
+- [x] MesWmBatchMapper + MesWmBatchService - 鎵规绠$悊
+- [x] MesQcOqcMapper + MesQcOqcService - 鍑鸿揣妫�楠屽崟
+- [x] MesProWorkOrderMapper + MesProWorkOrderService - 鐢熶骇宸ュ崟
+- [x] MesProMpsMapper + MesProMpsService - 鐢熶骇涓昏鍒�
+- [x] ErpSaleOrderMapper + ErpSaleOrderService - ERP 閿�鍞鍗�
+
+**缂栬瘧楠岃瘉锛�**
+- [x] `mvn compile -pl yudao-module-mes -am -q` 缂栬瘧閫氳繃 鉁�
+- [x] `mvn compile -pl yudao-module-erp -am -q` 缂栬瘧閫氳繃 鉁�
+
+### Step 9: CRM 妯″潡瀹㈡埛鏉冮檺杩囨护
+
+**宸叉坊鍔犲鎴锋潈闄愯繃婊わ細**
+- [x] CrmContractMapper + CrmContractService - 鍚堝悓绠$悊
+- [x] CrmSaleQuotationMapper + CrmSaleQuotationService - 閿�鍞姤浠峰崟
+
+**缂栬瘧楠岃瘉锛�**
+- [x] `mvn compile -pl yudao-module-crm -am -q` 缂栬瘧閫氳繃 鉁�
+
+---
+
+## 寰呮墜鍔ㄦ墽琛�
+
+### 鍒犻櫎妯″潡鏂囦欢
+
+鍦� IDE 鎴栫粓绔腑鎵ц浠ヤ笅鍛戒护鍒犻櫎 MES 瀹㈡埛/渚涘簲鍟嗘ā鍧楁枃浠讹細
+
+```bash
+rm -rf yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client
+rm -rf yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor
+rm -rf yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/client
+rm -rf yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/vendor
+rm -rf yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/client
+rm -rf yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/vendor
+rm -rf yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/client
+rm -rf yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/vendor
+```
+
+---
+
+## 淇敼瑙勫垯鎬荤粨
+
+- **瀹㈡埛 API 璋冪敤**锛�
+  - `clientService.getClientMap(ids)` 鈫� `customerApi.getCustomerMap(ids)`锛堢洿鎺ヨ繑鍥� Map锛�
+  - `clientService.validateClientExistsAndEnable(id)` 鈫� `customerApi.validateCustomer(id)`
+
+- **渚涘簲鍟� API 璋冪敤**锛�
+  - `vendorService.getVendorMap(ids)` 鈫� `supplierApi.getSupplierList(ids).getCheckedData()`锛堣繑鍥� List锛岄渶杞� Map锛�
+  - `vendorService.validateVendorExistsAndEnable(id)` 鈫� `supplierApi.validateSupplier(id)`
+
+- **DTO 瀛楁宸紓**锛�
+  - `CrmCustomerRespDTO` 鏃� `code` 鍜� `nickname` 瀛楁锛屽彧鏈� `name`
+  - `ErpSupplierRespDTO` 鏃� `code` 鍜� `nickname` 瀛楁锛屽彧鏈� `name`
diff --git a/docs/mps_integration.md b/docs/mps_integration.md
new file mode 100644
index 0000000..cad1176
--- /dev/null
+++ b/docs/mps_integration.md
@@ -0,0 +1,224 @@
+# 鐢熶骇涓昏鍒掞紙MPS锛�- 鍓嶇鑱旇皟鏂规
+
+## 娑夊強椤甸潰
+
+- 閿�鍞鍗曞垪琛ㄩ〉锛堟柊澧�"鏄惁闇�瑕佺敓浜�"鍒楋級
+- 閿�鍞鍗曡鎯呴〉锛堟柊澧�"鏄惁闇�瑕佺敓浜�"寮�鍏筹級
+- 鐢熶骇涓昏鍒掑垪琛ㄩ〉锛堟柊澧烇級
+- 鐢熶骇涓昏鍒掕鎯呴〉锛堟柊澧烇級
+- 鐢熶骇涓昏鍒掓柊澧為〉锛堟柊澧烇紝鏀寔鎵嬪姩鍒涘缓锛�
+
+## 涓氬姟娴佺▼涓庢暟鎹甫鍏�
+
+### 1. 鎵嬪姩鍒涘缓 MPS
+
+```
+鐢熶骇涓昏鍒掓柊澧為〉
+    鈫�
+濉啓锛氫骇鍝併�佹暟閲忋�佸鎴枫�侀渶姹傛棩鏈熺瓑
+    鈫�
+鎻愪氦鍒涘缓 MPS锛堢紪鐮佽嚜鍔ㄧ敓鎴愶級
+    鈫�
+MPS 鐘舵�佷负鑽夌
+```
+
+**鑷姩鐢熸垚缂栫爜鏍煎紡**锛歚MPS + yyyyMMdd + 001`锛堝 MPS20240701001锛�
+
+### 2. 閿�鍞鍗曞鏍搁�氳繃 -> 鑷姩鍒涘缓 MPS
+
+```
+閿�鍞鍗曞鏍搁�氳繃
+    鈫�
+BPM 鐩戝惉鍣ㄨЕ鍙�
+    鈫�
+閬嶅巻閿�鍞鍗曟槑缁嗭紝瀵逛簬 need_production=1 鐨勬槑缁�
+    鈫�
+璋冪敤 MesProMpsApi.createMps() 鍒涘缓 MPS
+    鈫�
+鏇存柊閿�鍞鍗曟槑缁嗙殑 mps_id 瀛楁
+```
+
+**鏁版嵁甯﹀叆锛�**
+- MPS.sale_order_id 鈫� 閿�鍞鍗�.id
+- MPS.sale_order_no 鈫� 閿�鍞鍗�.no
+- MPS.sale_order_item_id 鈫� 閿�鍞鍗曟槑缁�.id
+- MPS.product_id 鈫� 閿�鍞鍗曟槑缁�.productId
+- MPS.quantity 鈫� 閿�鍞鍗曟槑缁�.count
+- MPS.client_id 鈫� 閿�鍞鍗�.customerId
+- MPS.request_date 鈫� 閿�鍞鍗�.orderTime
+
+### 2. MPS 涓嬪彂 -> 鐢熸垚鐢熶骇璁㈠崟
+
+```
+MPS 鍗曟潯涓嬪彂
+    鈫�
+鍒涘缓鐢熶骇宸ュ崟锛堢被鍨�=鑷鐢熶骇锛屾潵婧愮被鍨�=瀹㈡埛璁㈠崟锛�
+    鈫�
+宸ュ崟鑷姩纭涓哄凡纭鐘舵��
+    鈫�
+鏇存柊 MPS 鐘舵�佷负宸蹭笅鍙戯紝鍏宠仈宸ュ崟 ID
+```
+
+### 3. MPS 鍚堝苟涓嬪彂
+
+```
+閫夋嫨澶氭潯鐩稿悓浜у搧鐨� MPS
+    鈫�
+鏍¢獙锛氱浉鍚屼骇鍝併�佽崏绋跨姸鎬�
+    鈫�
+璁$畻鍚堝苟鏁伴噺 = SUM(quantity)
+    鈫�
+鍒涘缓涓�鏉$敓浜у伐鍗曪紙鏁伴噺涓哄悎骞舵暟閲忥級
+    鈫�
+鏇存柊鎵�鏈� MPS 鐘舵�佷负宸蹭笅鍙戯紝鍏宠仈鍚屼竴宸ュ崟
+    鈫�
+璁板綍鍚堝苟鏄庣粏鍒� mes_pro_mps_merge_item
+```
+
+## API
+
+### MPS 鐩稿叧鎺ュ彛
+
+| 鏂规硶 | 璺緞 | 璇存槑 |
+|------|------|------|
+| POST | /mes/pro-mps/create | 鍒涘缓 MPS |
+| PUT | /mes/pro-mps/update | 鏇存柊 MPS |
+| DELETE | /mes/pro-mps/delete | 鍒犻櫎 MPS |
+| GET | /mes/pro-mps/get | 鑾峰彇 MPS 璇︽儏 |
+| GET | /mes/pro-mps/page | 鍒嗛〉鏌ヨ MPS |
+| POST | /mes/pro-mps/issue | 涓嬪彂鍗曟潯 MPS |
+| POST | /mes/pro-mps/merge-issue | 鍚堝苟涓嬪彂澶氭潯 MPS |
+| POST | /mes/pro-mps/cancel | 鍙栨秷 MPS |
+| GET | /mes/pro-mps/export-excel | 瀵煎嚭 MPS |
+
+### 閿�鍞鍗曟帴鍙e彉鏇�
+
+| 鏂规硶 | 璺緞 | 鍙樻洿璇存槑 |
+|------|------|----------|
+| GET | /erp/sale-order/get | 鍝嶅簲鏂板 needProduction銆乵psId 瀛楁 |
+| GET | /erp/sale-order/page | 鍝嶅簲鏂板 needProduction 瀛楁 |
+| POST | /erp/sale-order/create | 璇锋眰鏂板 needProduction 瀛楁 |
+| PUT | /erp/sale-order/update | 璇锋眰鏂板 needProduction 瀛楁 |
+
+## 璇锋眰鍙傛暟
+
+### MPS 鍒涘缓璇锋眰
+
+```json
+{
+  "productId": 300,
+  "quantity": 100.00,
+  "unitMeasureId": 1,
+  "clientId": 400,
+  "requestDate": "2024-01-01T00:00:00",
+  "remark": "澶囨敞"
+}
+```
+
+**璇存槑**锛�
+- `code` 瀛楁鍙�夛紝涓嶅~鍒欒嚜鍔ㄧ敓鎴�
+- `saleOrderId`銆乣saleOrderNo`銆乣saleOrderItemId` 鍙�夛紝鎵嬪姩鍒涘缓鏃朵笉濉�
+```
+
+### MPS 涓嬪彂璇锋眰
+
+```
+POST /mes/pro-mps/issue?id=123
+```
+
+### MPS 鍚堝苟涓嬪彂璇锋眰
+
+```json
+// POST /mes/pro-mps/merge-issue
+[123, 124, 125]
+```
+
+## 鍝嶅簲瀛楁
+
+### MPS 璇︽儏鍝嶅簲
+
+| 瀛楁 | 绫诲瀷 | 璇存槑 |
+|------|------|------|
+| id | Long | MPS 缂栧彿 |
+| code | String | MPS 缂栫爜 |
+| status | Integer | 鐘舵�侊紙0=鑽夌 1=宸蹭笅鍙� 2=宸插畬鎴� 3=宸插彇娑堬級 |
+| saleOrderId | Long | 閿�鍞鍗旾D |
+| saleOrderNo | String | 閿�鍞鍗曞彿 |
+| saleOrderItemId | Long | 閿�鍞鍗曟槑缁咺D |
+| productId | Long | 浜у搧ID |
+| productCode | String | 浜у搧缂栫爜 |
+| productName | String | 浜у搧鍚嶇О |
+| productSpecification | String | 瑙勬牸鍨嬪彿 |
+| unitMeasureName | String | 鍗曚綅 |
+| quantity | BigDecimal | 璁″垝鐢熶骇鏁伴噺 |
+| quantityProduced | BigDecimal | 宸茬敓浜ф暟閲� |
+| clientId | Long | 瀹㈡埛ID |
+| clientCode | String | 瀹㈡埛缂栫爜 |
+| clientName | String | 瀹㈡埛鍚嶇О |
+| requestDate | DateTime | 闇�姹傛棩鏈� |
+| issueDate | DateTime | 涓嬪彂鏃ユ湡 |
+| finishDate | DateTime | 瀹屾垚鏃ユ湡 |
+| workOrderId | Long | 鐢熶骇宸ュ崟ID |
+| workOrderCode | String | 鐢熶骇宸ュ崟缂栫爜 |
+| mergeFlag | Integer | 鏄惁鍚堝苟涓嬪彂 |
+| mergeBatchNo | String | 鍚堝苟鎵规鍙� |
+| remark | String | 澶囨敞 |
+| createTime | DateTime | 鍒涘缓鏃堕棿 |
+
+### 鍝嶅簲绀轰緥
+
+```json
+{
+  "code": 0,
+  "data": {
+    "id": 1024,
+    "code": "MPS-001",
+    "status": 0,
+    "saleOrderId": 100,
+    "saleOrderNo": "SO-001",
+    "productId": 300,
+    "productCode": "P-001",
+    "productName": "浜у搧A",
+    "quantity": 100.00,
+    "quantityProduced": 0,
+    "clientId": 400,
+    "clientName": "瀹㈡埛A",
+    "requestDate": "2024-01-01T00:00:00",
+    "mergeFlag": 0,
+    "createTime": "2024-01-01T10:00:00"
+  },
+  "msg": "鎿嶄綔鎴愬姛"
+}
+```
+
+## 瀛楁灞曠ず瑙勫垯
+
+| 瀛楁 | 灞曠ず浣嶇疆 | 璇存槑 |
+|------|----------|------|
+| MPS 缂栫爜 | 鍒楄〃銆佽鎯� | 涓婚敭鏍囪瘑 |
+| 鐘舵�� | 鍒楄〃銆佽鎯� | 鑽夌(钃�)銆佸凡涓嬪彂(缁�)銆佸凡瀹屾垚(绱�)銆佸凡鍙栨秷(绾�) |
+| 閿�鍞鍗曞彿 | 鍒楄〃銆佽鎯� | 鍏宠仈鏉ユ簮 |
+| 浜у搧缂栫爜/鍚嶇О | 鍒楄〃銆佽鎯� | 鐢熶骇瀵硅薄 |
+| 璁″垝鏁伴噺 | 鍒楄〃銆佽鎯� | 鏍稿績鏁版嵁 |
+| 宸茬敓浜ф暟閲� | 璇︽儏 | 杩涘害璺熻釜 |
+| 瀹㈡埛鍚嶇О | 鍒楄〃銆佽鎯� | 闇�姹傛柟 |
+| 闇�姹傛棩鏈� | 鍒楄〃銆佽鎯� | 浜ゆ湡瑕佹眰 |
+| 鐢熶骇宸ュ崟缂栫爜 | 鍒楄〃銆佽鎯� | 涓嬪彂鍚庢樉绀猴紝鍙偣鍑昏烦杞� |
+
+## 涓氬姟瑙勫垯璇存槑
+
+| 鍦烘櫙 | 瑙勫垯 |
+|------|------|
+| 鍒涘缓 MPS | 浠呰崏绋跨姸鎬佸彲缂栬緫銆佸垹闄� |
+| 涓嬪彂 MPS | 浠呰崏绋跨姸鎬佸彲涓嬪彂锛屼笅鍙戝悗鐢熸垚鐢熶骇宸ュ崟骞惰嚜鍔ㄧ‘璁� |
+| 鍚堝苟涓嬪彂 | 鑷冲皯閫夋嫨 2 鏉★紝蹇呴』鐩稿悓浜у搧锛屽繀椤婚兘鏄崏绋跨姸鎬� |
+| 鍙栨秷 MPS | 浠呭凡涓嬪彂鐘舵�佸彲鍙栨秷 |
+| 瀹屾垚 MPS | 鐢辩敓浜у伐鍗曞畬鎴愭椂鑷姩瑙﹀彂 |
+
+## 娉ㄦ剰浜嬮」
+
+1. **閿�鍞鍗曞鎵规祦绋�**锛氶攢鍞鍗曞鏍搁�氳繃鍚庝細鑷姩鍒涘缓 MPS锛屾棤闇�鍓嶇鎵嬪姩瑙﹀彂
+2. **MPS 涓庨攢鍞鍗曞叧鑱�**锛氶�氳繃 saleOrderItemId 瀛楁鍏宠仈锛屽彲杩芥函鏉ユ簮
+3. **鍚堝苟涓嬪彂闄愬埗**锛氬彧鑳藉悎骞剁浉鍚屼骇鍝佺殑 MPS锛屼笉鍚屼骇鍝佷笉鑳藉悎骞�
+4. **鐘舵�佷笉鍙��**锛氫笅鍙戝悗鏃犳硶鍥炲埌鑽夌鐘舵�侊紝鍙兘鍙栨秷鎴栧畬鎴�
+5. **鐢熶骇杩涘害鍚屾**锛歁PS 鐨勫凡鐢熶骇鏁伴噺鐢辩敓浜у伐鍗曟姤宸ユ椂鑷姩鏇存柊
\ No newline at end of file
diff --git a/docs/sql/mes_pro_mps.sql b/docs/sql/mes_pro_mps.sql
new file mode 100644
index 0000000..5c6b4d7
--- /dev/null
+++ b/docs/sql/mes_pro_mps.sql
@@ -0,0 +1,92 @@
+-- =============================================
+-- MES 鐢熶骇涓昏鍒掞紙MPS锛夎〃
+-- =============================================
+CREATE TABLE IF NOT EXISTS `mes_pro_mps` (
+    `id` bigint NOT NULL AUTO_INCREMENT COMMENT '缂栧彿',
+    `code` varchar(64) NOT NULL COMMENT 'MPS 缂栫爜',
+    `status` tinyint NOT NULL DEFAULT 0 COMMENT '鐘舵�侊紙0=鑽夌 1=宸蹭笅鍙� 2=宸插畬鎴� 3=宸插彇娑堬級',
+
+    -- 鏉ユ簮淇℃伅锛堟潵鑷攢鍞鍗曪級
+    `sale_order_id` bigint DEFAULT NULL COMMENT '閿�鍞鍗旾D',
+    `sale_order_no` varchar(64) DEFAULT NULL COMMENT '閿�鍞鍗曞彿',
+    `sale_order_item_id` bigint DEFAULT NULL COMMENT '閿�鍞鍗曟槑缁咺D',
+
+    -- 浜у搧淇℃伅
+    `product_id` bigint NOT NULL COMMENT '浜у搧缂栧彿',
+    `quantity` decimal(24,6) NOT NULL COMMENT '璁″垝鐢熶骇鏁伴噺',
+    `quantity_produced` decimal(24,6) DEFAULT 0 COMMENT '宸茬敓浜ф暟閲�',
+    `unit_measure_id` bigint DEFAULT NULL COMMENT '璁¢噺鍗曚綅ID',
+
+    -- 瀹㈡埛淇℃伅
+    `client_id` bigint DEFAULT NULL COMMENT '瀹㈡埛缂栧彿',
+
+    -- 鏃堕棿淇℃伅
+    `request_date` datetime DEFAULT NULL COMMENT '闇�姹傛棩鏈�',
+    `issue_date` datetime DEFAULT NULL COMMENT '涓嬪彂鏃ユ湡',
+    `finish_date` datetime DEFAULT NULL COMMENT '瀹屾垚鏃ユ湡',
+
+    -- 鐢熶骇宸ュ崟鍏宠仈锛堜笅鍙戝悗鐢熸垚锛�
+    `work_order_id` bigint DEFAULT NULL COMMENT '鐢熶骇宸ュ崟ID',
+    `work_order_code` varchar(64) DEFAULT NULL COMMENT '鐢熶骇宸ュ崟缂栫爜',
+
+    -- 鍚堝苟涓嬪彂鏍囪瘑
+    `merge_flag` tinyint DEFAULT 0 COMMENT '鏄惁鍚堝苟涓嬪彂锛�0=鍚� 1=鏄級',
+    `merge_batch_no` varchar(64) DEFAULT NULL COMMENT '鍚堝苟鎵规鍙�',
+
+    -- 鍏朵粬
+    `remark` varchar(500) DEFAULT NULL COMMENT '澶囨敞',
+    `creator` varchar(64) DEFAULT '' COMMENT '鍒涘缓鑰�',
+    `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿',
+    `updater` varchar(64) DEFAULT '' COMMENT '鏇存柊鑰�',
+    `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '鏇存柊鏃堕棿',
+    `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '鏄惁鍒犻櫎',
+    `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '绉熸埛缂栧彿',
+    PRIMARY KEY (`id`),
+    KEY `idx_sale_order_item_id` (`sale_order_item_id`),
+    KEY `idx_product_id` (`product_id`),
+    KEY `idx_status` (`status`),
+    KEY `idx_merge_batch_no` (`merge_batch_no`)
+) ENGINE=InnoDB COMMENT='MES 鐢熶骇涓昏鍒�';
+
+-- =============================================
+-- MPS 鍚堝苟涓嬪彂鏄庣粏琛�
+-- =============================================
+CREATE TABLE IF NOT EXISTS `mes_pro_mps_merge_item` (
+    `id` bigint NOT NULL AUTO_INCREMENT COMMENT '缂栧彿',
+    `merge_batch_no` varchar(64) NOT NULL COMMENT '鍚堝苟鎵规鍙�',
+    `mps_id` bigint NOT NULL COMMENT 'MPS 缂栧彿',
+    `work_order_id` bigint DEFAULT NULL COMMENT '鐢熸垚鐨勭敓浜у伐鍗旾D',
+    `quantity` decimal(24,6) NOT NULL COMMENT '鍒嗛厤鏁伴噺',
+    `remark` varchar(500) DEFAULT NULL COMMENT '澶囨敞',
+    `creator` varchar(64) DEFAULT '' COMMENT '鍒涘缓鑰�',
+    `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿',
+    `updater` varchar(64) DEFAULT '' COMMENT '鏇存柊鑰�',
+    `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '鏇存柊鏃堕棿',
+    `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '鏄惁鍒犻櫎',
+    `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '绉熸埛缂栧彿',
+    PRIMARY KEY (`id`),
+    KEY `idx_merge_batch_no` (`merge_batch_no`),
+    KEY `idx_mps_id` (`mps_id`)
+) ENGINE=InnoDB COMMENT='MPS 鍚堝苟涓嬪彂鏄庣粏';
+
+-- =============================================
+-- 閿�鍞鍗曟槑缁嗚〃鎵╁睍瀛楁
+-- =============================================
+ALTER TABLE `erp_sale_order_items`
+ADD COLUMN `need_production` tinyint DEFAULT 0 COMMENT '鏄惁闇�瑕佺敓浜э紙0=鍚� 1=鏄級' AFTER `out_count`,
+ADD COLUMN `mps_id` bigint DEFAULT NULL COMMENT '鍏宠仈鐨凪PS缂栧彿' AFTER `need_production`;
+
+-- =============================================
+-- 瀛楀吀绫诲瀷 - MPS 鐘舵��
+-- =============================================
+INSERT INTO `system_dict_type` (`name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES
+('MPS 鐘舵��', 'mes_pro_mps_status', 0, 'MPS 鐘舵��', '1', NOW(), '1', NOW(), b'0');
+
+-- =============================================
+-- 瀛楀吀鏁版嵁 - MPS 鐘舵��
+-- =============================================
+INSERT INTO `system_dict_data` (`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES
+(0, '鑽夌', '0', 'mes_pro_mps_status', 0, 'info', '', '', '1', NOW(), '1', NOW(), b'0'),
+(1, '宸蹭笅鍙�', '1', 'mes_pro_mps_status', 0, 'success', '', '', '1', NOW(), '1', NOW(), b'0'),
+(2, '宸插畬鎴�', '2', 'mes_pro_mps_status', 0, 'primary', '', '', '1', NOW(), '1', NOW(), b'0'),
+(3, '宸插彇娑�', '3', 'mes_pro_mps_status', 0, 'danger', '', '', '1', NOW(), '1', NOW(), b'0');
\ No newline at end of file
diff --git a/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/api/customer/CrmCustomerApi.java b/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/api/customer/CrmCustomerApi.java
index 7aea86c..10a6769 100644
--- a/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/api/customer/CrmCustomerApi.java
+++ b/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/api/customer/CrmCustomerApi.java
@@ -47,4 +47,13 @@
      */
     CrmCustomerRespDTO validateCustomer(Long id);
 
+    /**
+     * 鑾峰彇褰撳墠鐢ㄦ埛鏈夋潈闄愮殑瀹㈡埛 ID 鍒楄〃
+     *
+     * 鍖呮嫭锛氱敤鎴疯嚜宸卞湪鍥㈤槦涓�佺敤鎴风殑涓嬬骇鍦ㄥ洟闃熶腑銆佸叕娴锋暟鎹�
+     *
+     * @return 鏈夋潈闄愮殑瀹㈡埛 ID 鍒楄〃锛坣ull 琛ㄧず涓嶉檺鍒讹紝鍗宠秴绠★級
+     */
+    List<Long> getPermittedCustomerIds();
+
 }
\ No newline at end of file
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/api/customer/CrmCustomerApi.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/api/customer/CrmCustomerApi.java
index 7aea86c..df583d2 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/api/customer/CrmCustomerApi.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/api/customer/CrmCustomerApi.java
@@ -47,4 +47,13 @@
      */
     CrmCustomerRespDTO validateCustomer(Long id);
 
+    /**
+     * 鑾峰彇褰撳墠鐢ㄦ埛鏈夋潈闄愮殑瀹㈡埛 ID 鍒楄〃
+     *
+     * 鍖呮嫭锛氱敤鎴疯嚜宸卞湪鍥㈤槦涓�佺敤鎴风殑涓嬬骇鍦ㄥ洟闃熶腑銆佸叕娴锋暟鎹�
+     *
+     * @return 鏈夋潈闄愮殑瀹㈡埛 ID 鍒楄〃
+     */
+    List<Long> getPermittedCustomerIds();
+
 }
\ No newline at end of file
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/api/customer/CrmCustomerApiImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/api/customer/CrmCustomerApiImpl.java
index f6d901a..75d0cc3 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/api/customer/CrmCustomerApiImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/api/customer/CrmCustomerApiImpl.java
@@ -1,15 +1,25 @@
 package cn.iocoder.yudao.module.crm.api.customer;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
 import cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerRespDTO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
+import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
+import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
+import cn.iocoder.yudao.module.crm.util.CrmPermissionUtils;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
 import jakarta.annotation.Resource;
 import org.springframework.stereotype.Service;
 
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import java.util.stream.Collectors;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.anyMatch;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
 
 /**
  * CRM 瀹㈡埛 API 瀹炵幇绫�
@@ -21,6 +31,10 @@
 
     @Resource
     private CrmCustomerService customerService;
+    @Resource
+    private CrmPermissionService permissionService;
+    @Resource
+    private AdminUserApi adminUserApi;
 
     @Override
     public CrmCustomerRespDTO getCustomer(Long id) {
@@ -30,15 +44,25 @@
 
     @Override
     public List<CrmCustomerRespDTO> getCustomerList(Collection<Long> ids) {
+        if (CollUtil.isEmpty(ids)) {
+            return Collections.emptyList();
+        }
         List<CrmCustomerDO> customers = customerService.getCustomerList(ids);
-        return BeanUtils.toBean(customers, CrmCustomerRespDTO.class);
+        // 杩囨护鎺夌敤鎴锋病鏈夋潈闄愮殑瀹㈡埛
+        List<CrmCustomerDO> filteredCustomers = filterCustomersByPermission(customers);
+        return BeanUtils.toBean(filteredCustomers, CrmCustomerRespDTO.class);
     }
 
     @Override
     public Map<Long, CrmCustomerRespDTO> getCustomerMap(Collection<Long> ids) {
+        if (CollUtil.isEmpty(ids)) {
+            return Collections.emptyMap();
+        }
         List<CrmCustomerDO> customers = customerService.getCustomerList(ids);
-        return customers.stream()
-                .collect(java.util.stream.Collectors.toMap(
+        // 杩囨护鎺夌敤鎴锋病鏈夋潈闄愮殑瀹㈡埛
+        List<CrmCustomerDO> filteredCustomers = filterCustomersByPermission(customers);
+        return filteredCustomers.stream()
+                .collect(Collectors.toMap(
                         CrmCustomerDO::getId,
                         customer -> BeanUtils.toBean(customer, CrmCustomerRespDTO.class)));
     }
@@ -49,4 +73,130 @@
         return getCustomer(id);
     }
 
-}
\ No newline at end of file
+    @Override
+    public List<Long> getPermittedCustomerIds() {
+        // 1. 瓒呯骇绠$悊鍛樻湁鎵�鏈夋潈闄�
+        if (CrmPermissionUtils.isCrmAdmin()) {
+            return null; // null 琛ㄧず涓嶉檺鍒�
+        }
+
+        Long userId = WebFrameworkUtils.getLoginUserId();
+        if (userId == null) {
+            return Collections.emptyList();
+        }
+
+        // 2. 鑾峰彇鐢ㄦ埛鑷繁鏈夋潈闄愮殑瀹㈡埛 ID
+        List<CrmPermissionDO> userPermissions = permissionService.getPermissionListByBizTypeAndUserId(
+                CrmBizTypeEnum.CRM_CUSTOMER.getType(), userId);
+        Set<Long> permittedIds = new HashSet<>(convertSet(userPermissions, CrmPermissionDO::getBizId));
+
+        // 3. 鑾峰彇鐢ㄦ埛鐨勪笅绾х敤鎴锋湁鏉冮檺鐨勫鎴� ID
+        List<AdminUserRespDTO> subordinates = adminUserApi.getUserListBySubordinate(userId);
+        if (CollUtil.isNotEmpty(subordinates)) {
+            Set<Long> subordinateUserIds = convertSet(subordinates, AdminUserRespDTO::getId);
+            for (Long subordinateId : subordinateUserIds) {
+                List<CrmPermissionDO> subordinatePermissions = permissionService.getPermissionListByBizTypeAndUserId(
+                        CrmBizTypeEnum.CRM_CUSTOMER.getType(), subordinateId);
+                permittedIds.addAll(convertSet(subordinatePermissions, CrmPermissionDO::getBizId));
+            }
+        }
+
+        // 4. 鏌ヨ鎵�鏈夊鎴凤紝鎵惧嚭鍏捣鏁版嵁锛堟病鏈夊洟闃熸垚鍛樼殑瀹㈡埛锛�
+        // 鍏捣鏁版嵁鎵�鏈変汉閮芥湁璇绘潈闄�
+        List<CrmCustomerDO> allCustomers = customerService.getCustomerList();
+        Set<Long> allCustomerIds = convertSet(allCustomers, CrmCustomerDO::getId);
+
+        // 鑾峰彇鏈夋潈闄愰厤缃殑瀹㈡埛
+        List<CrmPermissionDO> allPermissions = permissionService.getPermissionListByBiz(
+                CrmBizTypeEnum.CRM_CUSTOMER.getType(), allCustomerIds);
+        Set<Long> hasTeamCustomerIds = convertSet(allPermissions, CrmPermissionDO::getBizId);
+
+        // 鍏捣鏁版嵁 = 鎵�鏈夊鎴� - 鏈夊洟闃熺殑瀹㈡埛
+        Set<Long> publicSeaCustomerIds = new HashSet<>(allCustomerIds);
+        publicSeaCustomerIds.removeAll(hasTeamCustomerIds);
+
+        // 鍚堝苟锛氭湁鏉冮檺鐨勫鎴� + 鍏捣瀹㈡埛
+        permittedIds.addAll(publicSeaCustomerIds);
+
+        return new ArrayList<>(permittedIds);
+    }
+
+    /**
+     * 杩囨护鎺夌敤鎴锋病鏈夋潈闄愮殑瀹㈡埛
+     * <p>
+     * 鏉冮檺鍒ゆ柇閫昏緫锛�
+     * 1. 瓒呯骇绠$悊鍛樻湁鎵�鏈夋潈闄�
+     * 2. 鍏捣鏁版嵁锛堟病鏈夊洟闃熸垚鍛橈級鎵�鏈変汉閮芥湁璇绘潈闄�
+     * 3. 鐢ㄦ埛鑷繁鍦ㄥ洟闃熸垚鍛樹腑
+     * 4. 鐢ㄦ埛鐨勪笅绾у湪鍥㈤槦鎴愬憳涓�
+     *
+     * @param customers 瀹㈡埛鍒楄〃
+     * @return 杩囨护鍚庣殑瀹㈡埛鍒楄〃
+     */
+    private List<CrmCustomerDO> filterCustomersByPermission(List<CrmCustomerDO> customers) {
+        if (CollUtil.isEmpty(customers)) {
+            return Collections.emptyList();
+        }
+        // 1. 瓒呯骇绠$悊鍛樻湁鎵�鏈夋潈闄�
+        if (CrmPermissionUtils.isCrmAdmin()) {
+            return customers;
+        }
+
+        Long userId = WebFrameworkUtils.getLoginUserId();
+        if (userId == null) {
+            // 娌℃湁鐧诲綍鐢ㄦ埛锛岃繑鍥炵┖鍒楄〃
+            return Collections.emptyList();
+        }
+
+        // 2. 鑾峰彇杩欎簺瀹㈡埛鐨勬潈闄愰厤缃�
+        Set<Long> customerIds = convertSet(customers, CrmCustomerDO::getId);
+        List<CrmPermissionDO> permissionList = permissionService.getPermissionListByBiz(
+                CrmBizTypeEnum.CRM_CUSTOMER.getType(), customerIds);
+        Map<Long, List<CrmPermissionDO>> permissionMap = permissionList.stream()
+                .collect(Collectors.groupingBy(CrmPermissionDO::getBizId));
+
+        // 3. 鑾峰彇鐢ㄦ埛鐨勪笅绾х敤鎴�
+        List<AdminUserRespDTO> subordinates = adminUserApi.getUserListBySubordinate(userId);
+        Set<Long> subordinateUserIds = convertSet(subordinates, AdminUserRespDTO::getId);
+
+        // 4. 杩囨护鏈夋潈闄愮殑瀹㈡埛
+        return customers.stream()
+                .filter(customer -> hasCustomerPermission(customer.getId(), permissionMap, userId, subordinateUserIds))
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * 鍒ゆ柇鐢ㄦ埛鏄惁鏈夊鎴锋潈闄�
+     */
+    private boolean hasCustomerPermission(Long customerId,
+                                           Map<Long, List<CrmPermissionDO>> permissionMap,
+                                           Long userId,
+                                           Set<Long> subordinateUserIds) {
+        List<CrmPermissionDO> permissions = permissionMap.get(customerId);
+
+        // 鍏捣鏁版嵁锛堟病鏈夊洟闃熸垚鍛橈級锛屾墍鏈変汉閮芥湁璇绘潈闄�
+        if (CollUtil.isEmpty(permissions)) {
+            return true;
+        }
+
+        // 娌℃湁璐熻矗浜虹殑鎯呭喌锛屾墍鏈変汉閮芥湁璇绘潈闄�
+        if (!anyMatch(permissions, item -> item.getLevel() == 1)) { // 1 = 璐熻矗浜�
+            return true;
+        }
+
+        // 妫�鏌ョ敤鎴疯嚜宸卞湪鍥㈤槦鎴愬憳涓�
+        if (anyMatch(permissions, item -> item.getUserId().equals(userId))) {
+            return true;
+        }
+
+        // 妫�鏌ョ敤鎴风殑涓嬬骇鍦ㄥ洟闃熸垚鍛樹腑
+        for (Long subordinateId : subordinateUserIds) {
+            if (anyMatch(permissions, item -> item.getUserId().equals(subordinateId))) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+}
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java
index b85d74c..8b635f1 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java
@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.crm.dal.mysql.contract;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.date.LocalDateTimeUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
@@ -51,6 +52,18 @@
     }
 
     default PageResult<CrmContractDO> selectPage(CrmContractPageReqVO pageReqVO, Long userId, CrmContractConfigDO config) {
+        return selectPage(pageReqVO, userId, config, null);
+    }
+
+    /**
+     * 鍒嗛〉鏌ヨ锛堝甫瀹㈡埛鏉冮檺杩囨护锛�
+     *
+     * @param pageReqVO 鏌ヨ鏉′欢
+     * @param userId 鐢ㄦ埛ID
+     * @param config 鍚堝悓閰嶇疆
+     * @param permittedCustomerIds 鏈夋潈闄愮殑瀹㈡埛ID鍒楄〃锛坣ull琛ㄧず涓嶉檺鍒讹級
+     */
+    default PageResult<CrmContractDO> selectPage(CrmContractPageReqVO pageReqVO, Long userId, CrmContractConfigDO config, List<Long> permittedCustomerIds) {
         MPJLambdaWrapperX<CrmContractDO> query = new MPJLambdaWrapperX<>();
         // 鎷兼帴鏁版嵁鏉冮檺鐨勬煡璇㈡潯浠�
         CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(),
@@ -64,6 +77,14 @@
                 .eqIfPresent(CrmContractDO::getAuditStatus, pageReqVO.getAuditStatus())
                 .orderByDesc(CrmContractDO::getId);
 
+        // 瀹㈡埛鏉冮檺杩囨护
+        if (permittedCustomerIds != null) {
+            if (CollUtil.isEmpty(permittedCustomerIds)) {
+                return PageResult.empty();
+            }
+            query.in(CrmContractDO::getCustomerId, permittedCustomerIds);
+        }
+
         // Backlog: 鍗冲皢鍒版湡鐨勫悎鍚�
         LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now());
         LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now());
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/quotation/CrmSaleQuotationMapper.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/quotation/CrmSaleQuotationMapper.java
index f43e8b1..7a3a05b 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/quotation/CrmSaleQuotationMapper.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/quotation/CrmSaleQuotationMapper.java
@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.crm.dal.mysql.quotation;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
@@ -27,6 +28,17 @@
     }
 
     default PageResult<CrmSaleQuotationDO> selectPage(CrmSaleQuotationPageReqVO pageReqVO, Long userId) {
+        return selectPage(pageReqVO, userId, null);
+    }
+
+    /**
+     * 鍒嗛〉鏌ヨ锛堝甫瀹㈡埛鏉冮檺杩囨护锛�
+     *
+     * @param pageReqVO 鏌ヨ鏉′欢
+     * @param userId 鐢ㄦ埛ID
+     * @param permittedCustomerIds 鏈夋潈闄愮殑瀹㈡埛ID鍒楄〃锛坣ull琛ㄧず涓嶉檺鍒讹級
+     */
+    default PageResult<CrmSaleQuotationDO> selectPage(CrmSaleQuotationPageReqVO pageReqVO, Long userId, List<Long> permittedCustomerIds) {
         MPJLambdaWrapperX<CrmSaleQuotationDO> query = new MPJLambdaWrapperX<>();
         // 鎷兼帴鏁版嵁鏉冮檺鐨勬煡璇㈡潯浠�
         CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_SALE_QUOTATION.getType(),
@@ -39,6 +51,15 @@
                 .eqIfPresent(CrmSaleQuotationDO::getBusinessId, pageReqVO.getBusinessId())
                 .eqIfPresent(CrmSaleQuotationDO::getStatus, pageReqVO.getStatus())
                 .orderByDesc(CrmSaleQuotationDO::getId);
+
+        // 瀹㈡埛鏉冮檺杩囨护
+        if (permittedCustomerIds != null) {
+            if (CollUtil.isEmpty(permittedCustomerIds)) {
+                return PageResult.empty();
+            }
+            query.in(CrmSaleQuotationDO::getCustomerId, permittedCustomerIds);
+        }
+
         return selectJoinPage(pageReqVO, CrmSaleQuotationDO.class, query);
     }
 
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
index 6518016..74fae39 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
@@ -28,6 +28,7 @@
 import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission;
 import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService;
 import cn.iocoder.yudao.module.crm.service.contact.CrmContactService;
+import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
@@ -99,6 +100,8 @@
     private CrmPermissionService crmPermissionService;
     @Resource
     private CrmCustomerService customerService;
+    @Resource
+    private CrmCustomerApi customerApi;
     @Resource
     private CrmBusinessService businessService;
     @Resource
@@ -468,8 +471,10 @@
                 return PageResult.empty();
             }
         }
-        // 2. 鏌ヨ鍒嗛〉
-        return contractMapper.selectPage(pageReqVO, userId, config);
+        // 2. 鑾峰彇鐢ㄦ埛鏈夋潈闄愮殑瀹㈡埛 ID 鍒楄〃
+        List<Long> permittedCustomerIds = customerApi.getPermittedCustomerIds();
+        // 3. 鏌ヨ鍒嗛〉
+        return contractMapper.selectPage(pageReqVO, userId, config, permittedCustomerIds);
     }
 
     @Override
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java
index 70b4f9f..3222134 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java
@@ -78,6 +78,13 @@
     List<CrmCustomerDO> getCustomerList(Collection<Long> ids);
 
     /**
+     * 鑾峰緱鎵�鏈夊鎴峰垪琛�
+     *
+     * @return 瀹㈡埛鍒楄〃
+     */
+    List<CrmCustomerDO> getCustomerList();
+
+    /**
      * 鑾峰緱瀹㈡埛 Map
      *
      * @param ids 瀹㈡埛缂栧彿鏁扮粍
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java
index 11ac107..756a962 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java
@@ -494,6 +494,11 @@
     }
 
     @Override
+    public List<CrmCustomerDO> getCustomerList() {
+        return customerMapper.selectList();
+    }
+
+    @Override
     public PageResult<CrmCustomerDO> getCustomerPage(CrmCustomerPageReqVO pageReqVO, Long userId) {
         return customerMapper.selectPage(pageReqVO, userId);
     }
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/quotation/CrmSaleQuotationServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/quotation/CrmSaleQuotationServiceImpl.java
index e5ad277..99dda59 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/quotation/CrmSaleQuotationServiceImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/quotation/CrmSaleQuotationServiceImpl.java
@@ -20,6 +20,7 @@
 import cn.iocoder.yudao.module.crm.service.contact.CrmContactService;
 import cn.iocoder.yudao.module.crm.service.contract.CrmContractService;
 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
+import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
 import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
@@ -60,6 +61,8 @@
 
     @Resource
     private CrmCustomerService customerService;
+    @Resource
+    private CrmCustomerApi customerApi;
     @Resource
     private CrmBusinessService businessService;
     @Resource
@@ -229,7 +232,9 @@
 
     @Override
     public PageResult<CrmSaleQuotationDO> getSaleQuotationPage(CrmSaleQuotationPageReqVO pageReqVO, Long userId) {
-        return saleQuotationMapper.selectPage(pageReqVO, userId);
+        // 鑾峰彇鐢ㄦ埛鏈夋潈闄愮殑瀹㈡埛 ID 鍒楄〃
+        List<Long> permittedCustomerIds = customerApi.getPermittedCustomerIds();
+        return saleQuotationMapper.selectPage(pageReqVO, userId, permittedCustomerIds);
     }
 
     @Override
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 34a8891..ad74f35 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
@@ -18,6 +18,7 @@
 import cn.iocoder.yudao.module.erp.service.sale.ErpSaleOrderService;
 import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
 import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO;
+import cn.iocoder.yudao.module.mes.api.salesnotice.MesWmSalesNoticeApi;
 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
 import io.swagger.v3.oas.annotations.Operation;
@@ -55,6 +56,8 @@
     private MdmItemApi mdmItemApi;
     @Resource
     private AdminUserApi adminUserApi;
+    @Resource
+    private MesWmSalesNoticeApi salesNoticeApi;
 
     @PostMapping("/create")
     @Operation(summary = "鍒涘缓閿�鍞鍗�")
@@ -165,6 +168,9 @@
         // 1.4 绠$悊鍛樹俊鎭�
         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
                 convertSet(pageResult.getList(), saleOrder -> Long.parseLong(saleOrder.getCreator())));
+        // 1.5 鍙戣揣閫氱煡鍗曚俊鎭�
+        Map<Long, Boolean> salesNoticeMap = salesNoticeApi.checkSalesNoticeBySaleOrderIds(
+                convertSet(pageResult.getList(), ErpSaleOrderDO::getId));
         // 2. 寮�濮嬫嫾鎺�
         return BeanUtils.toBean(pageResult, ErpSaleOrderRespVO.class, saleOrder -> {
             saleOrder.setItems(BeanUtils.toBean(saleOrderItemMap.get(saleOrder.getId()), ErpSaleOrderRespVO.Item.class,
@@ -173,6 +179,8 @@
             saleOrder.setProductNames(CollUtil.join(saleOrder.getItems(), "锛�", ErpSaleOrderRespVO.Item::getProductName));
             MapUtils.findAndThen(customerMap, saleOrder.getCustomerId(), supplier -> saleOrder.setCustomerName(supplier.getName()));
             MapUtils.findAndThen(userMap, Long.parseLong(saleOrder.getCreator()), user -> saleOrder.setCreatorName(user.getNickname()));
+            // 璁剧疆鏄惁宸茬敓鎴愬彂璐ч�氱煡鍗�
+            saleOrder.setHasSalesNotice(salesNoticeMap.getOrDefault(saleOrder.getId(), false));
         });
     }
 
diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java
index 0ddc4a2..34085c4 100644
--- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java
+++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java
@@ -104,6 +104,11 @@
     @Schema(description = "鍑哄簱鐘舵��", example = "0")
     private Integer outStatus;
 
+    // ========== 鍙戣揣閫氱煡 ==========
+
+    @Schema(description = "鏄惁宸茬敓鎴愬彂璐ч�氱煡鍗�", example = "false")
+    private Boolean hasSalesNotice;
+
     @Data
     public static class Item {
 
@@ -137,6 +142,14 @@
         @Schema(description = "閿�鍞嚭搴撴暟閲�", example = "100.00")
         private BigDecimal outCount;
 
+        // ========== 鐢熶骇鍏宠仈 ==========
+
+        @Schema(description = "鏄惁闇�瑕佺敓浜э紙0=鍚� 1=鏄級", example = "1")
+        private Integer needProduction;
+
+        @Schema(description = "鍏宠仈鐨� MPS 缂栧彿", example = "1024")
+        private Long mpsId;
+
         // ========== 鍏宠仈瀛楁 ==========
 
         @Schema(description = "浜у搧鍚嶇О", requiredMode = Schema.RequiredMode.REQUIRED, example = "宸у厠鍔�")
diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderSaveReqVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderSaveReqVO.java
index 95dcd7a..dcf7c68 100644
--- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderSaveReqVO.java
+++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderSaveReqVO.java
@@ -74,6 +74,9 @@
         @Schema(description = "绋庣巼锛岀櫨鍒嗘瘮", example = "99.88")
         private BigDecimal taxPercent;
 
+        @Schema(description = "鏄惁闇�瑕佺敓浜э紙0=鍚� 1=鏄級", example = "1")
+        private Integer needProduction;
+
         @Schema(description = "澶囨敞", example = "闅忎究")
         private String remark;
 
diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderItemDO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderItemDO.java
index 235c305..5d91f51 100644
--- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderItemDO.java
+++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderItemDO.java
@@ -84,4 +84,18 @@
      */
     private BigDecimal outCount;
 
+    // ========== 鐢熶骇鍏宠仈 ==========
+
+    /**
+     * 鏄惁闇�瑕佺敓浜э紙0=鍚� 1=鏄級
+     */
+    private Integer needProduction;
+
+    /**
+     * 鍏宠仈鐨� MPS 缂栧彿
+     *
+     * 鍏宠仈 {@link cn.iocoder.yudao.module.mes.dal.dataobject.pro.mps.MesProMpsDO#getId()}
+     */
+    private Long mpsId;
+
 }
\ No newline at end of file
diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java
index 79e4533..7382197 100644
--- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java
+++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java
@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.erp.dal.mysql.sale;
 
 
+import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
@@ -9,6 +10,8 @@
 import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderItemDO;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
 
 /**
  * ERP 閿�鍞鍗� Mapper
@@ -35,6 +38,33 @@
         return selectJoinPage(reqVO, ErpSaleOrderDO.class, query);
     }
 
+    /**
+     * 鍒嗛〉鏌ヨ锛堝甫瀹㈡埛鏉冮檺杩囨护锛�
+     */
+    default PageResult<ErpSaleOrderDO> selectPage(ErpSaleOrderPageReqVO reqVO, List<Long> permittedCustomerIds) {
+        MPJLambdaWrapperX<ErpSaleOrderDO> query = new MPJLambdaWrapperX<ErpSaleOrderDO>()
+                .likeIfPresent(ErpSaleOrderDO::getNo, reqVO.getNo())
+                .eqIfPresent(ErpSaleOrderDO::getCustomerId, reqVO.getCustomerId())
+                .betweenIfPresent(ErpSaleOrderDO::getOrderTime, reqVO.getOrderTime())
+                .eqIfPresent(ErpSaleOrderDO::getStatus, reqVO.getStatus())
+                .likeIfPresent(ErpSaleOrderDO::getRemark, reqVO.getRemark())
+                .eqIfPresent(ErpSaleOrderDO::getCreator, reqVO.getCreator())
+                .orderByDesc(ErpSaleOrderDO::getId);
+        // 瀹㈡埛鏉冮檺杩囨护
+        if (permittedCustomerIds != null) {
+            if (CollUtil.isEmpty(permittedCustomerIds)) {
+                return PageResult.empty();
+            }
+            query.in(ErpSaleOrderDO::getCustomerId, permittedCustomerIds);
+        }
+        if (reqVO.getProductId() != null) {
+            query.leftJoin(ErpSaleOrderItemDO.class, ErpSaleOrderItemDO::getOrderId, ErpSaleOrderDO::getId)
+                    .eq(reqVO.getProductId() != null, ErpSaleOrderItemDO::getProductId, reqVO.getProductId())
+                    .groupBy(ErpSaleOrderDO::getId); // 閬垮厤 1 瀵瑰鏌ヨ锛屼骇鐢熺浉鍚岀殑 1
+        }
+        return selectJoinPage(reqVO, ErpSaleOrderDO.class, query);
+    }
+
     default int updateByIdAndStatus(Long id, Integer status, ErpSaleOrderDO updateObj) {
         return update(updateObj, new LambdaUpdateWrapper<ErpSaleOrderDO>()
                 .eq(ErpSaleOrderDO::getId, id).eq(ErpSaleOrderDO::getStatus, status));
diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java
index 1451e01..5018ce3 100644
--- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java
+++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java
@@ -309,7 +309,8 @@
 
     @Override
     public PageResult<ErpSaleOrderDO> getSaleOrderPage(ErpSaleOrderPageReqVO pageReqVO) {
-        return saleOrderMapper.selectPage(pageReqVO);
+        List<Long> permittedCustomerIds = customerApi.getPermittedCustomerIds();
+        return saleOrderMapper.selectPage(pageReqVO, permittedCustomerIds);
     }
 
     // ==================== 璁㈠崟椤� ====================
diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/sale/listener/ErpSaleOrderStatusListener.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/sale/listener/ErpSaleOrderStatusListener.java
new file mode 100644
index 0000000..f068d75
--- /dev/null
+++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/sale/listener/ErpSaleOrderStatusListener.java
@@ -0,0 +1,160 @@
+package cn.iocoder.yudao.module.erp.service.sale.listener;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEvent;
+import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
+import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderDO;
+import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderItemDO;
+import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleOrderItemMapper;
+import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleOrderMapper;
+import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus;
+import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
+import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO;
+import cn.iocoder.yudao.module.mes.api.mps.MesProMpsApi;
+import cn.iocoder.yudao.module.mes.api.mps.dto.MesProMpsCreateReqDTO;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+
+/**
+ * 閿�鍞鍗曞鎵圭姸鎬佺洃鍚櫒
+ *
+ * 鐩戝惉 BPM 娴佺▼瀹炰緥鐘舵�佸彉鏇翠簨浠讹紝瀹℃牳閫氳繃鏃惰嚜鍔ㄥ垱寤� MPS
+ *
+ * @author 鑺嬮亾婧愮爜
+ */
+@Component
+@Slf4j
+public class ErpSaleOrderStatusListener extends cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEventListener {
+
+    /**
+     * 閿�鍞鍗曞鎵规祦绋嬪畾涔� Key
+     */
+    private static final String PROCESS_DEFINITION_KEY = "sale_order_approve";
+
+    @Resource
+    private ErpSaleOrderMapper saleOrderMapper;
+    @Resource
+    private ErpSaleOrderItemMapper saleOrderItemMapper;
+    @Resource
+    private MesProMpsApi mpsApi;
+    @Resource
+    private MdmItemApi mdmItemApi;
+
+    @Override
+    protected String getProcessDefinitionKey() {
+        return PROCESS_DEFINITION_KEY;
+    }
+
+    @Override
+    protected void onEvent(BpmProcessInstanceStatusEvent event) {
+        Long orderId;
+        try {
+            orderId = Long.parseLong(event.getBusinessKey());
+        } catch (NumberFormatException e) {
+            log.warn("[onEvent] businessKey({}) 涓嶆槸鏈夋晥鐨勯攢鍞鍗曠紪鍙�", event.getBusinessKey());
+            return;
+        }
+
+        log.info("[onEvent] 鏀跺埌 BPM 瀹℃壒浜嬩欢锛宱rderId={}, status={}", orderId, event.getStatus());
+
+        // 鍙湁瀹℃壒閫氳繃鎵嶅垱寤� MPS
+        if (!BpmTaskStatusEnum.APPROVE.getStatus().equals(event.getStatus())) {
+            return;
+        }
+
+        try {
+            // 1. 鑾峰彇閿�鍞鍗�
+            ErpSaleOrderDO saleOrder = saleOrderMapper.selectById(orderId);
+            if (saleOrder == null) {
+                log.warn("[onEvent] 閿�鍞鍗曚笉瀛樺湪锛宱rderId={}", orderId);
+                return;
+            }
+
+            // 2. 鑾峰彇閿�鍞鍗曟槑缁�
+            List<ErpSaleOrderItemDO> items = saleOrderItemMapper.selectListByOrderId(orderId);
+            if (CollUtil.isEmpty(items)) {
+                log.info("[onEvent] 閿�鍞鍗�({}) 娌℃湁鏄庣粏锛屾棤闇�鍒涘缓 MPS", orderId);
+                return;
+            }
+
+            // 3. 鏇存柊璁㈠崟鐘舵�佷负宸插鏍�
+            saleOrderMapper.updateById(new ErpSaleOrderDO()
+                    .setId(orderId)
+                    .setStatus(ErpAuditStatus.APPROVE.getStatus()));
+
+            // 4. 閬嶅巻鏄庣粏锛屼负闇�瑕佺敓浜х殑鏄庣粏鍒涘缓 MPS
+            int mpsCount = 0;
+            for (ErpSaleOrderItemDO item : items) {
+                if (item.getNeedProduction() == null || item.getNeedProduction() != 1) {
+                    continue;
+                }
+                try {
+                    Long mpsId = createMpsForSaleOrderItem(saleOrder, item);
+                    if (mpsId != null) {
+                        mpsCount++;
+                        // 鏇存柊閿�鍞鍗曟槑缁嗙殑 MPS 鍏宠仈
+                        saleOrderItemMapper.updateById(new ErpSaleOrderItemDO()
+                                .setId(item.getId())
+                                .setMpsId(mpsId));
+                    }
+                } catch (Exception e) {
+                    log.error("[onEvent] 鍒涘缓 MPS 澶辫触锛宻aleOrderItemId={}", item.getId(), e);
+                }
+            }
+
+            log.info("[onEvent] 閿�鍞鍗�({}) 瀹℃壒瀹屾垚锛屽垱寤� MPS {} 鏉�", orderId, mpsCount);
+        } catch (Exception e) {
+            log.error("[onEvent] 澶勭悊閿�鍞鍗曞鎵逛簨浠跺け璐ワ紝orderId={}", orderId, e);
+        }
+    }
+
+    /**
+     * 涓洪攢鍞鍗曟槑缁嗗垱寤� MPS
+     *
+     * 娉ㄦ剰锛氶攢鍞鍗曟槑缁嗙殑 productId 鏄� MDM 鐗╂枡 ID锛岄渶瑕佹槧灏勫埌 MES 浜у搧
+     */
+    private Long createMpsForSaleOrderItem(ErpSaleOrderDO saleOrder, ErpSaleOrderItemDO item) {
+        // 鑾峰彇 MDM 鐗╂枡淇℃伅锛堢敤浜庤幏鍙栦骇鍝佸悕绉帮級
+        String productName = null;
+        try {
+            MdmItemRespDTO mdmItem = mdmItemApi.getItem(item.getProductId()).getCheckedData();
+            if (mdmItem != null) {
+                productName = mdmItem.getName();
+            }
+        } catch (Exception e) {
+            log.warn("[createMpsForSaleOrderItem] 鑾峰彇 MDM 鐗╂枡淇℃伅澶辫触锛宲roductId={}", item.getProductId(), e);
+        }
+
+        MesProMpsCreateReqDTO createReqDTO = new MesProMpsCreateReqDTO();
+        createReqDTO.setSaleOrderId(saleOrder.getId());
+        createReqDTO.setSaleOrderNo(saleOrder.getNo());
+        createReqDTO.setSaleOrderItemId(item.getId());
+        createReqDTO.setMdmItemId(item.getProductId()); // 閿�鍞鍗曟槑缁嗙殑 productId 鏄� MDM 鐗╂枡 ID
+        createReqDTO.setProductName(productName); // 浜у搧鍚嶇О鐢ㄤ簬閿欒鎻愮ず
+        createReqDTO.setQuantity(item.getCount());
+        createReqDTO.setClientId(saleOrder.getCustomerId());
+        createReqDTO.setRequestDate(formatRequestDate(saleOrder.getOrderTime()));
+        createReqDTO.setRemark("鑷姩鐢熸垚锛屾潵鑷攢鍞鍗曪細" + saleOrder.getNo());
+
+        Long mpsId = mpsApi.createMps(createReqDTO);
+        log.info("[createMpsForSaleOrderItem] MPS 鍒涘缓鎴愬姛锛宮psId={}, saleOrderItemId={}", mpsId, item.getId());
+        return mpsId;
+    }
+
+    /**
+     * 鏍煎紡鍖栭渶姹傛棩鏈�
+     */
+    private String formatRequestDate(LocalDateTime dateTime) {
+        if (dateTime == null) {
+            return null;
+        }
+        return dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+    }
+
+}
\ No newline at end of file
diff --git a/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/mps/MesProMpsApi.java b/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/mps/MesProMpsApi.java
new file mode 100644
index 0000000..6d75372
--- /dev/null
+++ b/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/mps/MesProMpsApi.java
@@ -0,0 +1,49 @@
+package cn.iocoder.yudao.module.mes.api.mps;
+
+import cn.iocoder.yudao.module.mes.api.mps.dto.MesProMpsCreateReqDTO;
+import cn.iocoder.yudao.module.mes.api.mps.dto.MesProMpsRespDTO;
+
+import java.util.List;
+
+/**
+ * MES 鐢熶骇涓昏鍒掞紙MPS锛堿PI 鎺ュ彛
+ *
+ * 渚� ERP 妯″潡璋冪敤锛屽湪閿�鍞鍗曞鏍搁�氳繃鏃跺垱寤� MPS
+ *
+ * @author 鑺嬮亾婧愮爜
+ */
+public interface MesProMpsApi {
+
+    /**
+     * 鍒涘缓 MPS
+     *
+     * @param createReqDTO 鍒涘缓淇℃伅
+     * @return MPS 缂栧彿
+     */
+    Long createMps(MesProMpsCreateReqDTO createReqDTO);
+
+    /**
+     * 鏍规嵁 ID 鑾峰彇 MPS
+     *
+     * @param id MPS 缂栧彿
+     * @return MPS 淇℃伅
+     */
+    MesProMpsRespDTO getMps(Long id);
+
+    /**
+     * 鏍规嵁閿�鍞鍗曟槑缁咺D鑾峰彇 MPS
+     *
+     * @param saleOrderItemId 閿�鍞鍗曟槑缁咺D
+     * @return MPS 淇℃伅
+     */
+    MesProMpsRespDTO getMpsBySaleOrderItemId(Long saleOrderItemId);
+
+    /**
+     * 鎵归噺鑾峰彇 MPS
+     *
+     * @param saleOrderItemIds 閿�鍞鍗曟槑缁咺D鍒楄〃
+     * @return MPS 鍒楄〃
+     */
+    List<MesProMpsRespDTO> getMpsListBySaleOrderItemIds(List<Long> saleOrderItemIds);
+
+}
\ No newline at end of file
diff --git a/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/mps/dto/MesProMpsCreateReqDTO.java b/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/mps/dto/MesProMpsCreateReqDTO.java
new file mode 100644
index 0000000..9d860a3
--- /dev/null
+++ b/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/mps/dto/MesProMpsCreateReqDTO.java
@@ -0,0 +1,44 @@
+package cn.iocoder.yudao.module.mes.api.mps.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * MPS 鍒涘缓璇锋眰 DTO
+ *
+ * @author 鑺嬮亾婧愮爜
+ */
+@Schema(description = "RPC 鏈嶅姟 - MPS 鍒涘缓 Request DTO")
+@Data
+public class MesProMpsCreateReqDTO {
+
+    @Schema(description = "閿�鍞鍗旾D", example = "100")
+    private Long saleOrderId;
+
+    @Schema(description = "閿�鍞鍗曞彿", example = "SO-001")
+    private String saleOrderNo;
+
+    @Schema(description = "閿�鍞鍗曟槑缁咺D", example = "200")
+    private Long saleOrderItemId;
+
+    @Schema(description = "MDM 鐗╂枡ID锛堥攢鍞鍗曟槑缁嗙殑 productId锛�", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
+    private Long mdmItemId;
+
+    @Schema(description = "浜у搧鍚嶇О锛堢敤浜庨敊璇彁绀猴級", example = "鐢佃矾鏉緼")
+    private String productName;
+
+    @Schema(description = "璁″垝鐢熶骇鏁伴噺", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
+    private BigDecimal quantity;
+
+    @Schema(description = "瀹㈡埛ID", example = "300")
+    private Long clientId;
+
+    @Schema(description = "闇�姹傛棩鏈�", example = "2024-01-01")
+    private String requestDate;
+
+    @Schema(description = "澶囨敞", example = "鑷姩鐢熸垚")
+    private String remark;
+
+}
\ No newline at end of file
diff --git a/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/mps/dto/MesProMpsRespDTO.java b/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/mps/dto/MesProMpsRespDTO.java
new file mode 100644
index 0000000..d9cbb59
--- /dev/null
+++ b/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/mps/dto/MesProMpsRespDTO.java
@@ -0,0 +1,69 @@
+package cn.iocoder.yudao.module.mes.api.mps.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * MPS 鍝嶅簲 DTO
+ *
+ * @author 鑺嬮亾婧愮爜
+ */
+@Schema(description = "RPC 鏈嶅姟 - MPS Response DTO")
+@Data
+public class MesProMpsRespDTO {
+
+    @Schema(description = "MPS 缂栧彿", example = "1024")
+    private Long id;
+
+    @Schema(description = "MPS 缂栫爜", example = "MPS-001")
+    private String code;
+
+    @Schema(description = "鐘舵��", example = "0")
+    private Integer status;
+
+    @Schema(description = "閿�鍞鍗旾D", example = "100")
+    private Long saleOrderId;
+
+    @Schema(description = "閿�鍞鍗曞彿", example = "SO-001")
+    private String saleOrderNo;
+
+    @Schema(description = "閿�鍞鍗曟槑缁咺D", example = "200")
+    private Long saleOrderItemId;
+
+    @Schema(description = "浜у搧ID", example = "100")
+    private Long productId;
+
+    @Schema(description = "璁″垝鐢熶骇鏁伴噺", example = "100.00")
+    private BigDecimal quantity;
+
+    @Schema(description = "宸茬敓浜ф暟閲�", example = "50.00")
+    private BigDecimal quantityProduced;
+
+    @Schema(description = "瀹㈡埛ID", example = "300")
+    private Long clientId;
+
+    @Schema(description = "闇�姹傛棩鏈�")
+    private LocalDateTime requestDate;
+
+    @Schema(description = "涓嬪彂鏃ユ湡")
+    private LocalDateTime issueDate;
+
+    @Schema(description = "瀹屾垚鏃ユ湡")
+    private LocalDateTime finishDate;
+
+    @Schema(description = "鐢熶骇宸ュ崟ID", example = "500")
+    private Long workOrderId;
+
+    @Schema(description = "鐢熶骇宸ュ崟缂栫爜", example = "WO-001")
+    private String workOrderCode;
+
+    @Schema(description = "鏄惁鍚堝苟涓嬪彂", example = "0")
+    private Integer mergeFlag;
+
+    @Schema(description = "鍚堝苟鎵规鍙�", example = "MERGE-001")
+    private String mergeBatchNo;
+
+}
\ No newline at end of file
diff --git a/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/salesnotice/MesWmSalesNoticeApi.java b/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/salesnotice/MesWmSalesNoticeApi.java
new file mode 100644
index 0000000..dce0af1
--- /dev/null
+++ b/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/salesnotice/MesWmSalesNoticeApi.java
@@ -0,0 +1,21 @@
+package cn.iocoder.yudao.module.mes.api.salesnotice;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * MES 鍙戣揣閫氱煡鍗� API 鎺ュ彛
+ *
+ * @author 鑺嬮亾婧愮爜
+ */
+public interface MesWmSalesNoticeApi {
+
+    /**
+     * 鏍规嵁閿�鍞鍗� ID 鍒楄〃妫�鏌ユ槸鍚﹀凡鐢熸垚鍙戣揣閫氱煡鍗�
+     *
+     * @param saleOrderIds 閿�鍞鍗� ID 鍒楄〃
+     * @return Map<閿�鍞鍗旾D, 鏄惁宸茬敓鎴愬彂璐ч�氱煡鍗�>
+     */
+    Map<Long, Boolean> checkSalesNoticeBySaleOrderIds(Collection<Long> saleOrderIds);
+
+}
\ No newline at end of file
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/api/mps/MesProMpsApiImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/api/mps/MesProMpsApiImpl.java
new file mode 100644
index 0000000..ddd0f82
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/api/mps/MesProMpsApiImpl.java
@@ -0,0 +1,63 @@
+package cn.iocoder.yudao.module.mes.api.mps;
+
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.mes.api.mps.dto.MesProMpsCreateReqDTO;
+import cn.iocoder.yudao.module.mes.api.mps.dto.MesProMpsRespDTO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.mps.MesProMpsDO;
+import cn.iocoder.yudao.module.mes.service.pro.mps.MesProMpsService;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * MPS API 瀹炵幇绫�
+ *
+ * @author 鑺嬮亾婧愮爜
+ */
+@Service
+@Validated
+public class MesProMpsApiImpl implements MesProMpsApi {
+
+    @Resource
+    private MesProMpsService mpsService;
+
+    @Override
+    public Long createMps(MesProMpsCreateReqDTO createReqDTO) {
+        return mpsService.createMps(
+                createReqDTO.getSaleOrderId(),
+                createReqDTO.getSaleOrderNo(),
+                createReqDTO.getSaleOrderItemId(),
+                createReqDTO.getMdmItemId(),
+                createReqDTO.getProductName(),
+                createReqDTO.getQuantity(),
+                createReqDTO.getClientId(),
+                createReqDTO.getRequestDate(),
+                createReqDTO.getRemark()
+        );
+    }
+
+    @Override
+    public MesProMpsRespDTO getMps(Long id) {
+        MesProMpsDO mps = mpsService.getMps(id);
+        return BeanUtils.toBean(mps, MesProMpsRespDTO.class);
+    }
+
+    @Override
+    public MesProMpsRespDTO getMpsBySaleOrderItemId(Long saleOrderItemId) {
+        MesProMpsDO mps = mpsService.getMpsBySaleOrderItemId(saleOrderItemId);
+        return BeanUtils.toBean(mps, MesProMpsRespDTO.class);
+    }
+
+    @Override
+    public List<MesProMpsRespDTO> getMpsListBySaleOrderItemIds(List<Long> saleOrderItemIds) {
+        if (saleOrderItemIds == null || saleOrderItemIds.isEmpty()) {
+            return Collections.emptyList();
+        }
+        List<MesProMpsDO> mpsList = mpsService.getMpsListBySaleOrderItemIds(saleOrderItemIds);
+        return BeanUtils.toBean(mpsList, MesProMpsRespDTO.class);
+    }
+
+}
\ No newline at end of file
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/api/salesnotice/MesWmSalesNoticeApiImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/api/salesnotice/MesWmSalesNoticeApiImpl.java
new file mode 100644
index 0000000..4e97503
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/api/salesnotice/MesWmSalesNoticeApiImpl.java
@@ -0,0 +1,41 @@
+package cn.iocoder.yudao.module.mes.api.salesnotice;
+
+import cn.iocoder.yudao.module.mes.dal.mysql.wm.salesnotice.MesWmSalesNoticeMapper;
+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.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * MES 鍙戣揣閫氱煡鍗� API 瀹炵幇绫�
+ *
+ * @author 鑺嬮亾婧愮爜
+ */
+@Service
+@Validated
+public class MesWmSalesNoticeApiImpl implements MesWmSalesNoticeApi {
+
+    @Resource
+    private MesWmSalesNoticeMapper salesNoticeMapper;
+
+    @Override
+    public Map<Long, Boolean> checkSalesNoticeBySaleOrderIds(Collection<Long> saleOrderIds) {
+        if (saleOrderIds == null || saleOrderIds.isEmpty()) {
+            return Collections.emptyMap();
+        }
+        // 鏌ヨ宸插瓨鍦ㄧ殑閿�鍞鍗� ID
+        List<Long> existingSaleOrderIds = salesNoticeMapper.selectExistingSaleOrderIds(saleOrderIds);
+        // 鏋勫缓杩斿洖缁撴灉
+        Map<Long, Boolean> result = new HashMap<>();
+        for (Long saleOrderId : saleOrderIds) {
+            result.put(saleOrderId, existingSaleOrderIds.contains(saleOrderId));
+        }
+        return result;
+    }
+
+}
\ No newline at end of file
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/MesMdClientController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/MesMdClientController.java
deleted file mode 100644
index 95fd5c5..0000000
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/MesMdClientController.java
+++ /dev/null
@@ -1,126 +0,0 @@
-package cn.iocoder.yudao.module.mes.controller.admin.md.client;
-
-import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
-
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.framework.common.pojo.PageParam;
-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.md.client.vo.MesMdClientImportExcelVO;
-import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientImportRespVO;
-import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientPageReqVO;
-import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientRespVO;
-import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientSaveReqVO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO;
-import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.Parameters;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import jakarta.annotation.Resource;
-import jakarta.servlet.http.HttpServletResponse;
-import jakarta.validation.Valid;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.List;
-
-import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
-import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-
-
-@Tag(name = "绠$悊鍚庡彴 - MES 瀹㈡埛")
-@RestController
-@RequestMapping("/mes/md-client")
-@Validated
-public class MesMdClientController {
-
-    @Resource
-    private MesMdClientService clientService;
-
-    @PostMapping("/create")
-    @Operation(summary = "鍒涘缓瀹㈡埛")
-    @PreAuthorize("@ss.hasPermission('mes:md-client:create')")
-    public CommonResult<Long> createClient(@Valid @RequestBody MesMdClientSaveReqVO createReqVO) {
-        return success(clientService.createClient(createReqVO));
-    }
-
-    @PutMapping("/update")
-    @Operation(summary = "鏇存柊瀹㈡埛")
-    @PreAuthorize("@ss.hasPermission('mes:md-client:update')")
-    public CommonResult<Boolean> updateClient(@Valid @RequestBody MesMdClientSaveReqVO updateReqVO) {
-        clientService.updateClient(updateReqVO);
-        return success(true);
-    }
-
-    @DeleteMapping("/delete")
-    @Operation(summary = "鍒犻櫎瀹㈡埛")
-    @Parameter(name = "id", description = "缂栧彿", required = true)
-    @PreAuthorize("@ss.hasPermission('mes:md-client:delete')")
-    public CommonResult<Boolean> deleteClient(@RequestParam("id") Long id) {
-        clientService.deleteClient(id);
-        return success(true);
-    }
-
-    @GetMapping("/get")
-    @Operation(summary = "鑾峰緱瀹㈡埛")
-    @Parameter(name = "id", description = "缂栧彿", required = true, example = "1024")
-    @PreAuthorize("@ss.hasPermission('mes:md-client:query')")
-    public CommonResult<MesMdClientRespVO> getClient(@RequestParam("id") Long id) {
-        MesMdClientDO client = clientService.getClient(id);
-        return success(BeanUtils.toBean(client, MesMdClientRespVO.class));
-    }
-
-    @GetMapping("/page")
-    @Operation(summary = "鑾峰緱瀹㈡埛鍒嗛〉")
-    @PreAuthorize("@ss.hasPermission('mes:md-client:query')")
-    public CommonResult<PageResult<MesMdClientRespVO>> getClientPage(@Valid MesMdClientPageReqVO pageReqVO) {
-        PageResult<MesMdClientDO> pageResult = clientService.getClientPage(pageReqVO);
-        return success(BeanUtils.toBean(pageResult, MesMdClientRespVO.class));
-    }
-
-    @GetMapping("/export-excel")
-    @Operation(summary = "瀵煎嚭瀹㈡埛 Excel")
-    @PreAuthorize("@ss.hasPermission('mes:md-client:export')")
-    @ApiAccessLog(operateType = EXPORT)
-    public void exportClientExcel(@Valid MesMdClientPageReqVO pageReqVO,
-                                  HttpServletResponse response) throws IOException {
-        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
-        List<MesMdClientDO> list = clientService.getClientPage(pageReqVO).getList();
-        // 瀵煎嚭 Excel
-        ExcelUtils.write(response, "瀹㈡埛.xls", "鏁版嵁", MesMdClientRespVO.class,
-                BeanUtils.toBean(list, MesMdClientRespVO.class));
-    }
-
-    @GetMapping("/get-import-template")
-    @Operation(summary = "鑾峰緱瀹㈡埛瀵煎叆妯℃澘")
-    public void importTemplate(HttpServletResponse response) throws IOException {
-        // 鎵嬪姩鍒涘缓瀵煎嚭 demo
-        List<MesMdClientImportExcelVO> list = Collections.singletonList(
-                MesMdClientImportExcelVO.builder().code("C001").name("绀轰緥瀹㈡埛").nickname("绀轰緥")
-                        .type(1).telephone("13800138000").status(0).build()
-        );
-        // 杈撳嚭
-        ExcelUtils.write(response, "瀹㈡埛瀵煎叆妯℃澘.xls", "瀹㈡埛鍒楄〃", MesMdClientImportExcelVO.class, list);
-    }
-
-    @PostMapping("/import")
-    @Operation(summary = "瀵煎叆瀹㈡埛")
-    @Parameters({
-            @Parameter(name = "file", description = "Excel 鏂囦欢", required = true),
-            @Parameter(name = "updateSupport", description = "鏄惁鏀寔鏇存柊锛岄粯璁や负 false", example = "true")
-    })
-    @PreAuthorize("@ss.hasPermission('mes:md-client:import')")
-    public CommonResult<MesMdClientImportRespVO> importExcel(@RequestParam("file") MultipartFile file,
-                                                              @RequestParam(value = "updateSupport", required = false,
-                                                                      defaultValue = "false") Boolean updateSupport) throws Exception {
-        List<MesMdClientImportExcelVO> list = ExcelUtils.read(file, MesMdClientImportExcelVO.class);
-        return success(clientService.importClientList(list, updateSupport));
-    }
-
-}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientImportExcelVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientImportExcelVO.java
deleted file mode 100644
index ee99e1c..0000000
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientImportExcelVO.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package cn.iocoder.yudao.module.mes.controller.admin.md.client.vo;
-
-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.mes.enums.DictTypeConstants;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * 瀹㈡埛 Excel 瀵煎叆 VO
- */
-@Data
-@Builder
-@AllArgsConstructor
-@NoArgsConstructor
-public class MesMdClientImportExcelVO {
-
-    @ExcelProperty("瀹㈡埛缂栫爜")
-    private String code;
-
-    @ExcelProperty("瀹㈡埛鍚嶇О")
-    private String name;
-
-    @ExcelProperty("瀹㈡埛绠�绉�")
-    private String nickname;
-
-    @ExcelProperty(value = "瀹㈡埛绫诲瀷", converter = DictConvert.class)
-    @DictFormat(DictTypeConstants.MES_CLIENT_TYPE)
-    private Integer type;
-
-    @ExcelProperty("瀹㈡埛鐢佃瘽")
-    private String telephone;
-
-    @ExcelProperty("瀹㈡埛閭鍦板潃")
-    private String email;
-
-    @ExcelProperty("瀹㈡埛鑻辨枃鍚嶇О")
-    private String englishName;
-
-    @ExcelProperty("瀹㈡埛绠�浠�")
-    private String description;
-
-    @ExcelProperty("瀹㈡埛鍦板潃")
-    private String address;
-
-    @ExcelProperty("瀹㈡埛瀹樼綉鍦板潃")
-    private String website;
-
-    @ExcelProperty("鑱旂郴浜�1")
-    private String contact1Name;
-
-    @ExcelProperty("鑱旂郴浜�1-鐢佃瘽")
-    private String contact1Telephone;
-
-    @ExcelProperty("鑱旂郴浜�1-閭")
-    private String contact1Email;
-
-    @ExcelProperty("鑱旂郴浜�2")
-    private String contact2Name;
-
-    @ExcelProperty("鑱旂郴浜�2-鐢佃瘽")
-    private String contact2Telephone;
-
-    @ExcelProperty("鑱旂郴浜�2-閭")
-    private String contact2Email;
-
-    @ExcelProperty("缁熶竴绀句細淇$敤浠g爜")
-    private String creditCode;
-
-    @ExcelProperty(value = "鐘舵��", converter = DictConvert.class)
-    @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.COMMON_STATUS)
-    private Integer status;
-
-}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientImportRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientImportRespVO.java
deleted file mode 100644
index 7554dd0..0000000
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientImportRespVO.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package cn.iocoder.yudao.module.mes.controller.admin.md.client.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Builder;
-import lombok.Data;
-
-import java.util.List;
-import java.util.Map;
-
-@Schema(description = "绠$悊鍚庡彴 - MES 瀹㈡埛瀵煎叆 Response VO")
-@Data
-@Builder
-public class MesMdClientImportRespVO {
-
-    @Schema(description = "鍒涘缓鎴愬姛鐨勫鎴风紪鐮佹暟缁�", requiredMode = Schema.RequiredMode.REQUIRED)
-    private List<String> createCodes;
-
-    @Schema(description = "鏇存柊鎴愬姛鐨勫鎴风紪鐮佹暟缁�", requiredMode = Schema.RequiredMode.REQUIRED)
-    private List<String> updateCodes;
-
-    @Schema(description = "瀵煎叆澶辫触鐨勫鎴烽泦鍚堬紝key 涓哄鎴风紪鐮侊紝value 涓哄け璐ュ師鍥�", requiredMode = Schema.RequiredMode.REQUIRED)
-    private Map<String, String> failureCodes;
-
-}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientPageReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientPageReqVO.java
deleted file mode 100644
index a9c0e52..0000000
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientPageReqVO.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package cn.iocoder.yudao.module.mes.controller.admin.md.client.vo;
-
-import cn.iocoder.yudao.framework.common.pojo.PageParam;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-
-@Schema(description = "绠$悊鍚庡彴 - MES 瀹㈡埛鍒嗛〉 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class MesMdClientPageReqVO extends PageParam {
-
-    @Schema(description = "瀹㈡埛缂栫爜", example = "C00184")
-    private String code;
-
-    @Schema(description = "瀹㈡埛鍚嶇О", example = "姣斾簹杩�")
-    private String name;
-
-    @Schema(description = "瀹㈡埛绠�绉�", example = "姣斾簹杩�")
-    private String nickname;
-
-    @Schema(description = "瀹㈡埛鑻辨枃鍚嶇О", example = "BYD")
-    private String englishName;
-
-    @Schema(description = "瀹㈡埛绫诲瀷", example = "1")
-    private Integer type;
-
-    @Schema(description = "鐘舵��", example = "0")
-    private Integer status;
-
-}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientRespVO.java
deleted file mode 100644
index 9ed58bb..0000000
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientRespVO.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package cn.iocoder.yudao.module.mes.controller.admin.md.client.vo;
-
-import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
-import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
-import cn.iocoder.yudao.module.mes.enums.DictTypeConstants;
-import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
-import cn.idev.excel.annotation.ExcelProperty;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.time.LocalDateTime;
-
-@Schema(description = "绠$悊鍚庡彴 - MES 瀹㈡埛 Response VO")
-@Data
-@ExcelIgnoreUnannotated
-public class MesMdClientRespVO {
-
-    @Schema(description = "瀹㈡埛缂栧彿", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
-    @ExcelProperty("瀹㈡埛缂栧彿")
-    private Long id;
-
-    @Schema(description = "瀹㈡埛缂栫爜", requiredMode = Schema.RequiredMode.REQUIRED, example = "C00184")
-    @ExcelProperty("瀹㈡埛缂栫爜")
-    private String code;
-
-    @Schema(description = "瀹㈡埛鍚嶇О", requiredMode = Schema.RequiredMode.REQUIRED, example = "姣斾簹杩�")
-    @ExcelProperty("瀹㈡埛鍚嶇О")
-    private String name;
-
-    @Schema(description = "瀹㈡埛绠�绉�", example = "姣斾簹杩�")
-    @ExcelProperty("瀹㈡埛绠�绉�")
-    private String nickname;
-
-    @Schema(description = "瀹㈡埛鑻辨枃鍚嶇О", example = "BYD")
-    @ExcelProperty("瀹㈡埛鑻辨枃鍚嶇О")
-    private String englishName;
-
-    @Schema(description = "瀹㈡埛绠�浠�", example = "姣斾簹杩搧鐗岃癁鐢熶簬娣卞湷")
-    @ExcelProperty("瀹㈡埛绠�浠�")
-    private String description;
-
-    @Schema(description = "瀹㈡埛LOGO鍦板潃", example = "https://xxx.com/logo.png")
-    private String logo;
-
-    @Schema(description = "瀹㈡埛绫诲瀷", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    @ExcelProperty(value = "瀹㈡埛绫诲瀷", converter = DictConvert.class)
-    @DictFormat(DictTypeConstants.MES_CLIENT_TYPE)
-    private Integer type;
-
-    @Schema(description = "瀹㈡埛鍦板潃", example = "娣卞湷鍗楀北鍖�")
-    @ExcelProperty("瀹㈡埛鍦板潃")
-    private String address;
-
-    @Schema(description = "瀹㈡埛瀹樼綉鍦板潃", example = "https://www.bydglobal.com")
-    @ExcelProperty("瀹㈡埛瀹樼綉鍦板潃")
-    private String website;
-
-    @Schema(description = "瀹㈡埛閭鍦板潃", example = "salse@bydglobal.com")
-    @ExcelProperty("瀹㈡埛閭鍦板潃")
-    private String email;
-
-    @Schema(description = "瀹㈡埛鐢佃瘽", example = "123432222")
-    @ExcelProperty("瀹㈡埛鐢佃瘽")
-    private String telephone;
-
-    @Schema(description = "鑱旂郴浜�1", example = "寮犱笁")
-    @ExcelProperty("鑱旂郴浜�1")
-    private String contact1Name;
-
-    @Schema(description = "鑱旂郴浜�1-鐢佃瘽", example = "122212312")
-    @ExcelProperty("鑱旂郴浜�1-鐢佃瘽")
-    private String contact1Telephone;
-
-    @Schema(description = "鑱旂郴浜�1-閭", example = "s1@bydglobal.com")
-    @ExcelProperty("鑱旂郴浜�1-閭")
-    private String contact1Email;
-
-    @Schema(description = "鑱旂郴浜�2", example = "鏉庡洓")
-    @ExcelProperty("鑱旂郴浜�2")
-    private String contact2Name;
-
-    @Schema(description = "鑱旂郴浜�2-鐢佃瘽", example = "1132323232")
-    @ExcelProperty("鑱旂郴浜�2-鐢佃瘽")
-    private String contact2Telephone;
-
-    @Schema(description = "鑱旂郴浜�2-閭", example = "s2@bydglobal.com")
-    @ExcelProperty("鑱旂郴浜�2-閭")
-    private String contact2Email;
-
-    @Schema(description = "缁熶竴绀句細淇$敤浠g爜", example = "11212121")
-    @ExcelProperty("缁熶竴绀句細淇$敤浠g爜")
-    private String creditCode;
-
-    @Schema(description = "鐘舵��", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
-    @ExcelProperty(value = "鐘舵��", converter = DictConvert.class)
-    @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.COMMON_STATUS)
-    private Integer status;
-
-    @Schema(description = "澶囨敞", example = "澶囨敞")
-    @ExcelProperty("澶囨敞")
-    private String remark;
-
-    @Schema(description = "鍒涘缓鏃堕棿", requiredMode = Schema.RequiredMode.REQUIRED)
-    @ExcelProperty("鍒涘缓鏃堕棿")
-    private LocalDateTime createTime;
-
-}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientSaveReqVO.java
deleted file mode 100644
index 2166f92..0000000
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientSaveReqVO.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package cn.iocoder.yudao.module.mes.controller.admin.md.client.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.Email;
-import jakarta.validation.constraints.NotEmpty;
-import jakarta.validation.constraints.NotNull;
-import jakarta.validation.constraints.Size;
-import lombok.Data;
-
-@Schema(description = "绠$悊鍚庡彴 - MES 瀹㈡埛鏂板/淇敼 Request VO")
-@Data
-public class MesMdClientSaveReqVO {
-
-    @Schema(description = "瀹㈡埛缂栧彿", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
-    private Long id;
-
-    @Schema(description = "瀹㈡埛缂栫爜", requiredMode = Schema.RequiredMode.REQUIRED, example = "C00184")
-    @NotEmpty(message = "瀹㈡埛缂栫爜涓嶈兘涓虹┖")
-    @Size(max = 64, message = "瀹㈡埛缂栫爜闀垮害涓嶈兘瓒呰繃 64 涓瓧绗�")
-    private String code;
-
-    @Schema(description = "瀹㈡埛鍚嶇О", requiredMode = Schema.RequiredMode.REQUIRED, example = "姣斾簹杩�")
-    @NotEmpty(message = "瀹㈡埛鍚嶇О涓嶈兘涓虹┖")
-    @Size(max = 255, message = "瀹㈡埛鍚嶇О闀垮害涓嶈兘瓒呰繃 255 涓瓧绗�")
-    private String name;
-
-    @Schema(description = "瀹㈡埛绠�绉�", example = "姣斾簹杩�")
-    @Size(max = 255, message = "瀹㈡埛绠�绉伴暱搴︿笉鑳借秴杩� 255 涓瓧绗�")
-    private String nickname;
-
-    @Schema(description = "瀹㈡埛鑻辨枃鍚嶇О", example = "BYD")
-    @Size(max = 255, message = "瀹㈡埛鑻辨枃鍚嶇О闀垮害涓嶈兘瓒呰繃 255 涓瓧绗�")
-    private String englishName;
-
-    @Schema(description = "瀹㈡埛绠�浠�", example = "姣斾簹杩搧鐗岃癁鐢熶簬娣卞湷")
-    @Size(max = 500, message = "瀹㈡埛绠�浠嬮暱搴︿笉鑳借秴杩� 500 涓瓧绗�")
-    private String description;
-
-    @Schema(description = "瀹㈡埛LOGO鍦板潃", example = "https://xxx.com/logo.png")
-    @Size(max = 255, message = "瀹㈡埛LOGO鍦板潃闀垮害涓嶈兘瓒呰繃 255 涓瓧绗�")
-    private String logo;
-
-    @Schema(description = "瀹㈡埛绫诲瀷", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    @NotNull(message = "瀹㈡埛绫诲瀷涓嶈兘涓虹┖")
-    private Integer type;
-
-    @Schema(description = "瀹㈡埛鍦板潃", example = "娣卞湷鍗楀北鍖�")
-    @Size(max = 500, message = "瀹㈡埛鍦板潃闀垮害涓嶈兘瓒呰繃 500 涓瓧绗�")
-    private String address;
-
-    @Schema(description = "瀹㈡埛瀹樼綉鍦板潃", example = "https://www.bydglobal.com")
-    @Size(max = 255, message = "瀹㈡埛瀹樼綉鍦板潃闀垮害涓嶈兘瓒呰繃 255 涓瓧绗�")
-    private String website;
-
-    @Schema(description = "瀹㈡埛閭鍦板潃", example = "salse@bydglobal.com")
-    @Size(max = 255, message = "瀹㈡埛閭鍦板潃闀垮害涓嶈兘瓒呰繃 255 涓瓧绗�")
-    @Email(message = "瀹㈡埛閭鍦板潃鏍煎紡涓嶆纭�")
-    private String email;
-
-    @Schema(description = "瀹㈡埛鐢佃瘽", example = "123432222")
-    @Size(max = 64, message = "瀹㈡埛鐢佃瘽闀垮害涓嶈兘瓒呰繃 64 涓瓧绗�")
-    private String telephone;
-
-    @Schema(description = "鑱旂郴浜�1", example = "寮犱笁")
-    @Size(max = 64, message = "鑱旂郴浜�1闀垮害涓嶈兘瓒呰繃 64 涓瓧绗�")
-    private String contact1Name;
-
-    @Schema(description = "鑱旂郴浜�1-鐢佃瘽", example = "122212312")
-    @Size(max = 64, message = "鑱旂郴浜�1-鐢佃瘽闀垮害涓嶈兘瓒呰繃 64 涓瓧绗�")
-    private String contact1Telephone;
-
-    @Schema(description = "鑱旂郴浜�1-閭", example = "s1@bydglobal.com")
-    @Size(max = 255, message = "鑱旂郴浜�1-閭闀垮害涓嶈兘瓒呰繃 255 涓瓧绗�")
-    @Email(message = "鑱旂郴浜�1-閭鏍煎紡涓嶆纭�")
-    private String contact1Email;
-
-    @Schema(description = "鑱旂郴浜�2", example = "鏉庡洓")
-    @Size(max = 64, message = "鑱旂郴浜�2闀垮害涓嶈兘瓒呰繃 64 涓瓧绗�")
-    private String contact2Name;
-
-    @Schema(description = "鑱旂郴浜�2-鐢佃瘽", example = "1132323232")
-    @Size(max = 64, message = "鑱旂郴浜�2-鐢佃瘽闀垮害涓嶈兘瓒呰繃 64 涓瓧绗�")
-    private String contact2Telephone;
-
-    @Schema(description = "鑱旂郴浜�2-閭", example = "s2@bydglobal.com")
-    @Size(max = 255, message = "鑱旂郴浜�2-閭闀垮害涓嶈兘瓒呰繃 255 涓瓧绗�")
-    @Email(message = "鑱旂郴浜�2-閭鏍煎紡涓嶆纭�")
-    private String contact2Email;
-
-    @Schema(description = "缁熶竴绀句細淇$敤浠g爜", example = "11212121")
-    @Size(max = 64, message = "缁熶竴绀句細淇$敤浠g爜闀垮害涓嶈兘瓒呰繃 64 涓瓧绗�")
-    private String creditCode;
-
-    @Schema(description = "鐘舵��", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
-    @NotNull(message = "鐘舵�佷笉鑳戒负绌�")
-    private Integer status;
-
-    @Schema(description = "澶囨敞", example = "澶囨敞")
-    @Size(max = 500, message = "澶囨敞闀垮害涓嶈兘瓒呰繃 500 涓瓧绗�")
-    private String remark;
-
-}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/MesMdVendorController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/MesMdVendorController.java
deleted file mode 100644
index c362150..0000000
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/MesMdVendorController.java
+++ /dev/null
@@ -1,124 +0,0 @@
-package cn.iocoder.yudao.module.mes.controller.admin.md.vendor;
-
-import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.framework.common.pojo.PageParam;
-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.md.vendor.vo.MesMdVendorImportExcelVO;
-import cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo.MesMdVendorImportRespVO;
-import cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo.MesMdVendorPageReqVO;
-import cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo.MesMdVendorRespVO;
-import cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo.MesMdVendorSaveReqVO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO;
-import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.Parameters;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import jakarta.annotation.Resource;
-import jakarta.servlet.http.HttpServletResponse;
-import jakarta.validation.Valid;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.List;
-
-import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
-import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-
-@Tag(name = "绠$悊鍚庡彴 - MES 渚涘簲鍟�")
-@RestController
-@RequestMapping("/mes/md-vendor")
-@Validated
-public class MesMdVendorController {
-
-    @Resource
-    private MesMdVendorService vendorService;
-
-    @PostMapping("/create")
-    @Operation(summary = "鍒涘缓渚涘簲鍟�")
-    @PreAuthorize("@ss.hasPermission('mes:md-vendor:create')")
-    public CommonResult<Long> createVendor(@Valid @RequestBody MesMdVendorSaveReqVO createReqVO) {
-        return success(vendorService.createVendor(createReqVO));
-    }
-
-    @PutMapping("/update")
-    @Operation(summary = "鏇存柊渚涘簲鍟�")
-    @PreAuthorize("@ss.hasPermission('mes:md-vendor:update')")
-    public CommonResult<Boolean> updateVendor(@Valid @RequestBody MesMdVendorSaveReqVO updateReqVO) {
-        vendorService.updateVendor(updateReqVO);
-        return success(true);
-    }
-
-    @DeleteMapping("/delete")
-    @Operation(summary = "鍒犻櫎渚涘簲鍟�")
-    @Parameter(name = "id", description = "缂栧彿", required = true)
-    @PreAuthorize("@ss.hasPermission('mes:md-vendor:delete')")
-    public CommonResult<Boolean> deleteVendor(@RequestParam("id") Long id) {
-        vendorService.deleteVendor(id);
-        return success(true);
-    }
-
-    @GetMapping("/get")
-    @Operation(summary = "鑾峰緱渚涘簲鍟�")
-    @Parameter(name = "id", description = "缂栧彿", required = true, example = "1024")
-    @PreAuthorize("@ss.hasPermission('mes:md-vendor:query')")
-    public CommonResult<MesMdVendorRespVO> getVendor(@RequestParam("id") Long id) {
-        MesMdVendorDO vendor = vendorService.getVendor(id);
-        return success(BeanUtils.toBean(vendor, MesMdVendorRespVO.class));
-    }
-
-    @GetMapping("/page")
-    @Operation(summary = "鑾峰緱渚涘簲鍟嗗垎椤�")
-    @PreAuthorize("@ss.hasPermission('mes:md-vendor:query')")
-    public CommonResult<PageResult<MesMdVendorRespVO>> getVendorPage(@Valid MesMdVendorPageReqVO pageReqVO) {
-        PageResult<MesMdVendorDO> pageResult = vendorService.getVendorPage(pageReqVO);
-        return success(BeanUtils.toBean(pageResult, MesMdVendorRespVO.class));
-    }
-
-    @GetMapping("/export-excel")
-    @Operation(summary = "瀵煎嚭渚涘簲鍟� Excel")
-    @PreAuthorize("@ss.hasPermission('mes:md-vendor:export')")
-    @ApiAccessLog(operateType = EXPORT)
-    public void exportVendorExcel(@Valid MesMdVendorPageReqVO pageReqVO,
-                                  HttpServletResponse response) throws IOException {
-        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
-        List<MesMdVendorDO> list = vendorService.getVendorPage(pageReqVO).getList();
-        // 瀵煎嚭 Excel
-        ExcelUtils.write(response, "渚涘簲鍟�.xls", "鏁版嵁", MesMdVendorRespVO.class,
-                BeanUtils.toBean(list, MesMdVendorRespVO.class));
-    }
-
-    @GetMapping("/get-import-template")
-    @Operation(summary = "鑾峰緱渚涘簲鍟嗗鍏ユā鏉�")
-    public void importTemplate(HttpServletResponse response) throws IOException {
-        // 鎵嬪姩鍒涘缓瀵煎嚭 demo
-        List<MesMdVendorImportExcelVO> list = Collections.singletonList(
-                MesMdVendorImportExcelVO.builder().code("V001").name("绀轰緥渚涘簲鍟�").nickname("绀轰緥")
-                        .level("A").telephone("13800138000").status(0).build()
-        );
-        // 杈撳嚭
-        ExcelUtils.write(response, "渚涘簲鍟嗗鍏ユā鏉�.xls", "渚涘簲鍟嗗垪琛�", MesMdVendorImportExcelVO.class, list);
-    }
-
-    @PostMapping("/import")
-    @Operation(summary = "瀵煎叆渚涘簲鍟�")
-    @Parameters({
-            @Parameter(name = "file", description = "Excel 鏂囦欢", required = true),
-            @Parameter(name = "updateSupport", description = "鏄惁鏀寔鏇存柊锛岄粯璁や负 false", example = "true")
-    })
-    @PreAuthorize("@ss.hasPermission('mes:md-vendor:import')")
-    public CommonResult<MesMdVendorImportRespVO> importExcel(@RequestParam("file") MultipartFile file,
-                                                              @RequestParam(value = "updateSupport", required = false,
-                                                                      defaultValue = "false") Boolean updateSupport) throws Exception {
-        List<MesMdVendorImportExcelVO> list = ExcelUtils.read(file, MesMdVendorImportExcelVO.class);
-        return success(vendorService.importVendorList(list, updateSupport));
-    }
-
-}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorImportExcelVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorImportExcelVO.java
deleted file mode 100644
index 237e603..0000000
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorImportExcelVO.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo;
-
-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.mes.enums.DictTypeConstants;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * 渚涘簲鍟� Excel 瀵煎叆 VO
- */
-@Data
-@Builder
-@AllArgsConstructor
-@NoArgsConstructor
-public class MesMdVendorImportExcelVO {
-
-    @ExcelProperty("渚涘簲鍟嗙紪鐮�")
-    private String code;
-
-    @ExcelProperty("渚涘簲鍟嗗悕绉�")
-    private String name;
-
-    @ExcelProperty("渚涘簲鍟嗙畝绉�")
-    private String nickname;
-
-    @ExcelProperty(value = "渚涘簲鍟嗙瓑绾�", converter = DictConvert.class)
-    @DictFormat(DictTypeConstants.MES_VENDOR_LEVEL)
-    private String level;
-
-    @ExcelProperty("渚涘簲鍟嗙數璇�")
-    private String telephone;
-
-    @ExcelProperty("渚涘簲鍟嗛偖绠卞湴鍧�")
-    private String email;
-
-    @ExcelProperty("渚涘簲鍟嗚嫳鏂囧悕绉�")
-    private String englishName;
-
-    @ExcelProperty("渚涘簲鍟嗙畝浠�")
-    private String description;
-
-    @ExcelProperty("渚涘簲鍟嗗湴鍧�")
-    private String address;
-
-    @ExcelProperty("渚涘簲鍟嗗畼缃戝湴鍧�")
-    private String website;
-
-    @ExcelProperty("鑱旂郴浜�1")
-    private String contact1Name;
-
-    @ExcelProperty("鑱旂郴浜�1-鐢佃瘽")
-    private String contact1Telephone;
-
-    @ExcelProperty("鑱旂郴浜�1-閭")
-    private String contact1Email;
-
-    @ExcelProperty("鑱旂郴浜�2")
-    private String contact2Name;
-
-    @ExcelProperty("鑱旂郴浜�2-鐢佃瘽")
-    private String contact2Telephone;
-
-    @ExcelProperty("鑱旂郴浜�2-閭")
-    private String contact2Email;
-
-    @ExcelProperty("缁熶竴绀句細淇$敤浠g爜")
-    private String creditCode;
-
-    @ExcelProperty(value = "鐘舵��", converter = DictConvert.class)
-    @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.COMMON_STATUS)
-    private Integer status;
-
-}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorImportRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorImportRespVO.java
deleted file mode 100644
index 92b552e..0000000
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorImportRespVO.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Builder;
-import lombok.Data;
-
-import java.util.List;
-import java.util.Map;
-
-@Schema(description = "绠$悊鍚庡彴 - MES 渚涘簲鍟嗗鍏� Response VO")
-@Data
-@Builder
-public class MesMdVendorImportRespVO {
-
-    @Schema(description = "鍒涘缓鎴愬姛鐨勪緵搴斿晢缂栫爜鏁扮粍", requiredMode = Schema.RequiredMode.REQUIRED)
-    private List<String> createCodes;
-
-    @Schema(description = "鏇存柊鎴愬姛鐨勪緵搴斿晢缂栫爜鏁扮粍", requiredMode = Schema.RequiredMode.REQUIRED)
-    private List<String> updateCodes;
-
-    @Schema(description = "瀵煎叆澶辫触鐨勪緵搴斿晢闆嗗悎锛宬ey 涓轰緵搴斿晢缂栫爜锛寁alue 涓哄け璐ュ師鍥�", requiredMode = Schema.RequiredMode.REQUIRED)
-    private Map<String, String> failureCodes;
-
-}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorPageReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorPageReqVO.java
deleted file mode 100644
index 738b93c..0000000
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorPageReqVO.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo;
-
-import cn.iocoder.yudao.framework.common.pojo.PageParam;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-
-@Schema(description = "绠$悊鍚庡彴 - MES 渚涘簲鍟嗗垎椤� Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class MesMdVendorPageReqVO extends PageParam {
-
-    @Schema(description = "渚涘簲鍟嗙紪鐮�", example = "V00101")
-    private String code;
-
-    @Schema(description = "渚涘簲鍟嗗悕绉�", example = "娴峰姏寰�")
-    private String name;
-
-    @Schema(description = "渚涘簲鍟嗙畝绉�", example = "娴峰姏寰�")
-    private String nickname;
-
-    @Schema(description = "渚涘簲鍟嗚嫳鏂囧悕绉�", example = "HLD")
-    private String englishName;
-
-    @Schema(description = "鐘舵��", example = "0")
-    private Integer status;
-
-}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorRespVO.java
deleted file mode 100644
index 00450cc..0000000
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorRespVO.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo;
-
-import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
-import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
-import cn.iocoder.yudao.module.mes.enums.DictTypeConstants;
-import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
-import cn.idev.excel.annotation.ExcelProperty;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.time.LocalDateTime;
-
-@Schema(description = "绠$悊鍚庡彴 - MES 渚涘簲鍟� Response VO")
-@Data
-@ExcelIgnoreUnannotated
-public class MesMdVendorRespVO {
-
-    @Schema(description = "渚涘簲鍟嗙紪鍙�", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
-    @ExcelProperty("渚涘簲鍟嗙紪鍙�")
-    private Long id;
-
-    @Schema(description = "渚涘簲鍟嗙紪鐮�", requiredMode = Schema.RequiredMode.REQUIRED, example = "V00101")
-    @ExcelProperty("渚涘簲鍟嗙紪鐮�")
-    private String code;
-
-    @Schema(description = "渚涘簲鍟嗗悕绉�", requiredMode = Schema.RequiredMode.REQUIRED, example = "娴峰姏寰风數瀛�")
-    @ExcelProperty("渚涘簲鍟嗗悕绉�")
-    private String name;
-
-    @Schema(description = "渚涘簲鍟嗙畝绉�", example = "娴峰姏寰�")
-    @ExcelProperty("渚涘簲鍟嗙畝绉�")
-    private String nickname;
-
-    @Schema(description = "渚涘簲鍟嗚嫳鏂囧悕绉�", example = "HLD Electronics")
-    @ExcelProperty("渚涘簲鍟嗚嫳鏂囧悕绉�")
-    private String englishName;
-
-    @Schema(description = "渚涘簲鍟嗙畝浠�", example = "涓撲笟浠庝簨鐢靛瓙鍏冨櫒浠剁敓浜т笌閿�鍞�")
-    @ExcelProperty("渚涘簲鍟嗙畝浠�")
-    private String description;
-
-    @Schema(description = "渚涘簲鍟哃OGO鍦板潃", example = "https://xxx.com/logo.png")
-    private String logo;
-
-    @Schema(description = "渚涘簲鍟嗙瓑绾�", example = "A")
-    @ExcelProperty(value = "渚涘簲鍟嗙瓑绾�", converter = DictConvert.class)
-    @DictFormat(DictTypeConstants.MES_VENDOR_LEVEL)
-    private String level;
-
-    @Schema(description = "渚涘簲鍟嗚瘎鍒�", example = "95")
-    @ExcelProperty("渚涘簲鍟嗚瘎鍒�")
-    private Integer score;
-
-    @Schema(description = "渚涘簲鍟嗗湴鍧�", example = "娣卞湷甯傚疂瀹夊尯")
-    @ExcelProperty("渚涘簲鍟嗗湴鍧�")
-    private String address;
-
-    @Schema(description = "渚涘簲鍟嗗畼缃戝湴鍧�", example = "https://www.hld-elec.com")
-    @ExcelProperty("渚涘簲鍟嗗畼缃戝湴鍧�")
-    private String website;
-
-    @Schema(description = "渚涘簲鍟嗛偖绠卞湴鍧�", example = "info@hld-elec.com")
-    @ExcelProperty("渚涘簲鍟嗛偖绠卞湴鍧�")
-    private String email;
-
-    @Schema(description = "渚涘簲鍟嗙數璇�", example = "0755-12345678")
-    @ExcelProperty("渚涘簲鍟嗙數璇�")
-    private String telephone;
-
-    @Schema(description = "鑱旂郴浜�1", example = "鐜嬬粡鐞�")
-    @ExcelProperty("鑱旂郴浜�1")
-    private String contact1Name;
-
-    @Schema(description = "鑱旂郴浜�1-鐢佃瘽", example = "13800138001")
-    @ExcelProperty("鑱旂郴浜�1-鐢佃瘽")
-    private String contact1Telephone;
-
-    @Schema(description = "鑱旂郴浜�1-閭", example = "wang@hld-elec.com")
-    @ExcelProperty("鑱旂郴浜�1-閭")
-    private String contact1Email;
-
-    @Schema(description = "鑱旂郴浜�2", example = "璧靛姪鐞�")
-    @ExcelProperty("鑱旂郴浜�2")
-    private String contact2Name;
-
-    @Schema(description = "鑱旂郴浜�2-鐢佃瘽", example = "13800138002")
-    @ExcelProperty("鑱旂郴浜�2-鐢佃瘽")
-    private String contact2Telephone;
-
-    @Schema(description = "鑱旂郴浜�2-閭", example = "zhao@hld-elec.com")
-    @ExcelProperty("鑱旂郴浜�2-閭")
-    private String contact2Email;
-
-    @Schema(description = "缁熶竴绀句細淇$敤浠g爜", example = "91440300MA5EXAMPLE")
-    @ExcelProperty("缁熶竴绀句細淇$敤浠g爜")
-    private String creditCode;
-
-    @Schema(description = "鐘舵��", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
-    @ExcelProperty(value = "鐘舵��", converter = DictConvert.class)
-    @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.COMMON_STATUS)
-    private Integer status;
-
-    @Schema(description = "澶囨敞", example = "澶囨敞")
-    @ExcelProperty("澶囨敞")
-    private String remark;
-
-    @Schema(description = "鍒涘缓鏃堕棿", requiredMode = Schema.RequiredMode.REQUIRED)
-    @ExcelProperty("鍒涘缓鏃堕棿")
-    private LocalDateTime createTime;
-
-}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorSaveReqVO.java
deleted file mode 100644
index c17c653..0000000
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorSaveReqVO.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.Email;
-import jakarta.validation.constraints.NotEmpty;
-import jakarta.validation.constraints.NotNull;
-import jakarta.validation.constraints.Size;
-import lombok.Data;
-
-@Schema(description = "绠$悊鍚庡彴 - MES 渚涘簲鍟嗘柊澧�/淇敼 Request VO")
-@Data
-public class MesMdVendorSaveReqVO {
-
-    @Schema(description = "渚涘簲鍟嗙紪鍙�", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
-    private Long id;
-
-    @Schema(description = "渚涘簲鍟嗙紪鐮�", requiredMode = Schema.RequiredMode.REQUIRED, example = "V00101")
-    @NotEmpty(message = "渚涘簲鍟嗙紪鐮佷笉鑳戒负绌�")
-    @Size(max = 64, message = "渚涘簲鍟嗙紪鐮侀暱搴︿笉鑳借秴杩� 64 涓瓧绗�")
-    private String code;
-
-    @Schema(description = "渚涘簲鍟嗗悕绉�", requiredMode = Schema.RequiredMode.REQUIRED, example = "娴峰姏寰风數瀛�")
-    @NotEmpty(message = "渚涘簲鍟嗗悕绉颁笉鑳戒负绌�")
-    @Size(max = 255, message = "渚涘簲鍟嗗悕绉伴暱搴︿笉鑳借秴杩� 255 涓瓧绗�")
-    private String name;
-
-    @Schema(description = "渚涘簲鍟嗙畝绉�", example = "娴峰姏寰�")
-    @Size(max = 255, message = "渚涘簲鍟嗙畝绉伴暱搴︿笉鑳借秴杩� 255 涓瓧绗�")
-    private String nickname;
-
-    @Schema(description = "渚涘簲鍟嗚嫳鏂囧悕绉�", example = "HLD Electronics")
-    @Size(max = 255, message = "渚涘簲鍟嗚嫳鏂囧悕绉伴暱搴︿笉鑳借秴杩� 255 涓瓧绗�")
-    private String englishName;
-
-    @Schema(description = "渚涘簲鍟嗙畝浠�", example = "涓撲笟浠庝簨鐢靛瓙鍏冨櫒浠剁敓浜т笌閿�鍞�")
-    @Size(max = 500, message = "渚涘簲鍟嗙畝浠嬮暱搴︿笉鑳借秴杩� 500 涓瓧绗�")
-    private String description;
-
-    @Schema(description = "渚涘簲鍟哃OGO鍦板潃", example = "https://xxx.com/logo.png")
-    @Size(max = 255, message = "渚涘簲鍟哃OGO鍦板潃闀垮害涓嶈兘瓒呰繃 255 涓瓧绗�")
-    private String logo;
-
-    @Schema(description = "渚涘簲鍟嗙瓑绾�", example = "A")
-    @Size(max = 64, message = "渚涘簲鍟嗙瓑绾ч暱搴︿笉鑳借秴杩� 64 涓瓧绗�")
-    private String level;
-
-    @Schema(description = "渚涘簲鍟嗚瘎鍒�", example = "95")
-    private Integer score;
-
-    @Schema(description = "渚涘簲鍟嗗湴鍧�", example = "娣卞湷甯傚疂瀹夊尯")
-    @Size(max = 500, message = "渚涘簲鍟嗗湴鍧�闀垮害涓嶈兘瓒呰繃 500 涓瓧绗�")
-    private String address;
-
-    @Schema(description = "渚涘簲鍟嗗畼缃戝湴鍧�", example = "https://www.hld-elec.com")
-    @Size(max = 255, message = "渚涘簲鍟嗗畼缃戝湴鍧�闀垮害涓嶈兘瓒呰繃 255 涓瓧绗�")
-    private String website;
-
-    @Schema(description = "渚涘簲鍟嗛偖绠卞湴鍧�", example = "info@hld-elec.com")
-    @Size(max = 255, message = "渚涘簲鍟嗛偖绠卞湴鍧�闀垮害涓嶈兘瓒呰繃 255 涓瓧绗�")
-    @Email(message = "渚涘簲鍟嗛偖绠卞湴鍧�鏍煎紡涓嶆纭�")
-    private String email;
-
-    @Schema(description = "渚涘簲鍟嗙數璇�", example = "0755-12345678")
-    @Size(max = 64, message = "渚涘簲鍟嗙數璇濋暱搴︿笉鑳借秴杩� 64 涓瓧绗�")
-    private String telephone;
-
-    @Schema(description = "鑱旂郴浜�1", example = "鐜嬬粡鐞�")
-    @Size(max = 64, message = "鑱旂郴浜�1闀垮害涓嶈兘瓒呰繃 64 涓瓧绗�")
-    private String contact1Name;
-
-    @Schema(description = "鑱旂郴浜�1-鐢佃瘽", example = "13800138001")
-    @Size(max = 64, message = "鑱旂郴浜�1-鐢佃瘽闀垮害涓嶈兘瓒呰繃 64 涓瓧绗�")
-    private String contact1Telephone;
-
-    @Schema(description = "鑱旂郴浜�1-閭", example = "wang@hld-elec.com")
-    @Size(max = 255, message = "鑱旂郴浜�1-閭闀垮害涓嶈兘瓒呰繃 255 涓瓧绗�")
-    @Email(message = "鑱旂郴浜�1-閭鏍煎紡涓嶆纭�")
-    private String contact1Email;
-
-    @Schema(description = "鑱旂郴浜�2", example = "璧靛姪鐞�")
-    @Size(max = 64, message = "鑱旂郴浜�2闀垮害涓嶈兘瓒呰繃 64 涓瓧绗�")
-    private String contact2Name;
-
-    @Schema(description = "鑱旂郴浜�2-鐢佃瘽", example = "13800138002")
-    @Size(max = 64, message = "鑱旂郴浜�2-鐢佃瘽闀垮害涓嶈兘瓒呰繃 64 涓瓧绗�")
-    private String contact2Telephone;
-
-    @Schema(description = "鑱旂郴浜�2-閭", example = "zhao@hld-elec.com")
-    @Size(max = 255, message = "鑱旂郴浜�2-閭闀垮害涓嶈兘瓒呰繃 255 涓瓧绗�")
-    @Email(message = "鑱旂郴浜�2-閭鏍煎紡涓嶆纭�")
-    private String contact2Email;
-
-    @Schema(description = "缁熶竴绀句細淇$敤浠g爜", example = "91440300MA5EXAMPLE")
-    @Size(max = 64, message = "缁熶竴绀句細淇$敤浠g爜闀垮害涓嶈兘瓒呰繃 64 涓瓧绗�")
-    private String creditCode;
-
-    @Schema(description = "鐘舵��", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
-    @NotNull(message = "鐘舵�佷笉鑳戒负绌�")
-    private Integer status;
-
-    @Schema(description = "澶囨敞", example = "澶囨敞")
-    @Size(max = 500, message = "澶囨敞闀垮害涓嶈兘瓒呰繃 500 涓瓧绗�")
-    private String remark;
-
-}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/mps/MesProMpsController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/mps/MesProMpsController.java
new file mode 100644
index 0000000..b174b5a
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/mps/MesProMpsController.java
@@ -0,0 +1,156 @@
+package cn.iocoder.yudao.module.mes.controller.admin.pro.mps;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.ListUtil;
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
+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.mps.vo.MesProMpsPageReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.mps.vo.MesProMpsRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.mps.vo.MesProMpsSaveReqVO;
+import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
+import cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerRespDTO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.mps.MesProMpsDO;
+import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
+import cn.iocoder.yudao.module.mes.service.pro.mps.MesProMpsService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+
+@Tag(name = "绠$悊鍚庡彴 - MES 鐢熶骇涓昏鍒�")
+@RestController
+@RequestMapping("/mes/pro-mps")
+@Validated
+public class MesProMpsController {
+
+    @Resource
+    private MesProMpsService mpsService;
+    @Resource
+    private MesMdItemService itemService;
+    @Resource
+    private CrmCustomerApi customerApi;
+
+    @PostMapping("/create")
+    @Operation(summary = "鍒涘缓鐢熶骇涓昏鍒�")
+    @PreAuthorize("@ss.hasPermission('mes:pro-mps:create')")
+    public CommonResult<Long> createMps(@Valid @RequestBody MesProMpsSaveReqVO createReqVO) {
+        return success(mpsService.createMps(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "鏇存柊鐢熶骇涓昏鍒�")
+    @PreAuthorize("@ss.hasPermission('mes:pro-mps:update')")
+    public CommonResult<Boolean> updateMps(@Valid @RequestBody MesProMpsSaveReqVO updateReqVO) {
+        mpsService.updateMps(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "鍒犻櫎鐢熶骇涓昏鍒�")
+    @Parameter(name = "id", description = "缂栧彿", required = true)
+    @PreAuthorize("@ss.hasPermission('mes:pro-mps:delete')")
+    public CommonResult<Boolean> deleteMps(@RequestParam("id") Long id) {
+        mpsService.deleteMps(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "鑾峰緱鐢熶骇涓昏鍒�")
+    @Parameter(name = "id", description = "缂栧彿", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('mes:pro-mps:query')")
+    public CommonResult<MesProMpsRespVO> getMps(@RequestParam("id") Long id) {
+        MesProMpsDO mps = mpsService.getMps(id);
+        if (mps == null) {
+            return success(null);
+        }
+        return success(buildMpsRespVOList(ListUtil.of(mps)).get(0));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "鑾峰緱鐢熶骇涓昏鍒掑垎椤�")
+    @PreAuthorize("@ss.hasPermission('mes:pro-mps:query')")
+    public CommonResult<PageResult<MesProMpsRespVO>> getMpsPage(@Valid MesProMpsPageReqVO pageReqVO) {
+        PageResult<MesProMpsDO> pageResult = mpsService.getMpsPage(pageReqVO);
+        return success(new PageResult<>(buildMpsRespVOList(pageResult.getList()), pageResult.getTotal()));
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "瀵煎嚭鐢熶骇涓昏鍒� Excel")
+    @PreAuthorize("@ss.hasPermission('mes:pro-mps:export')")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportMpsExcel(@Valid MesProMpsPageReqVO pageReqVO,
+                               HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<MesProMpsDO> list = mpsService.getMpsPage(pageReqVO).getList();
+        List<MesProMpsRespVO> voList = buildMpsRespVOList(list);
+        ExcelUtils.write(response, "鐢熶骇涓昏鍒�.xls", "鏁版嵁", MesProMpsRespVO.class, voList);
+    }
+
+    @PostMapping("/issue")
+    @Operation(summary = "涓嬪彂鐢熶骇涓昏鍒�")
+    @Parameter(name = "id", description = "MPS 缂栧彿", required = true)
+    @PreAuthorize("@ss.hasPermission('mes:pro-mps:issue')")
+    public CommonResult<Long> issueMps(@RequestParam("id") Long id) {
+        return success(mpsService.issueMps(id));
+    }
+
+    @PostMapping("/merge-issue")
+    @Operation(summary = "鍚堝苟涓嬪彂鐢熶骇涓昏鍒�")
+    @PreAuthorize("@ss.hasPermission('mes:pro-mps:merge-issue')")
+    public CommonResult<Long> mergeAndIssueMps(@RequestBody List<Long> mpsIds) {
+        return success(mpsService.mergeAndIssueMps(mpsIds));
+    }
+
+    @PostMapping("/cancel")
+    @Operation(summary = "鍙栨秷鐢熶骇涓昏鍒�")
+    @Parameter(name = "id", description = "MPS 缂栧彿", required = true)
+    @PreAuthorize("@ss.hasPermission('mes:pro-mps:cancel')")
+    public CommonResult<Boolean> cancelMps(@RequestParam("id") Long id) {
+        mpsService.cancelMps(id);
+        return success(true);
+    }
+
+    // ==================== 鎷兼帴 VO ====================
+
+    private List<MesProMpsRespVO> buildMpsRespVOList(List<MesProMpsDO> list) {
+        if (CollUtil.isEmpty(list)) {
+            return Collections.emptyList();
+        }
+        // 1. 鎵归噺鑾峰彇鍏宠仈鏁版嵁
+        Map<Long, MesMdItemDO> itemMap = itemService.getItemMap(
+                convertSet(list, MesProMpsDO::getProductId));
+        Map<Long, CrmCustomerRespDTO> clientMap = customerApi.getCustomerMap(
+                convertSet(list, MesProMpsDO::getClientId));
+        // 2. 鎷兼帴 VO
+        return BeanUtils.toBean(list, MesProMpsRespVO.class, vo -> {
+            MapUtils.findAndThen(itemMap, vo.getProductId(), item -> {
+                vo.setProductName(item.getName())
+                        .setProductCode(item.getCode())
+                        .setProductSpecification(item.getSpecification());
+            });
+            MapUtils.findAndThen(clientMap, vo.getClientId(),
+                    client -> vo.setClientName(client.getName()));
+        });
+    }
+
+}
\ No newline at end of file
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/mps/vo/MesProMpsPageReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/mps/vo/MesProMpsPageReqVO.java
new file mode 100644
index 0000000..433e7c8
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/mps/vo/MesProMpsPageReqVO.java
@@ -0,0 +1,46 @@
+package cn.iocoder.yudao.module.mes.controller.admin.pro.mps.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "绠$悊鍚庡彴 - MES 鐢熶骇涓昏鍒掑垎椤� Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class MesProMpsPageReqVO extends PageParam {
+
+    @Schema(description = "MPS 缂栫爜", example = "MPS-001")
+    private String code;
+
+    @Schema(description = "鐘舵��", example = "0")
+    private Integer status;
+
+    @Schema(description = "浜у搧缂栧彿", example = "100")
+    private Long productId;
+
+    @Schema(description = "瀹㈡埛缂栧彿", example = "300")
+    private Long clientId;
+
+    @Schema(description = "閿�鍞鍗曞彿", example = "SO-001")
+    private String saleOrderNo;
+
+    @Schema(description = "鐢熶骇宸ュ崟ID", example = "500")
+    private Long workOrderId;
+
+    @Schema(description = "闇�姹傛棩鏈�")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] requestDate;
+
+    @Schema(description = "鍒涘缓鏃堕棿")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}
\ No newline at end of file
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/mps/vo/MesProMpsRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/mps/vo/MesProMpsRespVO.java
new file mode 100644
index 0000000..b7c2622
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/mps/vo/MesProMpsRespVO.java
@@ -0,0 +1,125 @@
+package cn.iocoder.yudao.module.mes.controller.admin.pro.mps.vo;
+
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
+import cn.iocoder.yudao.module.mes.enums.DictTypeConstants;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Schema(description = "绠$悊鍚庡彴 - MES 鐢熶骇涓昏鍒� Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class MesProMpsRespVO {
+
+    @Schema(description = "缂栧彿", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+    @ExcelProperty("缂栧彿")
+    private Long id;
+
+    @Schema(description = "MPS 缂栫爜", example = "MPS-001")
+    @ExcelProperty("MPS 缂栫爜")
+    private String code;
+
+    @Schema(description = "鐘舵��", example = "0")
+    @ExcelProperty(value = "鐘舵��", converter = DictConvert.class)
+    @DictFormat(DictTypeConstants.MES_PRO_MPS_STATUS)
+    private Integer status;
+
+    // ========== 鏉ユ簮淇℃伅 ==========
+
+    @Schema(description = "閿�鍞鍗旾D", example = "100")
+    private Long saleOrderId;
+
+    @Schema(description = "閿�鍞鍗曞彿", example = "SO-001")
+    @ExcelProperty("閿�鍞鍗曞彿")
+    private String saleOrderNo;
+
+    @Schema(description = "閿�鍞鍗曟槑缁咺D", example = "200")
+    private Long saleOrderItemId;
+
+    // ========== 浜у搧淇℃伅 ==========
+
+    @Schema(description = "浜у搧缂栧彿", example = "100")
+    private Long productId;
+
+    @Schema(description = "浜у搧缂栫爜", example = "P-001")
+    @ExcelProperty("浜у搧缂栫爜")
+    private String productCode;
+
+    @Schema(description = "浜у搧鍚嶇О", example = "鐢佃矾鏉� A")
+    @ExcelProperty("浜у搧鍚嶇О")
+    private String productName;
+
+    @Schema(description = "瑙勬牸鍨嬪彿", example = "100x200mm")
+    @ExcelProperty("瑙勬牸鍨嬪彿")
+    private String productSpecification;
+
+    @Schema(description = "鍗曚綅鍚嶇О", example = "涓�")
+    @ExcelProperty("鍗曚綅")
+    private String unitMeasureName;
+
+    @Schema(description = "璁″垝鐢熶骇鏁伴噺", example = "100.00")
+    @ExcelProperty("璁″垝鐢熶骇鏁伴噺")
+    private BigDecimal quantity;
+
+    @Schema(description = "宸茬敓浜ф暟閲�", example = "50.00")
+    @ExcelProperty("宸茬敓浜ф暟閲�")
+    private BigDecimal quantityProduced;
+
+    // ========== 瀹㈡埛淇℃伅 ==========
+
+    @Schema(description = "瀹㈡埛缂栧彿", example = "300")
+    private Long clientId;
+
+    @Schema(description = "瀹㈡埛缂栫爜", example = "C-001")
+    @ExcelProperty("瀹㈡埛缂栫爜")
+    private String clientCode;
+
+    @Schema(description = "瀹㈡埛鍚嶇О", example = "瀹㈡埛 A")
+    @ExcelProperty("瀹㈡埛鍚嶇О")
+    private String clientName;
+
+    // ========== 鏃堕棿淇℃伅 ==========
+
+    @Schema(description = "闇�姹傛棩鏈�")
+    @ExcelProperty("闇�姹傛棩鏈�")
+    private LocalDateTime requestDate;
+
+    @Schema(description = "涓嬪彂鏃ユ湡")
+    @ExcelProperty("涓嬪彂鏃ユ湡")
+    private LocalDateTime issueDate;
+
+    @Schema(description = "瀹屾垚鏃ユ湡")
+    @ExcelProperty("瀹屾垚鏃ユ湡")
+    private LocalDateTime finishDate;
+
+    // ========== 鐢熶骇宸ュ崟鍏宠仈 ==========
+
+    @Schema(description = "鐢熶骇宸ュ崟ID", example = "500")
+    private Long workOrderId;
+
+    @Schema(description = "鐢熶骇宸ュ崟缂栫爜", example = "WO-001")
+    @ExcelProperty("鐢熶骇宸ュ崟缂栫爜")
+    private String workOrderCode;
+
+    // ========== 鍚堝苟涓嬪彂鏍囪瘑 ==========
+
+    @Schema(description = "鏄惁鍚堝苟涓嬪彂", example = "0")
+    private Integer mergeFlag;
+
+    @Schema(description = "鍚堝苟鎵规鍙�", example = "MERGE-001")
+    private String mergeBatchNo;
+
+    @Schema(description = "澶囨敞", example = "澶囨敞")
+    @ExcelProperty("澶囨敞")
+    private String remark;
+
+    @Schema(description = "鍒涘缓鏃堕棿", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("鍒涘缓鏃堕棿")
+    private LocalDateTime createTime;
+
+}
\ No newline at end of file
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/mps/vo/MesProMpsSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/mps/vo/MesProMpsSaveReqVO.java
new file mode 100644
index 0000000..71c6a75
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/mps/vo/MesProMpsSaveReqVO.java
@@ -0,0 +1,58 @@
+package cn.iocoder.yudao.module.mes.controller.admin.pro.mps.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Schema(description = "绠$悊鍚庡彴 - MES 鐢熶骇涓昏鍒掓柊澧�/淇敼 Request VO")
+@Data
+public class MesProMpsSaveReqVO {
+
+    @Schema(description = "缂栧彿", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+    private Long id;
+
+    @Schema(description = "MPS 缂栫爜锛堟柊澧炴椂涓嶅~鑷姩鐢熸垚锛�", example = "MPS-001")
+    private String code;
+
+    // ========== 鏉ユ簮淇℃伅 ==========
+
+    @Schema(description = "閿�鍞鍗旾D", example = "100")
+    private Long saleOrderId;
+
+    @Schema(description = "閿�鍞鍗曞彿", example = "SO-001")
+    private String saleOrderNo;
+
+    @Schema(description = "閿�鍞鍗曟槑缁咺D", example = "200")
+    private Long saleOrderItemId;
+
+    // ========== 浜у搧淇℃伅 ==========
+
+    @Schema(description = "浜у搧缂栧彿", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
+    @NotNull(message = "浜у搧涓嶈兘涓虹┖")
+    private Long productId;
+
+    @Schema(description = "璁″垝鐢熶骇鏁伴噺", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
+    @NotNull(message = "璁″垝鐢熶骇鏁伴噺涓嶈兘涓虹┖")
+    private BigDecimal quantity;
+
+    @Schema(description = "璁¢噺鍗曚綅ID", example = "1")
+    private Long unitMeasureId;
+
+    // ========== 瀹㈡埛淇℃伅 ==========
+
+    @Schema(description = "瀹㈡埛缂栧彿", example = "300")
+    private Long clientId;
+
+    // ========== 鏃堕棿淇℃伅 ==========
+
+    @Schema(description = "闇�姹傛棩鏈�")
+    private LocalDateTime requestDate;
+
+    @Schema(description = "澶囨敞", example = "澶囨敞")
+    private String remark;
+
+}
\ No newline at end of file
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/MesProTaskController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/MesProTaskController.java
index 6f394e9..7bad646 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/MesProTaskController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/MesProTaskController.java
@@ -14,7 +14,8 @@
 import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskRespVO;
 import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskSaveReqVO;
 import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderPageReqVO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO;
+import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
+import cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerRespDTO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO;
@@ -22,7 +23,7 @@
 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
 import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants;
-import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService;
+import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
 import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService;
 import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService;
@@ -72,7 +73,7 @@
     @Resource
     private MesMdItemService itemService;
     @Resource
-    private MesMdClientService clientService;
+    private CrmCustomerApi customerApi;
     @Resource
     private MesMdUnitMeasureService unitMeasureService;
     @Resource
@@ -232,7 +233,7 @@
                 convertSet(list, MesProTaskDO::getItemId));
         Map<Long, MesMdUnitMeasureDO> unitMeasureMap = unitMeasureService.getUnitMeasureMap(
                 convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId));
-        Map<Long, MesMdClientDO> clientMap = clientService.getClientMap(
+        Map<Long, CrmCustomerRespDTO> customerMap = customerApi.getCustomerMap(
                 convertSet(list, MesProTaskDO::getClientId));
         // 宸ュ簭鐨� checkFlag锛氭壒閲忔煡璇㈠悗鏋勫缓 routeId -> processId -> checkFlag 鐨勫弻灞� Map
         Set<Long> routeIds = convertSet(list, MesProTaskDO::getRouteId);
@@ -279,8 +280,8 @@
                 findAndThen(unitMeasureMap, item.getUnitMeasureId(), unit ->
                         vo.setUnitMeasureName(unit.getName()));
             });
-            findAndThen(clientMap, task.getClientId(), c ->
-                    vo.setClientName(c.getName()));
+            findAndThen(customerMap, task.getClientId(), customer ->
+                    vo.setClientName(customer.getName()));
             findAndThen(routeProcessCheckFlagMap, task.getRouteId(), processCheckMap ->
                     findAndThen(processCheckMap, task.getProcessId(), vo::setCheckFlag));
             return vo;
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/MesProWorkOrderController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/MesProWorkOrderController.java
index 152502e..ac42fac 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/MesProWorkOrderController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/MesProWorkOrderController.java
@@ -12,15 +12,15 @@
 import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderPageReqVO;
 import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderRespVO;
 import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderSaveReqVO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO;
+import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
+import cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerRespDTO;
+import cn.iocoder.yudao.module.erp.api.purchase.ErpSupplierApi;
+import cn.iocoder.yudao.module.erp.api.purchase.dto.ErpSupplierRespDTO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
-import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService;
 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
 import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService;
-import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService;
 import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
@@ -50,9 +50,9 @@
     @Resource
     private MesMdItemService itemService;
     @Resource
-    private MesMdClientService clientService;
+    private CrmCustomerApi customerApi;
     @Resource
-    private MesMdVendorService vendorService;
+    private ErpSupplierApi supplierApi;
     @Resource
     private MesMdUnitMeasureService unitMeasureService;
 
@@ -148,10 +148,11 @@
         // 1. 鎵归噺鑾峰彇鍏宠仈鏁版嵁
         Map<Long, MesMdItemDO> itemMap = itemService.getItemMap(
                 convertSet(list, MesProWorkOrderDO::getProductId));
-        Map<Long, MesMdClientDO> clientMap = clientService.getClientMap(
+        Map<Long, CrmCustomerRespDTO> customerMap = customerApi.getCustomerMap(
                 convertSet(list, MesProWorkOrderDO::getClientId));
-        Map<Long, MesMdVendorDO> vendorMap = vendorService.getVendorMap(
-                convertSet(list, MesProWorkOrderDO::getVendorId));
+        Map<Long, ErpSupplierRespDTO> supplierMap = supplierApi.getSupplierList(
+                convertSet(list, MesProWorkOrderDO::getVendorId)).getCheckedData().stream()
+                .collect(java.util.stream.Collectors.toMap(ErpSupplierRespDTO::getId, s -> s));
         // 鍗曚綅浠庝骇鍝佸叧鑱旂殑 item 鑾峰緱
         Map<Long, MesMdUnitMeasureDO> unitMeasureMap = unitMeasureService.getUnitMeasureMap(
                 convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId));
@@ -165,10 +166,10 @@
                 MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(),
                         unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName()));
             });
-            MapUtils.findAndThen(clientMap, vo.getClientId(),
-                    client -> vo.setClientName(client.getName()).setClientCode(client.getCode()));
-            MapUtils.findAndThen(vendorMap, vo.getVendorId(),
-                    vendor -> vo.setVendorName(vendor.getName()).setVendorCode(vendor.getCode()));
+            MapUtils.findAndThen(customerMap, vo.getClientId(),
+                    customer -> vo.setClientName(customer.getName()));
+            MapUtils.findAndThen(supplierMap, vo.getVendorId(),
+                    supplier -> vo.setVendorName(supplier.getName()));
             MapUtils.findAndThen(parentMap, vo.getParentId(),
                     parent -> vo.setParentCode(parent.getCode()));
         });
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/MesQcIqcController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/MesQcIqcController.java
index 1602160..54b7169 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/MesQcIqcController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/MesQcIqcController.java
@@ -10,13 +10,13 @@
 import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.MesQcIqcPageReqVO;
 import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.MesQcIqcRespVO;
 import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.MesQcIqcSaveReqVO;
+import cn.iocoder.yudao.module.erp.api.purchase.ErpSupplierApi;
+import cn.iocoder.yudao.module.erp.api.purchase.dto.ErpSupplierRespDTO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcDO;
 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
 import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService;
-import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService;
 import cn.iocoder.yudao.module.mes.service.qc.iqc.MesQcIqcService;
 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
@@ -50,7 +50,7 @@
     @Resource
     private MesQcIqcService iqcService;
     @Resource
-    private MesMdVendorService vendorService;
+    private ErpSupplierApi supplierApi;
     @Resource
     private MesMdItemService itemService;
     @Resource
@@ -128,8 +128,9 @@
             return Collections.emptyList();
         }
         // 鎵归噺鏌ヨ渚涘簲鍟�
-        Map<Long, MesMdVendorDO> vendorMap = vendorService.getVendorMap(
-                convertSet(list, MesQcIqcDO::getVendorId));
+        Map<Long, ErpSupplierRespDTO> vendorMap = supplierApi.getSupplierList(
+                convertSet(list, MesQcIqcDO::getVendorId)).getCheckedData().stream()
+                .collect(java.util.stream.Collectors.toMap(ErpSupplierRespDTO::getId, s -> s));
         // 鎵归噺鏌ヨ鐗╂枡
         Map<Long, MesMdItemDO> itemMap = itemService.getItemMap(
                 convertSet(list, MesQcIqcDO::getItemId));
@@ -142,7 +143,7 @@
         // 鎷艰 VO
         return BeanUtils.toBean(list, MesQcIqcRespVO.class, vo -> {
             findAndThen(vendorMap, vo.getVendorId(),
-                    vendor -> vo.setVendorNickname(vendor.getNickname()));
+                    vendor -> vo.setVendorNickname(vendor.getName()));
             findAndThen(itemMap, vo.getItemId(), item -> {
                 vo.setItemCode(item.getCode());
                 vo.setItemName(item.getName());
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/MesQcOqcController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/MesQcOqcController.java
index 279ba1e..973218b 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/MesQcOqcController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/MesQcOqcController.java
@@ -10,11 +10,12 @@
 import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.MesQcOqcPageReqVO;
 import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.MesQcOqcRespVO;
 import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.MesQcOqcSaveReqVO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO;
+import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
+import cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerRespDTO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcDO;
-import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService;
+import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
 import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService;
 import cn.iocoder.yudao.module.mes.service.qc.oqc.MesQcOqcService;
@@ -49,7 +50,7 @@
     @Resource
     private MesQcOqcService oqcService;
     @Resource
-    private MesMdClientService clientService;
+    private CrmCustomerApi customerApi;
     @Resource
     private MesMdItemService itemService;
     @Resource
@@ -127,7 +128,7 @@
             return Collections.emptyList();
         }
         // 鎵归噺鏌ヨ瀹㈡埛
-        Map<Long, MesMdClientDO> clientMap = clientService.getClientMap(
+        Map<Long, CrmCustomerRespDTO> clientMap = customerApi.getCustomerMap(
                 convertSet(list, MesQcOqcDO::getClientId));
         // 鎵归噺鏌ヨ鐗╂枡
         Map<Long, MesMdItemDO> itemMap = itemService.getItemMap(
@@ -141,7 +142,7 @@
         // 鎷艰 VO
         return BeanUtils.toBean(list, MesQcOqcRespVO.class, vo -> {
             findAndThen(clientMap, vo.getClientId(),
-                    client -> vo.setClientNickname(client.getNickname()));
+                    client -> vo.setClientNickname(client.getName()));
             findAndThen(itemMap, vo.getItemId(), item -> {
                 vo.setItemCode(item.getCode()).setItemName(item.getName()).setItemSpecification(item.getSpecification());
                 findAndThen(unitMeasureMap, item.getUnitMeasureId(),
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/pendinginspect/MesQcPendingInspectController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/pendinginspect/MesQcPendingInspectController.java
index 65f6b13..7edafa6 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/pendinginspect/MesQcPendingInspectController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/pendinginspect/MesQcPendingInspectController.java
@@ -5,16 +5,16 @@
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.mes.controller.admin.qc.pendinginspect.vo.MesQcPendingInspectPageReqVO;
 import cn.iocoder.yudao.module.mes.controller.admin.qc.pendinginspect.vo.MesQcPendingInspectRespVO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO;
+import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
+import cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerRespDTO;
+import cn.iocoder.yudao.module.erp.api.purchase.ErpSupplierApi;
+import cn.iocoder.yudao.module.erp.api.purchase.dto.ErpSupplierRespDTO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO;
-import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService;
 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
 import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService;
-import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService;
 import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService;
 import cn.iocoder.yudao.module.mes.service.pro.task.MesProTaskService;
 import cn.iocoder.yudao.module.mes.service.qc.pendinginspect.MesQcPendingInspectService;
@@ -48,9 +48,9 @@
     @Resource
     private MesMdUnitMeasureService unitMeasureService;
     @Resource
-    private MesMdVendorService vendorService;
+    private ErpSupplierApi supplierApi;
     @Resource
-    private MesMdClientService clientService;
+    private CrmCustomerApi customerApi;
     @Resource
     private MesMdWorkstationService workstationService;
     @Resource
@@ -80,10 +80,11 @@
         Map<Long, MesMdUnitMeasureDO> unitMeasureMap = unitMeasureService.getUnitMeasureMap(
                 convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId));
         // 鎵归噺鏌ヨ渚涘簲鍟嗭紙IQC 鍦烘櫙锛�
-        Map<Long, MesMdVendorDO> vendorMap = vendorService.getVendorMap(
-                convertSet(list, MesQcPendingInspectRespVO::getVendorId));
+        Map<Long, ErpSupplierRespDTO> vendorMap = supplierApi.getSupplierList(
+                convertSet(list, MesQcPendingInspectRespVO::getVendorId)).getCheckedData().stream()
+                .collect(java.util.stream.Collectors.toMap(ErpSupplierRespDTO::getId, s -> s));
         // 鎵归噺鏌ヨ瀹㈡埛锛圤QC/RQC 鍦烘櫙锛�
-        Map<Long, MesMdClientDO> clientMap = clientService.getClientMap(
+        Map<Long, CrmCustomerRespDTO> clientMap = customerApi.getCustomerMap(
                 convertSet(list, MesQcPendingInspectRespVO::getClientId));
         // 鎵归噺鏌ヨ宸ヤ綔绔欙紙IPQC/RQC 鍦烘櫙锛�
         Map<Long, MesMdWorkstationDO> workstationMap = workstationService.getWorkstationMap(
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/batch/MesWmBatchController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/batch/MesWmBatchController.java
index 415c15d..398a808 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/batch/MesWmBatchController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/batch/MesWmBatchController.java
@@ -7,21 +7,21 @@
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchPageReqVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchRespVO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO;
+import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
+import cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerRespDTO;
+import cn.iocoder.yudao.module.erp.api.purchase.ErpSupplierApi;
+import cn.iocoder.yudao.module.erp.api.purchase.dto.ErpSupplierRespDTO;
 import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
 import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO;
 
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.tm.tool.MesTmToolDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO;
-import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService;
 import cn.iocoder.yudao.module.mdm.api.unit.MdmUnitMeasureApi;
 import cn.iocoder.yudao.module.mdm.api.unit.dto.MdmUnitMeasureRespDTO;
 
-import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService;
 import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService;
 import cn.iocoder.yudao.module.mes.service.pro.task.MesProTaskService;
 import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService;
@@ -60,9 +60,9 @@
     @Resource
     private MdmUnitMeasureApi mdmUnitMeasureApi;
     @Resource
-    private MesMdVendorService vendorService;
+    private ErpSupplierApi supplierApi;
     @Resource
-    private MesMdClientService clientService;
+    private CrmCustomerApi customerApi;
     @Resource
     private MesProWorkOrderService workOrderService;
     @Resource
@@ -116,9 +116,10 @@
         // 1. 鑾峰緱鍏宠仈鏁版嵁
         Map<Long, MdmItemRespDTO> itemMap = mdmItemApi.getItemMap(
                 convertSet(list, MesWmBatchDO::getItemId));
-        Map<Long, MesMdVendorDO> vendorMap = vendorService.getVendorMap(
-                convertSet(list, MesWmBatchDO::getVendorId));
-        Map<Long, MesMdClientDO> clientMap = clientService.getClientMap(
+        Map<Long, ErpSupplierRespDTO> vendorMap = supplierApi.getSupplierList(
+                convertSet(list, MesWmBatchDO::getVendorId)).getCheckedData().stream()
+                .collect(Collectors.toMap(ErpSupplierRespDTO::getId, s -> s));
+        Map<Long, CrmCustomerRespDTO> clientMap = customerApi.getCustomerMap(
                 convertSet(list, MesWmBatchDO::getClientId));
         Map<Long, MesProWorkOrderDO> workOrderMap = workOrderService.getWorkOrderMap(
                 convertSet(list, MesWmBatchDO::getWorkOrderId));
@@ -140,9 +141,9 @@
                         unitMeasure -> vo.setUnitName(unitMeasure.getName()));
             });
             MapUtils.findAndThen(vendorMap, vo.getVendorId(),
-                    vendor -> vo.setVendorCode(vendor.getCode()).setVendorName(vendor.getName()));
+                    vendor -> vo.setVendorName(vendor.getName()));
             MapUtils.findAndThen(clientMap, vo.getClientId(),
-                    client -> vo.setClientCode(client.getCode()).setClientName(client.getName()));
+                    client -> vo.setClientName(client.getName()));
             MapUtils.findAndThen(workOrderMap, vo.getWorkOrderId(),
                     workOrder -> vo.setWorkOrderCode(workOrder.getCode()));
             MapUtils.findAndThen(taskMap, vo.getTaskId(),
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/MesWmMaterialStockController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/MesWmMaterialStockController.java
index 5e3c014..621ebc8 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/MesWmMaterialStockController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/MesWmMaterialStockController.java
@@ -12,10 +12,11 @@
 import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockPageReqVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockRespVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockFreezeReqVO;
+import cn.iocoder.yudao.module.erp.api.purchase.ErpSupplierApi;
+import cn.iocoder.yudao.module.erp.api.purchase.dto.ErpSupplierRespDTO;
 import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
 import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO;
 
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO;
@@ -23,7 +24,6 @@
 import cn.iocoder.yudao.module.mdm.api.unit.MdmUnitMeasureApi;
 import cn.iocoder.yudao.module.mdm.api.unit.dto.MdmUnitMeasureRespDTO;
 
-import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService;
 import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService;
 import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService;
 import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService;
@@ -68,7 +68,7 @@
     @Resource
     private MesWmWarehouseAreaService areaService;
     @Resource
-    private MesMdVendorService vendorService;
+    private ErpSupplierApi supplierApi;
 
     @GetMapping("/get")
     @Operation(summary = "鑾峰緱搴撳瓨璁板綍")
@@ -144,8 +144,9 @@
                 convertSet(list, MesWmMaterialStockDO::getLocationId));
         Map<Long, MesWmWarehouseAreaDO> areaMap = areaService.getWarehouseAreaMap(
                 convertSet(list, MesWmMaterialStockDO::getAreaId));
-        Map<Long, MesMdVendorDO> vendorMap = vendorService.getVendorMap(
-                convertSet(list, MesWmMaterialStockDO::getVendorId));
+        Map<Long, ErpSupplierRespDTO> vendorMap = supplierApi.getSupplierList(
+                convertSet(list, MesWmMaterialStockDO::getVendorId)).getCheckedData().stream()
+                .collect(Collectors.toMap(ErpSupplierRespDTO::getId, s -> s));
         // 2. 鏋勫缓缁撴灉
         return BeanUtils.toBean(list, MesWmMaterialStockRespVO.class, vo -> {
             MapUtils.findAndThen(itemMap, vo.getItemId(), item -> {
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/MesWmOutsourceIssueController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/MesWmOutsourceIssueController.java
index a461d13..ea6ed6e 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/MesWmOutsourceIssueController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/MesWmOutsourceIssueController.java
@@ -11,10 +11,10 @@
 import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.MesWmOutsourceIssuePageReqVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.MesWmOutsourceIssueRespVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.MesWmOutsourceIssueSaveReqVO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO;
+import cn.iocoder.yudao.module.erp.api.purchase.ErpSupplierApi;
+import cn.iocoder.yudao.module.erp.api.purchase.dto.ErpSupplierRespDTO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueDO;
-import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService;
 import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService;
 import cn.iocoder.yudao.module.mes.service.wm.outsourceissue.MesWmOutsourceIssueService;
 import io.swagger.v3.oas.annotations.Operation;
@@ -45,7 +45,7 @@
     @Resource
     private MesWmOutsourceIssueService outsourceIssueService;
     @Resource
-    private MesMdVendorService vendorService;
+    private ErpSupplierApi supplierApi;
     @Resource
     private MesProWorkOrderService workOrderService;
 
@@ -157,14 +157,15 @@
             return Collections.emptyList();
         }
         // 1. 鑾峰緱鍏宠仈鏁版嵁
-        Map<Long, MesMdVendorDO> vendorMap = vendorService.getVendorMap(
-                convertSet(list, MesWmOutsourceIssueDO::getVendorId));
+        Map<Long, ErpSupplierRespDTO> vendorMap = supplierApi.getSupplierList(
+                convertSet(list, MesWmOutsourceIssueDO::getVendorId)).getCheckedData().stream()
+                .collect(java.util.stream.Collectors.toMap(ErpSupplierRespDTO::getId, s -> s));
         Map<Long, MesProWorkOrderDO> workOrderMap = workOrderService.getWorkOrderMap(
                 convertSet(list, MesWmOutsourceIssueDO::getWorkOrderId));
         // 2. 鏋勫缓缁撴灉
         return BeanUtils.toBean(list, MesWmOutsourceIssueRespVO.class, vo -> {
             MapUtils.findAndThen(vendorMap, vo.getVendorId(), vendor ->
-                    vo.setVendorCode(vendor.getCode()).setVendorName(vendor.getName()));
+                    vo.setVendorName(vendor.getName()));
             MapUtils.findAndThen(workOrderMap, vo.getWorkOrderId(), workOrder ->
                     vo.setWorkOrderCode(workOrder.getCode()).setWorkOrderName(workOrder.getName()));
         });
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/MesWmOutsourceReceiptController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/MesWmOutsourceReceiptController.java
index 34ed7dd..8e6b095 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/MesWmOutsourceReceiptController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/MesWmOutsourceReceiptController.java
@@ -11,10 +11,10 @@
 import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.MesWmOutsourceReceiptPageReqVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.MesWmOutsourceReceiptRespVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.MesWmOutsourceReceiptSaveReqVO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO;
+import cn.iocoder.yudao.module.erp.api.purchase.ErpSupplierApi;
+import cn.iocoder.yudao.module.erp.api.purchase.dto.ErpSupplierRespDTO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourcereceipt.MesWmOutsourceReceiptDO;
-import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService;
 import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService;
 import cn.iocoder.yudao.module.mes.service.wm.outsourcereceipt.MesWmOutsourceReceiptService;
 import io.swagger.v3.oas.annotations.Operation;
@@ -45,7 +45,7 @@
     @Resource
     private MesWmOutsourceReceiptService outsourceReceiptService;
     @Resource
-    private MesMdVendorService vendorService;
+    private ErpSupplierApi supplierApi;
     @Resource
     private MesProWorkOrderService workOrderService;
 
@@ -149,8 +149,9 @@
             return Collections.emptyList();
         }
         // 1. 鑾峰緱鍏宠仈鏁版嵁
-        Map<Long, MesMdVendorDO> vendorMap = vendorService.getVendorMap(
-                convertSet(list, MesWmOutsourceReceiptDO::getVendorId));
+        Map<Long, ErpSupplierRespDTO> vendorMap = supplierApi.getSupplierList(
+                convertSet(list, MesWmOutsourceReceiptDO::getVendorId)).getCheckedData().stream()
+                .collect(java.util.stream.Collectors.toMap(ErpSupplierRespDTO::getId, s -> s));
         Map<Long, MesProWorkOrderDO> workOrderMap = workOrderService.getWorkOrderMap(
                 convertSet(list, MesWmOutsourceReceiptDO::getWorkOrderId));
         // 2. 鏋勫缓缁撴灉
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/MesWmPackageController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/MesWmPackageController.java
index 70d546b..4a340ec 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/MesWmPackageController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/MesWmPackageController.java
@@ -8,10 +8,10 @@
 import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.MesWmPackagePageReqVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.MesWmPackageRespVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.MesWmPackageSaveReqVO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO;
+import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
+import cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerRespDTO;
 
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.packages.MesWmPackageDO;
-import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService;
 
 import cn.iocoder.yudao.module.mes.service.wm.packages.MesWmPackageService;
 import cn.iocoder.yudao.module.mdm.api.unit.MdmUnitMeasureApi;
@@ -44,7 +44,7 @@
     @Resource
     private MesWmPackageService packageService;
     @Resource
-    private MesMdClientService clientService;
+    private CrmCustomerApi customerApi;
     @Resource
     private MdmUnitMeasureApi mdmUnitMeasureApi;
 
@@ -131,7 +131,7 @@
             return Collections.emptyList();
         }
         // 鎵归噺鏌ヨ瀹㈡埛
-        Map<Long, MesMdClientDO> clientMap = clientService.getClientMap(
+        Map<Long, CrmCustomerRespDTO> clientMap = customerApi.getCustomerMap(
                 convertSet(list, MesWmPackageDO::getClientId));
         // 鎵归噺鏌ヨ璁¢噺鍗曚綅锛堝昂瀵� + 閲嶉噺锛�
         Map<Long, MdmUnitMeasureRespDTO> unitMeasureMap = mdmUnitMeasureApi.getUnitMeasureList(
@@ -143,8 +143,7 @@
         // 鏋勫缓杩斿洖缁撴灉
         return BeanUtils.toBean(list, MesWmPackageRespVO.class, vo -> {
             MapUtils.findAndThen(clientMap, vo.getClientId(),
-                    client -> vo.setClientCode(client.getCode()).setClientName(client.getName())
-                            .setClientNickname(client.getNickname()));
+                    client -> vo.setClientName(client.getName()));
             MapUtils.findAndThen(unitMeasureMap, vo.getSizeUnitId(),
                     unit -> vo.setSizeUnitName(unit.getName()));
             MapUtils.findAndThen(unitMeasureMap, vo.getWeightUnitId(),
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/MesWmProductIssueController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/MesWmProductIssueController.java
index 04e4ba3..c1f4a06 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/MesWmProductIssueController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/MesWmProductIssueController.java
@@ -11,12 +11,13 @@
 import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.MesWmProductIssuePageReqVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.MesWmProductIssueRespVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.MesWmProductIssueSaveReqVO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO;
+import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
+import cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerRespDTO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue.MesWmProductIssueDO;
-import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService;
+import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
 import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService;
 import cn.iocoder.yudao.module.mes.service.pro.task.MesProTaskService;
 import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService;
@@ -55,7 +56,7 @@
     @Resource
     private MesProTaskService taskService;
     @Resource
-    private MesMdClientService clientService;
+    private CrmCustomerApi customerApi;
 
     @PostMapping("/create")
     @Operation(summary = "鍒涘缓棰嗘枡鍑哄簱鍗�")
@@ -171,7 +172,7 @@
                 convertSet(list, MesWmProductIssueDO::getWorkOrderId));
         Map<Long, MesProTaskDO> taskMap = taskService.getTaskMap(
                 convertSet(list, MesWmProductIssueDO::getTaskId));
-        Map<Long, MesMdClientDO> clientMap = clientService.getClientMap(
+        Map<Long, CrmCustomerRespDTO> clientMap = customerApi.getCustomerMap(
                 convertSet(workOrderMap.values(), MesProWorkOrderDO::getClientId));
         // 2. 鏋勫缓缁撴灉
         return BeanUtils.toBean(list, MesWmProductIssueRespVO.class, vo -> {
@@ -182,7 +183,7 @@
             MapUtils.findAndThen(workOrderMap, vo.getWorkOrderId(), workOrder -> {
                 vo.setWorkOrderCode(workOrder.getCode());
                 MapUtils.findAndThen(clientMap, workOrder.getClientId(), client ->
-                        vo.setClientCode(client.getCode()).setClientName(client.getName()));
+                        vo.setClientName(client.getName()));
             });
         });
     }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/MesWmReturnVendorController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/MesWmReturnVendorController.java
index 35b4cd0..38c39e4 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/MesWmReturnVendorController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/MesWmReturnVendorController.java
@@ -11,9 +11,9 @@
 import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.MesWmReturnVendorPageReqVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.MesWmReturnVendorRespVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.MesWmReturnVendorSaveReqVO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO;
+import cn.iocoder.yudao.module.erp.api.purchase.ErpSupplierApi;
+import cn.iocoder.yudao.module.erp.api.purchase.dto.ErpSupplierRespDTO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor.MesWmReturnVendorDO;
-import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService;
 import cn.iocoder.yudao.module.mes.service.wm.returnvendor.MesWmReturnVendorService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
@@ -43,7 +43,7 @@
     @Resource
     private MesWmReturnVendorService returnVendorService;
     @Resource
-    private MesMdVendorService vendorService;
+    private ErpSupplierApi supplierApi;
 
     @PostMapping("/create")
     @Operation(summary = "鍒涘缓渚涘簲鍟嗛��璐у崟")
@@ -153,12 +153,13 @@
             return Collections.emptyList();
         }
         // 1. 鑾峰緱鍏宠仈鏁版嵁
-        Map<Long, MesMdVendorDO> vendorMap = vendorService.getVendorMap(
-                convertSet(list, MesWmReturnVendorDO::getVendorId));
+        Map<Long, ErpSupplierRespDTO> vendorMap = supplierApi.getSupplierList(
+                convertSet(list, MesWmReturnVendorDO::getVendorId)).getCheckedData().stream()
+                .collect(java.util.stream.Collectors.toMap(ErpSupplierRespDTO::getId, s -> s));
         // 2. 鏋勫缓缁撴灉
         return BeanUtils.toBean(list, MesWmReturnVendorRespVO.class, vo ->
                 MapUtils.findAndThen(vendorMap, vo.getVendorId(), vendor ->
-                        vo.setVendorCode(vendor.getCode()).setVendorName(vendor.getName()).setVendorNickname(vendor.getNickname())));
+                        vo.setVendorName(vendor.getName())));
     }
 
 }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/client/MesMdClientDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/client/MesMdClientDO.java
deleted file mode 100644
index 12ebb3e..0000000
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/client/MesMdClientDO.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package cn.iocoder.yudao.module.mes.dal.dataobject.md.client;
-
-import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
-import com.baomidou.mybatisplus.annotation.KeySequence;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import lombok.*;
-
-/**
- * MES 瀹㈡埛 DO
- *
- * @author 鑺嬮亾婧愮爜
- */
-@TableName("mes_md_client")
-@KeySequence("mes_md_client_seq") // 鐢ㄤ簬 Oracle銆丳ostgreSQL銆並ingbase銆丏B2銆丠2 鏁版嵁搴撶殑涓婚敭鑷銆傚鏋滄槸 MySQL 绛夋暟鎹簱锛屽彲涓嶅啓銆�
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class MesMdClientDO extends BaseDO {
-
-    /**
-     * 瀹㈡埛缂栧彿
-     */
-    @TableId
-    private Long id;
-    /**
-     * 瀹㈡埛缂栫爜
-     */
-    private String code;
-    /**
-     * 瀹㈡埛鍚嶇О
-     */
-    private String name;
-    /**
-     * 瀹㈡埛绠�绉�
-     */
-    private String nickname;
-    /**
-     * 瀹㈡埛鑻辨枃鍚嶇О
-     */
-    private String englishName;
-    /**
-     * 瀹㈡埛绠�浠�
-     */
-    private String description;
-    /**
-     * 瀹㈡埛LOGO鍦板潃
-     */
-    private String logo;
-    /**
-     * 瀹㈡埛绫诲瀷
-     *
-     * 瀛楀吀 {@link cn.iocoder.yudao.module.mes.enums.DictTypeConstants#MES_CLIENT_TYPE}
-     */
-    private Integer type;
-    /**
-     * 瀹㈡埛鍦板潃
-     */
-    private String address;
-    /**
-     * 瀹㈡埛瀹樼綉鍦板潃
-     */
-    private String website;
-    /**
-     * 瀹㈡埛閭鍦板潃
-     */
-    private String email;
-    /**
-     * 瀹㈡埛鐢佃瘽
-     */
-    private String telephone;
-    /**
-     * 鑱旂郴浜�1
-     */
-    private String contact1Name;
-    /**
-     * 鑱旂郴浜�1-鐢佃瘽
-     */
-    private String contact1Telephone;
-    /**
-     * 鑱旂郴浜�1-閭
-     */
-    private String contact1Email;
-    /**
-     * 鑱旂郴浜�2
-     */
-    private String contact2Name;
-    /**
-     * 鑱旂郴浜�2-鐢佃瘽
-     */
-    private String contact2Telephone;
-    /**
-     * 鑱旂郴浜�2-閭
-     */
-    private String contact2Email;
-    /**
-     * 缁熶竴绀句細淇$敤浠g爜
-     */
-    private String creditCode;
-    /**
-     * 鐘舵��
-     *
-     * 鏋氫妇 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum}
-     */
-    private Integer status;
-    /**
-     * 澶囨敞
-     */
-    private String remark;
-
-}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/vendor/MesMdVendorDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/vendor/MesMdVendorDO.java
deleted file mode 100644
index 1a931a7..0000000
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/vendor/MesMdVendorDO.java
+++ /dev/null
@@ -1,118 +0,0 @@
-package cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor;
-
-import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
-import com.baomidou.mybatisplus.annotation.KeySequence;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import lombok.*;
-
-/**
- * MES 渚涘簲鍟� DO
- *
- * @author 鑺嬮亾婧愮爜
- */
-@TableName("mes_md_vendor")
-@KeySequence("mes_md_vendor_seq") // 鐢ㄤ簬 Oracle銆丳ostgreSQL銆並ingbase銆丏B2銆丠2 鏁版嵁搴撶殑涓婚敭鑷銆傚鏋滄槸 MySQL 绛夋暟鎹簱锛屽彲涓嶅啓銆�
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class MesMdVendorDO extends BaseDO {
-
-    /**
-     * 渚涘簲鍟嗙紪鍙�
-     */
-    @TableId
-    private Long id;
-    /**
-     * 渚涘簲鍟嗙紪鐮�
-     */
-    private String code;
-    /**
-     * 渚涘簲鍟嗗悕绉�
-     */
-    private String name;
-    /**
-     * 渚涘簲鍟嗙畝绉�
-     */
-    private String nickname;
-    /**
-     * 渚涘簲鍟嗚嫳鏂囧悕绉�
-     */
-    private String englishName;
-    /**
-     * 渚涘簲鍟嗙畝浠�
-     */
-    private String description;
-    /**
-     * 渚涘簲鍟哃OGO鍦板潃
-     */
-    private String logo;
-    /**
-     * 渚涘簲鍟嗙瓑绾�
-     *
-     * 瀛楀吀 {@link cn.iocoder.yudao.module.mes.enums.DictTypeConstants#MES_VENDOR_LEVEL}
-     */
-    private String level;
-    /**
-     * 渚涘簲鍟嗚瘎鍒�
-     */
-    private Integer score;
-    /**
-     * 渚涘簲鍟嗗湴鍧�
-     */
-    private String address;
-    /**
-     * 渚涘簲鍟嗗畼缃戝湴鍧�
-     */
-    private String website;
-    /**
-     * 渚涘簲鍟嗛偖绠卞湴鍧�
-     */
-    private String email;
-    /**
-     * 渚涘簲鍟嗙數璇�
-     */
-    private String telephone;
-    /**
-     * 鑱旂郴浜�1
-     */
-    private String contact1Name;
-    /**
-     * 鑱旂郴浜�1-鐢佃瘽
-     */
-    private String contact1Telephone;
-    /**
-     * 鑱旂郴浜�1-閭
-     */
-    private String contact1Email;
-    /**
-     * 鑱旂郴浜�2
-     */
-    private String contact2Name;
-    /**
-     * 鑱旂郴浜�2-鐢佃瘽
-     */
-    private String contact2Telephone;
-    /**
-     * 鑱旂郴浜�2-閭
-     */
-    private String contact2Email;
-    /**
-     * 缁熶竴绀句細淇$敤浠g爜
-     */
-    private String creditCode;
-    /**
-     * 鐘舵��
-     *
-     * 鏋氫妇 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum}
-     */
-    private Integer status;
-    /**
-     * 澶囨敞
-     */
-    private String remark;
-
-}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/mps/MesProMpsDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/mps/MesProMpsDO.java
new file mode 100644
index 0000000..d4b1b10
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/mps/MesProMpsDO.java
@@ -0,0 +1,148 @@
+package cn.iocoder.yudao.module.mes.dal.dataobject.pro.mps;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
+import cn.iocoder.yudao.module.mes.enums.DictTypeConstants;
+import cn.iocoder.yudao.module.mes.enums.pro.MesProMpsStatusEnum;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * MES 鐢熶骇涓昏鍒掞紙MPS锛塂O
+ *
+ * @author 鑺嬮亾婧愮爜
+ */
+@TableName("mes_pro_mps")
+@KeySequence("mes_pro_mps_seq")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class MesProMpsDO extends BaseDO {
+
+    /**
+     * 缂栧彿
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * MPS 缂栫爜
+     */
+    private String code;
+
+    /**
+     * 鐘舵��
+     *
+     * 瀛楀吀 {@link DictTypeConstants#MES_PRO_MPS_STATUS}
+     * 鏋氫妇 {@link MesProMpsStatusEnum}
+     */
+    private Integer status;
+
+    // ========== 鏉ユ簮淇℃伅锛堟潵鑷攢鍞鍗曪級 ==========
+
+    /**
+     * 閿�鍞鍗旾D
+     */
+    private Long saleOrderId;
+
+    /**
+     * 閿�鍞鍗曞彿
+     */
+    private String saleOrderNo;
+
+    /**
+     * 閿�鍞鍗曟槑缁咺D
+     */
+    private Long saleOrderItemId;
+
+    // ========== 浜у搧淇℃伅 ==========
+
+    /**
+     * 浜у搧缂栧彿
+     *
+     * 鍏宠仈 {@link MesMdItemDO#getId()}
+     */
+    private Long productId;
+
+    /**
+     * 璁″垝鐢熶骇鏁伴噺
+     */
+    private BigDecimal quantity;
+
+    /**
+     * 宸茬敓浜ф暟閲�
+     */
+    private BigDecimal quantityProduced;
+
+    /**
+     * 璁¢噺鍗曚綅ID
+     */
+    private Long unitMeasureId;
+
+    // ========== 瀹㈡埛淇℃伅 ==========
+
+    /**
+     * 瀹㈡埛缂栧彿
+     *
+     * 鍏宠仈 CRM 瀹㈡埛 {@link cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerRespDTO#getId()}
+     */
+    private Long clientId;
+
+    // ========== 鏃堕棿淇℃伅 ==========
+
+    /**
+     * 闇�姹傛棩鏈�
+     */
+    private LocalDateTime requestDate;
+
+    /**
+     * 涓嬪彂鏃ユ湡
+     */
+    private LocalDateTime issueDate;
+
+    /**
+     * 瀹屾垚鏃ユ湡
+     */
+    private LocalDateTime finishDate;
+
+    // ========== 鐢熶骇宸ュ崟鍏宠仈锛堜笅鍙戝悗鐢熸垚锛� ==========
+
+    /**
+     * 鐢熶骇宸ュ崟ID
+     *
+     * 鍏宠仈 {@link MesProWorkOrderDO#getId()}
+     */
+    private Long workOrderId;
+
+    /**
+     * 鐢熶骇宸ュ崟缂栫爜
+     */
+    private String workOrderCode;
+
+    // ========== 鍚堝苟涓嬪彂鏍囪瘑 ==========
+
+    /**
+     * 鏄惁鍚堝苟涓嬪彂锛�0=鍚� 1=鏄級
+     */
+    private Integer mergeFlag;
+
+    /**
+     * 鍚堝苟鎵规鍙�
+     */
+    private String mergeBatchNo;
+
+    /**
+     * 澶囨敞
+     */
+    private String remark;
+
+}
\ No newline at end of file
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/mps/MesProMpsMergeItemDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/mps/MesProMpsMergeItemDO.java
new file mode 100644
index 0000000..3d736e5
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/mps/MesProMpsMergeItemDO.java
@@ -0,0 +1,62 @@
+package cn.iocoder.yudao.module.mes.dal.dataobject.pro.mps;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+import java.math.BigDecimal;
+
+/**
+ * MPS 鍚堝苟涓嬪彂鏄庣粏 DO
+ *
+ * @author 鑺嬮亾婧愮爜
+ */
+@TableName("mes_pro_mps_merge_item")
+@KeySequence("mes_pro_mps_merge_item_seq")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class MesProMpsMergeItemDO extends BaseDO {
+
+    /**
+     * 缂栧彿
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * 鍚堝苟鎵规鍙�
+     */
+    private String mergeBatchNo;
+
+    /**
+     * MPS 缂栧彿
+     *
+     * 鍏宠仈 {@link MesProMpsDO#getId()}
+     */
+    private Long mpsId;
+
+    /**
+     * 鐢熸垚鐨勭敓浜у伐鍗旾D
+     *
+     * 鍏宠仈 {@link MesProWorkOrderDO#getId()}
+     */
+    private Long workOrderId;
+
+    /**
+     * 鍒嗛厤鏁伴噺
+     */
+    private BigDecimal quantity;
+
+    /**
+     * 澶囨敞
+     */
+    private String remark;
+
+}
\ No newline at end of file
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskDO.java
index d8c06bd..84eebc0 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskDO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskDO.java
@@ -1,7 +1,6 @@
 package cn.iocoder.yudao.module.mes.dal.dataobject.pro.task;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO;
@@ -100,7 +99,7 @@
     /**
      * 瀹㈡埛缂栧彿
      *
-     * 鍏宠仈 {@link MesMdClientDO#getId()}
+     * 鍏宠仈 CRM 瀹㈡埛 {@link cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerRespDTO#getId()}
      */
     private Long clientId;
     /**
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workorder/MesProWorkOrderDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workorder/MesProWorkOrderDO.java
index 578cfd9..57c2d22 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workorder/MesProWorkOrderDO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workorder/MesProWorkOrderDO.java
@@ -1,9 +1,7 @@
 package cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO;
 import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderSourceTypeEnum;
 import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderStatusEnum;
 import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderTypeEnum;
@@ -92,13 +90,13 @@
     /**
      * 瀹㈡埛缂栧彿
      *
-     * 鍏宠仈 {@link MesMdClientDO#getId()}
+     * 鍏宠仈 CRM 瀹㈡埛 {@link cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerRespDTO#getId()}
      */
     private Long clientId;
     /**
      * 渚涘簲鍟嗙紪鍙�
      *
-     * 鍏宠仈 {@link MesMdVendorDO#getId()}
+     * 鍏宠仈 ERP 渚涘簲鍟� {@link cn.iocoder.yudao.module.erp.api.purchase.dto.ErpSupplierRespDTO#getId()}
      */
     private Long vendorId;
     /**
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/iqc/MesQcIqcDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/iqc/MesQcIqcDO.java
index 9ccc71b..22335da 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/iqc/MesQcIqcDO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/iqc/MesQcIqcDO.java
@@ -2,7 +2,6 @@
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeLineDO;
@@ -86,7 +85,7 @@
     /**
      * 渚涘簲鍟� ID
      *
-     * 鍏宠仈 {@link MesMdVendorDO#getId()}
+     * 鍏宠仈 ERP 渚涘簲鍟� {@link cn.iocoder.yudao.module.erp.api.purchase.dto.ErpSupplierRespDTO#getId()}
      */
     private Long vendorId;
     /**
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/oqc/MesQcOqcDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/oqc/MesQcOqcDO.java
index 62efd79..b4d9ee0 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/oqc/MesQcOqcDO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/oqc/MesQcOqcDO.java
@@ -1,7 +1,6 @@
 package cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateDO;
 import com.baomidou.mybatisplus.annotation.KeySequence;
@@ -81,7 +80,7 @@
     /**
      * 瀹㈡埛 ID
      *
-     * 鍏宠仈 {@link MesMdClientDO#getId()}
+     * 鍏宠仈 CRM 瀹㈡埛 {@link cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerRespDTO#getId()}
      */
     private Long clientId;
     /**
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/arrivalnotice/MesWmArrivalNoticeDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/arrivalnotice/MesWmArrivalNoticeDO.java
index 0e8bfa8..61b2011 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/arrivalnotice/MesWmArrivalNoticeDO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/arrivalnotice/MesWmArrivalNoticeDO.java
@@ -1,7 +1,6 @@
 package cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO;
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmArrivalNoticeStatusEnum;
 import com.baomidou.mybatisplus.annotation.KeySequence;
 import com.baomidou.mybatisplus.annotation.TableId;
@@ -50,7 +49,7 @@
     /**
      * 渚涘簲鍟嗙紪鍙�
      *
-     * 鍏宠仈 {@link MesMdVendorDO#getId()}
+     * 鍏宠仈 ERP 渚涘簲鍟� {@link cn.iocoder.yudao.module.erp.api.purchase.dto.ErpSupplierRespDTO#getId()}
      */
     private Long vendorId;
     /**
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/batch/MesWmBatchDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/batch/MesWmBatchDO.java
index 2617596..93364a0 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/batch/MesWmBatchDO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/batch/MesWmBatchDO.java
@@ -1,9 +1,7 @@
 package cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
@@ -60,13 +58,13 @@
     /**
      * 渚涘簲鍟咺D
      *
-     * 鍏宠仈 {@link MesMdVendorDO#getId()}
+     * 鍏宠仈 ERP 渚涘簲鍟� {@link cn.iocoder.yudao.module.erp.api.purchase.dto.ErpSupplierRespDTO#getId()}
      */
     private Long vendorId;
     /**
      * 瀹㈡埛ID
      *
-     * 鍏宠仈 {@link MesMdClientDO#getId()}
+     * 鍏宠仈 CRM 瀹㈡埛 {@link cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerRespDTO#getId()}
      */
     private Long clientId;
 
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptDO.java
index 7bb7d4c..bd8cfdf 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptDO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptDO.java
@@ -1,7 +1,6 @@
 package cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeDO;
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmItemReceiptStatusEnum;
@@ -60,7 +59,7 @@
     /**
      * 渚涘簲鍟嗙紪鍙�
      *
-     * 鍏宠仈 {@link MesMdVendorDO#getId()}
+     * 鍏宠仈 ERP 渚涘簲鍟� {@link cn.iocoder.yudao.module.erp.api.purchase.dto.ErpSupplierRespDTO#getId()}
      */
     private Long vendorId;
     /**
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/materialstock/MesWmMaterialStockDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/materialstock/MesWmMaterialStockDO.java
index 95b8d30..e387678 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/materialstock/MesWmMaterialStockDO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/materialstock/MesWmMaterialStockDO.java
@@ -3,7 +3,6 @@
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO;
@@ -87,7 +86,7 @@
     /**
      * 渚涘簲鍟嗙紪鍙�
      *
-     * 鍏宠仈 {@link MesMdVendorDO#getId()}
+     * 鍏宠仈 ERP 渚涘簲鍟� {@link cn.iocoder.yudao.module.erp.api.purchase.dto.ErpSupplierRespDTO#getId()}
      */
     private Long vendorId;
     /**
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueDO.java
index e69f659..45f542f 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueDO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueDO.java
@@ -1,7 +1,6 @@
 package cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmOutsourceIssueStatusEnum;
 import com.baomidou.mybatisplus.annotation.KeySequence;
@@ -43,7 +42,7 @@
     /**
      * 渚涘簲鍟咺D
      *
-     * 鍏宠仈 {@link MesMdVendorDO#getId()}
+     * 鍏宠仈 ERP 渚涘簲鍟� {@link cn.iocoder.yudao.module.erp.api.purchase.dto.ErpSupplierRespDTO#getId()}
      */
     private Long vendorId;
     /**
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourcereceipt/MesWmOutsourceReceiptDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourcereceipt/MesWmOutsourceReceiptDO.java
index cf1a903..333e1e9 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourcereceipt/MesWmOutsourceReceiptDO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourcereceipt/MesWmOutsourceReceiptDO.java
@@ -1,7 +1,6 @@
 package cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourcereceipt;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO;
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmOutsourceReceiptStatusEnum;
 import com.baomidou.mybatisplus.annotation.KeySequence;
 import com.baomidou.mybatisplus.annotation.TableId;
@@ -46,7 +45,7 @@
     /**
      * 渚涘簲鍟嗙紪鍙�
      *
-     * 鍏宠仈 {@link MesMdVendorDO#getId()}
+     * 鍏宠仈 ERP 渚涘簲鍟� {@link cn.iocoder.yudao.module.erp.api.purchase.dto.ErpSupplierRespDTO#getId()}
      */
     private Long vendorId;
     /**
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/packages/MesWmPackageDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/packages/MesWmPackageDO.java
index bfb2d87..7659ee1 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/packages/MesWmPackageDO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/packages/MesWmPackageDO.java
@@ -1,7 +1,6 @@
 package cn.iocoder.yudao.module.mes.dal.dataobject.wm.packages;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO;
 import com.baomidou.mybatisplus.annotation.KeySequence;
 import com.baomidou.mybatisplus.annotation.TableId;
@@ -54,7 +53,7 @@
     /**
      * 瀹㈡埛 ID
      *
-     * 鍏宠仈 {@link MesMdClientDO#getId()}
+     * 鍏宠仈 CRM 瀹㈡埛 {@link cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerRespDTO#getId()}
      */
     private Long clientId;
     /**
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesDO.java
index c7982f2..3da7777 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesDO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesDO.java
@@ -1,7 +1,6 @@
 package cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice.MesWmSalesNoticeDO;
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmProductSalesStatusEnum;
 import com.baomidou.mybatisplus.annotation.KeySequence;
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnvendor/MesWmReturnVendorDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnvendor/MesWmReturnVendorDO.java
index 779b0e5..9b8b4be 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnvendor/MesWmReturnVendorDO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnvendor/MesWmReturnVendorDO.java
@@ -1,7 +1,6 @@
 package cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO;
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmReturnVendorStatusEnum;
 import com.baomidou.mybatisplus.annotation.KeySequence;
 import com.baomidou.mybatisplus.annotation.TableId;
@@ -44,7 +43,7 @@
     /**
      * 渚涘簲鍟� ID
      *
-     * 鍏宠仈 {@link MesMdVendorDO#getId()}
+     * 鍏宠仈 ERP 渚涘簲鍟� {@link cn.iocoder.yudao.module.erp.api.purchase.dto.ErpSupplierRespDTO#getId()}
      */
     private Long vendorId;
     /**
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/salesnotice/MesWmSalesNoticeDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/salesnotice/MesWmSalesNoticeDO.java
index 66f1dea..4c69b80 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/salesnotice/MesWmSalesNoticeDO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/salesnotice/MesWmSalesNoticeDO.java
@@ -1,7 +1,6 @@
 package cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO;
 import com.baomidou.mybatisplus.annotation.KeySequence;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/client/MesMdClientMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/client/MesMdClientMapper.java
deleted file mode 100644
index a1e0f99..0000000
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/client/MesMdClientMapper.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package cn.iocoder.yudao.module.mes.dal.mysql.md.client;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
-import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
-import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientPageReqVO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO;
-import org.apache.ibatis.annotations.Mapper;
-
-
-
-
-/**
- * MES 瀹㈡埛 Mapper
- *
- * @author 鑺嬮亾婧愮爜
- */
-@Mapper
-public interface MesMdClientMapper extends BaseMapperX<MesMdClientDO> {
-
-    default PageResult<MesMdClientDO> selectPage(MesMdClientPageReqVO reqVO) {
-        return selectPage(reqVO, new LambdaQueryWrapperX<MesMdClientDO>()
-                .eqIfPresent(MesMdClientDO::getCode, reqVO.getCode())
-                .likeIfPresent(MesMdClientDO::getName, reqVO.getName())
-                .likeIfPresent(MesMdClientDO::getNickname, reqVO.getNickname())
-                .likeIfPresent(MesMdClientDO::getEnglishName, reqVO.getEnglishName())
-                .eqIfPresent(MesMdClientDO::getType, reqVO.getType())
-                .eqIfPresent(MesMdClientDO::getStatus, reqVO.getStatus())
-                .orderByDesc(MesMdClientDO::getId));
-    }
-
-    default MesMdClientDO selectByCode(String code) {
-        return selectOne(MesMdClientDO::getCode, code);
-    }
-
-    default MesMdClientDO selectByName(String name) {
-        return selectOne(MesMdClientDO::getName, name);
-    }
-
-    default MesMdClientDO selectByNickname(String nickname) {
-        return selectOne(MesMdClientDO::getNickname, nickname);
-    }
-
-}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdItemMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdItemMapper.java
index 64bfe6b..e6c2fad 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdItemMapper.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdItemMapper.java
@@ -43,4 +43,8 @@
         return selectCount(MesMdItemDO::getUnitMeasureId, unitMeasureId);
     }
 
+    default MesMdItemDO selectByMdmItemId(Long mdmItemId) {
+        return selectOne(MesMdItemDO::getMdmItemId, mdmItemId);
+    }
+
 }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/vendor/MesMdVendorMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/vendor/MesMdVendorMapper.java
deleted file mode 100644
index ac6feeb..0000000
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/vendor/MesMdVendorMapper.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package cn.iocoder.yudao.module.mes.dal.mysql.md.vendor;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
-import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
-import cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo.MesMdVendorPageReqVO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO;
-import org.apache.ibatis.annotations.Mapper;
-
-/**
- * MES 渚涘簲鍟� Mapper
- *
- * @author 鑺嬮亾婧愮爜
- */
-@Mapper
-public interface MesMdVendorMapper extends BaseMapperX<MesMdVendorDO> {
-
-    default PageResult<MesMdVendorDO> selectPage(MesMdVendorPageReqVO reqVO) {
-        return selectPage(reqVO, new LambdaQueryWrapperX<MesMdVendorDO>()
-                .eqIfPresent(MesMdVendorDO::getCode, reqVO.getCode())
-                .likeIfPresent(MesMdVendorDO::getName, reqVO.getName())
-                .likeIfPresent(MesMdVendorDO::getNickname, reqVO.getNickname())
-                .likeIfPresent(MesMdVendorDO::getEnglishName, reqVO.getEnglishName())
-                .eqIfPresent(MesMdVendorDO::getStatus, reqVO.getStatus())
-                .orderByDesc(MesMdVendorDO::getId));
-    }
-
-    default MesMdVendorDO selectByCode(String code) {
-        return selectOne(MesMdVendorDO::getCode, code);
-    }
-
-    default MesMdVendorDO selectByName(String name) {
-        return selectOne(MesMdVendorDO::getName, name);
-    }
-
-    default MesMdVendorDO selectByNickname(String nickname) {
-        return selectOne(MesMdVendorDO::getNickname, nickname);
-    }
-}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/mps/MesProMpsMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/mps/MesProMpsMapper.java
new file mode 100644
index 0000000..80152be
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/mps/MesProMpsMapper.java
@@ -0,0 +1,96 @@
+package cn.iocoder.yudao.module.mes.dal.mysql.pro.mps;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.mps.vo.MesProMpsPageReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.mps.MesProMpsDO;
+import cn.iocoder.yudao.module.mes.enums.pro.MesProMpsStatusEnum;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.math.BigDecimal;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * MES 鐢熶骇涓昏鍒掞紙MPS锛塎apper
+ *
+ * @author 鑺嬮亾婧愮爜
+ */
+@Mapper
+public interface MesProMpsMapper extends BaseMapperX<MesProMpsDO> {
+
+    default PageResult<MesProMpsDO> selectPage(MesProMpsPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<MesProMpsDO>()
+                .likeIfPresent(MesProMpsDO::getCode, reqVO.getCode())
+                .eqIfPresent(MesProMpsDO::getStatus, reqVO.getStatus())
+                .eqIfPresent(MesProMpsDO::getProductId, reqVO.getProductId())
+                .eqIfPresent(MesProMpsDO::getClientId, reqVO.getClientId())
+                .likeIfPresent(MesProMpsDO::getSaleOrderNo, reqVO.getSaleOrderNo())
+                .eqIfPresent(MesProMpsDO::getWorkOrderId, reqVO.getWorkOrderId())
+                .betweenIfPresent(MesProMpsDO::getRequestDate, reqVO.getRequestDate())
+                .betweenIfPresent(MesProMpsDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(MesProMpsDO::getId));
+    }
+
+    /**
+     * 鍒嗛〉鏌ヨ锛堝甫瀹㈡埛鏉冮檺杩囨护锛�
+     */
+    default PageResult<MesProMpsDO> selectPage(MesProMpsPageReqVO reqVO, List<Long> permittedClientIds) {
+        LambdaQueryWrapperX<MesProMpsDO> wrapper = new LambdaQueryWrapperX<MesProMpsDO>()
+                .likeIfPresent(MesProMpsDO::getCode, reqVO.getCode())
+                .eqIfPresent(MesProMpsDO::getStatus, reqVO.getStatus())
+                .eqIfPresent(MesProMpsDO::getProductId, reqVO.getProductId())
+                .eqIfPresent(MesProMpsDO::getClientId, reqVO.getClientId())
+                .likeIfPresent(MesProMpsDO::getSaleOrderNo, reqVO.getSaleOrderNo())
+                .eqIfPresent(MesProMpsDO::getWorkOrderId, reqVO.getWorkOrderId())
+                .betweenIfPresent(MesProMpsDO::getRequestDate, reqVO.getRequestDate())
+                .betweenIfPresent(MesProMpsDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(MesProMpsDO::getId);
+        if (permittedClientIds != null) {
+            if (CollUtil.isEmpty(permittedClientIds)) {
+                return PageResult.empty();
+            }
+            wrapper.in(MesProMpsDO::getClientId, permittedClientIds);
+        }
+        return selectPage(reqVO, wrapper);
+    }
+
+    default MesProMpsDO selectByCode(String code) {
+        return selectOne(MesProMpsDO::getCode, code);
+    }
+
+    default MesProMpsDO selectBySaleOrderItemId(Long saleOrderItemId) {
+        return selectOne(MesProMpsDO::getSaleOrderItemId, saleOrderItemId);
+    }
+
+    default List<MesProMpsDO> selectListBySaleOrderItemIds(Collection<Long> saleOrderItemIds) {
+        if (saleOrderItemIds == null || saleOrderItemIds.isEmpty()) {
+            return Collections.emptyList();
+        }
+        return selectList(MesProMpsDO::getSaleOrderItemId, saleOrderItemIds);
+    }
+
+    /**
+     * 鑾峰彇鍙悎骞剁殑 MPS 鍒楄〃锛堢浉鍚屼骇鍝併�佽崏绋跨姸鎬侊級
+     */
+    default List<MesProMpsDO> selectMergeableList(Long productId) {
+        return selectList(new LambdaQueryWrapperX<MesProMpsDO>()
+                .eq(MesProMpsDO::getProductId, productId)
+                .eq(MesProMpsDO::getStatus, MesProMpsStatusEnum.DRAFT.getStatus())
+                .orderByAsc(MesProMpsDO::getId));
+    }
+
+    /**
+     * 鏇存柊宸茬敓浜ф暟閲�
+     */
+    default void updateProducedQuantity(Long id, BigDecimal incrQuantity) {
+        update(null, new LambdaUpdateWrapper<MesProMpsDO>()
+                .eq(MesProMpsDO::getId, id)
+                .setSql("quantity_produced = IFNULL(quantity_produced, 0) + " + incrQuantity));
+    }
+
+}
\ No newline at end of file
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/mps/MesProMpsMergeItemMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/mps/MesProMpsMergeItemMapper.java
new file mode 100644
index 0000000..7837c6b
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/mps/MesProMpsMergeItemMapper.java
@@ -0,0 +1,25 @@
+package cn.iocoder.yudao.module.mes.dal.mysql.pro.mps;
+
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.mps.MesProMpsMergeItemDO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * MPS 鍚堝苟涓嬪彂鏄庣粏 Mapper
+ *
+ * @author 鑺嬮亾婧愮爜
+ */
+@Mapper
+public interface MesProMpsMergeItemMapper extends BaseMapperX<MesProMpsMergeItemDO> {
+
+    default List<MesProMpsMergeItemDO> selectListByMergeBatchNo(String mergeBatchNo) {
+        return selectList(MesProMpsMergeItemDO::getMergeBatchNo, mergeBatchNo);
+    }
+
+    default List<MesProMpsMergeItemDO> selectListByMpsId(Long mpsId) {
+        return selectList(MesProMpsMergeItemDO::getMpsId, mpsId);
+    }
+
+}
\ No newline at end of file
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workorder/MesProWorkOrderMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workorder/MesProWorkOrderMapper.java
index e9352b8..ce532cb 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workorder/MesProWorkOrderMapper.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workorder/MesProWorkOrderMapper.java
@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.mes.dal.mysql.pro.workorder;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
@@ -9,6 +10,7 @@
 import org.apache.ibatis.annotations.Mapper;
 
 import java.math.BigDecimal;
+import java.util.List;
 
 /**
  * MES 鐢熶骇宸ュ崟 Mapper
@@ -31,6 +33,29 @@
                 .orderByDesc(MesProWorkOrderDO::getId));
     }
 
+    /**
+     * 鍒嗛〉鏌ヨ锛堝甫瀹㈡埛鏉冮檺杩囨护锛�
+     */
+    default PageResult<MesProWorkOrderDO> selectPage(MesProWorkOrderPageReqVO reqVO, List<Long> permittedClientIds) {
+        LambdaQueryWrapperX<MesProWorkOrderDO> wrapper = new LambdaQueryWrapperX<MesProWorkOrderDO>()
+                .likeIfPresent(MesProWorkOrderDO::getCode, reqVO.getCode())
+                .likeIfPresent(MesProWorkOrderDO::getName, reqVO.getName())
+                .eqIfPresent(MesProWorkOrderDO::getType, reqVO.getType())
+                .likeIfPresent(MesProWorkOrderDO::getOrderSourceCode, reqVO.getOrderSourceCode())
+                .eqIfPresent(MesProWorkOrderDO::getProductId, reqVO.getProductId())
+                .eqIfPresent(MesProWorkOrderDO::getClientId, reqVO.getClientId())
+                .eqIfPresent(MesProWorkOrderDO::getStatus, reqVO.getStatus())
+                .betweenIfPresent(MesProWorkOrderDO::getRequestDate, reqVO.getRequestDate())
+                .orderByDesc(MesProWorkOrderDO::getId);
+        if (permittedClientIds != null) {
+            if (CollUtil.isEmpty(permittedClientIds)) {
+                return PageResult.empty();
+            }
+            wrapper.in(MesProWorkOrderDO::getClientId, permittedClientIds);
+        }
+        return selectPage(reqVO, wrapper);
+    }
+
     default MesProWorkOrderDO selectByCode(String code) {
         return selectOne(MesProWorkOrderDO::getCode, code);
     }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/oqc/MesQcOqcMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/oqc/MesQcOqcMapper.java
index 2625818..0876690 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/oqc/MesQcOqcMapper.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/oqc/MesQcOqcMapper.java
@@ -1,11 +1,14 @@
 package cn.iocoder.yudao.module.mes.dal.mysql.qc.oqc;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.MesQcOqcPageReqVO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcDO;
 import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
 
 /**
  * MES 鍑鸿揣妫�楠屽崟锛圤QC锛� Mapper
@@ -25,6 +28,26 @@
                 .orderByDesc(MesQcOqcDO::getId));
     }
 
+    /**
+     * 鍒嗛〉鏌ヨ锛堝甫瀹㈡埛鏉冮檺杩囨护锛�
+     */
+    default PageResult<MesQcOqcDO> selectPage(MesQcOqcPageReqVO reqVO, List<Long> permittedClientIds) {
+        LambdaQueryWrapperX<MesQcOqcDO> wrapper = new LambdaQueryWrapperX<MesQcOqcDO>()
+                .likeIfPresent(MesQcOqcDO::getCode, reqVO.getCode())
+                .eqIfPresent(MesQcOqcDO::getClientId, reqVO.getClientId())
+                .likeIfPresent(MesQcOqcDO::getBatchCode, reqVO.getBatchCode())
+                .eqIfPresent(MesQcOqcDO::getItemId, reqVO.getItemId())
+                .eqIfPresent(MesQcOqcDO::getCheckResult, reqVO.getCheckResult())
+                .orderByDesc(MesQcOqcDO::getId);
+        if (permittedClientIds != null) {
+            if (CollUtil.isEmpty(permittedClientIds)) {
+                return PageResult.empty();
+            }
+            wrapper.in(MesQcOqcDO::getClientId, permittedClientIds);
+        }
+        return selectPage(reqVO, wrapper);
+    }
+
     default MesQcOqcDO selectByCode(String code) {
         return selectOne(MesQcOqcDO::getCode, code);
     }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/batch/MesWmBatchMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/batch/MesWmBatchMapper.java
index db221d8..fd04fdd 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/batch/MesWmBatchMapper.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/batch/MesWmBatchMapper.java
@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.mes.dal.mysql.wm.batch;
 
 
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
@@ -50,6 +51,37 @@
     }
 
     /**
+     * 鍒嗛〉鏌ヨ锛堝甫瀹㈡埛鏉冮檺杩囨护锛�
+     */
+    default PageResult<MesWmBatchDO> selectPage(MesWmBatchPageReqVO reqVO, List<Long> permittedClientIds) {
+        LambdaQueryWrapperX<MesWmBatchDO> wrapper = new LambdaQueryWrapperX<MesWmBatchDO>()
+                .likeIfPresent(MesWmBatchDO::getCode, reqVO.getCode())
+                .eqIfPresent(MesWmBatchDO::getItemId, reqVO.getItemId())
+                .eqIfPresent(MesWmBatchDO::getVendorId, reqVO.getVendorId())
+                .eqIfPresent(MesWmBatchDO::getClientId, reqVO.getClientId())
+                .likeIfPresent(MesWmBatchDO::getSalesOrderCode, reqVO.getSalesOrderCode())
+                .likeIfPresent(MesWmBatchDO::getPurchaseOrderCode, reqVO.getPurchaseOrderCode())
+                .eqIfPresent(MesWmBatchDO::getWorkOrderId, reqVO.getWorkOrderId())
+                .eqIfPresent(MesWmBatchDO::getTaskId, reqVO.getTaskId())
+                .eqIfPresent(MesWmBatchDO::getWorkstationId, reqVO.getWorkstationId())
+                .eqIfPresent(MesWmBatchDO::getToolId, reqVO.getToolId())
+                .eqIfPresent(MesWmBatchDO::getMoldId, reqVO.getMoldId())
+                .likeIfPresent(MesWmBatchDO::getLotNumber, reqVO.getLotNumber())
+                .eqIfPresent(MesWmBatchDO::getQualityStatus, reqVO.getQualityStatus())
+                .betweenIfPresent(MesWmBatchDO::getProduceDate, reqVO.getProduceDate())
+                .betweenIfPresent(MesWmBatchDO::getExpireDate, reqVO.getExpireDate())
+                .betweenIfPresent(MesWmBatchDO::getReceiptDate, reqVO.getReceiptDate())
+                .orderByDesc(MesWmBatchDO::getId);
+        if (permittedClientIds != null) {
+            if (CollUtil.isEmpty(permittedClientIds)) {
+                return PageResult.empty();
+            }
+            wrapper.in(MesWmBatchDO::getClientId, permittedClientIds);
+        }
+        return selectPage(reqVO, wrapper);
+    }
+
+    /**
      * 鏍规嵁鍙傛暟鏌ヨ鍖归厤鐨勭涓�鏉℃壒娆¤褰�
      * <p>
      * 浣跨敤 NULL 鍊肩簿纭尮閰嶏紝杩斿洖 ID 鏈�灏忕殑鎵规
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/packages/MesWmPackageMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/packages/MesWmPackageMapper.java
index d964e2b..9fcf694 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/packages/MesWmPackageMapper.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/packages/MesWmPackageMapper.java
@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.mes.dal.mysql.wm.packages;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
@@ -30,6 +31,27 @@
                 .orderByDesc(MesWmPackageDO::getId));
     }
 
+    /**
+     * 鍒嗛〉鏌ヨ锛堝甫瀹㈡埛鏉冮檺杩囨护锛�
+     */
+    default PageResult<MesWmPackageDO> selectPage(MesWmPackagePageReqVO reqVO, List<Long> permittedClientIds) {
+        LambdaQueryWrapperX<MesWmPackageDO> wrapper = new LambdaQueryWrapperX<MesWmPackageDO>()
+                .likeIfPresent(MesWmPackageDO::getCode, reqVO.getCode())
+                .likeIfPresent(MesWmPackageDO::getSalesOrderCode, reqVO.getSalesOrderCode())
+                .eqIfPresent(MesWmPackageDO::getClientId, reqVO.getClientId())
+                .eqIfPresent(MesWmPackageDO::getParentId, reqVO.getParentId())
+                .eqIfPresent(MesWmPackageDO::getInspectorUserId, reqVO.getInspectorUserId())
+                .eqIfPresent(MesWmPackageDO::getStatus, reqVO.getStatus())
+                .orderByDesc(MesWmPackageDO::getId);
+        if (permittedClientIds != null) {
+            if (CollUtil.isEmpty(permittedClientIds)) {
+                return PageResult.empty();
+            }
+            wrapper.in(MesWmPackageDO::getClientId, permittedClientIds);
+        }
+        return selectPage(reqVO, wrapper);
+    }
+
     default MesWmPackageDO selectByCode(String code) {
         return selectOne(MesWmPackageDO::getCode, code);
     }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productsales/MesWmProductSalesMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productsales/MesWmProductSalesMapper.java
index 2218ba1..a3fd001 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productsales/MesWmProductSalesMapper.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productsales/MesWmProductSalesMapper.java
@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
@@ -27,6 +28,26 @@
                 .orderByDesc(MesWmProductSalesDO::getId));
     }
 
+    /**
+     * 鍒嗛〉鏌ヨ锛堝甫瀹㈡埛鏉冮檺杩囨护锛�
+     */
+    default PageResult<MesWmProductSalesDO> selectPage(MesWmProductSalesPageReqVO reqVO, List<Long> permittedClientIds) {
+        LambdaQueryWrapperX<MesWmProductSalesDO> wrapper = new LambdaQueryWrapperX<MesWmProductSalesDO>()
+                .likeIfPresent(MesWmProductSalesDO::getCode, reqVO.getCode())
+                .likeIfPresent(MesWmProductSalesDO::getName, reqVO.getName())
+                .eqIfPresent(MesWmProductSalesDO::getClientId, reqVO.getClientId())
+                .eqIfPresent(MesWmProductSalesDO::getStatus, reqVO.getStatus())
+                .betweenIfPresent(MesWmProductSalesDO::getSalesDate, reqVO.getShipmentDate())
+                .orderByDesc(MesWmProductSalesDO::getId);
+        if (permittedClientIds != null) {
+            if (CollUtil.isEmpty(permittedClientIds)) {
+                return PageResult.empty();
+            }
+            wrapper.in(MesWmProductSalesDO::getClientId, permittedClientIds);
+        }
+        return selectPage(reqVO, wrapper);
+    }
+
     default MesWmProductSalesDO selectByCode(String code) {
         return selectOne(MesWmProductSalesDO::getCode, code);
     }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnsales/MesWmReturnSalesMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnsales/MesWmReturnSalesMapper.java
index 8b3942b..208373a 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnsales/MesWmReturnSalesMapper.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnsales/MesWmReturnSalesMapper.java
@@ -1,11 +1,14 @@
 package cn.iocoder.yudao.module.mes.dal.mysql.wm.returnsales;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.MesWmReturnSalesPageReqVO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesDO;
 import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
 
 /**
  * MES 閿�鍞��璐у崟 Mapper
@@ -26,6 +29,27 @@
                 .orderByDesc(MesWmReturnSalesDO::getId));
     }
 
+    /**
+     * 鍒嗛〉鏌ヨ锛堝甫瀹㈡埛鏉冮檺杩囨护锛�
+     */
+    default PageResult<MesWmReturnSalesDO> selectPage(MesWmReturnSalesPageReqVO reqVO, List<Long> permittedClientIds) {
+        LambdaQueryWrapperX<MesWmReturnSalesDO> wrapper = new LambdaQueryWrapperX<MesWmReturnSalesDO>()
+                .likeIfPresent(MesWmReturnSalesDO::getCode, reqVO.getCode())
+                .likeIfPresent(MesWmReturnSalesDO::getName, reqVO.getName())
+                .likeIfPresent(MesWmReturnSalesDO::getSalesOrderCode, reqVO.getSalesOrderCode())
+                .eqIfPresent(MesWmReturnSalesDO::getClientId, reqVO.getClientId())
+                .eqIfPresent(MesWmReturnSalesDO::getStatus, reqVO.getStatus())
+                .betweenIfPresent(MesWmReturnSalesDO::getReturnDate, reqVO.getReturnDate())
+                .orderByDesc(MesWmReturnSalesDO::getId);
+        if (permittedClientIds != null) {
+            if (CollUtil.isEmpty(permittedClientIds)) {
+                return PageResult.empty();
+            }
+            wrapper.in(MesWmReturnSalesDO::getClientId, permittedClientIds);
+        }
+        return selectPage(reqVO, wrapper);
+    }
+
     default MesWmReturnSalesDO selectByCode(String code) {
         return selectOne(new LambdaQueryWrapperX<MesWmReturnSalesDO>()
                 .eq(MesWmReturnSalesDO::getCode, code));
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/salesnotice/MesWmSalesNoticeMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/salesnotice/MesWmSalesNoticeMapper.java
index 3ac2683..23f7af4 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/salesnotice/MesWmSalesNoticeMapper.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/salesnotice/MesWmSalesNoticeMapper.java
@@ -1,11 +1,15 @@
 package cn.iocoder.yudao.module.mes.dal.mysql.wm.salesnotice;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice.vo.MesWmSalesNoticePageReqVO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice.MesWmSalesNoticeDO;
 import org.apache.ibatis.annotations.Mapper;
+
+import java.util.Collection;
+import java.util.List;
 
 /**
  * MES 鍙戣揣閫氱煡鍗� Mapper
@@ -23,6 +27,32 @@
                 .orderByDesc(MesWmSalesNoticeDO::getId));
     }
 
+    /**
+     * 鍒嗛〉鏌ヨ锛堝甫瀹㈡埛鏉冮檺杩囨护锛�
+     *
+     * @param reqVO 鏌ヨ鏉′欢
+     * @param permittedClientIds 鏈夋潈闄愮殑瀹㈡埛 ID 鍒楄〃锛坣ull 琛ㄧず涓嶉檺鍒讹級
+     * @return 鍒嗛〉缁撴灉
+     */
+    default PageResult<MesWmSalesNoticeDO> selectPage(MesWmSalesNoticePageReqVO reqVO, List<Long> permittedClientIds) {
+        LambdaQueryWrapperX<MesWmSalesNoticeDO> wrapper = new LambdaQueryWrapperX<MesWmSalesNoticeDO>()
+                .likeIfPresent(MesWmSalesNoticeDO::getCode, reqVO.getCode())
+                .likeIfPresent(MesWmSalesNoticeDO::getName, reqVO.getName())
+                .likeIfPresent(MesWmSalesNoticeDO::getSaleOrderCode, reqVO.getSaleOrderCode())
+                .eqIfPresent(MesWmSalesNoticeDO::getClientId, reqVO.getClientId())
+                .eqIfPresent(MesWmSalesNoticeDO::getStatus, reqVO.getStatus())
+                .orderByDesc(MesWmSalesNoticeDO::getId);
+        // 瀹㈡埛鏉冮檺杩囨护
+        if (permittedClientIds != null) {
+            if (CollUtil.isEmpty(permittedClientIds)) {
+                // 绌哄垪琛ㄨ〃绀烘病鏈変换浣曟潈闄愶紝杩斿洖绌虹粨鏋�
+                return PageResult.empty();
+            }
+            wrapper.in(MesWmSalesNoticeDO::getClientId, permittedClientIds);
+        }
+        return selectPage(reqVO, wrapper);
+    }
+
     default MesWmSalesNoticeDO selectByCode(String code) {
         return selectOne(MesWmSalesNoticeDO::getCode, code);
     }
@@ -31,4 +61,13 @@
         return selectOne(MesWmSalesNoticeDO::getSaleOrderId, saleOrderId);
     }
 
+    /**
+     * 鏌ヨ宸插瓨鍦ㄥ彂璐ч�氱煡鍗曠殑閿�鍞鍗� ID 鍒楄〃
+     */
+    default List<Long> selectExistingSaleOrderIds(Collection<Long> saleOrderIds) {
+        return selectObjs(new LambdaQueryWrapperX<MesWmSalesNoticeDO>()
+                .select(MesWmSalesNoticeDO::getSaleOrderId)
+                .in(MesWmSalesNoticeDO::getSaleOrderId, saleOrderIds));
+    }
+
 }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/DictTypeConstants.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/DictTypeConstants.java
index 5a32a63..05f4b64 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/DictTypeConstants.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/DictTypeConstants.java
@@ -19,6 +19,7 @@
     String MES_PRO_WORK_ORDER_STATUS = "mes_pro_work_order_status"; // MES 鐢熶骇宸ュ崟鐘舵��
     String MES_PRO_WORK_ORDER_SOURCE_TYPE = "mes_pro_work_order_source_type"; // MES 宸ュ崟鏉ユ簮绫诲瀷
     String MES_PRO_WORK_ORDER_TYPE = "mes_pro_work_order_type"; // MES 宸ュ崟绫诲瀷
+    String MES_PRO_MPS_STATUS = "mes_pro_mps_status"; // MES 鐢熶骇涓昏鍒掔姸鎬�
     String MES_PRO_LINK_TYPE = "mes_pro_link_type"; // MES 宸ュ簭鍏崇郴绫诲瀷
     String MES_TIME_UNIT_TYPE = "mes_time_unit_type"; // MES 鏃堕棿鍗曚綅
     String MES_PRO_ANDON_STATUS = "mes_pro_andon_status"; // MES 瀹夌伅澶勭疆鐘舵��
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 52c0302..2dc155a 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
@@ -322,6 +322,17 @@
     ErrorCode WORK_RECORD_NOT_CLOCK_IN = new ErrorCode(1_040_508_001, "褰撳墠鐢ㄦ埛鏈笂宸ワ紝鏃犳硶涓嬪伐");
     ErrorCode WORK_RECORD_ALREADY_CLOCK_IN = new ErrorCode(1_040_508_002, "褰撳墠鐢ㄦ埛宸蹭笂宸ワ紝璇峰厛涓嬪伐鍐嶆搷浣�");
 
+    // ========== MES 鐢熶骇绠$悊-鐢熶骇涓昏鍒� MPS锛�1-040-509-000锛� ==========
+    ErrorCode PRO_MPS_NOT_EXISTS = new ErrorCode(1_040_509_000, "MPS 涓嶅瓨鍦�");
+    ErrorCode PRO_MPS_NOT_DRAFT = new ErrorCode(1_040_509_001, "鍙湁鑽夌鐘舵�佺殑 MPS 鎵嶈兘鎵ц姝ゆ搷浣�");
+    ErrorCode PRO_MPS_NOT_ISSUED = new ErrorCode(1_040_509_002, "鍙湁宸蹭笅鍙戠姸鎬佺殑 MPS 鎵嶈兘鎵ц姝ゆ搷浣�");
+    ErrorCode PRO_MPS_ALREADY_ISSUED = new ErrorCode(1_040_509_003, "MPS 宸蹭笅鍙戯紝鏃犳硶淇敼");
+    ErrorCode PRO_MPS_MERGE_AT_LEAST_TWO = new ErrorCode(1_040_509_004, "鍚堝苟涓嬪彂鑷冲皯闇�瑕侀�夋嫨涓ゆ潯 MPS");
+    ErrorCode PRO_MPS_MERGE_PRODUCT_MISMATCH = new ErrorCode(1_040_509_005, "鍚堝苟涓嬪彂鐨� MPS 蹇呴』鏄浉鍚屼骇鍝�");
+    ErrorCode PRO_MPS_CODE_DUPLICATE = new ErrorCode(1_040_509_006, "MPS 缂栫爜宸插瓨鍦�");
+    ErrorCode PRO_MPS_HAS_WORK_ORDER = new ErrorCode(1_040_509_007, "MPS 宸插叧鑱旂敓浜у伐鍗曪紝鏃犳硶鍒犻櫎");
+    ErrorCode PRO_MPS_MES_PRODUCT_NOT_EXISTS = new ErrorCode(1_040_509_008, "MES 浜у搧涓嶅瓨鍦紝鏃犳硶鍒涘缓 MPS锛屼骇鍝侊細{}");
+
     // ========== MES 璐ㄩ噺绠$悊-璐ㄦ鏂规锛�1-040-600-000锛� ==========
     ErrorCode QC_TEMPLATE_NOT_EXISTS = new ErrorCode(1_040_600_000, "璐ㄦ鏂规涓嶅瓨鍦�");
     ErrorCode QC_TEMPLATE_CODE_DUPLICATE = new ErrorCode(1_040_600_001, "璐ㄦ鏂规缂栧彿宸插瓨鍦�");
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProMpsStatusEnum.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProMpsStatusEnum.java
new file mode 100644
index 0000000..699d3ad
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProMpsStatusEnum.java
@@ -0,0 +1,52 @@
+package cn.iocoder.yudao.module.mes.enums.pro;
+
+import cn.iocoder.yudao.framework.common.core.ArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * MES 鐢熶骇涓昏鍒掞紙MPS锛夌姸鎬佹灇涓�
+ *
+ * @author 鑺嬮亾婧愮爜
+ */
+@Getter
+@AllArgsConstructor
+public enum MesProMpsStatusEnum implements ArrayValuable<Integer> {
+
+    /**
+     * 鑽夌
+     */
+    DRAFT(0, "鑽夌"),
+    /**
+     * 宸蹭笅鍙�
+     */
+    ISSUED(1, "宸蹭笅鍙�"),
+    /**
+     * 宸插畬鎴�
+     */
+    FINISHED(2, "宸插畬鎴�"),
+    /**
+     * 宸插彇娑�
+     */
+    CANCELED(3, "宸插彇娑�");
+
+    public static final Integer[] ARRAYS = Arrays.stream(values())
+            .map(MesProMpsStatusEnum::getStatus).toArray(Integer[]::new);
+
+    /**
+     * 鐘舵�佸��
+     */
+    private final Integer status;
+    /**
+     * 鐘舵�佸悕
+     */
+    private final String name;
+
+    @Override
+    public Integer[] array() {
+        return ARRAYS;
+    }
+
+}
\ No newline at end of file
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/client/MesMdClientService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/client/MesMdClientService.java
deleted file mode 100644
index f0887d1..0000000
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/client/MesMdClientService.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package cn.iocoder.yudao.module.mes.service.md.client;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientImportExcelVO;
-import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientImportRespVO;
-import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientPageReqVO;
-import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientSaveReqVO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO;
-import jakarta.validation.Valid;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
-
-/**
- * MES 瀹㈡埛 Service 鎺ュ彛
- *
- * @author 鑺嬮亾婧愮爜
- */
-public interface MesMdClientService {
-
-    /**
-     * 鍒涘缓瀹㈡埛
-     *
-     * @param createReqVO 鍒涘缓淇℃伅
-     * @return 缂栧彿
-     */
-    Long createClient(@Valid MesMdClientSaveReqVO createReqVO);
-
-    /**
-     * 鏇存柊瀹㈡埛
-     *
-     * @param updateReqVO 鏇存柊淇℃伅
-     */
-    void updateClient(@Valid MesMdClientSaveReqVO updateReqVO);
-
-    /**
-     * 鍒犻櫎瀹㈡埛
-     *
-     * @param id 缂栧彿
-     */
-    void deleteClient(Long id);
-
-    /**
-     * 鑾峰緱瀹㈡埛
-     *
-     * @param id 缂栧彿
-     * @return 瀹㈡埛
-     */
-    MesMdClientDO getClient(Long id);
-
-    /**
-     * 鑾峰緱瀹㈡埛鍒嗛〉
-     *
-     * @param pageReqVO 鍒嗛〉鏌ヨ
-     * @return 瀹㈡埛鍒嗛〉
-     */
-    PageResult<MesMdClientDO> getClientPage(MesMdClientPageReqVO pageReqVO);
-
-    /**
-     * 鑾峰緱瀹㈡埛鍒楄〃
-     *
-     * @param ids 缂栧彿鍒楄〃
-     * @return 瀹㈡埛鍒楄〃
-     */
-    List<MesMdClientDO> getClientList(Collection<Long> ids);
-
-    /**
-     * 鑾峰緱瀹㈡埛 Map
-     *
-     * @param ids 缂栧彿鍒楄〃
-     * @return 瀹㈡埛 Map
-     */
-    default Map<Long, MesMdClientDO> getClientMap(Collection<Long> ids) {
-        return convertMap(getClientList(ids), MesMdClientDO::getId);
-    }
-
-    /**
-     * 鏍¢獙瀹㈡埛鏄惁瀛樺湪
-     *
-     * @param id 缂栧彿
-     */
-    void validateClientExists(Long id);
-
-    /**
-     * 鏍¢獙瀹㈡埛瀛樺湪涓斿惎鐢�
-     *
-     * @param id 缂栧彿
-     */
-    void validateClientExistsAndEnable(Long id);
-
-    /**
-     * 鎵归噺瀵煎叆瀹㈡埛
-     *
-     * @param importClients 瀵煎叆瀹㈡埛鍒楄〃
-     * @param updateSupport 鏄惁鏀寔鏇存柊
-     * @return 瀵煎叆缁撴灉
-     */
-    MesMdClientImportRespVO importClientList(List<MesMdClientImportExcelVO> importClients, boolean updateSupport);
-
-}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/client/MesMdClientServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/client/MesMdClientServiceImpl.java
deleted file mode 100644
index 516058f..0000000
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/client/MesMdClientServiceImpl.java
+++ /dev/null
@@ -1,229 +0,0 @@
-package cn.iocoder.yudao.module.mes.service.md.client;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.ObjUtil;
-import cn.hutool.core.util.StrUtil;
-import cn.iocoder.yudao.framework.common.exception.ServiceException;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientImportExcelVO;
-import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientImportRespVO;
-import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientPageReqVO;
-import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientSaveReqVO;
-import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO;
-import cn.iocoder.yudao.module.mes.dal.mysql.md.client.MesMdClientMapper;
-import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum;
-import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService;
-import jakarta.annotation.Resource;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.validation.annotation.Validated;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
-
-/**
- * MES 瀹㈡埛 Service 瀹炵幇绫�
- *
- * @author 鑺嬮亾婧愮爜
- */
-@Service
-@Validated
-public class MesMdClientServiceImpl implements MesMdClientService {
-
-    @Resource
-    private MesMdClientMapper clientMapper;
-
-    @Resource
-    private MesWmBarcodeService barcodeService;
-
-    @Override
-    public Long createClient(MesMdClientSaveReqVO createReqVO) {
-        // 鏍¢獙鏁版嵁
-        validateClientSaveData(createReqVO);
-
-        // 鎻掑叆
-        MesMdClientDO client = BeanUtils.toBean(createReqVO, MesMdClientDO.class);
-        clientMapper.insert(client);
-
-        // 鑷姩鐢熸垚鏉$爜
-        barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.CLIENT.getValue(),
-                client.getId(), client.getCode(), client.getName());
-        return client.getId();
-    }
-
-    @Override
-    public void updateClient(MesMdClientSaveReqVO updateReqVO) {
-        // 鏍¢獙瀛樺湪
-        validateClientExists(updateReqVO.getId());
-        // 鏍¢獙鏁版嵁
-        validateClientSaveData(updateReqVO);
-
-        // 鏇存柊
-        MesMdClientDO updateObj = BeanUtils.toBean(updateReqVO, MesMdClientDO.class);
-        clientMapper.updateById(updateObj);
-    }
-
-    private void validateClientSaveData(MesMdClientSaveReqVO reqVO) {
-        // 鏍¢獙缂栫爜鍞竴
-        validateClientCodeUnique(reqVO.getId(), reqVO.getCode());
-        // 鏍¢獙鍚嶇О鍞竴
-        validateClientNameUnique(reqVO.getId(), reqVO.getName());
-        // 鏍¢獙绠�绉板敮涓�
-        validateClientNicknameUnique(reqVO.getId(), reqVO.getNickname());
-    }
-
-    @Override
-    public void deleteClient(Long id) {
-        // 鏍¢獙瀛樺湪
-        validateClientExists(id);
-        // 鍒犻櫎
-        clientMapper.deleteById(id);
-    }
-
-    @Override
-    public void validateClientExists(Long id) {
-        if (clientMapper.selectById(id) == null) {
-            throw exception(MD_CLIENT_NOT_EXISTS);
-        }
-    }
-
-    @Override
-    public void validateClientExistsAndEnable(Long id) {
-        MesMdClientDO client = clientMapper.selectById(id);
-        if (client == null) {
-            throw exception(MD_CLIENT_NOT_EXISTS);
-        }
-        if (ObjUtil.notEqual(CommonStatusEnum.ENABLE.getStatus(), client.getStatus())) {
-            throw exception(MD_CLIENT_IS_DISABLE);
-        }
-    }
-
-    private void validateClientCodeUnique(Long id, String code) {
-        MesMdClientDO client = clientMapper.selectByCode(code);
-        if (client == null) {
-            return;
-        }
-        if (ObjUtil.notEqual(client.getId(), id)) {
-            throw exception(MD_CLIENT_CODE_DUPLICATE);
-        }
-    }
-
-    private void validateClientNameUnique(Long id, String name) {
-        MesMdClientDO client = clientMapper.selectByName(name);
-        if (client == null) {
-            return;
-        }
-        if (ObjUtil.notEqual(client.getId(), id)) {
-            throw exception(MD_CLIENT_NAME_DUPLICATE);
-        }
-    }
-
-    private void validateClientNicknameUnique(Long id, String nickname) {
-        if (StrUtil.isEmpty(nickname)) {
-            return;
-        }
-        MesMdClientDO client = clientMapper.selectByNickname(nickname);
-        if (client == null) {
-            return;
-        }
-        if (ObjUtil.notEqual(client.getId(), id)) {
-            throw exception(MD_CLIENT_NICKNAME_DUPLICATE);
-        }
-    }
-
-    @Override
-    public MesMdClientDO getClient(Long id) {
-        return clientMapper.selectById(id);
-    }
-
-    @Override
-    public PageResult<MesMdClientDO> getClientPage(MesMdClientPageReqVO pageReqVO) {
-        return clientMapper.selectPage(pageReqVO);
-    }
-
-    @Override
-    public List<MesMdClientDO> getClientList(Collection<Long> ids) {
-        if (CollUtil.isEmpty(ids)) {
-            return Collections.emptyList();
-        }
-        return clientMapper.selectByIds(ids);
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public MesMdClientImportRespVO importClientList(List<MesMdClientImportExcelVO> importClients, boolean updateSupport) {
-        // 1. 鍙傛暟鏍¢獙
-        if (CollUtil.isEmpty(importClients)) {
-            throw exception(MD_CLIENT_IMPORT_LIST_IS_EMPTY);
-        }
-
-        // 2. 閬嶅巻锛岄�愪釜鍒涘缓 or 鏇存柊
-        MesMdClientImportRespVO respVO = MesMdClientImportRespVO.builder()
-                .createCodes(new ArrayList<>()).updateCodes(new ArrayList<>())
-                .failureCodes(new LinkedHashMap<>()).build();
-        AtomicInteger index = new AtomicInteger(1);
-        importClients.forEach(importClient -> {
-            int currentIndex = index.getAndIncrement();
-            // 2.1 鏍¢獙瀛楁
-            String key = StrUtil.blankToDefault(importClient.getCode(), "绗� " + currentIndex + " 琛�");
-            if (StrUtil.isBlank(importClient.getCode())) {
-                respVO.getFailureCodes().put(key, "瀹㈡埛缂栫爜涓嶈兘涓虹┖");
-                return;
-            }
-            if (StrUtil.isBlank(importClient.getName())) {
-                respVO.getFailureCodes().put(key, "瀹㈡埛鍚嶇О涓嶈兘涓虹┖");
-                return;
-            }
-            if (importClient.getType() == null) {
-                respVO.getFailureCodes().put(key, "瀹㈡埛绫诲瀷涓嶈兘涓虹┖");
-                return;
-            }
-
-            // 2.2 鍒ゆ柇锛氬垱寤� or 鏇存柊
-            MesMdClientDO existClient = clientMapper.selectByCode(importClient.getCode());
-            if (existClient == null) {
-                // 2.2.1 鍒涘缓
-                try {
-                    validateClientNameUnique(null, importClient.getName());
-                    validateClientNicknameUnique(null, importClient.getNickname());
-                } catch (ServiceException ex) {
-                    respVO.getFailureCodes().put(key, ex.getMessage());
-                    return;
-                }
-                MesMdClientDO client = BeanUtils.toBean(importClient, MesMdClientDO.class);
-                clientMapper.insert(client);
-                // 鑷姩鐢熸垚鏉$爜
-                barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.CLIENT.getValue(),
-                        client.getId(), client.getCode(), client.getName());
-                respVO.getCreateCodes().add(importClient.getCode());
-            } else if (updateSupport) {
-                // 2.2.2 鏇存柊
-                try {
-                    validateClientNameUnique(existClient.getId(), importClient.getName());
-                    validateClientNicknameUnique(existClient.getId(), importClient.getNickname());
-                } catch (ServiceException ex) {
-                    respVO.getFailureCodes().put(key, ex.getMessage());
-                    return;
-                }
-                MesMdClientDO updateObj = BeanUtils.toBean(importClient, MesMdClientDO.class);
-                updateObj.setId(existClient.getId());
-                clientMapper.updateById(updateObj);
-                respVO.getUpdateCodes().add(importClient.getCode());
-            } else {
-                // 涓嶆敮鎸佹洿鏂�
-                respVO.getFailureCodes().put(key, "瀹㈡埛缂栫爜宸插瓨鍦�");
-            }
-        });
-        return respVO;
-    }
-
-}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemService.java
index c86b91e..a8b407a 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemService.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemService.java
@@ -134,4 +134,21 @@
      */
     Long getItemCountByUnitMeasureId(Long unitMeasureId);
 
+    /**
+     * 鏍规嵁 MDM 鐗╂枡 ID 鑾峰彇 MES 浜у搧
+     *
+     * @param mdmItemId MDM 鐗╂枡 ID
+     * @return MES 浜у搧锛屼笉瀛樺湪杩斿洖 null
+     */
+    MesMdItemDO getItemByMdmItemId(Long mdmItemId);
+
+    /**
+     * 鏍规嵁 MDM 鐗╂枡 ID 鏍¢獙 MES 浜у搧瀛樺湪
+     *
+     * @param mdmItemId MDM 鐗╂枡 ID
+     * @return MES 浜у搧
+     * @throws cn.iocoder.yudao.framework.common.exception.ServiceException 濡傛灉浜у搧涓嶅瓨鍦�
+     */
+    MesMdItemDO validateItemExistsByMdmItemId(Long mdmItemId);
+
 }
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 9067574..2300bb2 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
@@ -478,4 +478,21 @@
         return 1; // 榛樿鍘熸枡
     }
 
+    @Override
+    public MesMdItemDO getItemByMdmItemId(Long mdmItemId) {
+        if (mdmItemId == null) {
+            return null;
+        }
+        return itemMapper.selectByMdmItemId(mdmItemId);
+    }
+
+    @Override
+    public MesMdItemDO validateItemExistsByMdmItemId(Long mdmItemId) {
+        MesMdItemDO item = getItemByMdmItemId(mdmItemId);
+        if (item == null) {
+            throw exception(MD_ITEM_NOT_EXISTS);
+        }
+        return item;
+    }
+
 }
\ No newline at end of file
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/mps/MesProMpsService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/mps/MesProMpsService.java
new file mode 100644
index 0000000..8c6af1f
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/mps/MesProMpsService.java
@@ -0,0 +1,148 @@
+package cn.iocoder.yudao.module.mes.service.pro.mps;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.mps.vo.MesProMpsPageReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.mps.vo.MesProMpsSaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.mps.MesProMpsDO;
+import jakarta.validation.Valid;
+
+import java.math.BigDecimal;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * MES 鐢熶骇涓昏鍒掞紙MPS锛塖ervice 鎺ュ彛
+ *
+ * @author 鑺嬮亾婧愮爜
+ */
+public interface MesProMpsService {
+
+    /**
+     * 鍒涘缓 MPS锛堜緵 API 璋冪敤锛岃嚜鍔ㄦ槧灏勭墿鏂欙級
+     *
+     * @param saleOrderId 閿�鍞鍗旾D
+     * @param saleOrderNo 閿�鍞鍗曞彿
+     * @param saleOrderItemId 閿�鍞鍗曟槑缁咺D
+     * @param mdmItemId MDM 鐗╂枡ID
+     * @param productName 浜у搧鍚嶇О锛堢敤浜庨敊璇彁绀猴級
+     * @param quantity 璁″垝鏁伴噺
+     * @param clientId 瀹㈡埛ID
+     * @param requestDate 闇�姹傛棩鏈�
+     * @param remark 澶囨敞
+     * @return MPS 缂栧彿锛屽鏋� MES 浜у搧涓嶅瓨鍦ㄨ繑鍥� null
+     * @throws cn.iocoder.yudao.framework.common.exception.ServiceException 濡傛灉 MES 浜у搧涓嶅瓨鍦�
+     */
+    Long createMps(Long saleOrderId, String saleOrderNo, Long saleOrderItemId,
+                   Long mdmItemId, String productName, BigDecimal quantity, Long clientId,
+                   String requestDate, String remark);
+
+    /**
+     * 鍒涘缓 MPS
+     *
+     * @param createReqVO 鍒涘缓淇℃伅
+     * @return MPS 缂栧彿
+     */
+    Long createMps(@Valid MesProMpsSaveReqVO createReqVO);
+
+    /**
+     * 鏇存柊 MPS
+     *
+     * @param updateReqVO 鏇存柊淇℃伅
+     */
+    void updateMps(@Valid MesProMpsSaveReqVO updateReqVO);
+
+    /**
+     * 鍒犻櫎 MPS锛堜粎鑽夌鐘舵�侊級
+     *
+     * @param id 缂栧彿
+     */
+    void deleteMps(Long id);
+
+    /**
+     * 涓嬪彂鍗曟潯 MPS
+     *
+     * @param id MPS 缂栧彿
+     * @return 鐢熸垚鐨勫伐鍗� ID
+     */
+    Long issueMps(Long id);
+
+    /**
+     * 鍚堝苟涓嬪彂澶氭潯 MPS
+     * 灏嗗鏉$浉鍚屼骇鍝佺殑 MPS 鍚堝苟鐢熸垚涓�鏉$敓浜у伐鍗�
+     *
+     * @param mpsIds MPS 缂栧彿鍒楄〃
+     * @return 鐢熸垚鐨勫伐鍗� ID
+     */
+    Long mergeAndIssueMps(List<Long> mpsIds);
+
+    /**
+     * 鍙栨秷 MPS
+     *
+     * @param id 缂栧彿
+     */
+    void cancelMps(Long id);
+
+    /**
+     * 瀹屾垚 MPS锛堢敱鐢熶骇宸ュ崟瀹屾垚鏃惰Е鍙戯級
+     *
+     * @param id 缂栧彿
+     */
+    void finishMps(Long id);
+
+    /**
+     * 鏍规嵁閿�鍞鍗曟槑缁嗚幏鍙� MPS
+     *
+     * @param saleOrderItemId 閿�鍞鍗曟槑缁咺D
+     * @return MPS
+     */
+    MesProMpsDO getMpsBySaleOrderItemId(Long saleOrderItemId);
+
+    /**
+     * 鑾峰彇 MPS
+     *
+     * @param id 缂栧彿
+     * @return MPS
+     */
+    MesProMpsDO getMps(Long id);
+
+    /**
+     * 鑾峰彇 MPS 鍒嗛〉
+     *
+     * @param pageReqVO 鍒嗛〉鏌ヨ
+     * @return 鍒嗛〉缁撴灉
+     */
+    PageResult<MesProMpsDO> getMpsPage(MesProMpsPageReqVO pageReqVO);
+
+    /**
+     * 鑾峰彇 MPS 鍒楄〃
+     *
+     * @param ids 缂栧彿鍒楄〃
+     * @return MPS 鍒楄〃
+     */
+    List<MesProMpsDO> getMpsList(Collection<Long> ids);
+
+    /**
+     * 鏍规嵁閿�鍞鍗曟槑缁咺D鍒楄〃鑾峰彇 MPS 鍒楄〃
+     *
+     * @param saleOrderItemIds 閿�鍞鍗曟槑缁咺D鍒楄〃
+     * @return MPS 鍒楄〃
+     */
+    List<MesProMpsDO> getMpsListBySaleOrderItemIds(Collection<Long> saleOrderItemIds);
+
+    /**
+     * 鑾峰彇鍙悎骞剁殑 MPS 鍒楄〃锛堢浉鍚屼骇鍝併�佽崏绋跨姸鎬侊級
+     *
+     * @param productId 浜у搧ID
+     * @return MPS 鍒楄〃
+     */
+    List<MesProMpsDO> getMergeableMpsList(Long productId);
+
+    /**
+     * 鏇存柊宸茬敓浜ф暟閲�
+     *
+     * @param id MPS 缂栧彿
+     * @param incrQuantity 澧為噺
+     */
+    void updateProducedQuantity(Long id, BigDecimal incrQuantity);
+
+}
\ No newline at end of file
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/mps/MesProMpsServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/mps/MesProMpsServiceImpl.java
new file mode 100644
index 0000000..34ca046
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/mps/MesProMpsServiceImpl.java
@@ -0,0 +1,433 @@
+package cn.iocoder.yudao.module.mes.service.pro.mps;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.mps.vo.MesProMpsPageReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.mps.vo.MesProMpsSaveReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderSaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.mps.MesProMpsDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.mps.MesProMpsMergeItemDO;
+import cn.iocoder.yudao.module.mes.dal.mysql.pro.mps.MesProMpsMapper;
+import cn.iocoder.yudao.module.mes.dal.mysql.pro.mps.MesProMpsMergeItemMapper;
+import cn.iocoder.yudao.module.mes.enums.pro.MesProMpsStatusEnum;
+import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderSourceTypeEnum;
+import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService;
+import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
+import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService;
+import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.validation.annotation.Validated;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
+
+/**
+ * MES 鐢熶骇涓昏鍒掞紙MPS锛塖ervice 瀹炵幇绫�
+ *
+ * @author 鑺嬮亾婧愮爜
+ */
+@Service
+@Validated
+@Slf4j
+public class MesProMpsServiceImpl implements MesProMpsService {
+
+    /**
+     * MPS 缂栫爜瑙勫垯
+     */
+    private static final String MPS_CODE_RULE = "MPS";
+
+    @Resource
+    private MesProMpsMapper mpsMapper;
+    @Resource
+    private MesProMpsMergeItemMapper mergeItemMapper;
+    @Resource
+    private MesProWorkOrderService workOrderService;
+    @Resource
+    private MesMdItemService itemService;
+    @Resource
+    private MesMdAutoCodeRecordService autoCodeRecordService;
+    @Resource
+    private CrmCustomerApi customerApi;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Long createMps(Long saleOrderId, String saleOrderNo, Long saleOrderItemId,
+                          Long mdmItemId, String productName, BigDecimal quantity, Long clientId,
+                          String requestDate, String remark) {
+        // 1. 鏍规嵁 MDM 鐗╂枡 ID 鏌ユ壘 MES 浜у搧
+        cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO mesItem = itemService.getItemByMdmItemId(mdmItemId);
+        if (mesItem == null) {
+            // MES 浜у搧涓嶅瓨鍦紝鎶涘嚭寮傚父骞跺寘鍚骇鍝佸悕绉版彁绀�
+            throw exception(PRO_MPS_MES_PRODUCT_NOT_EXISTS, productName != null ? productName : mdmItemId);
+        }
+
+        // 2. 鐢熸垚 MPS 缂栫爜
+        String code = generateMpsCode();
+
+        // 3. 瑙f瀽闇�姹傛棩鏈�
+        LocalDateTime requestDateTime = null;
+        if (StrUtil.isNotBlank(requestDate)) {
+            try {
+                requestDateTime = LocalDateTime.parse(requestDate, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+            } catch (Exception e) {
+                requestDateTime = LocalDateTime.parse(requestDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+            }
+        }
+
+        // 4. 鍒涘缓 MPS锛堜娇鐢� MES 浜у搧 ID锛�
+        MesProMpsDO mps = new MesProMpsDO();
+        mps.setCode(code);
+        mps.setStatus(MesProMpsStatusEnum.DRAFT.getStatus());
+        mps.setSaleOrderId(saleOrderId);
+        mps.setSaleOrderNo(saleOrderNo);
+        mps.setSaleOrderItemId(saleOrderItemId);
+        mps.setProductId(mesItem.getId()); // 浣跨敤 MES 浜у搧 ID
+        mps.setQuantity(quantity);
+        mps.setQuantityProduced(BigDecimal.ZERO);
+        mps.setUnitMeasureId(mesItem.getUnitMeasureId()); // 浠� MES 浜у搧鑾峰彇璁¢噺鍗曚綅
+        mps.setClientId(clientId);
+        mps.setRequestDate(requestDateTime);
+        mps.setMergeFlag(0);
+        mps.setRemark(remark);
+
+        mpsMapper.insert(mps);
+        log.info("[createMps] 鍒涘缓 MPS 鎴愬姛锛宨d={}, code={}, saleOrderItemId={}, mdmItemId={}, productId={}",
+                mps.getId(), mps.getCode(), mps.getSaleOrderItemId(), mdmItemId, mesItem.getId());
+        return mps.getId();
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Long createMps(MesProMpsSaveReqVO createReqVO) {
+        // 鏍¢獙浜у搧瀛樺湪
+        itemService.validateItemExists(createReqVO.getProductId());
+
+        // 濡傛灉鏈~鍐欑紪鐮侊紝鑷姩鐢熸垚
+        if (StrUtil.isBlank(createReqVO.getCode())) {
+            createReqVO.setCode(generateMpsCode());
+        } else {
+            // 鏍¢獙缂栫爜鍞竴
+            validateMpsCodeUnique(null, createReqVO.getCode());
+        }
+
+        // 鎻掑叆
+        MesProMpsDO mps = BeanUtils.toBean(createReqVO, MesProMpsDO.class);
+        mps.setStatus(MesProMpsStatusEnum.DRAFT.getStatus());
+        mps.setQuantityProduced(BigDecimal.ZERO);
+        mps.setMergeFlag(0);
+        mpsMapper.insert(mps);
+
+        log.info("[createMps] 鎵嬪姩鍒涘缓 MPS 鎴愬姛锛宨d={}, code={}", mps.getId(), mps.getCode());
+        return mps.getId();
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void updateMps(MesProMpsSaveReqVO updateReqVO) {
+        // 鏍¢獙瀛樺湪 + 鑽夌鐘舵��
+        validateMpsExistsAndDraft(updateReqVO.getId());
+
+        // 鏍¢獙缂栫爜鍞竴
+        validateMpsCodeUnique(updateReqVO.getId(), updateReqVO.getCode());
+
+        // 鏇存柊
+        MesProMpsDO updateObj = BeanUtils.toBean(updateReqVO, MesProMpsDO.class);
+        mpsMapper.updateById(updateObj);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void deleteMps(Long id) {
+        // 鏍¢獙瀛樺湪 + 鑽夌鐘舵��
+        MesProMpsDO mps = validateMpsExistsAndDraft(id);
+
+        // 鏍¢獙鏄惁宸插叧鑱斿伐鍗�
+        if (mps.getWorkOrderId() != null) {
+            throw exception(PRO_MPS_HAS_WORK_ORDER);
+        }
+
+        // 鍒犻櫎
+        mpsMapper.deleteById(id);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Long issueMps(Long id) {
+        // 鏍¢獙瀛樺湪 + 鑽夌鐘舵��
+        MesProMpsDO mps = validateMpsExistsAndDraft(id);
+
+        // 鍒涘缓鐢熶骇宸ュ崟
+        Long workOrderId = createWorkOrderFromMps(mps, mps.getQuantity());
+
+        // 鏇存柊 MPS 鐘舵��
+        mpsMapper.updateById(new MesProMpsDO()
+                .setId(id)
+                .setStatus(MesProMpsStatusEnum.ISSUED.getStatus())
+                .setWorkOrderId(workOrderId)
+                .setIssueDate(LocalDateTime.now()));
+
+        log.info("[issueMps] MPS 涓嬪彂鎴愬姛锛宮psId={}, workOrderId={}", id, workOrderId);
+        return workOrderId;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Long mergeAndIssueMps(List<Long> mpsIds) {
+        // 鏍¢獙 MPS 鍒楄〃
+        if (CollUtil.isEmpty(mpsIds) || mpsIds.size() < 2) {
+            throw exception(PRO_MPS_MERGE_AT_LEAST_TWO);
+        }
+
+        List<MesProMpsDO> mpsList = mpsMapper.selectBatchIds(mpsIds);
+        if (mpsList.size() != mpsIds.size()) {
+            throw exception(PRO_MPS_NOT_EXISTS);
+        }
+
+        // 鏍¢獙锛氬繀椤绘槸鐩稿悓浜у搧銆佽崏绋跨姸鎬�
+        Long productId = null;
+        for (MesProMpsDO mps : mpsList) {
+            if (!MesProMpsStatusEnum.DRAFT.getStatus().equals(mps.getStatus())) {
+                throw exception(PRO_MPS_NOT_DRAFT);
+            }
+            if (productId == null) {
+                productId = mps.getProductId();
+            } else if (!productId.equals(mps.getProductId())) {
+                throw exception(PRO_MPS_MERGE_PRODUCT_MISMATCH);
+            }
+        }
+
+        // 璁$畻鍚堝苟鏁伴噺
+        BigDecimal totalQuantity = mpsList.stream()
+                .map(MesProMpsDO::getQuantity)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+        // 鍙栫涓�鏉� MPS 浣滀负涓昏褰曪紝鍒涘缓鐢熶骇宸ュ崟
+        MesProMpsDO firstMps = mpsList.get(0);
+        Long workOrderId = createWorkOrderFromMps(firstMps, totalQuantity);
+
+        // 鐢熸垚鍚堝苟鎵规鍙�
+        String mergeBatchNo = generateMergeBatchNo();
+
+        // 鏇存柊鎵�鏈� MPS 鐘舵�侊紝璁板綍鍚堝苟鍏崇郴
+        for (MesProMpsDO mps : mpsList) {
+            mpsMapper.updateById(new MesProMpsDO()
+                    .setId(mps.getId())
+                    .setStatus(MesProMpsStatusEnum.ISSUED.getStatus())
+                    .setWorkOrderId(workOrderId)
+                    .setMergeFlag(1)
+                    .setMergeBatchNo(mergeBatchNo)
+                    .setIssueDate(LocalDateTime.now()));
+
+            // 璁板綍鍚堝苟鏄庣粏
+            MesProMpsMergeItemDO mergeItem = new MesProMpsMergeItemDO();
+            mergeItem.setMergeBatchNo(mergeBatchNo);
+            mergeItem.setMpsId(mps.getId());
+            mergeItem.setWorkOrderId(workOrderId);
+            mergeItem.setQuantity(mps.getQuantity());
+            mergeItemMapper.insert(mergeItem);
+        }
+
+        log.info("[mergeAndIssueMps] MPS 鍚堝苟涓嬪彂鎴愬姛锛宮psIds={}, workOrderId={}, totalQuantity={}",
+                mpsIds, workOrderId, totalQuantity);
+        return workOrderId;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void cancelMps(Long id) {
+        // 鏍¢獙瀛樺湪
+        MesProMpsDO mps = validateMpsExists(id);
+
+        // 鏍¢獙鐘舵�侊細鍙湁宸蹭笅鍙戠姸鎬佹墠鑳藉彇娑�
+        if (!MesProMpsStatusEnum.ISSUED.getStatus().equals(mps.getStatus())) {
+            throw exception(PRO_MPS_NOT_ISSUED);
+        }
+
+        // 绾ц仈鍙栨秷鍏宠仈鐨勭敓浜у伐鍗�
+        if (mps.getWorkOrderId() != null) {
+            try {
+                workOrderService.cancelWorkOrder(mps.getWorkOrderId());
+                log.info("[cancelMps] 绾ц仈鍙栨秷鐢熶骇宸ュ崟锛寃orkOrderId={}", mps.getWorkOrderId());
+            } catch (Exception e) {
+                // 宸ュ崟鍙兘宸插畬鎴愭垨宸插彇娑堬紝璁板綍鏃ュ織浣嗕笉闃绘 MPS 鍙栨秷
+                log.warn("[cancelMps] 鍙栨秷鐢熶骇宸ュ崟澶辫触锛寃orkOrderId={}锛屽師鍥狅細{}", mps.getWorkOrderId(), e.getMessage());
+            }
+        }
+
+        // 鏇存柊 MPS 鐘舵��
+        mpsMapper.updateById(new MesProMpsDO()
+                .setId(id)
+                .setStatus(MesProMpsStatusEnum.CANCELED.getStatus()));
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void finishMps(Long id) {
+        // 鏍¢獙瀛樺湪
+        MesProMpsDO mps = validateMpsExists(id);
+
+        // 鏍¢獙鐘舵�侊細鍙湁宸蹭笅鍙戠姸鎬佹墠鑳藉畬鎴�
+        if (!MesProMpsStatusEnum.ISSUED.getStatus().equals(mps.getStatus())) {
+            throw exception(PRO_MPS_NOT_ISSUED);
+        }
+
+        // 鏇存柊鐘舵��
+        mpsMapper.updateById(new MesProMpsDO()
+                .setId(id)
+                .setStatus(MesProMpsStatusEnum.FINISHED.getStatus())
+                .setFinishDate(LocalDateTime.now()));
+    }
+
+    @Override
+    public MesProMpsDO getMpsBySaleOrderItemId(Long saleOrderItemId) {
+        return mpsMapper.selectBySaleOrderItemId(saleOrderItemId);
+    }
+
+    @Override
+    public MesProMpsDO getMps(Long id) {
+        return mpsMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<MesProMpsDO> getMpsPage(MesProMpsPageReqVO pageReqVO) {
+        // 鑾峰彇鐢ㄦ埛鏈夋潈闄愮殑瀹㈡埛 ID 鍒楄〃
+        List<Long> permittedClientIds = customerApi.getPermittedCustomerIds();
+        return mpsMapper.selectPage(pageReqVO, permittedClientIds);
+    }
+
+    @Override
+    public List<MesProMpsDO> getMpsList(Collection<Long> ids) {
+        if (CollUtil.isEmpty(ids)) {
+            return Collections.emptyList();
+        }
+        return mpsMapper.selectBatchIds(ids);
+    }
+
+    @Override
+    public List<MesProMpsDO> getMpsListBySaleOrderItemIds(Collection<Long> saleOrderItemIds) {
+        return mpsMapper.selectListBySaleOrderItemIds(saleOrderItemIds);
+    }
+
+    @Override
+    public List<MesProMpsDO> getMergeableMpsList(Long productId) {
+        return mpsMapper.selectMergeableList(productId);
+    }
+
+    @Override
+    public void updateProducedQuantity(Long id, BigDecimal incrQuantity) {
+        mpsMapper.updateProducedQuantity(id, incrQuantity);
+    }
+
+    // ========== 绉佹湁鏂规硶 ==========
+
+    /**
+     * 鐢熸垚 MPS 缂栫爜
+     */
+    private String generateMpsCode() {
+        try {
+            return autoCodeRecordService.generateAutoCode(MPS_CODE_RULE);
+        } catch (Exception e) {
+            // 濡傛灉缂栫爜瑙勫垯涓嶅瓨鍦紝浣跨敤鏃堕棿鎴崇敓鎴�
+            log.warn("[generateMpsCode] 缂栫爜瑙勫垯 {} 涓嶅瓨鍦紝浣跨敤鏃堕棿鎴崇敓鎴�", MPS_CODE_RULE);
+            return "MPS" + System.currentTimeMillis();
+        }
+    }
+
+    /**
+     * 鐢熸垚鍚堝苟鎵规鍙�
+     */
+    private String generateMergeBatchNo() {
+        return "MERGE" + System.currentTimeMillis();
+    }
+
+    /**
+     * 鏍¢獙 MPS 瀛樺湪
+     */
+    private MesProMpsDO validateMpsExists(Long id) {
+        MesProMpsDO mps = mpsMapper.selectById(id);
+        if (mps == null) {
+            throw exception(PRO_MPS_NOT_EXISTS);
+        }
+        return mps;
+    }
+
+    /**
+     * 鏍¢獙 MPS 瀛樺湪 + 鑽夌鐘舵��
+     */
+    private MesProMpsDO validateMpsExistsAndDraft(Long id) {
+        MesProMpsDO mps = validateMpsExists(id);
+        if (!MesProMpsStatusEnum.DRAFT.getStatus().equals(mps.getStatus())) {
+            throw exception(PRO_MPS_NOT_DRAFT);
+        }
+        return mps;
+    }
+
+    /**
+     * 鏍¢獙 MPS 缂栫爜鍞竴
+     */
+    private void validateMpsCodeUnique(Long id, String code) {
+        if (StrUtil.isBlank(code)) {
+            return;
+        }
+        MesProMpsDO mps = mpsMapper.selectByCode(code);
+        if (mps == null) {
+            return;
+        }
+        if (id == null) {
+            throw exception(PRO_MPS_CODE_DUPLICATE);
+        }
+        if (!id.equals(mps.getId())) {
+            throw exception(PRO_MPS_CODE_DUPLICATE);
+        }
+    }
+
+    /**
+     * 鏍规嵁 MPS 鍒涘缓鐢熶骇宸ュ崟
+     */
+    private Long createWorkOrderFromMps(MesProMpsDO mps, BigDecimal quantity) {
+        MesProWorkOrderSaveReqVO workOrderReq = new MesProWorkOrderSaveReqVO();
+        workOrderReq.setCode(generateWorkOrderCode());
+        workOrderReq.setName("鐢熶骇宸ュ崟-" + mps.getCode());
+        workOrderReq.setType(1); // 鑷鐢熶骇
+        workOrderReq.setOrderSourceType(MesProWorkOrderSourceTypeEnum.ORDER.getType());
+        workOrderReq.setOrderSourceCode(mps.getSaleOrderNo());
+        workOrderReq.setProductId(mps.getProductId());
+        workOrderReq.setQuantity(quantity);
+        workOrderReq.setClientId(mps.getClientId());
+        workOrderReq.setRequestDate(mps.getRequestDate() != null ? mps.getRequestDate() : LocalDateTime.now());
+        workOrderReq.setRemark("鏉ヨ嚜 MPS: " + mps.getCode());
+
+        Long workOrderId = workOrderService.createWorkOrder(workOrderReq);
+
+        // 宸ュ崟鐩存帴纭涓哄凡纭鐘舵�侊紙璺宠繃鑽夌锛�
+        workOrderService.confirmWorkOrder(workOrderId);
+
+        return workOrderId;
+    }
+
+    /**
+     * 鐢熸垚鐢熶骇宸ュ崟缂栫爜
+     */
+    private String generateWorkOrderCode() {
+        try {
+            return autoCodeRecordService.generateAutoCode("WO");
+        } catch (Exception e) {
+            log.warn("[generateWorkOrderCode] 缂栫爜瑙勫垯 WO 涓嶅瓨鍦紝浣跨敤鏃堕棿鎴崇敓鎴�");
+            return "WO" + System.currentTimeMillis();
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderServiceImpl.java
index 99332dd..2a695c9 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderServiceImpl.java
@@ -15,6 +15,7 @@
 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
 import cn.iocoder.yudao.module.mes.service.pro.task.MesProTaskService;
 import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService;
+import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
 import jakarta.annotation.Resource;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -51,6 +52,8 @@
     private MesWmBarcodeService barcodeService;
     @Resource
     private MesProTaskService taskService;
+    @Resource
+    private CrmCustomerApi customerApi;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -140,7 +143,9 @@
 
     @Override
     public PageResult<MesProWorkOrderDO> getWorkOrderPage(MesProWorkOrderPageReqVO pageReqVO) {
-        return workOrderMapper.selectPage(pageReqVO);
+        // 鑾峰彇鐢ㄦ埛鏈夋潈闄愮殑瀹㈡埛 ID 鍒楄〃
+        List<Long> permittedClientIds = customerApi.getPermittedCustomerIds();
+        return workOrderMapper.selectPage(pageReqVO, permittedClientIds);
     }
 
     @Override
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImpl.java
index 6c5f535..e6d21c5 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImpl.java
@@ -17,7 +17,6 @@
 import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum;
 import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum;
 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
-import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService;
 import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService;
 import cn.iocoder.yudao.module.mes.service.qc.indicatorresult.MesQcIndicatorResultService;
 import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService;
@@ -64,7 +63,7 @@
     @Resource
     private MesWmOutsourceReceiptService outsourceReceiptService;
     @Resource
-    private MesMdVendorService vendorService;
+    private ErpSupplierApi supplierApi;
     @Resource
     private MesMdItemService itemService;
     @Resource
@@ -76,10 +75,6 @@
 
     @Resource
     private MdmItemApi mdmItemApi;
-
-    @Resource
-    @Lazy
-    private ErpSupplierApi supplierApi;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -126,14 +121,9 @@
     private void validateIqcSaveData(MesQcIqcSaveReqVO reqVO) {
         // 鏍¢獙缂栧彿鍞竴
         validateIqcCodeUnique(reqVO.getId(), reqVO.getCode());
-        // 鏍¢獙渚涘簲鍟嗗瓨鍦紙浼樺厛鏍¢獙 ERP 渚涘簲鍟嗭紝澶辫触鍒欐牎楠� MDM 渚涘簲鍟嗭級
+        // 鏍¢獙渚涘簲鍟嗗瓨鍦�
         if (reqVO.getVendorId() != null) {
-            try {
-                supplierApi.validateSupplier(reqVO.getVendorId());
-            } catch (Exception e) {
-                // ERP 渚涘簲鍟嗘牎楠屽け璐ワ紝灏濊瘯 MDM 渚涘簲鍟�
-                vendorService.validateVendorExists(reqVO.getVendorId());
-            }
+            supplierApi.validateSupplier(reqVO.getVendorId());
         }
         // 鏍¢獙鐗╂枡瀛樺湪锛堜娇鐢� MDM 鐗╂枡锛�
         if (reqVO.getItemId() != null) {
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcService.java
index cb36324..efce393 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcService.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcService.java
@@ -5,6 +5,7 @@
 import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.MesQcOqcSaveReqVO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO;
 import jakarta.validation.Valid;
 
 import java.util.List;
@@ -77,4 +78,15 @@
      */
     void recalculateDefectStats(Long oqcId, List<MesQcDefectRecordDO> records);
 
+    /**
+     * 鏍规嵁閿�鍞嚭搴撳崟鏄庣粏鑷姩鍒涘缓 OQC 妫�楠屽崟
+     *
+     * @param salesId       閿�鍞嚭搴撳崟 ID
+     * @param line          閿�鍞嚭搴撳崟鏄庣粏
+     * @param salesCode     閿�鍞嚭搴撳崟缂栫爜
+     * @param clientId      瀹㈡埛 ID
+     * @return OQC 妫�楠屽崟 ID
+     */
+    Long createOqcFromProductSales(Long salesId, MesWmProductSalesLineDO line, String salesCode, Long clientId);
+
 }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImpl.java
index ba304b9..b392411 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImpl.java
@@ -13,7 +13,6 @@
 import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum;
 import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum;
 import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants;
-import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService;
 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
 import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService;
 import cn.iocoder.yudao.module.mes.service.qc.indicatorresult.MesQcIndicatorResultService;
@@ -22,6 +21,8 @@
 import cn.iocoder.yudao.module.mes.service.wm.productsales.MesWmProductSalesService;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO;
+import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
+import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
 import jakarta.annotation.Resource;
 import org.springframework.context.annotation.Lazy;
@@ -58,9 +59,6 @@
     private MesQcDefectRecordService defectRecordService;
     @Resource
     @Lazy
-    private MesMdClientService clientService;
-    @Resource
-    @Lazy
     private MesMdItemService itemService;
     @Resource
     @Lazy
@@ -74,6 +72,10 @@
 
     @Resource
     private AdminUserApi adminUserApi;
+    @Resource
+    private MdmItemApi mdmItemApi;
+    @Resource
+    private CrmCustomerApi customerApi;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -118,8 +120,8 @@
     private void validateOqcSaveData(MesQcOqcSaveReqVO reqVO) {
         // 鏍¢獙缂栧彿鍞竴
         validateOqcCodeUnique(reqVO.getId(), reqVO.getCode());
-        // 鏍¢獙瀹㈡埛銆佺墿鏂欍�佹娴嬩汉鍛樺瓨鍦�
-        clientService.validateClientExists(reqVO.getClientId());
+        // 鏍¢獙鐗╂枡銆佹娴嬩汉鍛樺瓨鍦�
+        // 娉細瀹㈡埛 ID 鏉ヨ嚜 CRM锛屼笉闇�瑕佸湪 MES 涓牎楠�
         itemService.validateItemExists(reqVO.getItemId());
         adminUserApi.validateUser(reqVO.getInspectorUserId());
     }
@@ -246,7 +248,9 @@
 
     @Override
     public PageResult<MesQcOqcDO> getOqcPage(MesQcOqcPageReqVO pageReqVO) {
-        return oqcMapper.selectPage(pageReqVO);
+        // 鑾峰彇鐢ㄦ埛鏈夋潈闄愮殑瀹㈡埛 ID 鍒楄〃
+        List<Long> permittedClientIds = customerApi.getPermittedCustomerIds();
+        return oqcMapper.selectPage(pageReqVO, permittedClientIds);
     }
 
     @Override
@@ -289,4 +293,66 @@
         oqcMapper.updateById(updateOqc);
     }
 
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Long createOqcFromProductSales(Long salesId, MesWmProductSalesLineDO line, String salesCode, Long clientId) {
+        // 1. 鏍¢獙鐗╂枡鏄惁閰嶇疆浜� OQC 妫�楠屾ā鏉�
+        MesQcTemplateItemDO templateItem;
+        try {
+            templateItem = templateItemService.getRequiredTemplateByItemIdAndType(
+                    line.getItemId(), MesQcTypeEnum.OQC.getType());
+        } catch (Exception e) {
+            // 鑾峰彇鐗╂枡淇℃伅锛屾彁渚涙洿鏄庣‘鐨勯敊璇彁绀�
+            String itemInfo = getItemInfo(line.getItemId());
+            throw exception(QC_NO_TEMPLATE_FOR_ITEM, itemInfo);
+        }
+        Long templateId = templateItem.getTemplateId();
+
+        // 2. 鐢熸垚妫�楠屽崟缂栫爜
+        String code = "OQC" + System.currentTimeMillis();
+
+        // 3. 鍒涘缓 OQC 涓昏〃锛堝緟妫�楠岀姸鎬侊紝鍒濆鏁伴噺涓� 0锛�
+        MesQcOqcDO oqc = new MesQcOqcDO();
+        oqc.setCode(code);
+        oqc.setName(salesCode + "-鍑鸿揣妫�楠�");
+        oqc.setTemplateId(templateId);
+        oqc.setSourceDocType(MesBizTypeConstants.WM_PRODUCT_SALES);
+        oqc.setSourceDocId(salesId);
+        oqc.setSourceLineId(line.getId());
+        oqc.setSourceDocCode(salesCode);
+        oqc.setClientId(clientId);
+        oqc.setItemId(line.getItemId());
+        oqc.setBatchCode(line.getBatchCode());
+        oqc.setOutQuantity(line.getQuantity());
+        oqc.setCheckQuantity(BigDecimal.ZERO); // 寰呭~鍐�
+        oqc.setQualifiedQuantity(BigDecimal.ZERO); // 寰呭~鍐�
+        oqc.setUnqualifiedQuantity(BigDecimal.ZERO); // 寰呭~鍐�
+        oqc.setOutDate(java.time.LocalDateTime.now());
+        oqc.setStatus(MesQcStatusEnum.DRAFT.getStatus());
+        oqcMapper.insert(oqc);
+
+        // 4. 浠庢ā鏉挎寚鏍囪嚜鍔ㄧ敓鎴愭楠岃
+        oqcLineService.createLinesFromTemplate(oqc.getId(), templateId);
+
+        return oqc.getId();
+    }
+
+    /**
+     * 鑾峰彇鐗╂枡淇℃伅锛堢紪鐮�+鍚嶇О锛�
+     */
+    private String getItemInfo(Long itemId) {
+        if (itemId == null) {
+            return "鏈煡鐗╂枡";
+        }
+        try {
+            cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO item = mdmItemApi.getItem(itemId).getCheckedData();
+            if (item != null) {
+                return item.getCode() + "-" + item.getName();
+            }
+        } catch (Exception e) {
+            // 蹇界暐寮傚父
+        }
+        return "鐗╂枡ID:" + itemId;
+    }
+
 }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchServiceImpl.java
index 151f178..bed3c88 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchServiceImpl.java
@@ -14,6 +14,7 @@
 import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService;
 import cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService;
 import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService;
+import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
 import cn.iocoder.yudao.module.mdm.api.item.MdmItemBatchConfigApi;
 import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemBatchConfigRespDTO;
 import jakarta.annotation.Resource;
@@ -56,10 +57,14 @@
     private MesMdAutoCodeRecordService autoCodeRecordService;
     @Resource
     private MesWmBarcodeService barcodeService;
+    @Resource
+    private CrmCustomerApi customerApi;
 
     @Override
     public PageResult<MesWmBatchDO> getBatchPage(MesWmBatchPageReqVO pageReqVO) {
-        return batchMapper.selectPage(pageReqVO);
+        // 鑾峰彇鐢ㄦ埛鏈夋潈闄愮殑瀹㈡埛 ID 鍒楄〃
+        List<Long> permittedClientIds = customerApi.getPermittedCustomerIds();
+        return batchMapper.selectPage(pageReqVO, permittedClientIds);
     }
 
     @Override
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueServiceImpl.java
index 68154fe..c88f3a2 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueServiceImpl.java
@@ -21,7 +21,7 @@
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmOutsourceIssueStatusEnum;
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum;
 import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService;
-import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService;
+import cn.iocoder.yudao.module.erp.api.purchase.ErpSupplierApi;
 import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService;
 import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService;
 import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO;
@@ -56,7 +56,7 @@
     @Resource
     private MesWmOutsourceIssueDetailService outsourceIssueDetailService;
     @Resource
-    private MesMdVendorService vendorService;
+    private ErpSupplierApi supplierApi;
     @Resource
     private MesProWorkOrderService workOrderService;
     @Resource
@@ -259,7 +259,7 @@
         validateCodeUnique(saveReqVO.getId(), saveReqVO.getCode());
         // 鏍¢獙渚涘簲鍟嗗瓨鍦�
         if (saveReqVO.getVendorId() != null) {
-            vendorService.validateVendorExistsAndEnable(saveReqVO.getVendorId());
+            supplierApi.validateSupplier(saveReqVO.getVendorId());
         }
         // 鏍¢獙宸ュ崟瀛樺湪涓旂被鍨嬩负澶栧崗锛堜唬宸ワ級
         MesProWorkOrderDO workOrder = workOrderService.validateWorkOrderConfirmed(saveReqVO.getWorkOrderId());
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptServiceImpl.java
index 4ab00b6..dafe1d3 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptServiceImpl.java
@@ -21,7 +21,7 @@
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum;
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum;
 import cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService;
-import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService;
+import cn.iocoder.yudao.module.erp.api.purchase.ErpSupplierApi;
 import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService;
 import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService;
 import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO;
@@ -56,7 +56,7 @@
     @Resource
     private MesWmTransactionService wmTransactionService;
     @Resource
-    private MesMdVendorService vendorService;
+    private ErpSupplierApi supplierApi;
     @Resource
     private MesMdmItemService mdmItemService;
     @Resource
@@ -309,7 +309,7 @@
         // 鏍¢獙缂栫爜鍞竴
         validateCodeUnique(id, reqVO.getCode());
         // 鏍¢獙渚涘簲鍟嗗瓨鍦�
-        vendorService.validateVendorExistsAndEnable(reqVO.getVendorId());
+        supplierApi.validateSupplier(reqVO.getVendorId());
         // 鏍¢獙澶栧崗宸ュ崟瀛樺湪
         if (reqVO.getWorkOrderId() != null) {
             workOrderService.validateWorkOrderConfirmed(reqVO.getWorkOrderId());
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageServiceImpl.java
index b5b9b22..001b411 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageServiceImpl.java
@@ -4,6 +4,7 @@
 import cn.hutool.core.util.ObjUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.MesWmPackagePageReqVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.MesWmPackageSaveReqVO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.packages.MesWmPackageDO;
@@ -39,6 +40,8 @@
     private MesWmPackageLineService packageLineService;
     @Resource
     private MesWmBarcodeService barcodeService;
+    @Resource
+    private CrmCustomerApi customerApi;
 
     @Override
     public Long createPackage(MesWmPackageSaveReqVO createReqVO) {
@@ -93,7 +96,8 @@
 
     @Override
     public PageResult<MesWmPackageDO> getPackagePage(MesWmPackagePageReqVO pageReqVO) {
-        return packageMapper.selectPage(pageReqVO);
+        List<Long> permittedClientIds = customerApi.getPermittedCustomerIds();
+        return packageMapper.selectPage(pageReqVO, permittedClientIds);
     }
 
     @Override
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineServiceImpl.java
index 2ba2348..590df99 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineServiceImpl.java
@@ -17,6 +17,7 @@
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice.MesWmSalesNoticeLineDO;
 import cn.iocoder.yudao.module.mes.service.wm.salesnotice.MesWmSalesNoticeLineService;
+import cn.iocoder.yudao.module.mes.service.qc.oqc.MesQcOqcService;
 import jakarta.annotation.Resource;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.context.annotation.Lazy;
@@ -56,6 +57,9 @@
     @Resource
     @Lazy
     private MesWmSalesNoticeLineService salesNoticeLineService;
+    @Resource
+    @Lazy
+    private MesQcOqcService oqcService;
 
     @Override
     public Long createProductSalesLine(MesWmProductSalesLineSaveReqVO createReqVO) {
@@ -79,6 +83,34 @@
         // 鏇存柊
         MesWmProductSalesLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmProductSalesLineDO.class);
         productSalesLineMapper.updateById(updateObj);
+
+        // 妫�鏌ユ槸鍚﹂渶瑕佸垱寤� OQC 妫�楠屽崟锛氫粠涓嶉渶瑕佹楠屽彉涓洪渶瑕佹楠�
+        if (Boolean.TRUE.equals(updateReqVO.getOqcCheckFlag())
+                && !Boolean.TRUE.equals(oldLine.getOqcCheckFlag())) {
+            // 鑾峰彇鍑哄簱鍗曚俊鎭�
+            MesWmProductSalesDO sales = productSalesService.getProductSales(updateReqVO.getSalesId());
+            if (sales == null) {
+                log.warn("[updateProductSalesLine] 鍑哄簱鍗曚笉瀛樺湪锛宻alesId={}", updateReqVO.getSalesId());
+                return;
+            }
+
+            // 鏋勫缓鍑哄簱鏄庣粏 DO
+            MesWmProductSalesLineDO line = new MesWmProductSalesLineDO();
+            line.setId(updateReqVO.getId());
+            line.setItemId(updateReqVO.getItemId());
+            line.setBatchCode(updateReqVO.getBatchCode());
+            line.setQuantity(updateReqVO.getQuantity());
+
+            // 鍒涘缓 OQC 妫�楠屽崟锛岃寮傚父鎶涘嚭
+            Long oqcId = oqcService.createOqcFromProductSales(
+                    sales.getId(), line, sales.getCode(), sales.getClientId());
+
+            // 鏇存柊鍑哄簱鏄庣粏鐨� oqcId 鍜岃川閲忕姸鎬�
+            productSalesLineMapper.updateById(new MesWmProductSalesLineDO()
+                    .setId(updateReqVO.getId())
+                    .setOqcId(oqcId)
+                    .setQualityStatus(MesWmQualityStatusEnum.PENDING.getStatus()));
+        }
     }
 
     @Override
@@ -175,7 +207,8 @@
             }
             MesWmSalesNoticeLineDO noticeLine = salesNoticeLineService.validateSalesNoticeLineExists(
                     noticeLineId, sales.getNoticeId());
-            // 鏍¢獙鍏抽敭瀛楁涓�鑷存�э細鐗╂枡銆佹暟閲忋�佹壒娆″彿銆丱QC 妫�楠屾爣璇�
+            // 鏍¢獙鍏抽敭瀛楁涓�鑷存�э細鐗╂枡銆佹暟閲忋�佹壒娆″彿
+            // 娉細OQC 妫�楠屾爣璇嗗厑璁稿湪鍑哄簱鏃剁嫭绔嬭缃紝涓嶅己鍒朵笌閫氱煡鍗曚竴鑷�
             if (ObjUtil.notEqual(reqVO.getItemId(), noticeLine.getItemId())) {
                 throw exception(WM_PRODUCT_SALES_LINE_NOTICE_LINE_ITEM_MISMATCH);
             }
@@ -186,10 +219,6 @@
             if (StrUtil.isNotBlank(noticeLine.getBatchCode())
                     && ObjUtil.notEqual(reqVO.getBatchCode(), noticeLine.getBatchCode())) {
                 throw exception(WM_PRODUCT_SALES_LINE_NOTICE_LINE_BATCH_MISMATCH);
-            }
-            if (noticeLine.getOqcCheckFlag() != null
-                    && ObjUtil.notEqual(reqVO.getOqcCheckFlag(), noticeLine.getOqcCheckFlag())) {
-                throw exception(WM_PRODUCT_SALES_LINE_NOTICE_LINE_OQC_MISMATCH);
             }
             return;
         }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java
index 352debd..fff9c10 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java
@@ -14,21 +14,25 @@
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDetailDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO;
 import cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales.MesWmProductSalesMapper;
+import cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales.MesWmProductSalesLineMapper;
 import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants;
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmProductSalesStatusEnum;
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum;
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmSalesNoticeStatusEnum;
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmStockReserveBizTypeEnum;
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum;
-import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService;
+import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
 import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService;
 import cn.iocoder.yudao.module.mes.service.wm.salesnotice.MesWmSalesNoticeService;
 import cn.iocoder.yudao.module.mes.service.wm.stockreserve.MesWmStockReserveService;
 import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService;
 import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO;
+import cn.iocoder.yudao.module.mes.service.qc.oqc.MesQcOqcService;
 import cn.iocoder.yudao.module.erp.api.sale.ErpSaleOrderApi;
 import cn.iocoder.yudao.module.erp.api.sale.enums.ErpSaleOrderOutStatusEnum;
 import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
@@ -47,17 +51,20 @@
  */
 @Service
 @Validated
+@Slf4j
 public class MesWmProductSalesServiceImpl implements MesWmProductSalesService {
 
     @Resource
     private MesWmProductSalesMapper productSalesMapper;
+    @Resource
+    private MesWmProductSalesLineMapper productSalesLineMapper;
 
     @Resource
     private MesWmProductSalesLineService productSalesLineService;
     @Resource
     private MesWmProductSalesDetailService productSalesDetailService;
     @Resource
-    private MesMdClientService clientService;
+    private CrmCustomerApi customerApi;
     @Resource
     private MesWmSalesNoticeService salesNoticeService;
     @Resource
@@ -66,6 +73,9 @@
     private MesWmMaterialStockService materialStockService;
     @Resource
     private MesWmStockReserveService stockReserveService;
+    @Resource
+    @Lazy
+    private MesQcOqcService oqcService;
 
     @Resource
     private ErpSaleOrderApi saleOrderApi;
@@ -114,7 +124,8 @@
 
     @Override
     public PageResult<MesWmProductSalesDO> getProductSalesPage(MesWmProductSalesPageReqVO pageReqVO) {
-        return productSalesMapper.selectPage(pageReqVO);
+        List<Long> permittedClientIds = customerApi.getPermittedCustomerIds();
+        return productSalesMapper.selectPage(pageReqVO, permittedClientIds);
     }
 
     @Override
@@ -134,10 +145,26 @@
             }
         }
 
+        // 鑾峰彇鍑哄簱鍗曚俊鎭�
+        MesWmProductSalesDO sales = productSalesMapper.selectById(id);
+
         // 妫�鏌ユ墍鏈夎鐨� oqcCheckFlag锛氬鏋滄湁闇�瑕� OQC 妫�楠岀殑琛岋紝杩涘叆寰呮娴嬬姸鎬�
         boolean needOqc = CollectionUtils.anyMatch(lines,
                 line -> Boolean.TRUE.equals(line.getOqcCheckFlag()));
         if (needOqc) {
+            // 涓洪渶瑕� OQC 妫�楠屼笖灏氭湭鍒涘缓妫�楠屽崟鐨勬槑缁嗗垱寤� OQC 妫�楠屽崟
+            List<MesWmProductSalesLineDO> oqcLines = CollectionUtils.filterList(lines,
+                    line -> Boolean.TRUE.equals(line.getOqcCheckFlag()) && line.getOqcId() == null);
+            for (MesWmProductSalesLineDO line : oqcLines) {
+                // 鐩存帴璋冪敤锛岃寮傚父鎶涘嚭锛屼繚璇佹暟鎹竴鑷存��
+                Long oqcId = oqcService.createOqcFromProductSales(
+                        sales.getId(), line, sales.getCode(), sales.getClientId());
+                // 鏇存柊鍑哄簱鏄庣粏鐨� oqcId
+                productSalesLineMapper.updateById(new MesWmProductSalesLineDO()
+                        .setId(line.getId())
+                        .setOqcId(oqcId));
+            }
+
             // 鎵归噺鍒濆鍖� OQC 琛岀殑璐ㄩ噺鐘舵�佷负"寰呮楠�"
             List<Long> oqcLineIds = convertList(
                     CollectionUtils.filterList(lines, line -> Boolean.TRUE.equals(line.getOqcCheckFlag())),
@@ -366,7 +393,7 @@
         // 鏍¢獙缂栫爜鍞竴
         validateCodeUnique(id, reqVO.getCode());
         // 鏍¢獙瀹㈡埛瀛樺湪
-        clientService.validateClientExistsAndEnable(reqVO.getClientId());
+        customerApi.validateCustomer(reqVO.getClientId());
         // 鏍¢獙鍙戣揣閫氱煡鍗�
         if (reqVO.getNoticeId() != null) {
             MesWmSalesNoticeDO notice = salesNoticeService.validateSalesNoticeExists(reqVO.getNoticeId());
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesServiceImpl.java
index 82abbb2..3435611 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesServiceImpl.java
@@ -18,7 +18,7 @@
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum;
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmReturnSalesStatusEnum;
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum;
-import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService;
+import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
 import cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService;
 import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService;
 import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO;
@@ -53,7 +53,7 @@
     @Resource
     private MesWmReturnSalesDetailService returnSalesDetailService;
     @Resource
-    private MesMdClientService clientService;
+    private CrmCustomerApi customerApi;
     @Resource
     private MesMdmItemService mdmItemService;
     @Resource
@@ -106,7 +106,8 @@
 
     @Override
     public PageResult<MesWmReturnSalesDO> getReturnSalesPage(MesWmReturnSalesPageReqVO pageReqVO) {
-        return returnSalesMapper.selectPage(pageReqVO);
+        List<Long> permittedClientIds = customerApi.getPermittedCustomerIds();
+        return returnSalesMapper.selectPage(pageReqVO, permittedClientIds);
     }
 
     @Override
@@ -272,7 +273,7 @@
      */
     private void validateSaveData(MesWmReturnSalesSaveReqVO reqVO) {
         validateCodeUnique(reqVO.getId(), reqVO.getCode());
-        clientService.validateClientExistsAndEnable(reqVO.getClientId());
+        customerApi.validateCustomer(reqVO.getClientId());
     }
 
 }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorServiceImpl.java
index f6a674a..34ca27b 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorServiceImpl.java
@@ -15,7 +15,7 @@
 import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants;
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmReturnVendorStatusEnum;
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum;
-import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService;
+import cn.iocoder.yudao.module.erp.api.purchase.ErpSupplierApi;
 import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService;
 import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO;
 import jakarta.annotation.Resource;
@@ -45,7 +45,7 @@
     @Resource
     private MesWmReturnVendorDetailService returnVendorDetailService;
     @Resource
-    private MesMdVendorService vendorService;
+    private ErpSupplierApi supplierApi;
     @Resource
     private MesWmTransactionService wmTransactionService;
 
@@ -217,7 +217,7 @@
             validateReturnVendorExistsAndPrepare(reqVO.getId());
         }
         // 鏍¢獙渚涘簲鍟嗗瓨鍦�
-        vendorService.validateVendorExistsAndEnable(reqVO.getVendorId());
+        supplierApi.validateSupplier(reqVO.getVendorId());
         // 鏍¢獙缂栫爜鍞竴
         validateCodeUnique(reqVO.getId(), reqVO.getCode());
     }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeServiceImpl.java
index d7124e9..a233210 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeServiceImpl.java
@@ -17,7 +17,7 @@
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmOutStatusEnum;
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmProductSalesStatusEnum;
 import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService;
-import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService;
+import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
 import cn.iocoder.yudao.module.erp.api.sale.ErpSaleOrderApi;
 import cn.iocoder.yudao.module.erp.api.sale.dto.ErpSaleOrderItemRespDTO;
 import cn.iocoder.yudao.module.erp.api.sale.dto.ErpSaleOrderRespDTO;
@@ -51,7 +51,7 @@
     @Resource
     private MesWmSalesNoticeLineService salesNoticeLineService;
     @Resource
-    private MesMdClientService clientService;
+    private CrmCustomerApi customerApi;
 
     @Resource
     private ErpSaleOrderApi saleOrderApi;
@@ -103,12 +103,22 @@
 
     @Override
     public MesWmSalesNoticeDO getSalesNotice(Long id) {
-        return salesNoticeMapper.selectById(id);
+        MesWmSalesNoticeDO notice = salesNoticeMapper.selectById(id);
+        // 鏍¢獙瀹㈡埛鏉冮檺
+        if (notice != null && notice.getClientId() != null) {
+            List<Long> permittedIds = customerApi.getPermittedCustomerIds();
+            if (permittedIds != null && !permittedIds.contains(notice.getClientId())) {
+                return null; // 鏃犳潈闄愬垯杩斿洖 null
+            }
+        }
+        return notice;
     }
 
     @Override
     public PageResult<MesWmSalesNoticeDO> getSalesNoticePage(MesWmSalesNoticePageReqVO pageReqVO) {
-        return salesNoticeMapper.selectPage(pageReqVO);
+        // 鑾峰彇鐢ㄦ埛鏈夋潈闄愮殑瀹㈡埛 ID 鍒楄〃
+        List<Long> permittedClientIds = customerApi.getPermittedCustomerIds();
+        return salesNoticeMapper.selectPage(pageReqVO, permittedClientIds);
     }
 
     @Override
@@ -166,7 +176,7 @@
         validateNoticeCodeUnique(saveReqVO.getId(), saveReqVO.getCode());
         // 鏍¢獙瀹㈡埛瀛樺湪
         if (saveReqVO.getClientId() != null) {
-            clientService.validateClientExistsAndEnable(saveReqVO.getClientId());
+            customerApi.validateCustomer(saveReqVO.getClientId());
         }
     }
 

--
Gitblit v1.9.3