From e10c196ff7348a4461e8facee10a208779244ece Mon Sep 17 00:00:00 2001
From: 吴羡 <16976746+Xian-TT3@user.noreply.gitee.com>
Date: 星期三, 30 九月 2026 15:33:30 +0800
Subject: [PATCH] 宁夏万通需求:出库单行支持主/辅单位录入;考勤节假日配置改为时间段;物料型号维护;设备批量删除;来料检验默认方案解析

---
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptLineDO.java                        |   25 
 yudao-module-mdm-api/src/main/java/cn/iocoder/yudao/module/mdm/api/item/MdmItemModelApi.java                                                |   73 ++
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesLineDO.java                      |   21 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/MesWmReturnVendorLineController.java            |   21 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/line/MesWmItemReceiptLineRespVO.java          |   22 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/line/MesWmMiscIssueLineRespVO.java              |   22 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueLineServiceImpl.java                |   28 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/MesWmOutsourceIssueLineController.java        |   21 
 yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/enums/ErrorCodeConstants.java                                                    |    6 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/line/MesWmOutsourceIssueLineRespVO.java    |   22 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/MesWmProductSalesLineController.java            |   22 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/unitconvert/MesWmItemUnitConvertService.java                          |   39 +
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/MesDvMachineryController.java                      |    9 
 yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmAttendanceHolidayService.java                              |    2 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueLineServiceImpl.java                          |   38 +
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/line/MesWmItemReceiptLineSaveReqVO.java       |   15 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImpl.java                                          |   49 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLineRespVO.java        |   22 
 yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/dataobject/attendance/HrmAttendanceHolidayDO.java                            |   12 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/line/MesWmProductIssueLineSaveReqVO.java     |   15 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java                                                    |   25 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/MesWmItemReceiptLineController.java              |   22 
 yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/service/item/MdmItemModelService.java                                            |  111 +++
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/line/MesWmOutsourceIssueLineSaveReqVO.java |   13 
 yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmAttendanceHolidayServiceImpl.java                          |   39 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/MesWmProductIssueLineController.java            |   19 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productissue/MesWmProductIssueLineDO.java                      |   21 
 yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/HrmAttendanceHolidayPageReqVO.java                |    2 
 yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/mysql/attendance/HrmAttendanceHolidayMapper.java                             |   31 
 yudao-module-mdm-api/src/main/java/cn/iocoder/yudao/module/mdm/api/item/dto/MdmItemModelRespDTO.java                                        |   33 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueLineDO.java                  |   21 
 yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/MdmItemModelController.java                                |  141 ++++
 yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/dal/mysql/item/MdmItemModelMapper.java                                           |   49 +
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorLineServiceImpl.java                    |   28 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/MesWmMiscIssueLineController.java                  |   22 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/line/MesWmMiscIssueLineSaveReqVO.java           |   13 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineServiceImpl.java                    |   29 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/unitconvert/MesWmItemUnitConvertServiceImpl.java                      |  127 +++
 yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/dal/dataobject/item/MdmItemModelDO.java                                          |   77 ++
 yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/service/item/MdmItemModelServiceImpl.java                                        |  173 +++++
 yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/dal/mysql/item/MdmItemMapper.java                                                |    3 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/line/MesWmReturnVendorLineSaveReqVO.java     |   15 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryServiceImpl.java                              |   55 +
 yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/vo/MdmItemModelSaveReqVO.java                              |   43 +
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLineSaveReqVO.java     |   15 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/line/MesWmReturnVendorLineRespVO.java        |   22 
 yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/HrmAttendanceHolidayRespVO.java                   |   10 
 yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/api/item/dto/MdmItemRespDTO.java                                                 |   12 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/line/MesWmProductIssueLineRespVO.java        |   22 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryService.java                                  |    7 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnvendor/MesWmReturnVendorLineDO.java                      |   21 
 yudao-module-hrm-api/src/main/java/cn/iocoder/yudao/module/hrm/enums/ErrorCodeConstants.java                                                |    3 
 yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/HrmAttendanceHolidaySaveReqVO.java                |   10 
 yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/api/item/MdmItemModelApiImpl.java                                                |   69 ++
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptLineServiceImpl.java                      |   35 
 yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/vo/MdmItemModelPageReqVO.java                              |   24 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscissue/MesWmMiscIssueLineDO.java                            |   21 
 docs/sql/gen_config_export_all.py                                                                                                           |   50 
 yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/vo/MdmItemModelRespVO.java                                 |   46 +
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueLineServiceImpl.java                    |   26 
 60 files changed, 1,826 insertions(+), 163 deletions(-)

diff --git a/docs/sql/gen_config_export_all.py b/docs/sql/gen_config_export_all.py
index 1069f9e..c384254 100644
--- a/docs/sql/gen_config_export_all.py
+++ b/docs/sql/gen_config_export_all.py
@@ -1,8 +1,8 @@
 # -*- coding: utf-8 -*-
-"""閲嶆柊鐢熸垚 docs/sql/config_export_all_20260928.sql锛堝叏閲忛噸鐢熸垚锛屾浛鎹� 0918 鐗堬級銆�
+"""閲嶆柊鐢熸垚 docs/sql/config_export_all_20260930.sql锛堝叏閲忛噸鐢熸垚锛屾浛鎹� 0929 鐗堬級銆�
 
-闃舵涓�锛氬綋鍓嶆簮搴� ruoyi-vue-pro 鍏ㄥ簱 416 寮犺〃 CREATE TABLE + 6 绫婚厤缃暟鎹紙mysqldump 瀛楅潰閲忥級銆�
-闃舵浜岋細娌跨敤 0918 鏂囦欢鐨勮法搴撹韩浠�/鑿滃崟/OAuth2 琛ュ娈碉紙閫愬瓧澶嶇敤锛夈��
+闃舵涓�锛氬綋鍓嶆簮搴� ruoyi-vue-pro 鍏ㄥ簱 CREATE TABLE + 6 绫婚厤缃暟鎹紙mysqldump 瀛楅潰閲忥級銆�
+闃舵浜岋細娌跨敤 0929 鏂囦欢鐨勮法搴撹韩浠�/鑿滃崟/OAuth2 琛ュ娈碉紙閫愬瓧澶嶇敤锛夈��
 """
 import re
 import subprocess
@@ -13,9 +13,9 @@
 USER = "root"
 PWD = "1234"
 
-BASE_DIR = r"D:\develop\XingRuan\MOM\mom-pro2-after\docs\sql"
-SRC_0918 = BASE_DIR + r"\config_export_all_20260918.sql"
-OUT = BASE_DIR + r"\config_export_all_20260928.sql"
+BASE_DIR = r"D:\develop\XingRuan\MOM-LXWT\mom-pro2-after\docs\sql"
+SRC_PREV = BASE_DIR + r"\config_export_all_20260929.sql"
+OUT = BASE_DIR + r"\config_export_all_20260930.sql"
 
 MYSQL = MYSQL_BIN + r"\mysql.exe"
 MYSQLDUMP = MYSQL_BIN + r"\mysqldump.exe"
@@ -181,36 +181,40 @@
 
 
 def load_stage2_block():
-    with open(SRC_0918, encoding="utf-8") as f:
+    with open(SRC_PREV, encoding="utf-8") as f:
         lines = f.read().splitlines()
     for i, line in enumerate(lines):
         if "闃舵浜岋細琛ュ韬唤" in line:
             start = i - 1  # 涓婃柟 =============== 妯嚎
             return "\n".join(lines[start:]).rstrip() + "\n"
-    raise RuntimeError("0918 鏂囦欢鏈壘鍒伴樁娈典簩娈佃惤")
+    raise RuntimeError("0929 鏂囦欢鏈壘鍒伴樁娈典簩娈佃惤")
 
 
 HEADER = """-- =======================================================================
--- 鏂囦欢锛歝onfig_export_all_20260928.sql
+-- 鏂囦欢锛歝onfig_export_all_20260930.sql
 -- 鐢ㄩ�旓細ruoyi-vue-pro銆屽叏搴撹〃缁撴瀯 + 6 绫婚厤缃暟鎹�嶅鍑猴紝渚涘悓缁撴瀯鍏ㄦ柊搴撳垵濮嬪寲
 --       闃舵涓�锛氬叏搴� {n_tables} 寮犺〃 CREATE TABLE + 6 绫婚厤缃暟鎹紙瀛楅潰閲忥紝鑷寘鍚紝涓嶄緷璧栨簮搴撳湪绾匡級
 --       闃舵浜岋細璺ㄥ簱琛ュ 鑿滃崟/瑙掕壊/鐢ㄦ埛/OAuth2 绛夎韩浠芥暟鎹紙鎵ц鏈熶粠婧愬簱鎷疯礉锛�
 -- 鏉ユ簮搴擄細ruoyi-vue-pro
--- 鍩虹嚎锛�2026-09-18 鐗堬紙419 寮犺〃锛夆啋 鏈涓�**鍏ㄩ噺閲嶇敓鎴�**锛堜笉鍐嶅熀浜庢棫鏂囦欢鎵撹ˉ涓侊級锛�
---       鐩存帴鎸夊綋鍓嶆簮搴撴渶鏂扮姸鎬侀噸瀵硷紝涓�娆℃�ц鐩� 0918 涔嬪悗鍏ㄩ儴缁撴瀯涓庨厤缃紓绉汇��
--- 鏈鍙樻洿锛堢浉瀵� 0918锛�2026-09-28锛夛細
---   鈶� 琛ㄧ粨鏋勶細419 鈫� {n_tables} 寮�
---      - 鍒犻櫎 6 寮犲巻鍙插浠借〃锛坆pm_bak_20260904_bytearray/category/deployment/model/procdef/procinfo锛屾簮搴撳凡鏃狅級
---      + 鏂板 3 寮犺〃锛坅fter_sale_problem銆乤fter_sale_visit銆乥pm_process_auto_approve_config锛屼粎缁撴瀯锛屾簮搴撴棤鏁版嵁锛�
---      + 10 寮犺〃 DDL 涓� 0918 涓嶅悓锛屼互褰撳墠婧愬簱涓哄噯锛坅fter_sale_ticket銆乵es_qc_indicator銆乵es_qc_indicator_result_detail銆�
---        mes_qc_ipqc銆乵es_qc_iqc銆乵es_qc_oqc銆乵es_qc_rqc銆乵es_qc_template銆乵es_qc_template_indicator銆乵es_wm_return_issue_line锛�
---   鈶� 閰嶇疆鏁版嵁浠ュ綋鍓嶆簮搴撲负鍑嗛噸瀵硷紙涓嬪垪涓� 0918 澹版槑鍊� 鈫� 鏈瀵煎嚭鍊硷級锛�
---      - system_dict_type 241鈫抺n_dicttype}銆乻ystem_dict_data 1157鈫抺n_dictdata}锛堝惈 hrm_holiday_type 鑺傚亣鏃ョ被鍨嬬瓑鏂板瀛楀吀锛�
---      - system_company_config 0鈫�1銆乥i_chart_config 36鈫�37銆乥i_warehouse_coordinate 1鈫�2銆乤i_api_key 1鈫�3銆乥pm_user_group 3鈫�4
---      - bpm_business_attach 11鈫�4銆乥pm_category 22鈫�15銆乥pm_form 4鈫�3銆乥pm_process_listener 1鈫�0锛堟簮搴撳凡鍒犻櫎鐨勮涓嶅啀瀵煎嚭锛�
+-- 鍩虹嚎锛�2026-09-29 鐗堬紙417 寮犺〃锛夆啋 鏈涓�**鍏ㄩ噺閲嶇敓鎴�**锛堜笉鍐嶅熀浜庢棫鏂囦欢鎵撹ˉ涓侊級锛�
+--       鐩存帴鎸夊綋鍓嶆簮搴撴渶鏂扮姸鎬侀噸瀵硷紝涓�娆℃�ц鐩� 0929 涔嬪悗鍏ㄩ儴缁撴瀯涓庨厤缃紓绉汇��
+-- 鏈鍙樻洿锛堢浉瀵� 0929锛�2026-09-30锛夛細
+--   鈶� 琛ㄦ暟閲忎笉鍙橈紙{n_tables} 寮狅級锛屾棤鏂板/鍒犻櫎琛ㄣ��
+--   鈶� 5 寮犲嚭搴撳崟鏄庣粏琛屽鍔� 3 鍒楋紙鍑哄簱鍗曡鏀寔銆屼富鍗曚綅 + 杈呭崟浣嶏紙缁撳悎鍨嬪彿鎹㈢畻锛夈�嶅綍鍏ワ級锛�
+--      mes_wm_misc_issue_line锛堟潅椤瑰嚭搴擄級銆乵es_wm_outsource_issue_line锛堝鍗忓彂鏂欙級銆�
+--      mes_wm_product_issue_line锛堢敓浜ч鏂欙級銆乵es_wm_product_sales_line锛堥攢鍞嚭搴擄級銆�
+--      mes_wm_return_vendor_line锛堥噰璐��璐э級锛�
+--      item_model_id锛堢墿鏂欏瀷鍙风紪鍙凤級銆乪nter_unit_measure_id锛堝綍鍏ュ崟浣嶇紪鍙凤級銆�
+--      enter_quantity锛堝綍鍏ユ暟閲忥紝鎸夊綍鍏ュ崟浣嶈锛夛紱
+--      quantity 淇濇寔涓恒�岀墿鏂欎富鍗曚綅鍙e緞鐨勫嚭搴撴暟閲忋�嶏紝搴撳瓨涓庡簱瀛樻祦姘村彛寰勪笉鍙樸��
+--   鈶� hrm_attendance_holiday 澧炲姞 2 鍒楋紙鑰冨嫟鑺傚亣鏃ラ厤缃敱銆屽崟鏃ャ�嶆敼涓恒�屾椂闂存銆嶅綍鍏ワ級锛�
+--      start_date锛堝紑濮嬫棩鏈燂級銆乪nd_date锛堢粨鏉熸棩鏈燂級锛涘師 date 鍒椾繚鐣欎笉鍔紝
+--      鍚庣淇濆瓨鏃朵粛鍐欏叆寮�濮嬫棩鏈燂紝浠呬綔瀛橀噺鍏煎锛屼笟鍔″垽鏂敼鐢� start_date/end_date銆�
+--   鈶� 閰嶇疆鏁版嵁浠ュ綋鍓嶆簮搴撲负鍑嗛噸瀵硷細
+--      - system_dict_type {n_dicttype}銆乻ystem_dict_data {n_dictdata}
 --      - 鍗忓悓娴佺▼瀹氫箟鎸夋簮搴撳綋鍓�**婵�娲�**闆嗗悎閲嶅锛坽n_procdef} 涓祦绋嬪畾涔� + 瀵瑰簲閮ㄧ讲/瀛楄妭璧勬簮 + 璁捐鎬佹ā鍨嬶級
---   鈶� 鑿滃崟/鏉冮檺鑺傜偣锛堣妭鍋囨棩閰嶇疆 6014/60141-60145銆佸悇妯″潡瀵煎叆鎸夐挳 1075311/1075417-1075420 绛夛級鐢遍樁娈典簩
---      璺ㄥ簱鍏ㄩ噺鎷疯礉鑷姩鎼哄甫锛屾棤闇�鏀瑰姩鏈枃浠舵暟鎹锛涘湪姝ょ櫥璁颁互璇存槑鏈増鏂囦欢纭疄瑕嗙洊杩欎簺鍙樻洿銆�
+--   鈶� 鑿滃崟/鏉冮檺鑺傜偣鐢遍樁娈典簩璺ㄥ簱鍏ㄩ噺鎷疯礉鑷姩鎼哄甫锛屾棤闇�鏀瑰姩鏈枃浠舵暟鎹銆�
+--      鏈鏈柊澧炶彍鍗�/鏉冮檺鐐癸紙鑺傚亣鏃ラ厤缃彍鍗曞強鍏舵寜閽潈闄愭鍓嶅凡鍏ュ簱锛岄殢闃舵浜岃嚜鍔ㄦ惡甯︼級銆�
 -- 楠岃瘉锛歿verify}
 -- 鑼冨洿锛氬叏搴� BASE TABLE 鍏� {n_tables} 寮狅紝鍏ㄩ儴杈撳嚭 CREATE TABLE锛�
 --       浠呬互涓嬮厤缃被琛ㄥ甫鏁版嵁(INSERT)锛屽叾浣欎笟鍔�/绯荤粺/杩愯鍘嗗彶琛ㄥ彧淇濈暀绌鸿〃缁撴瀯锛�
diff --git a/yudao-module-hrm-api/src/main/java/cn/iocoder/yudao/module/hrm/enums/ErrorCodeConstants.java b/yudao-module-hrm-api/src/main/java/cn/iocoder/yudao/module/hrm/enums/ErrorCodeConstants.java
index 19fb474..ec3dae4 100644
--- a/yudao-module-hrm-api/src/main/java/cn/iocoder/yudao/module/hrm/enums/ErrorCodeConstants.java
+++ b/yudao-module-hrm-api/src/main/java/cn/iocoder/yudao/module/hrm/enums/ErrorCodeConstants.java
@@ -85,7 +85,7 @@
     ErrorCode ATTENDANCE_RULE_NAME_EXISTS = new ErrorCode(1_030_004_006, "鑰冨嫟瑙勫垯鍚嶇О宸插瓨鍦�");
     ErrorCode ATTENDANCE_RULE_DEPT_EXISTS = new ErrorCode(1_030_004_007, "璇ラ儴闂ㄥ凡閰嶇疆鑰冨嫟瑙勫垯");
     ErrorCode ATTENDANCE_HOLIDAY_NOT_EXISTS = new ErrorCode(1_030_004_008, "鑺傚亣鏃ラ厤缃笉瀛樺湪锛圛D={}锛夛紝鍙兘宸茶浠栦汉鍒犻櫎銆傝鍒锋柊鍒楄〃鍚庨噸璇�");
-    ErrorCode ATTENDANCE_HOLIDAY_DATE_EXISTS = new ErrorCode(1_030_004_009, "鏃ユ湡銆恵}銆戝凡瀛樺湪鑺傚亣鏃ラ厤缃紝涓嶈兘閲嶅鏂板銆傝鏀逛负缂栬緫璇ユ棩鏈熺殑璁板綍锛堝彲鐩存帴淇敼绫诲瀷涓庡娉級锛屾垨鍏堝垹闄ゅ師璁板綍鍐嶆柊澧�");
+    ErrorCode ATTENDANCE_HOLIDAY_RANGE_OVERLAP = new ErrorCode(1_030_004_009, "鏃ユ湡鍖洪棿銆恵} ~ {}銆戜笌宸叉湁閰嶇疆銆寋}銆嶏紙{} ~ {}锛夐噸鍙狅紝鏃犳硶淇濆瓨銆傝璋冩暣鏈鏃ユ湡鍖洪棿閬垮紑璇ラ厤缃紝鎴栫洿鎺ョ紪杈�/鍒犻櫎宸叉湁閰嶇疆鍚庡啀淇濆瓨");
     ErrorCode ATTENDANCE_CLOCK_FAIL_NO_RULE = new ErrorCode(1_030_004_010, "鎵撳崱澶辫触锛屾湭鎵惧埌鑰冨嫟瑙勫垯");
     ErrorCode ATTENDANCE_CLOCK_FAIL_HOLIDAY = new ErrorCode(1_030_004_011, "鎵撳崱澶辫触锛屽綋鏃ヤ负浼戞伅鏃�");
     ErrorCode ATTENDANCE_CLOCK_FAIL_NOT_WORKDAY = new ErrorCode(1_030_004_012, "鎵撳崱澶辫触锛屽綋鏃ヤ笉鏄伐浣滄棩");
@@ -93,6 +93,7 @@
     ErrorCode ATTENDANCE_EXCEPTION_UPDATE_AUDIT_STATUS_FAIL = new ErrorCode(1_030_004_014, "鏇存柊鑰冨嫟寮傚父瀹℃壒鐘舵�佸け璐ワ紝鍘熷洜锛氫笉鏄鎵逛腑鐘舵��");
     ErrorCode ATTENDANCE_EXCEPTION_BPM_PROCESS_DEFINITION_NOT_EXISTS = new ErrorCode(1_030_004_015, "鑰冨嫟寮傚父瀹℃壒娴佺▼涓嶅瓨鍦�");
     ErrorCode ATTENDANCE_CLOCK_ALREADY_CLOCKED = new ErrorCode(1_030_004_016, "宸叉墦杩囧崱锛岃鍕块噸澶嶆墦鍗�");
+    ErrorCode ATTENDANCE_HOLIDAY_DATE_RANGE_INVALID = new ErrorCode(1_030_004_017, "缁撴潫鏃ユ湡銆恵}銆戜笉鑳芥棭浜庡紑濮嬫棩鏈熴�恵}銆戯紝鏃犳硶淇濆瓨銆傝閲嶆柊閫夋嫨姝g‘鐨勬棩鏈熷尯闂�");
 
     // ========== 钖叕绠$悊 1-030-005-000 ==========
     ErrorCode SALARY_STRUCTURE_NOT_EXISTS = new ErrorCode(1_030_005_000, "钖叕缁撴瀯涓嶅瓨鍦�");
diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/HrmAttendanceHolidayPageReqVO.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/HrmAttendanceHolidayPageReqVO.java
index 1afb65e..893bac3 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/HrmAttendanceHolidayPageReqVO.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/HrmAttendanceHolidayPageReqVO.java
@@ -23,7 +23,7 @@
     @Schema(description = "鏄惁娉曞畾鑺傚亣鏃ワ細0-鍚︼紝1-鏄�", example = "1")
     private Integer isLegal;
 
-    @Schema(description = "鏃ユ湡鍖洪棿锛屼紶 [寮�濮嬫棩鏈�, 缁撴潫鏃ユ湡]", example = "[\"2026-01-01\", \"2026-12-31\"]")
+    @Schema(description = "鏃ユ湡鍖洪棿锛屼紶 [寮�濮嬫棩鏈�, 缁撴潫鏃ユ湡]锛岃繑鍥炰笌閰嶇疆鏃堕棿娈垫湁浜ら泦鐨勬暟鎹�", example = "[\"2026-01-01\", \"2026-12-31\"]")
     private LocalDate[] date;
 
 }
\ No newline at end of file
diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/HrmAttendanceHolidayRespVO.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/HrmAttendanceHolidayRespVO.java
index 9a53176..133ab30 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/HrmAttendanceHolidayRespVO.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/HrmAttendanceHolidayRespVO.java
@@ -23,9 +23,13 @@
     @ExcelProperty("鑺傚亣鏃ュ悕绉�")
     private String name;
 
-    @Schema(description = "鏃ユ湡")
-    @ExcelProperty("鏃ユ湡")
-    private LocalDate date;
+    @Schema(description = "寮�濮嬫棩鏈�")
+    @ExcelProperty("寮�濮嬫棩鏈�")
+    private LocalDate startDate;
+
+    @Schema(description = "缁撴潫鏃ユ湡")
+    @ExcelProperty("缁撴潫鏃ユ湡")
+    private LocalDate endDate;
 
     @Schema(description = "绫诲瀷锛�1-浼戞伅鏃ワ紝2-宸ヤ綔鏃�")
     @ExcelProperty(value = "绫诲瀷", converter = DictConvert.class)
diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/HrmAttendanceHolidaySaveReqVO.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/HrmAttendanceHolidaySaveReqVO.java
index 8f2fcb6..f11563c 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/HrmAttendanceHolidaySaveReqVO.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/HrmAttendanceHolidaySaveReqVO.java
@@ -18,9 +18,13 @@
     @NotBlank(message = "鑺傚亣鏃ュ悕绉颁笉鑳戒负绌�")
     private String name;
 
-    @Schema(description = "鏃ユ湡", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-02-10")
-    @NotNull(message = "鏃ユ湡涓嶈兘涓虹┖")
-    private LocalDate date;
+    @Schema(description = "寮�濮嬫棩鏈�", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-02-10")
+    @NotNull(message = "寮�濮嬫棩鏈熶笉鑳戒负绌�")
+    private LocalDate startDate;
+
+    @Schema(description = "缁撴潫鏃ユ湡", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-02-17")
+    @NotNull(message = "缁撴潫鏃ユ湡涓嶈兘涓虹┖")
+    private LocalDate endDate;
 
     @Schema(description = "绫诲瀷锛�1-浼戞伅鏃ワ紝2-宸ヤ綔鏃�", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "绫诲瀷涓嶈兘涓虹┖")
diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/dataobject/attendance/HrmAttendanceHolidayDO.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/dataobject/attendance/HrmAttendanceHolidayDO.java
index 3b79774..4ea1136 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/dataobject/attendance/HrmAttendanceHolidayDO.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/dataobject/attendance/HrmAttendanceHolidayDO.java
@@ -35,11 +35,21 @@
     private String name;
 
     /**
-     * 鏃ユ湡
+     * 鏃ユ湡锛堝吋瀹瑰瓨閲� NOT NULL 鍒楃殑鍐椾綑瀛楁锛屽缁堝啓鍏� startDate锛�
      */
     private LocalDate date;
 
     /**
+     * 寮�濮嬫棩鏈�
+     */
+    private LocalDate startDate;
+
+    /**
+     * 缁撴潫鏃ユ湡
+     */
+    private LocalDate endDate;
+
+    /**
      * 绫诲瀷锛�1-浼戞伅鏃ワ紝2-宸ヤ綔鏃�
      *
      * 鏋氫妇 {@link cn.iocoder.yudao.module.hrm.enums.HrmAttendanceHolidayTypeEnum}
diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/mysql/attendance/HrmAttendanceHolidayMapper.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/mysql/attendance/HrmAttendanceHolidayMapper.java
index c675ee3..2ebdc80 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/mysql/attendance/HrmAttendanceHolidayMapper.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/mysql/attendance/HrmAttendanceHolidayMapper.java
@@ -19,23 +19,30 @@
 public interface HrmAttendanceHolidayMapper extends BaseMapperX<HrmAttendanceHolidayDO> {
 
     default PageResult<HrmAttendanceHolidayDO> selectPage(HrmAttendanceHolidayPageReqVO reqVO) {
-        return selectPage(reqVO, new LambdaQueryWrapperX<HrmAttendanceHolidayDO>()
+        LambdaQueryWrapperX<HrmAttendanceHolidayDO> query = new LambdaQueryWrapperX<HrmAttendanceHolidayDO>()
                 .likeIfPresent(HrmAttendanceHolidayDO::getName, reqVO.getName())
                 .eqIfPresent(HrmAttendanceHolidayDO::getType, reqVO.getType())
-                .eqIfPresent(HrmAttendanceHolidayDO::getIsLegal, reqVO.getIsLegal())
-                .betweenIfPresent(HrmAttendanceHolidayDO::getDate, reqVO.getDate())
-                .orderByDesc(HrmAttendanceHolidayDO::getDate));
+                .eqIfPresent(HrmAttendanceHolidayDO::getIsLegal, reqVO.getIsLegal());
+        // 鏃ユ湡绛涢�夛細閰嶇疆鏃堕棿娈典笌鏌ヨ鍖洪棿鏈変氦闆嗗嵆鍛戒腑
+        LocalDate[] dateRange = reqVO.getDate();
+        if (dateRange != null && dateRange.length >= 2 && dateRange[0] != null && dateRange[1] != null) {
+            query.le(HrmAttendanceHolidayDO::getStartDate, dateRange[1])
+                    .ge(HrmAttendanceHolidayDO::getEndDate, dateRange[0]);
+        }
+        return selectPage(reqVO, query.orderByDesc(HrmAttendanceHolidayDO::getStartDate)
+                .orderByDesc(HrmAttendanceHolidayDO::getId));
     }
 
-    default HrmAttendanceHolidayDO selectByDate(LocalDate date) {
-        return selectOne(HrmAttendanceHolidayDO::getDate, date);
-    }
-
-    default List<HrmAttendanceHolidayDO> selectListByDateBetween(LocalDate startDate, LocalDate endDate) {
+    /**
+     * 鏌ヨ鏃堕棿娈典笌 [startDate, endDate] 鏈変氦闆嗙殑閰嶇疆
+     * 浼犲叆鍚屼竴澶╋紙date, date锛夋椂锛屽嵆鏌ヨ瑕嗙洊璇ユ棩鐨勯厤缃�
+     */
+    default List<HrmAttendanceHolidayDO> selectListByDateRange(LocalDate startDate, LocalDate endDate) {
         return selectList(new LambdaQueryWrapperX<HrmAttendanceHolidayDO>()
-                .ge(HrmAttendanceHolidayDO::getDate, startDate)
-                .le(HrmAttendanceHolidayDO::getDate, endDate)
-                .orderByAsc(HrmAttendanceHolidayDO::getDate));
+                .le(HrmAttendanceHolidayDO::getStartDate, endDate)
+                .ge(HrmAttendanceHolidayDO::getEndDate, startDate)
+                .orderByAsc(HrmAttendanceHolidayDO::getStartDate)
+                .orderByAsc(HrmAttendanceHolidayDO::getId));
     }
 
 }
\ No newline at end of file
diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmAttendanceHolidayService.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmAttendanceHolidayService.java
index 7127029..a3af424 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmAttendanceHolidayService.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmAttendanceHolidayService.java
@@ -55,7 +55,7 @@
     PageResult<HrmAttendanceHolidayDO> getAttendanceHolidayPage(HrmAttendanceHolidayPageReqVO pageReqVO);
 
     /**
-     * 鑾峰緱鎸囧畾鏃ユ湡鑼冨洿鐨勮妭鍋囨棩鍒楄〃
+     * 鑾峰緱鏃堕棿娈典笌鎸囧畾鏃ユ湡鑼冨洿鏈変氦闆嗙殑鑺傚亣鏃ュ垪琛�
      *
      * @param startDate 寮�濮嬫棩鏈�
      * @param endDate 缁撴潫鏃ユ湡
diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmAttendanceHolidayServiceImpl.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmAttendanceHolidayServiceImpl.java
index 4f03275..d894d4c 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmAttendanceHolidayServiceImpl.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmAttendanceHolidayServiceImpl.java
@@ -32,9 +32,10 @@
 
     @Override
     public Long createAttendanceHoliday(HrmAttendanceHolidaySaveReqVO createReqVO) {
-        // 鏍¢獙鏃ユ湡鏄惁宸插瓨鍦ㄩ厤缃�
-        validateAttendanceHolidayDateExists(createReqVO.getDate());
+        validateDateRange(createReqVO);
+        validateDateRangeNoOverlap(createReqVO.getStartDate(), createReqVO.getEndDate(), null);
         HrmAttendanceHolidayDO attendanceHoliday = BeanUtils.toBean(createReqVO, HrmAttendanceHolidayDO.class);
+        attendanceHoliday.setDate(createReqVO.getStartDate());
         if (attendanceHoliday.getIsLegal() == null) {
             attendanceHoliday.setIsLegal(0);
         }
@@ -45,12 +46,10 @@
     @Override
     public void updateAttendanceHoliday(HrmAttendanceHolidaySaveReqVO updateReqVO) {
         validateAttendanceHolidayExists(updateReqVO.getId());
-        // 濡傛灉鏃ユ湡鍙樻洿锛屾牎楠屾柊鏃ユ湡鏄惁宸插瓨鍦ㄩ厤缃�
-        HrmAttendanceHolidayDO oldHoliday = attendanceHolidayMapper.selectById(updateReqVO.getId());
-        if (!oldHoliday.getDate().equals(updateReqVO.getDate())) {
-            validateAttendanceHolidayDateExists(updateReqVO.getDate());
-        }
+        validateDateRange(updateReqVO);
+        validateDateRangeNoOverlap(updateReqVO.getStartDate(), updateReqVO.getEndDate(), updateReqVO.getId());
         HrmAttendanceHolidayDO updateObj = BeanUtils.toBean(updateReqVO, HrmAttendanceHolidayDO.class);
+        updateObj.setDate(updateReqVO.getStartDate());
         attendanceHolidayMapper.updateById(updateObj);
     }
 
@@ -66,9 +65,19 @@
         }
     }
 
-    private void validateAttendanceHolidayDateExists(LocalDate date) {
-        if (attendanceHolidayMapper.selectByDate(date) != null) {
-            throw exception(ATTENDANCE_HOLIDAY_DATE_EXISTS, date);
+    private void validateDateRange(HrmAttendanceHolidaySaveReqVO reqVO) {
+        if (reqVO.getEndDate().isBefore(reqVO.getStartDate())) {
+            throw exception(ATTENDANCE_HOLIDAY_DATE_RANGE_INVALID, reqVO.getEndDate(), reqVO.getStartDate());
+        }
+    }
+
+    private void validateDateRangeNoOverlap(LocalDate startDate, LocalDate endDate, Long excludeId) {
+        for (HrmAttendanceHolidayDO exist : attendanceHolidayMapper.selectListByDateRange(startDate, endDate)) {
+            if (excludeId != null && excludeId.equals(exist.getId())) {
+                continue;
+            }
+            throw exception(ATTENDANCE_HOLIDAY_RANGE_OVERLAP, startDate, endDate,
+                    exist.getName(), exist.getStartDate(), exist.getEndDate());
         }
     }
 
@@ -84,16 +93,16 @@
 
     @Override
     public List<HrmAttendanceHolidayDO> getAttendanceHolidayListByDateRange(LocalDate startDate, LocalDate endDate) {
-        return attendanceHolidayMapper.selectListByDateBetween(startDate, endDate);
+        return attendanceHolidayMapper.selectListByDateRange(startDate, endDate);
     }
 
     @Override
     public boolean isWorkDay(LocalDate date) {
-        // 1. 鏌ヨ鑺傚亣鏃ラ厤缃�
-        HrmAttendanceHolidayDO holiday = attendanceHolidayMapper.selectByDate(date);
-        if (holiday != null) {
+        // 1. 鏌ヨ瑕嗙洊璇ユ棩鏈熺殑鑺傚亣鏃ラ厤缃紙閰嶇疆鏃堕棿娈典笉鍏佽閲嶅彔锛岃嚦澶氬懡涓竴鏉★級
+        List<HrmAttendanceHolidayDO> holidays = attendanceHolidayMapper.selectListByDateRange(date, date);
+        if (!holidays.isEmpty()) {
             // 鏈夐厤缃椂锛屾寜閰嶇疆鍒ゆ柇
-            return HrmAttendanceHolidayTypeEnum.WORK_DAY.getType().equals(holiday.getType());
+            return HrmAttendanceHolidayTypeEnum.WORK_DAY.getType().equals(holidays.get(0).getType());
         }
         // 2. 鏃犻厤缃椂锛屾寜鍛ㄦ湯鍒ゆ柇
         DayOfWeek dayOfWeek = date.getDayOfWeek();
diff --git a/yudao-module-mdm-api/src/main/java/cn/iocoder/yudao/module/mdm/api/item/MdmItemModelApi.java b/yudao-module-mdm-api/src/main/java/cn/iocoder/yudao/module/mdm/api/item/MdmItemModelApi.java
new file mode 100644
index 0000000..04e2bb7
--- /dev/null
+++ b/yudao-module-mdm-api/src/main/java/cn/iocoder/yudao/module/mdm/api/item/MdmItemModelApi.java
@@ -0,0 +1,73 @@
+package cn.iocoder.yudao.module.mdm.api.item;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemModelRespDTO;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
+
+/**
+ * MDM 鐗╂枡鍨嬪彿 API 鎺ュ彛
+ *
+ * @author 瓒呯骇绠$悊鍛�
+ */
+public interface MdmItemModelApi {
+
+    String PREFIX = "/rpc-api/mdm/item-model";
+
+    /**
+     * 鑾峰彇鐗╂枡鍨嬪彿
+     *
+     * @param id 鍨嬪彿缂栧彿
+     * @return 鐗╂枡鍨嬪彿
+     */
+    CommonResult<MdmItemModelRespDTO> getItemModel(Long id);
+
+    /**
+     * 鑾峰彇鐗╂枡鍨嬪彿鍒楄〃
+     *
+     * @param ids 鍨嬪彿缂栧彿鍒楄〃
+     * @return 鐗╂枡鍨嬪彿鍒楄〃
+     */
+    CommonResult<List<MdmItemModelRespDTO>> getItemModelList(Collection<Long> ids);
+
+    /**
+     * 鑾峰彇鐗╂枡鍨嬪彿 Map
+     *
+     * @param ids 鍨嬪彿缂栧彿鍒楄〃
+     * @return 鐗╂枡鍨嬪彿 Map
+     */
+    default Map<Long, MdmItemModelRespDTO> getItemModelMap(Collection<Long> ids) {
+        List<MdmItemModelRespDTO> list = getItemModelList(ids).getCheckedData();
+        return convertMap(list, MdmItemModelRespDTO::getId);
+    }
+
+    /**
+     * 鑾峰彇鎸囧畾鐗╂枡鐨勫瀷鍙峰垪琛�
+     *
+     * @param itemId 鐗╂枡缂栧彿
+     * @return 鐗╂枡鍨嬪彿鍒楄〃
+     */
+    CommonResult<List<MdmItemModelRespDTO>> getItemModelListByItemId(Long itemId);
+
+    /**
+     * 鏍¢獙鐗╂枡鍨嬪彿瀛樺湪
+     *
+     * @param id 鍨嬪彿缂栧彿
+     * @return 鐗╂枡鍨嬪彿
+     */
+    CommonResult<MdmItemModelRespDTO> validateItemModelExists(Long id);
+
+    /**
+     * 鏍¢獙鐗╂枡鍨嬪彿瀛樺湪銆佸惎鐢紝涓斿綊灞炰簬鎸囧畾鐗╂枡
+     *
+     * @param id     鍨嬪彿缂栧彿
+     * @param itemId 鐗╂枡缂栧彿
+     * @return 鐗╂枡鍨嬪彿
+     */
+    CommonResult<MdmItemModelRespDTO> validateItemModelExistsAndEnable(Long id, Long itemId);
+
+}
diff --git a/yudao-module-mdm-api/src/main/java/cn/iocoder/yudao/module/mdm/api/item/dto/MdmItemModelRespDTO.java b/yudao-module-mdm-api/src/main/java/cn/iocoder/yudao/module/mdm/api/item/dto/MdmItemModelRespDTO.java
new file mode 100644
index 0000000..76b4ee4
--- /dev/null
+++ b/yudao-module-mdm-api/src/main/java/cn/iocoder/yudao/module/mdm/api/item/dto/MdmItemModelRespDTO.java
@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.mdm.api.item.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Schema(description = "RPC 鏈嶅姟 - MDM 鐗╂枡鍨嬪彿 Response DTO")
+@Data
+public class MdmItemModelRespDTO {
+
+    @Schema(description = "鍨嬪彿缂栧彿", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    private Long id;
+
+    @Schema(description = "鐗╂枡缂栧彿", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    private Long itemId;
+
+    @Schema(description = "鍨嬪彿鍚嶇О", requiredMode = Schema.RequiredMode.REQUIRED, example = "4绫�/鏍�")
+    private String model;
+
+    @Schema(description = "鍨嬪彿璁¢噺鍗曚綅缂栧彿", requiredMode = Schema.RequiredMode.REQUIRED, example = "7")
+    private Long unitMeasureId;
+
+    @Schema(description = "鎹㈢畻姣旂巼锛�1 鍨嬪彿鍗曚綅 = N 鐗╂枡涓诲崟浣�", requiredMode = Schema.RequiredMode.REQUIRED, example = "4")
+    private BigDecimal unitMeasureRate;
+
+    @Schema(description = "鐘舵��", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
+    private Integer status;
+
+    @Schema(description = "澶囨敞", example = "澶囨敞淇℃伅")
+    private String remark;
+
+}
diff --git a/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/api/item/MdmItemModelApiImpl.java b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/api/item/MdmItemModelApiImpl.java
new file mode 100644
index 0000000..8dba692
--- /dev/null
+++ b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/api/item/MdmItemModelApiImpl.java
@@ -0,0 +1,69 @@
+package cn.iocoder.yudao.module.mdm.api.item;
+
+import cn.hutool.core.util.ObjUtil;
+import cn.iocoder.yudao.framework.common.exception.ServiceException;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemModelRespDTO;
+import cn.iocoder.yudao.module.mdm.dal.dataobject.item.MdmItemModelDO;
+import cn.iocoder.yudao.module.mdm.service.item.MdmItemModelService;
+import jakarta.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Collection;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.module.mdm.enums.ErrorCodeConstants.MDM_ITEM_MODEL_UNIT_MISMATCH;
+
+/**
+ * MDM 鐗╂枡鍨嬪彿 API 瀹炵幇绫�
+ *
+ * @author 瓒呯骇绠$悊鍛�
+ */
+@RestController
+@RequestMapping(MdmItemModelApi.PREFIX)
+@Validated
+public class MdmItemModelApiImpl implements MdmItemModelApi {
+
+    @Resource
+    private MdmItemModelService itemModelService;
+
+    @Override
+    public CommonResult<MdmItemModelRespDTO> getItemModel(Long id) {
+        MdmItemModelDO itemModel = itemModelService.getItemModel(id);
+        return success(BeanUtils.toBean(itemModel, MdmItemModelRespDTO.class));
+    }
+
+    @Override
+    public CommonResult<List<MdmItemModelRespDTO>> getItemModelList(Collection<Long> ids) {
+        List<MdmItemModelDO> list = itemModelService.getItemModelList(ids);
+        return success(BeanUtils.toBean(list, MdmItemModelRespDTO.class));
+    }
+
+    @Override
+    public CommonResult<List<MdmItemModelRespDTO>> getItemModelListByItemId(Long itemId) {
+        List<MdmItemModelDO> list = itemModelService.getItemModelListByItemId(itemId);
+        return success(BeanUtils.toBean(list, MdmItemModelRespDTO.class));
+    }
+
+    @Override
+    public CommonResult<MdmItemModelRespDTO> validateItemModelExists(Long id) {
+        MdmItemModelDO itemModel = itemModelService.validateItemModelExists(id);
+        return success(BeanUtils.toBean(itemModel, MdmItemModelRespDTO.class));
+    }
+
+    @Override
+    public CommonResult<MdmItemModelRespDTO> validateItemModelExistsAndEnable(Long id, Long itemId) {
+        MdmItemModelDO itemModel = itemModelService.validateItemModelExistsAndEnable(id);
+        if (ObjUtil.notEqual(itemModel.getItemId(), itemId)) {
+            throw new ServiceException(MDM_ITEM_MODEL_UNIT_MISMATCH.getCode(),
+                    String.format("鎵�閫夊瀷鍙穂%s](ID=%d)涓嶅睘浜庡綋鍓嶇墿鏂�(ID=%d)锛岃閲嶆柊閫夋嫨璇ョ墿鏂欑殑鍨嬪彿",
+                            itemModel.getModel(), itemModel.getId(), itemId));
+        }
+        return success(BeanUtils.toBean(itemModel, MdmItemModelRespDTO.class));
+    }
+
+}
diff --git a/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/api/item/dto/MdmItemRespDTO.java b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/api/item/dto/MdmItemRespDTO.java
index b3c1993..a5414ef 100644
--- a/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/api/item/dto/MdmItemRespDTO.java
+++ b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/api/item/dto/MdmItemRespDTO.java
@@ -30,6 +30,18 @@
     @Schema(description = "璁¢噺鍗曚綅缂栧彿", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Long unitMeasureId;
 
+    @Schema(description = "杈呭崟浣�1缂栧彿", example = "2")
+    private Long unitMeasureId2;
+
+    @Schema(description = "杈呭崟浣�1鎹㈢畻姣旂巼", example = "12")
+    private BigDecimal unitMeasureRate1;
+
+    @Schema(description = "杈呭崟浣�2缂栧彿", example = "3")
+    private Long unitMeasureId3;
+
+    @Schema(description = "杈呭崟浣�2鎹㈢畻姣旂巼", example = "100")
+    private BigDecimal unitMeasureRate2;
+
     @Schema(description = "鍝佺墝缂栧彿", example = "1")
     private Long brandId;
 
diff --git a/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/MdmItemModelController.java b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/MdmItemModelController.java
new file mode 100644
index 0000000..b1d039d
--- /dev/null
+++ b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/MdmItemModelController.java
@@ -0,0 +1,141 @@
+package cn.iocoder.yudao.module.mdm.controller.admin.item;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemModelPageReqVO;
+import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemModelRespVO;
+import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemModelSaveReqVO;
+import cn.iocoder.yudao.module.mdm.dal.dataobject.item.MdmItemDO;
+import cn.iocoder.yudao.module.mdm.dal.dataobject.item.MdmItemModelDO;
+import cn.iocoder.yudao.module.mdm.dal.dataobject.unit.MdmUnitMeasureDO;
+import cn.iocoder.yudao.module.mdm.service.item.MdmItemModelService;
+import cn.iocoder.yudao.module.mdm.service.item.MdmItemService;
+import cn.iocoder.yudao.module.mdm.service.unit.MdmUnitMeasureService;
+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.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+
+@Tag(name = "绠$悊鍚庡彴 - MDM 鐗╂枡鍨嬪彿锛堝瀷鍙� + 涓昏緟鍗曚綅鎹㈢畻锛�")
+@RestController
+@RequestMapping("/mdm/item-model")
+@Validated
+public class MdmItemModelController {
+
+    @Resource
+    private MdmItemModelService itemModelService;
+
+    @Resource
+    private MdmItemService itemService;
+    @Resource
+    private MdmUnitMeasureService unitMeasureService;
+
+    @PostMapping("/create")
+    @Operation(summary = "鍒涘缓鐗╂枡鍨嬪彿")
+    @PreAuthorize("@ss.hasPermission('mdm:item:create')")
+    public CommonResult<Long> createItemModel(@Valid @RequestBody MdmItemModelSaveReqVO createReqVO) {
+        return success(itemModelService.createItemModel(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "鏇存柊鐗╂枡鍨嬪彿")
+    @PreAuthorize("@ss.hasPermission('mdm:item:update')")
+    public CommonResult<Boolean> updateItemModel(@Valid @RequestBody MdmItemModelSaveReqVO updateReqVO) {
+        itemModelService.updateItemModel(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "鍒犻櫎鐗╂枡鍨嬪彿")
+    @Parameter(name = "id", description = "鍨嬪彿缂栧彿", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('mdm:item:delete')")
+    public CommonResult<Boolean> deleteItemModel(@RequestParam("id") Long id) {
+        itemModelService.deleteItemModel(id);
+        return success(true);
+    }
+
+    @PostMapping("/save-list")
+    @Operation(summary = "鍏ㄩ噺瑕嗙洊淇濆瓨鐗╂枡鐨勫瀷鍙峰垪琛�")
+    @PreAuthorize("@ss.hasPermission('mdm:item:update')")
+    public CommonResult<Boolean> saveItemModelList(@RequestParam("itemId") Long itemId,
+                                                   @RequestBody List<MdmItemModelSaveReqVO> modelList) {
+        itemModelService.saveItemModelList(itemId, modelList);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "鑾峰緱鐗╂枡鍨嬪彿")
+    @Parameter(name = "id", description = "鍨嬪彿缂栧彿", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('mdm:item:query')")
+    public CommonResult<MdmItemModelRespVO> getItemModel(@RequestParam("id") Long id) {
+        MdmItemModelDO itemModel = itemModelService.getItemModel(id);
+        if (itemModel == null) {
+            return success(null);
+        }
+        return success(buildRespVOList(List.of(itemModel)).get(0));
+    }
+
+    @GetMapping("/list-by-item")
+    @Operation(summary = "鑾峰緱鎸囧畾鐗╂枡鐨勫瀷鍙峰垪琛�")
+    @Parameter(name = "itemId", description = "鐗╂枡缂栧彿", required = true, example = "1")
+    @PreAuthorize("@ss.hasPermission('mdm:item:query')")
+    public CommonResult<List<MdmItemModelRespVO>> getItemModelListByItemId(@RequestParam("itemId") Long itemId) {
+        return success(buildRespVOList(itemModelService.getItemModelListByItemId(itemId)));
+    }
+
+    @GetMapping("/list-by-items")
+    @Operation(summary = "鑾峰緱鎸囧畾澶氫釜鐗╂枡鐨勫瀷鍙峰垪琛�")
+    @Parameter(name = "itemIds", description = "鐗╂枡缂栧彿鍒楄〃", required = true)
+    @PreAuthorize("@ss.hasPermission('mdm:item:query')")
+    public CommonResult<List<MdmItemModelRespVO>> getItemModelListByItemIds(@RequestParam("itemIds") Collection<Long> itemIds) {
+        List<MdmItemModelDO> list = itemModelService.getItemModelListByItemIds(itemIds);
+        return success(buildRespVOList(list));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "鑾峰緱鐗╂枡鍨嬪彿鍒嗛〉")
+    @PreAuthorize("@ss.hasPermission('mdm:item:query')")
+    public CommonResult<PageResult<MdmItemModelRespVO>> getItemModelPage(@Valid MdmItemModelPageReqVO pageReqVO) {
+        PageResult<MdmItemModelDO> pageResult = itemModelService.getItemModelPage(pageReqVO);
+        return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal()));
+    }
+
+    private List<MdmItemModelRespVO> buildRespVOList(List<MdmItemModelDO> list) {
+        if (list == null || list.isEmpty()) {
+            return List.of();
+        }
+        List<MdmItemModelRespVO> respList = BeanUtils.toBean(list, MdmItemModelRespVO.class);
+
+        Map<Long, MdmItemDO> itemMap = convertMap(itemService.getItemList(convertSet(list, MdmItemModelDO::getItemId)),
+                MdmItemDO::getId);
+        Map<Long, MdmUnitMeasureDO> unitMap = convertMap(
+                unitMeasureService.getUnitMeasureList(convertSet(list, MdmItemModelDO::getUnitMeasureId)),
+                MdmUnitMeasureDO::getId);
+
+        respList.forEach(resp -> {
+            MdmItemDO item = itemMap.get(resp.getItemId());
+            if (item != null) {
+                resp.setItemCode(item.getCode()).setItemName(item.getName());
+            }
+            MdmUnitMeasureDO unit = unitMap.get(resp.getUnitMeasureId());
+            if (unit != null) {
+                resp.setUnitMeasureName(unit.getName());
+            }
+        });
+        return respList;
+    }
+
+}
diff --git a/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/vo/MdmItemModelPageReqVO.java b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/vo/MdmItemModelPageReqVO.java
new file mode 100644
index 0000000..597d51d
--- /dev/null
+++ b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/vo/MdmItemModelPageReqVO.java
@@ -0,0 +1,24 @@
+package cn.iocoder.yudao.module.mdm.controller.admin.item.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 = "绠$悊鍚庡彴 - MDM 鐗╂枡鍨嬪彿鍒嗛〉 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class MdmItemModelPageReqVO extends PageParam {
+
+    @Schema(description = "鐗╂枡缂栧彿", example = "1")
+    private Long itemId;
+
+    @Schema(description = "鍨嬪彿鍚嶇О", example = "4绫�/鏍�")
+    private String model;
+
+    @Schema(description = "鐘舵��", example = "0")
+    private Integer status;
+
+}
diff --git a/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/vo/MdmItemModelRespVO.java b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/vo/MdmItemModelRespVO.java
new file mode 100644
index 0000000..7fd01d2
--- /dev/null
+++ b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/vo/MdmItemModelRespVO.java
@@ -0,0 +1,46 @@
+package cn.iocoder.yudao.module.mdm.controller.admin.item.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Schema(description = "绠$悊鍚庡彴 - MDM 鐗╂枡鍨嬪彿 Response VO")
+@Data
+public class MdmItemModelRespVO {
+
+    @Schema(description = "鍨嬪彿缂栧彿", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+    private Long id;
+
+    @Schema(description = "鐗╂枡缂栧彿", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    private Long itemId;
+
+    @Schema(description = "鐗╂枡缂栫爜", example = "M001")
+    private String itemCode;
+
+    @Schema(description = "鐗╂枡鍚嶇О", example = "涓嶉攬閽㈢")
+    private String itemName;
+
+    @Schema(description = "鍨嬪彿鍚嶇О", requiredMode = Schema.RequiredMode.REQUIRED, example = "4绫�/鏍�")
+    private String model;
+
+    @Schema(description = "鍨嬪彿璁¢噺鍗曚綅缂栧彿", requiredMode = Schema.RequiredMode.REQUIRED, example = "7")
+    private Long unitMeasureId;
+
+    @Schema(description = "鍨嬪彿璁¢噺鍗曚綅鍚嶇О", example = "鏍�")
+    private String unitMeasureName;
+
+    @Schema(description = "鎹㈢畻姣旂巼锛�1 鍨嬪彿璁¢噺鍗曚綅 = N 鐗╂枡涓昏閲忓崟浣�", requiredMode = Schema.RequiredMode.REQUIRED, example = "4")
+    private BigDecimal unitMeasureRate;
+
+    @Schema(description = "鐘舵��", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
+    private Integer status;
+
+    @Schema(description = "澶囨敞", example = "澶囨敞")
+    private String remark;
+
+    @Schema(description = "鍒涘缓鏃堕棿", requiredMode = Schema.RequiredMode.REQUIRED)
+    private LocalDateTime createTime;
+
+}
diff --git a/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/vo/MdmItemModelSaveReqVO.java b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/vo/MdmItemModelSaveReqVO.java
new file mode 100644
index 0000000..c3e0402
--- /dev/null
+++ b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/vo/MdmItemModelSaveReqVO.java
@@ -0,0 +1,43 @@
+package cn.iocoder.yudao.module.mdm.controller.admin.item.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.DecimalMin;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Schema(description = "绠$悊鍚庡彴 - MDM 鐗╂枡鍨嬪彿鏂板/淇敼 Request VO")
+@Data
+public class MdmItemModelSaveReqVO {
+
+    @Schema(description = "鍨嬪彿缂栧彿", example = "1024")
+    private Long id;
+
+    @Schema(description = "鐗╂枡缂栧彿", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @NotNull(message = "鐗╂枡缂栧彿涓嶈兘涓虹┖")
+    private Long itemId;
+
+    @Schema(description = "鍨嬪彿鍚嶇О", requiredMode = Schema.RequiredMode.REQUIRED, example = "4绫�/鏍�")
+    @NotBlank(message = "鍨嬪彿鍚嶇О涓嶈兘涓虹┖")
+    @Size(max = 128, message = "鍨嬪彿鍚嶇О闀垮害涓嶈兘瓒呰繃 128 涓瓧绗�")
+    private String model;
+
+    @Schema(description = "鍨嬪彿璁¢噺鍗曚綅缂栧彿锛堣鍨嬪彿涓嬪嚭鍏ュ簱褰曞叆浣跨敤鐨勫崟浣嶏級", requiredMode = Schema.RequiredMode.REQUIRED, example = "7")
+    @NotNull(message = "鍨嬪彿璁¢噺鍗曚綅涓嶈兘涓虹┖")
+    private Long unitMeasureId;
+
+    @Schema(description = "鎹㈢畻姣旂巼锛�1 鍨嬪彿璁¢噺鍗曚綅 = N 鐗╂枡涓昏閲忓崟浣�", requiredMode = Schema.RequiredMode.REQUIRED, example = "4")
+    @NotNull(message = "鎹㈢畻姣旂巼涓嶈兘涓虹┖")
+    @DecimalMin(value = "0", inclusive = false, message = "鎹㈢畻姣旂巼蹇呴』澶т簬 0")
+    private BigDecimal unitMeasureRate;
+
+    @Schema(description = "鐘舵��", example = "0")
+    private Integer status;
+
+    @Schema(description = "澶囨敞", example = "澶囨敞")
+    private String remark;
+
+}
diff --git a/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/dal/dataobject/item/MdmItemModelDO.java b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/dal/dataobject/item/MdmItemModelDO.java
new file mode 100644
index 0000000..bd09325
--- /dev/null
+++ b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/dal/dataobject/item/MdmItemModelDO.java
@@ -0,0 +1,77 @@
+package cn.iocoder.yudao.module.mdm.dal.dataobject.item;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.module.mdm.dal.dataobject.unit.MdmUnitMeasureDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+import java.math.BigDecimal;
+
+/**
+ * MDM 鐗╂枡鍨嬪彿 DO
+ *
+ * 鍚屼竴鐗╂枡鍙淮鎶ゅ涓瀷鍙凤紝姣忎釜鍨嬪彿鍗曠嫭閰嶇疆銆屽瀷鍙峰崟浣� + 鎹㈢畻姣旂巼銆嶏紝
+ * 鐢ㄤ簬鍑哄叆搴撴椂鎸夊瀷鍙峰崟浣嶅綍鍏ャ�佺敱绯荤粺鎹㈢畻鎴愮墿鏂欎富鍗曚綅鏁伴噺璁拌处銆�
+ *
+ * @author 瓒呯骇绠$悊鍛�
+ */
+@TableName("mdm_item_model")
+@KeySequence("mdm_item_model_seq")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class MdmItemModelDO extends BaseDO {
+
+    /**
+     * 鍨嬪彿缂栧彿
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * 鐗╂枡缂栧彿
+     *
+     * 鍏宠仈 {@link MdmItemDO#getId()}
+     */
+    private Long itemId;
+
+    /**
+     * 鍨嬪彿鍚嶇О
+     *
+     * 渚嬪锛�4绫�/鏍�
+     */
+    private String model;
+
+    /**
+     * 鍨嬪彿璁¢噺鍗曚綅缂栧彿
+     *
+     * 鍏宠仈 {@link MdmUnitMeasureDO#getId()}
+     * 渚嬪锛氭牴
+     */
+    private Long unitMeasureId;
+
+    /**
+     * 鎹㈢畻姣旂巼
+     *
+     * 1 鍨嬪彿璁¢噺鍗曚綅 = N 鐗╂枡涓昏閲忓崟浣嶃�備緥濡� 1鏍� = 4绫筹紝鍒欐瘮鐜囦负 4
+     */
+    private BigDecimal unitMeasureRate;
+
+    /**
+     * 鐘舵��
+     *
+     * 鏋氫妇 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum}
+     */
+    private Integer status;
+
+    /**
+     * 澶囨敞
+     */
+    private String remark;
+
+}
diff --git a/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/dal/mysql/item/MdmItemMapper.java b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/dal/mysql/item/MdmItemMapper.java
index 1309623..3363066 100644
--- a/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/dal/mysql/item/MdmItemMapper.java
+++ b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/dal/mysql/item/MdmItemMapper.java
@@ -30,7 +30,8 @@
                 .eqIfPresent(MdmItemDO::getBrandId, reqVO.getBrandId())
                 .eqIfPresent(MdmItemDO::getStatus, reqVO.getStatus())
                 .betweenIfPresent(MdmItemDO::getCreateTime, reqVO.getCreateTime())
-                .orderByDesc(MdmItemDO::getId));
+                .orderByAsc(MdmItemDO::getCategoryId)
+                .orderByAsc(MdmItemDO::getCode));
     }
 
     default List<MdmItemDO> selectList(MdmItemPageReqVO reqVO, Collection<Long> categoryIds) {
diff --git a/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/dal/mysql/item/MdmItemModelMapper.java b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/dal/mysql/item/MdmItemModelMapper.java
new file mode 100644
index 0000000..6c4e2e1
--- /dev/null
+++ b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/dal/mysql/item/MdmItemModelMapper.java
@@ -0,0 +1,49 @@
+package cn.iocoder.yudao.module.mdm.dal.mysql.item;
+
+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.mdm.controller.admin.item.vo.MdmItemModelPageReqVO;
+import cn.iocoder.yudao.module.mdm.dal.dataobject.item.MdmItemModelDO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * MDM 鐗╂枡鍨嬪彿 Mapper
+ *
+ * @author 瓒呯骇绠$悊鍛�
+ */
+@Mapper
+public interface MdmItemModelMapper extends BaseMapperX<MdmItemModelDO> {
+
+    default List<MdmItemModelDO> selectListByItemId(Long itemId) {
+        return selectList(new LambdaQueryWrapperX<MdmItemModelDO>()
+                .eq(MdmItemModelDO::getItemId, itemId)
+                .orderByAsc(MdmItemModelDO::getId));
+    }
+
+    default List<MdmItemModelDO> selectListByItemIds(Collection<Long> itemIds) {
+        return selectList(MdmItemModelDO::getItemId, itemIds);
+    }
+
+    default MdmItemModelDO selectByItemIdAndModel(Long itemId, String model) {
+        return selectOne(new LambdaQueryWrapperX<MdmItemModelDO>()
+                .eq(MdmItemModelDO::getItemId, itemId)
+                .eq(MdmItemModelDO::getModel, model));
+    }
+
+    default int deleteByItemId(Long itemId) {
+        return delete(MdmItemModelDO::getItemId, itemId);
+    }
+
+    default PageResult<MdmItemModelDO> selectPage(MdmItemModelPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<MdmItemModelDO>()
+                .eqIfPresent(MdmItemModelDO::getItemId, reqVO.getItemId())
+                .likeIfPresent(MdmItemModelDO::getModel, reqVO.getModel())
+                .eqIfPresent(MdmItemModelDO::getStatus, reqVO.getStatus())
+                .orderByAsc(MdmItemModelDO::getId));
+    }
+
+}
diff --git a/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/enums/ErrorCodeConstants.java b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/enums/ErrorCodeConstants.java
index a3df052..390e586 100644
--- a/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/enums/ErrorCodeConstants.java
+++ b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/enums/ErrorCodeConstants.java
@@ -18,6 +18,12 @@
     ErrorCode MDM_ITEM_SKU_CODE_DUPLICATE = new ErrorCode(1_050_006, "SKU缂栫爜宸插瓨鍦�");
     ErrorCode MDM_ITEM_EXISTS_REFERENCE = new ErrorCode(1_050_007, "鐗╂枡宸茶涓氬姟寮曠敤锛屾棤娉曞垹闄�");
     ErrorCode MDM_ITEM_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_050_008, "瀵煎叆鐨勭墿鏂欐暟鎹笉鑳戒负绌�");
+    ErrorCode MDM_ITEM_MODEL_NOT_EXISTS = new ErrorCode(1_050_009, "鐗╂枡鍨嬪彿涓嶅瓨鍦�");
+    ErrorCode MDM_ITEM_MODEL_IS_DISABLE = new ErrorCode(1_050_010, "鐗╂枡鍨嬪彿宸茬鐢�");
+    ErrorCode MDM_ITEM_MODEL_NAME_DUPLICATE = new ErrorCode(1_050_011, "璇ョ墿鏂欎笅宸插瓨鍦ㄥ瀷鍙峰悕绉般�恵}銆戯紝璇蜂慨鏀瑰瀷鍙峰悕绉板悗閲嶈瘯");
+    ErrorCode MDM_ITEM_MODEL_RATE_INVALID = new ErrorCode(1_050_012, "鍨嬪彿銆恵}銆戠殑鎹㈢畻姣旂巼銆恵}銆戜笉鍚堢悊锛�1 涓瀷鍙疯閲忓崟浣嶅繀椤诲搴斿ぇ浜� 0 鐨勭墿鏂欎富鍗曚綅鏁伴噺锛岃濉啓澶т簬 0 鐨勬崲绠楁瘮鐜�");
+    ErrorCode MDM_ITEM_MODEL_UNIT_MISMATCH = new ErrorCode(1_050_013, "鍨嬪彿鐨勮閲忓崟浣嶄笌鎵�閫夊崟浣嶄笉涓�鑷�");
+    ErrorCode MDM_ITEM_MODEL_RATE_MUST_BE_ONE = new ErrorCode(1_050_014, "鍨嬪彿銆恵}銆戠殑璁¢噺鍗曚綅銆恵}銆戜笌鐗╂枡涓诲崟浣嶃�恵}銆戠浉鍚岋紝鎹㈢畻姣旂巼蹇呴』濉� 1锛岃淇敼鎹㈢畻姣旂巼鎴栨敼閫夊叾浠栬閲忓崟浣�");
 
     // ========== 鐗╂枡鍒嗙被鐩稿叧 1-050-051 ~ 1-050-100 ==========
     ErrorCode MDM_ITEM_CATEGORY_NOT_EXISTS = new ErrorCode(1_050_051, "鐗╂枡鍒嗙被涓嶅瓨鍦�");
diff --git a/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/service/item/MdmItemModelService.java b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/service/item/MdmItemModelService.java
new file mode 100644
index 0000000..c6144b4
--- /dev/null
+++ b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/service/item/MdmItemModelService.java
@@ -0,0 +1,111 @@
+package cn.iocoder.yudao.module.mdm.service.item;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemModelPageReqVO;
+import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemModelSaveReqVO;
+import cn.iocoder.yudao.module.mdm.dal.dataobject.item.MdmItemModelDO;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * MDM 鐗╂枡鍨嬪彿 Service 鎺ュ彛
+ *
+ * @author 瓒呯骇绠$悊鍛�
+ */
+public interface MdmItemModelService {
+
+    /**
+     * 鍒涘缓鐗╂枡鍨嬪彿
+     *
+     * @param createReqVO 鍒涘缓淇℃伅
+     * @return 鍨嬪彿缂栧彿
+     */
+    Long createItemModel(MdmItemModelSaveReqVO createReqVO);
+
+    /**
+     * 鏇存柊鐗╂枡鍨嬪彿
+     *
+     * @param updateReqVO 鏇存柊淇℃伅
+     */
+    void updateItemModel(MdmItemModelSaveReqVO updateReqVO);
+
+    /**
+     * 鍒犻櫎鐗╂枡鍨嬪彿
+     *
+     * @param id 鍨嬪彿缂栧彿
+     */
+    void deleteItemModel(Long id);
+
+    /**
+     * 鍏ㄩ噺瑕嗙洊淇濆瓨鐗╂枡鐨勫瀷鍙峰垪琛紙鍏堝垹鍚庢彃锛�
+     *
+     * @param itemId    鐗╂枡缂栧彿
+     * @param modelList 鍨嬪彿鍒楄〃
+     */
+    void saveItemModelList(Long itemId, List<MdmItemModelSaveReqVO> modelList);
+
+    /**
+     * 鑾峰緱鐗╂枡鍨嬪彿
+     *
+     * @param id 鍨嬪彿缂栧彿
+     * @return 鐗╂枡鍨嬪彿
+     */
+    MdmItemModelDO getItemModel(Long id);
+
+    /**
+     * 鑾峰緱鐗╂枡鍨嬪彿鍒楄〃
+     *
+     * @param ids 鍨嬪彿缂栧彿鍒楄〃
+     * @return 鐗╂枡鍨嬪彿鍒楄〃
+     */
+    List<MdmItemModelDO> getItemModelList(Collection<Long> ids);
+
+    /**
+     * 鑾峰緱鎸囧畾鐗╂枡鐨勫瀷鍙峰垪琛�
+     *
+     * @param itemId 鐗╂枡缂栧彿
+     * @return 鐗╂枡鍨嬪彿鍒楄〃
+     */
+    List<MdmItemModelDO> getItemModelListByItemId(Long itemId);
+
+    /**
+     * 鑾峰緱鎸囧畾澶氫釜鐗╂枡鐨勫瀷鍙峰垪琛�
+     *
+     * @param itemIds 鐗╂枡缂栧彿鍒楄〃
+     * @return 鐗╂枡鍨嬪彿鍒楄〃
+     */
+    List<MdmItemModelDO> getItemModelListByItemIds(Collection<Long> itemIds);
+
+    /**
+     * 鑾峰緱鐗╂枡鍨嬪彿鍒嗛〉
+     *
+     * @param pageReqVO 鍒嗛〉鏌ヨ
+     * @return 鐗╂枡鍨嬪彿鍒嗛〉
+     */
+    PageResult<MdmItemModelDO> getItemModelPage(MdmItemModelPageReqVO pageReqVO);
+
+    /**
+     * 鏍¢獙鐗╂枡鍨嬪彿瀛樺湪
+     *
+     * @param id 鍨嬪彿缂栧彿
+     * @return 鐗╂枡鍨嬪彿
+     */
+    MdmItemModelDO validateItemModelExists(Long id);
+
+    /**
+     * 鏍¢獙鐗╂枡鍨嬪彿瀛樺湪涓斿惎鐢�
+     *
+     * @param id 鍨嬪彿缂栧彿
+     * @return 鐗╂枡鍨嬪彿
+     */
+    MdmItemModelDO validateItemModelExistsAndEnable(Long id);
+
+    /**
+     * 鍒犻櫎鎸囧畾鐗╂枡鐨勫叏閮ㄥ瀷鍙�
+     *
+     * @param itemId 鐗╂枡缂栧彿
+     */
+    void deleteItemModelListByItemId(Long itemId);
+
+}
diff --git a/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/service/item/MdmItemModelServiceImpl.java b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/service/item/MdmItemModelServiceImpl.java
new file mode 100644
index 0000000..8f708da
--- /dev/null
+++ b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/service/item/MdmItemModelServiceImpl.java
@@ -0,0 +1,173 @@
+package cn.iocoder.yudao.module.mdm.service.item;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemModelPageReqVO;
+import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemModelSaveReqVO;
+import cn.iocoder.yudao.module.mdm.dal.dataobject.item.MdmItemDO;
+import cn.iocoder.yudao.module.mdm.dal.dataobject.item.MdmItemModelDO;
+import cn.iocoder.yudao.module.mdm.dal.dataobject.unit.MdmUnitMeasureDO;
+import cn.iocoder.yudao.module.mdm.dal.mysql.item.MdmItemModelMapper;
+import cn.iocoder.yudao.module.mdm.service.unit.MdmUnitMeasureService;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.validation.annotation.Validated;
+
+import java.math.BigDecimal;
+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.mdm.enums.ErrorCodeConstants.*;
+
+/**
+ * MDM 鐗╂枡鍨嬪彿 Service 瀹炵幇绫�
+ *
+ * @author 瓒呯骇绠$悊鍛�
+ */
+@Service
+@Validated
+public class MdmItemModelServiceImpl implements MdmItemModelService {
+
+    @Resource
+    private MdmItemModelMapper itemModelMapper;
+
+    @Resource
+    private MdmItemService itemService;
+    @Resource
+    private MdmUnitMeasureService unitMeasureService;
+
+    @Override
+    public Long createItemModel(MdmItemModelSaveReqVO createReqVO) {
+        validateItemModelSaveData(null, createReqVO);
+
+        MdmItemModelDO itemModel = BeanUtils.toBean(createReqVO, MdmItemModelDO.class);
+        if (itemModel.getStatus() == null) {
+            itemModel.setStatus(CommonStatusEnum.ENABLE.getStatus());
+        }
+        itemModelMapper.insert(itemModel);
+        return itemModel.getId();
+    }
+
+    @Override
+    public void updateItemModel(MdmItemModelSaveReqVO updateReqVO) {
+        validateItemModelExists(updateReqVO.getId());
+        validateItemModelSaveData(updateReqVO.getId(), updateReqVO);
+
+        itemModelMapper.updateById(BeanUtils.toBean(updateReqVO, MdmItemModelDO.class));
+    }
+
+    private void validateItemModelSaveData(Long id, MdmItemModelSaveReqVO reqVO) {
+        // 鏍¢獙鐗╂枡瀛樺湪
+        MdmItemDO item = itemService.validateItemExists(reqVO.getItemId());
+        // 鏍¢獙鍨嬪彿鍗曚綅瀛樺湪
+        unitMeasureService.validateUnitMeasureExists(reqVO.getUnitMeasureId());
+        // 鏍¢獙鎹㈢畻姣旂巼澶т簬 0
+        if (reqVO.getUnitMeasureRate() == null
+                || reqVO.getUnitMeasureRate().compareTo(BigDecimal.ZERO) <= 0) {
+            throw exception(MDM_ITEM_MODEL_RATE_INVALID, reqVO.getModel(), reqVO.getUnitMeasureRate());
+        }
+        // 鏍¢獙鍚屼竴鐗╂枡涓嬪瀷鍙峰悕绉板敮涓�
+        if (StrUtil.isNotBlank(reqVO.getModel())) {
+            MdmItemModelDO exists = itemModelMapper.selectByItemIdAndModel(reqVO.getItemId(), reqVO.getModel());
+            if (exists != null && ObjUtil.notEqual(exists.getId(), id)) {
+                throw exception(MDM_ITEM_MODEL_NAME_DUPLICATE, reqVO.getModel());
+            }
+        }
+        // 鍨嬪彿鍗曚綅涓庣墿鏂欎富鍗曚綅涓�鑷存椂锛屾瘮鐜囧繀椤讳负 1锛堝惁鍒欐崲绠楁棤鎰忎箟涓旀槗璇厤锛�
+        if (ObjUtil.equal(item.getUnitMeasureId(), reqVO.getUnitMeasureId())
+                && reqVO.getUnitMeasureRate().compareTo(BigDecimal.ONE) != 0) {
+            throw exception(MDM_ITEM_MODEL_RATE_MUST_BE_ONE, reqVO.getModel(),
+                    unitName(reqVO.getUnitMeasureId()), unitName(item.getUnitMeasureId()));
+        }
+    }
+
+    private String unitName(Long unitMeasureId) {
+        MdmUnitMeasureDO unit = unitMeasureService.getUnitMeasure(unitMeasureId);
+        return unit != null ? unit.getName() : "ID=" + unitMeasureId;
+    }
+
+    @Override
+    public void deleteItemModel(Long id) {
+        validateItemModelExists(id);
+        itemModelMapper.deleteById(id);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void saveItemModelList(Long itemId, List<MdmItemModelSaveReqVO> modelList) {
+        itemService.validateItemExists(itemId);
+        // 绗竴姝ワ紝鍒犻櫎鏃х殑鍨嬪彿
+        itemModelMapper.deleteByItemId(itemId);
+        if (CollUtil.isEmpty(modelList)) {
+            return;
+        }
+        // 绗簩姝ワ紝鎻掑叆鏂扮殑鍨嬪彿
+        for (MdmItemModelSaveReqVO reqVO : modelList) {
+            reqVO.setItemId(itemId);
+            reqVO.setId(null);
+            createItemModel(reqVO);
+        }
+    }
+
+    @Override
+    public MdmItemModelDO getItemModel(Long id) {
+        return itemModelMapper.selectById(id);
+    }
+
+    @Override
+    public List<MdmItemModelDO> getItemModelList(Collection<Long> ids) {
+        if (CollUtil.isEmpty(ids)) {
+            return Collections.emptyList();
+        }
+        return itemModelMapper.selectBatchIds(ids);
+    }
+
+    @Override
+    public List<MdmItemModelDO> getItemModelListByItemId(Long itemId) {
+        return itemModelMapper.selectListByItemId(itemId);
+    }
+
+    @Override
+    public List<MdmItemModelDO> getItemModelListByItemIds(Collection<Long> itemIds) {
+        if (CollUtil.isEmpty(itemIds)) {
+            return Collections.emptyList();
+        }
+        return itemModelMapper.selectListByItemIds(itemIds);
+    }
+
+    @Override
+    public PageResult<MdmItemModelDO> getItemModelPage(MdmItemModelPageReqVO pageReqVO) {
+        return itemModelMapper.selectPage(pageReqVO);
+    }
+
+    @Override
+    public MdmItemModelDO validateItemModelExists(Long id) {
+        MdmItemModelDO itemModel = itemModelMapper.selectById(id);
+        if (itemModel == null) {
+            throw exception(MDM_ITEM_MODEL_NOT_EXISTS);
+        }
+        return itemModel;
+    }
+
+    @Override
+    public MdmItemModelDO validateItemModelExistsAndEnable(Long id) {
+        MdmItemModelDO itemModel = validateItemModelExists(id);
+        if (CommonStatusEnum.isDisable(itemModel.getStatus())) {
+            throw exception(MDM_ITEM_MODEL_IS_DISABLE);
+        }
+        return itemModel;
+    }
+
+    @Override
+    public void deleteItemModelListByItemId(Long itemId) {
+        itemModelMapper.deleteByItemId(itemId);
+    }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/MesDvMachineryController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/MesDvMachineryController.java
index 864bf15..d1fdcab 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/MesDvMachineryController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/MesDvMachineryController.java
@@ -79,6 +79,15 @@
         return success(true);
     }
 
+    @DeleteMapping("/delete-list")
+    @Operation(summary = "鎵归噺鍒犻櫎璁惧")
+    @Parameter(name = "ids", description = "缂栧彿鍒楄〃", required = true, example = "1024,2048")
+    @PreAuthorize("@ss.hasPermission('mes:dv-machinery:delete')")
+    public CommonResult<Boolean> deleteMachineryList(@RequestParam("ids") List<Long> ids) {
+        machineryService.deleteMachineryList(ids);
+        return success(true);
+    }
+
     @GetMapping("/get")
     @Operation(summary = "鑾峰緱璁惧")
     @Parameter(name = "id", description = "缂栧彿", required = true, example = "1024")
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/MesWmItemReceiptLineController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/MesWmItemReceiptLineController.java
index 2c056ba..59a0810 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/MesWmItemReceiptLineController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/MesWmItemReceiptLineController.java
@@ -9,6 +9,8 @@
 import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.line.MesWmItemReceiptLineRespVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.line.MesWmItemReceiptLineSaveReqVO;
 import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
+import cn.iocoder.yudao.module.mdm.api.item.MdmItemModelApi;
+import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemModelRespDTO;
 import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO;
 
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDO;
@@ -28,8 +30,10 @@
 import org.springframework.web.bind.annotation.*;
 
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@@ -45,6 +49,8 @@
     private MesWmItemReceiptLineService itemReceiptLineService;
     @Resource
     private MdmItemApi mdmItemApi;
+    @Resource
+    private MdmItemModelApi mdmItemModelApi;
     @Resource
     private MdmUnitMeasureApi mdmUnitMeasureApi;
     @Resource
@@ -104,18 +110,26 @@
         // 1. 鑾峰緱鍏宠仈鏁版嵁
         Map<Long, MdmItemRespDTO> itemMap = mdmItemApi.getItemMap(
                 convertSet(list, MesWmItemReceiptLineDO::getItemId));
-        Map<Long, MdmUnitMeasureRespDTO> unitMeasureMap = mdmUnitMeasureApi.getUnitMeasureList(
-                convertSet(itemMap.values(), MdmItemRespDTO::getUnitMeasureId)).getCheckedData()
-                .stream().collect(Collectors.toMap(MdmUnitMeasureRespDTO::getId, e -> e));
+        Set<Long> unitMeasureIds = new HashSet<>(convertSet(itemMap.values(), MdmItemRespDTO::getUnitMeasureId));
+        unitMeasureIds.addAll(convertSet(list, MesWmItemReceiptLineDO::getEnterUnitMeasureId));
+        Map<Long, MdmUnitMeasureRespDTO> unitMeasureMap = mdmUnitMeasureApi.getUnitMeasureList(unitMeasureIds)
+                .getCheckedData().stream().collect(Collectors.toMap(MdmUnitMeasureRespDTO::getId, e -> e));
         Map<Long, MesWmItemReceiptDO> receiptMap = itemReceiptService.getItemReceiptMap(
                 convertSet(list, MesWmItemReceiptLineDO::getReceiptId));
+        Map<Long, MdmItemModelRespDTO> itemModelMap = mdmItemModelApi.getItemModelMap(
+                convertSet(list, MesWmItemReceiptLineDO::getItemModelId));
         // 2. 鏋勫缓缁撴灉
         return BeanUtils.toBean(list, MesWmItemReceiptLineRespVO.class, vo -> {
             MapUtils.findAndThen(itemMap, vo.getItemId(), item -> {
-                vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification());
+                vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification())
+                        .setUnitMeasureId(item.getUnitMeasureId());
                 MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(),
                         unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName()));
             });
+            MapUtils.findAndThen(unitMeasureMap, vo.getEnterUnitMeasureId(),
+                    unitMeasure -> vo.setEnterUnitMeasureName(unitMeasure.getName()));
+            MapUtils.findAndThen(itemModelMap, vo.getItemModelId(),
+                    itemModel -> vo.setItemModel(itemModel.getModel()));
             MapUtils.findAndThen(receiptMap, vo.getReceiptId(), receipt ->
                     vo.setReceiptCode(receipt.getCode()).setPurchaseOrderCode(receipt.getPurchaseOrderCode()));
         });
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/line/MesWmItemReceiptLineRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/line/MesWmItemReceiptLineRespVO.java
index c05e7ae..62ce1c5 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/line/MesWmItemReceiptLineRespVO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/line/MesWmItemReceiptLineRespVO.java
@@ -40,10 +40,28 @@
     @Schema(description = "瑙勬牸鍨嬪彿", example = "10mm*100mm")
     private String specification;
 
-    @Schema(description = "璁¢噺鍗曚綅鍚嶇О", example = "鍗冨厠")
+    @Schema(description = "涓昏閲忓崟浣嶇紪鍙凤紙鐗╂枡涓诲崟浣嶏級", example = "1")
+    private Long unitMeasureId;
+
+    @Schema(description = "涓昏閲忓崟浣嶅悕绉帮紙鐗╂枡涓诲崟浣嶏級", example = "绫�")
     private String unitMeasureName;
 
-    @Schema(description = "鍏ュ簱鏁伴噺", example = "500.00")
+    @Schema(description = "鐗╂枡鍨嬪彿缂栧彿", example = "1")
+    private Long itemModelId;
+
+    @Schema(description = "鐗╂枡鍨嬪彿鍚嶇О", example = "4绫�/鏍�")
+    private String itemModel;
+
+    @Schema(description = "褰曞叆鍗曚綅缂栧彿", example = "7")
+    private Long enterUnitMeasureId;
+
+    @Schema(description = "褰曞叆鍗曚綅鍚嶇О", example = "鏍�")
+    private String enterUnitMeasureName;
+
+    @Schema(description = "褰曞叆鏁伴噺锛堟寜褰曞叆鍗曚綅璁★級", example = "10.00")
+    private BigDecimal enterQuantity;
+
+    @Schema(description = "鍏ュ簱鏁伴噺锛堢墿鏂欎富鍗曚綅鍙e緞锛�", example = "40.00")
     private BigDecimal receivedQuantity;
 
     @Schema(description = "鎵规缂栧彿", example = "1")
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/line/MesWmItemReceiptLineSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/line/MesWmItemReceiptLineSaveReqVO.java
index e9b053b..9c91816 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/line/MesWmItemReceiptLineSaveReqVO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/line/MesWmItemReceiptLineSaveReqVO.java
@@ -29,8 +29,17 @@
     @NotNull(message = "鐗╂枡缂栧彿涓嶈兘涓虹┖")
     private Long itemId;
 
-    @Schema(description = "鍏ュ簱鏁伴噺", requiredMode = Schema.RequiredMode.REQUIRED, example = "500.00")
-    @NotNull(message = "鍏ュ簱鏁伴噺涓嶈兘涓虹┖")
+    @Schema(description = "鐗╂枡鍨嬪彿缂栧彿锛堥�夋嫨鍨嬪彿鍚庢寜鍏跺崟浣嶄笌鎹㈢畻姣旂巼鎹㈢畻涓轰富鍗曚綅鏁伴噺锛�", example = "1")
+    private Long itemModelId;
+
+    @Schema(description = "褰曞叆鍗曚綅缂栧彿锛堜笉浼犳垨浼犵墿鏂欎富鍗曚綅鏃舵寜涓诲崟浣嶅綍鍏ワ級", example = "7")
+    private Long enterUnitMeasureId;
+
+    @Schema(description = "褰曞叆鏁伴噺锛堟寜褰曞叆鍗曚綅璁★紝绯荤粺鎹鎹㈢畻鍑哄叆搴撴暟閲忥級", example = "10.00")
+    @DecimalMin(value = "0", inclusive = false, message = "褰曞叆鏁伴噺蹇呴』澶т簬 0")
+    private BigDecimal enterQuantity;
+
+    @Schema(description = "鍏ュ簱鏁伴噺锛堢墿鏂欎富鍗曚綅鍙e緞锛涗紶浜嗗綍鍏ユ暟閲忔椂鐢辩郴缁熸崲绠楋紝鏃犻渶濉啓锛�", example = "40.00")
     @DecimalMin(value = "0", inclusive = false, message = "鍏ュ簱鏁伴噺蹇呴』澶т簬 0")
     private BigDecimal receivedQuantity;
 
@@ -46,4 +55,4 @@
     @Schema(description = "澶囨敞", example = "澶囨敞")
     private String remark;
 
-    }
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/MesWmMiscIssueLineController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/MesWmMiscIssueLineController.java
index 654daa3..e57e95b 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/MesWmMiscIssueLineController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/MesWmMiscIssueLineController.java
@@ -9,6 +9,8 @@
 import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.line.MesWmMiscIssueLineRespVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.line.MesWmMiscIssueLineSaveReqVO;
 import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
+import cn.iocoder.yudao.module.mdm.api.item.MdmItemModelApi;
+import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemModelRespDTO;
 import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO;
 
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscissue.MesWmMiscIssueLineDO;
@@ -32,8 +34,10 @@
 import org.springframework.web.bind.annotation.*;
 
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@@ -49,6 +53,8 @@
     private MesWmMiscIssueLineService miscIssueLineService;
     @Resource
     private MdmItemApi mdmItemApi;
+    @Resource
+    private MdmItemModelApi mdmItemModelApi;
     @Resource
     private MdmUnitMeasureApi mdmUnitMeasureApi;
     @Resource
@@ -112,9 +118,12 @@
         // 1. 鑾峰緱鍏宠仈鏁版嵁
         Map<Long, MdmItemRespDTO> itemMap = mdmItemApi.getItemMap(
                 convertSet(list, MesWmMiscIssueLineDO::getItemId));
-        Map<Long, MdmUnitMeasureRespDTO> unitMeasureMap = mdmUnitMeasureApi.getUnitMeasureList(
-                convertSet(itemMap.values(), MdmItemRespDTO::getUnitMeasureId)).getCheckedData()
-                .stream().collect(Collectors.toMap(MdmUnitMeasureRespDTO::getId, e -> e));
+        Set<Long> unitMeasureIds = new HashSet<>(convertSet(itemMap.values(), MdmItemRespDTO::getUnitMeasureId));
+        unitMeasureIds.addAll(convertSet(list, MesWmMiscIssueLineDO::getEnterUnitMeasureId));
+        Map<Long, MdmUnitMeasureRespDTO> unitMeasureMap = mdmUnitMeasureApi.getUnitMeasureList(unitMeasureIds)
+                .getCheckedData().stream().collect(Collectors.toMap(MdmUnitMeasureRespDTO::getId, e -> e));
+        Map<Long, MdmItemModelRespDTO> itemModelMap = mdmItemModelApi.getItemModelMap(
+                convertSet(list, MesWmMiscIssueLineDO::getItemModelId));
         Map<Long, MesWmWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(
                 convertSet(list, MesWmMiscIssueLineDO::getWarehouseId));
         Map<Long, MesWmWarehouseLocationDO> locationMap = warehouseLocationService.getWarehouseLocationMap(
@@ -125,10 +134,15 @@
         // 2. 鏋勫缓缁撴灉
         return BeanUtils.toBean(list, MesWmMiscIssueLineRespVO.class, vo -> {
             MapUtils.findAndThen(itemMap, vo.getItemId(), item -> {
-                vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification());
+                vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification())
+                        .setUnitMeasureId(item.getUnitMeasureId());
                 MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(),
                         unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName()));
             });
+            MapUtils.findAndThen(unitMeasureMap, vo.getEnterUnitMeasureId(),
+                    unitMeasure -> vo.setEnterUnitMeasureName(unitMeasure.getName()));
+            MapUtils.findAndThen(itemModelMap, vo.getItemModelId(),
+                    itemModel -> vo.setItemModel(itemModel.getModel()));
             MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), warehouse -> vo.setWarehouseName(warehouse.getName()));
             MapUtils.findAndThen(locationMap, vo.getLocationId(), location -> vo.setLocationName(location.getName()));
             MapUtils.findAndThen(areaMap, vo.getAreaId(), area -> vo.setAreaName(area.getName()));
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/line/MesWmMiscIssueLineRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/line/MesWmMiscIssueLineRespVO.java
index 119733f..878f95c 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/line/MesWmMiscIssueLineRespVO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/line/MesWmMiscIssueLineRespVO.java
@@ -34,10 +34,28 @@
     @Schema(description = "瑙勬牸鍨嬪彿", example = "10mm*100mm")
     private String specification;
 
-    @Schema(description = "璁¢噺鍗曚綅鍚嶇О", example = "鍗冨厠")
+    @Schema(description = "涓昏閲忓崟浣嶇紪鍙凤紙鐗╂枡涓诲崟浣嶏級", example = "1")
+    private Long unitMeasureId;
+
+    @Schema(description = "涓昏閲忓崟浣嶅悕绉帮紙鐗╂枡涓诲崟浣嶏級", example = "鍗冨厠")
     private String unitMeasureName;
 
-    @Schema(description = "鍑哄簱鏁伴噺", example = "100.00")
+    @Schema(description = "鐗╂枡鍨嬪彿缂栧彿", example = "1")
+    private Long itemModelId;
+
+    @Schema(description = "鐗╂枡鍨嬪彿鍚嶇О", example = "4绫�/鏍�")
+    private String itemModel;
+
+    @Schema(description = "褰曞叆鍗曚綅缂栧彿", example = "7")
+    private Long enterUnitMeasureId;
+
+    @Schema(description = "褰曞叆鍗曚綅鍚嶇О", example = "鏍�")
+    private String enterUnitMeasureName;
+
+    @Schema(description = "褰曞叆鏁伴噺锛堟寜褰曞叆鍗曚綅璁★級", example = "10.00")
+    private BigDecimal enterQuantity;
+
+    @Schema(description = "鍑哄簱鏁伴噺锛堢墿鏂欎富鍗曚綅鍙e緞锛�", example = "100.00")
     private BigDecimal quantity;
 
     @Schema(description = "鎵规缂栧彿", example = "1")
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/line/MesWmMiscIssueLineSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/line/MesWmMiscIssueLineSaveReqVO.java
index d005005..c3109f3 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/line/MesWmMiscIssueLineSaveReqVO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/line/MesWmMiscIssueLineSaveReqVO.java
@@ -28,8 +28,17 @@
     @NotNull(message = "鐗╂枡缂栧彿涓嶈兘涓虹┖")
     private Long itemId;
 
-    @Schema(description = "鍑哄簱鏁伴噺", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
-    @NotNull(message = "鍑哄簱鏁伴噺涓嶈兘涓虹┖")
+    @Schema(description = "鐗╂枡鍨嬪彿缂栧彿锛堥�夋嫨鍨嬪彿鍚庢寜鍏跺崟浣嶄笌鎹㈢畻姣旂巼鎹㈢畻涓轰富鍗曚綅鏁伴噺锛�", example = "1")
+    private Long itemModelId;
+
+    @Schema(description = "褰曞叆鍗曚綅缂栧彿锛堜笉浼犳垨浼犵墿鏂欎富鍗曚綅鏃舵寜涓诲崟浣嶅綍鍏ワ級", example = "7")
+    private Long enterUnitMeasureId;
+
+    @Schema(description = "褰曞叆鏁伴噺锛堟寜褰曞叆鍗曚綅璁★紝绯荤粺鎹鎹㈢畻鍑哄叆搴撴暟閲忥級", example = "10.00")
+    @DecimalMin(value = "0", inclusive = false, message = "褰曞叆鏁伴噺蹇呴』澶т簬 0")
+    private BigDecimal enterQuantity;
+
+    @Schema(description = "鍑哄簱鏁伴噺锛堢墿鏂欎富鍗曚綅鍙e緞锛涗紶浜嗗綍鍏ユ暟閲忔椂鐢辩郴缁熸崲绠楋紝鏃犻渶濉啓锛�", example = "100.00")
     @DecimalMin(value = "0.01", message = "鍑哄簱鏁伴噺蹇呴』澶т簬0")
     private BigDecimal quantity;
 
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/MesWmOutsourceIssueLineController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/MesWmOutsourceIssueLineController.java
index 20230d5..a931632 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/MesWmOutsourceIssueLineController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/MesWmOutsourceIssueLineController.java
@@ -9,6 +9,8 @@
 import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.line.MesWmOutsourceIssueLineRespVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.line.MesWmOutsourceIssueLineSaveReqVO;
 import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
+import cn.iocoder.yudao.module.mdm.api.item.MdmItemModelApi;
+import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemModelRespDTO;
 import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO;
 
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO;
@@ -28,6 +30,7 @@
 import org.springframework.web.bind.annotation.*;
 
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
@@ -47,6 +50,8 @@
     private MesWmOutsourceIssueLineService outsourceIssueLineService;
     @Resource
     private MdmItemApi mdmItemApi;
+    @Resource
+    private MdmItemModelApi mdmItemModelApi;
     @Resource
     private MdmUnitMeasureApi mdmUnitMeasureApi;
     @Resource
@@ -116,9 +121,12 @@
         // 1. 鑾峰緱鍏宠仈鏁版嵁
         Map<Long, MdmItemRespDTO> itemMap = mdmItemApi.getItemMap(
                 convertSet(list, MesWmOutsourceIssueLineDO::getItemId));
-        Map<Long, MdmUnitMeasureRespDTO> unitMeasureMap = mdmUnitMeasureApi.getUnitMeasureList(
-                convertSet(itemMap.values(), MdmItemRespDTO::getUnitMeasureId)).getCheckedData()
-                .stream().collect(Collectors.toMap(MdmUnitMeasureRespDTO::getId, e -> e));
+        Set<Long> unitMeasureIds = new HashSet<>(convertSet(itemMap.values(), MdmItemRespDTO::getUnitMeasureId));
+        unitMeasureIds.addAll(convertSet(list, MesWmOutsourceIssueLineDO::getEnterUnitMeasureId));
+        Map<Long, MdmUnitMeasureRespDTO> unitMeasureMap = mdmUnitMeasureApi.getUnitMeasureList(unitMeasureIds)
+                .getCheckedData().stream().collect(Collectors.toMap(MdmUnitMeasureRespDTO::getId, e -> e));
+        Map<Long, MdmItemModelRespDTO> itemModelMap = mdmItemModelApi.getItemModelMap(
+                convertSet(list, MesWmOutsourceIssueLineDO::getItemModelId));
         // 1.2 鑾峰緱鎵规鏁版嵁
         Set<Long> batchIds = convertSet(list, MesWmOutsourceIssueLineDO::getBatchId);
         batchIds.remove(null);
@@ -127,10 +135,15 @@
         // 2. 鏋勫缓缁撴灉
         return BeanUtils.toBean(list, MesWmOutsourceIssueLineRespVO.class, vo -> {
             MapUtils.findAndThen(itemMap, vo.getItemId(), item -> {
-                vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification());
+                vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification())
+                        .setUnitMeasureId(item.getUnitMeasureId());
                 MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(),
                         unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName()));
             });
+            MapUtils.findAndThen(unitMeasureMap, vo.getEnterUnitMeasureId(),
+                    unitMeasure -> vo.setEnterUnitMeasureName(unitMeasure.getName()));
+            MapUtils.findAndThen(itemModelMap, vo.getItemModelId(),
+                    itemModel -> vo.setItemModel(itemModel.getModel()));
             MapUtils.findAndThen(batchMap, vo.getBatchId(), batch -> vo.setBatchCode(batch.getCode()));
         });
     }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/line/MesWmOutsourceIssueLineRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/line/MesWmOutsourceIssueLineRespVO.java
index 753e971..4659794 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/line/MesWmOutsourceIssueLineRespVO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/line/MesWmOutsourceIssueLineRespVO.java
@@ -28,10 +28,28 @@
     @Schema(description = "瑙勬牸鍨嬪彿", example = "10mm*100mm")
     private String specification;
 
-    @Schema(description = "璁¢噺鍗曚綅鍚嶇О", example = "鍗冨厠")
+    @Schema(description = "涓昏閲忓崟浣嶇紪鍙凤紙鐗╂枡涓诲崟浣嶏級", example = "1")
+    private Long unitMeasureId;
+
+    @Schema(description = "涓昏閲忓崟浣嶅悕绉帮紙鐗╂枡涓诲崟浣嶏級", example = "鍗冨厠")
     private String unitMeasureName;
 
-    @Schema(description = "鍙戞枡鏁伴噺", requiredMode = Schema.RequiredMode.REQUIRED, example = "500.00")
+    @Schema(description = "鐗╂枡鍨嬪彿缂栧彿", example = "1")
+    private Long itemModelId;
+
+    @Schema(description = "鐗╂枡鍨嬪彿鍚嶇О", example = "4绫�/鏍�")
+    private String itemModel;
+
+    @Schema(description = "褰曞叆鍗曚綅缂栧彿", example = "7")
+    private Long enterUnitMeasureId;
+
+    @Schema(description = "褰曞叆鍗曚綅鍚嶇О", example = "鏍�")
+    private String enterUnitMeasureName;
+
+    @Schema(description = "褰曞叆鏁伴噺锛堟寜褰曞叆鍗曚綅璁★級", example = "10.00")
+    private BigDecimal enterQuantity;
+
+    @Schema(description = "鍙戞枡鏁伴噺锛堢墿鏂欎富鍗曚綅鍙e緞锛�", requiredMode = Schema.RequiredMode.REQUIRED, example = "500.00")
     private BigDecimal quantity;
 
     @Schema(description = "搴撳瓨ID", example = "1")
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/line/MesWmOutsourceIssueLineSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/line/MesWmOutsourceIssueLineSaveReqVO.java
index 7bfabd0..5a65859 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/line/MesWmOutsourceIssueLineSaveReqVO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/line/MesWmOutsourceIssueLineSaveReqVO.java
@@ -22,8 +22,17 @@
     @NotNull(message = "鐗╂枡ID涓嶈兘涓虹┖")
     private Long itemId;
 
-    @Schema(description = "鍙戞枡鏁伴噺", requiredMode = Schema.RequiredMode.REQUIRED, example = "500.00")
-    @NotNull(message = "鍙戞枡鏁伴噺涓嶈兘涓虹┖")
+    @Schema(description = "鐗╂枡鍨嬪彿缂栧彿锛堥�夋嫨鍨嬪彿鍚庢寜鍏跺崟浣嶄笌鎹㈢畻姣旂巼鎹㈢畻涓轰富鍗曚綅鏁伴噺锛�", example = "1")
+    private Long itemModelId;
+
+    @Schema(description = "褰曞叆鍗曚綅缂栧彿锛堜笉浼犳垨浼犵墿鏂欎富鍗曚綅鏃舵寜涓诲崟浣嶅綍鍏ワ級", example = "7")
+    private Long enterUnitMeasureId;
+
+    @Schema(description = "褰曞叆鏁伴噺锛堟寜褰曞叆鍗曚綅璁★紝绯荤粺鎹鎹㈢畻鍑哄彂鏂欐暟閲忥級", example = "10.00")
+    @DecimalMin(value = "0", inclusive = false, message = "褰曞叆鏁伴噺蹇呴』澶т簬 0")
+    private BigDecimal enterQuantity;
+
+    @Schema(description = "鍙戞枡鏁伴噺锛堢墿鏂欎富鍗曚綅鍙e緞锛涗紶浜嗗綍鍏ユ暟閲忔椂鐢辩郴缁熸崲绠楋紝鏃犻渶濉啓锛�", example = "500.00")
     @DecimalMin(value = "0.01", message = "鍙戞枡鏁伴噺蹇呴』澶т簬 0")
     private BigDecimal quantity;
 
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/MesWmProductIssueLineController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/MesWmProductIssueLineController.java
index 42a1e39..0e329aa 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/MesWmProductIssueLineController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/MesWmProductIssueLineController.java
@@ -10,6 +10,8 @@
 import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.line.MesWmProductIssueLineRespVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.line.MesWmProductIssueLineReturnableRespVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.line.MesWmProductIssueLineSaveReqVO;
+import cn.iocoder.yudao.module.mdm.api.item.MdmItemModelApi;
+import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemModelRespDTO;
 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.pro.task.MesProTaskDO;
@@ -34,9 +36,11 @@
 import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
@@ -59,6 +63,8 @@
     private MesMdUnitMeasureService unitMeasureService;
     @Resource
     private MesProTaskService taskService;
+    @Resource
+    private MdmItemModelApi mdmItemModelApi;
 
     @PostMapping("/create")
     @Operation(summary = "鍒涘缓棰嗘枡鍑哄簱鍗曡")
@@ -174,17 +180,26 @@
         // 1. 鑾峰緱鍏宠仈鏁版嵁
         Map<Long, MesMdItemDO> itemMap = mdmItemService.getItemMap(
                 convertSet(list, MesWmProductIssueLineDO::getItemId));
-        Map<Long, MesMdUnitMeasureDO> unitMeasureMap = unitMeasureService.getUnitMeasureMap(
-                convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId));
+        // 鐗╂枡涓诲崟浣嶄笌褰曞叆鍗曚綅閮借瑙f瀽鍚嶇О
+        Set<Long> unitMeasureIds = new HashSet<>(convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId));
+        unitMeasureIds.addAll(convertSet(list, MesWmProductIssueLineDO::getEnterUnitMeasureId));
+        Map<Long, MesMdUnitMeasureDO> unitMeasureMap = unitMeasureService.getUnitMeasureMap(unitMeasureIds);
+        Map<Long, MdmItemModelRespDTO> itemModelMap = mdmItemModelApi.getItemModelMap(
+                convertSet(list, MesWmProductIssueLineDO::getItemModelId));
         Map<Long, MesProTaskDO> taskMap = taskService.getTaskMap(
                 convertSet(list, MesWmProductIssueLineDO::getTaskId));
         // 2. 鏋勫缓缁撴灉
         return BeanUtils.toBean(list, MesWmProductIssueLineRespVO.class, vo -> {
             MapUtils.findAndThen(itemMap, vo.getItemId(), item -> {
                 vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()).setMdmItemId(item.getMdmItemId());
+                vo.setUnitMeasureId(item.getUnitMeasureId());
                 MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(),
                         unit -> vo.setUnitMeasureName(unit.getName()));
             });
+            MapUtils.findAndThen(unitMeasureMap, vo.getEnterUnitMeasureId(),
+                    unit -> vo.setEnterUnitMeasureName(unit.getName()));
+            MapUtils.findAndThen(itemModelMap, vo.getItemModelId(),
+                    itemModel -> vo.setItemModel(itemModel.getModel()));
             MapUtils.findAndThen(taskMap, vo.getTaskId(), task ->
                     vo.setTaskCode(task.getCode()).setTaskName(task.getName()));
         });
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/line/MesWmProductIssueLineRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/line/MesWmProductIssueLineRespVO.java
index dd79b0e..866c729 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/line/MesWmProductIssueLineRespVO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/line/MesWmProductIssueLineRespVO.java
@@ -37,10 +37,28 @@
     @Schema(description = "瑙勬牸鍨嬪彿", example = "10mm*100mm")
     private String specification;
 
-    @Schema(description = "璁¢噺鍗曚綅鍚嶇О", example = "鍗冨厠")
+    @Schema(description = "涓昏閲忓崟浣嶇紪鍙凤紙鐗╂枡涓诲崟浣嶏級", example = "1")
+    private Long unitMeasureId;
+
+    @Schema(description = "涓昏閲忓崟浣嶅悕绉�", example = "鍗冨厠")
     private String unitMeasureName;
 
-    @Schema(description = "棰嗘枡鏁伴噺", example = "100.00")
+    @Schema(description = "鐗╂枡鍨嬪彿缂栧彿", example = "1")
+    private Long itemModelId;
+
+    @Schema(description = "鐗╂枡鍨嬪彿鍚嶇О", example = "4绫�/鏍�")
+    private String itemModel;
+
+    @Schema(description = "褰曞叆鍗曚綅缂栧彿", example = "7")
+    private Long enterUnitMeasureId;
+
+    @Schema(description = "褰曞叆鍗曚綅鍚嶇О", example = "鏍�")
+    private String enterUnitMeasureName;
+
+    @Schema(description = "褰曞叆鏁伴噺锛堟寜褰曞叆鍗曚綅璁★級", example = "10.00")
+    private BigDecimal enterQuantity;
+
+    @Schema(description = "棰嗘枡鏁伴噺锛堢墿鏂欎富鍗曚綅鍙e緞锛�", example = "100.00")
     private BigDecimal quantity;
 
     @Schema(description = "鎵规ID", example = "1")
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/line/MesWmProductIssueLineSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/line/MesWmProductIssueLineSaveReqVO.java
index 3b369a2..50d6817 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/line/MesWmProductIssueLineSaveReqVO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/line/MesWmProductIssueLineSaveReqVO.java
@@ -25,9 +25,18 @@
     @NotNull(message = "鐗╂枡ID涓嶈兘涓虹┖")
     private Long itemId;
 
-    @Schema(description = "棰嗘枡鏁伴噺", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
-    @NotNull(message = "棰嗘枡鏁伴噺涓嶈兘涓虹┖")
-    @DecimalMin(value = "0", inclusive = false, message = "棰嗘枡鏁伴噺蹇呴』澶т簬 0")
+    @Schema(description = "鐗╂枡鍨嬪彿缂栧彿锛堥�夋嫨鍨嬪彿鍚庢寜鍏跺崟浣嶄笌鎹㈢畻姣旂巼鎹㈢畻涓轰富鍗曚綅鏁伴噺锛�", example = "1")
+    private Long itemModelId;
+
+    @Schema(description = "褰曞叆鍗曚綅缂栧彿锛堜笉浼犳垨浼犵墿鏂欎富鍗曚綅鏃舵寜涓诲崟浣嶅綍鍏ワ級", example = "7")
+    private Long enterUnitMeasureId;
+
+    @Schema(description = "褰曞叆鏁伴噺锛堟寜褰曞叆鍗曚綅璁★紝绯荤粺鎹鎹㈢畻鍑洪鏂欐暟閲忥級", example = "10.00")
+    @DecimalMin(value = "0", inclusive = false, message = "褰曞叆鏁伴噺蹇呴』澶т簬 0")
+    private BigDecimal enterQuantity;
+
+    @Schema(description = "棰嗘枡鏁伴噺锛堢墿鏂欎富鍗曚綅鍙e緞锛涗紶浜嗗綍鍏ユ暟閲忔椂鐢辩郴缁熸崲绠楋紝鏃犻渶濉啓锛�", example = "100.00")
+    @DecimalMin(value = "0.01", message = "棰嗘枡鏁伴噺蹇呴』澶т簬 0")
     private BigDecimal quantity;
 
     @Schema(description = "鎵规ID", example = "1")
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/MesWmProductSalesLineController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/MesWmProductSalesLineController.java
index 336da58..b016839 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/MesWmProductSalesLineController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/MesWmProductSalesLineController.java
@@ -9,6 +9,8 @@
 import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.line.MesWmProductSalesLineRespVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.line.MesWmProductSalesLineSaveReqVO;
 import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
+import cn.iocoder.yudao.module.mdm.api.item.MdmItemModelApi;
+import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemModelRespDTO;
 import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO;
 
 
@@ -28,8 +30,10 @@
 import org.springframework.web.bind.annotation.*;
 
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@@ -45,6 +49,8 @@
     private MesWmProductSalesLineService productSalesLineService;
     @Resource
     private MdmItemApi mdmItemApi;
+    @Resource
+    private MdmItemModelApi mdmItemModelApi;
     @Resource
     private MdmUnitMeasureApi mdmUnitMeasureApi;
 
@@ -103,17 +109,25 @@
         // 1. 鑾峰緱鍏宠仈鏁版嵁
         Map<Long, MdmItemRespDTO> itemMap = mdmItemApi.getItemMap(
                 convertSet(list, MesWmProductSalesLineDO::getItemId));
-        Map<Long, MdmUnitMeasureRespDTO> unitMeasureMap = mdmUnitMeasureApi.getUnitMeasureList(
-                        convertSet(itemMap.values(), MdmItemRespDTO::getUnitMeasureId)).getCheckedData()
-                .stream().collect(Collectors.toMap(MdmUnitMeasureRespDTO::getId, e -> e));
+        // 鐗╂枡涓诲崟浣嶄笌褰曞叆鍗曚綅閮借瑙f瀽鍚嶇О
+        Set<Long> unitMeasureIds = new HashSet<>(convertSet(itemMap.values(), MdmItemRespDTO::getUnitMeasureId));
+        unitMeasureIds.addAll(convertSet(list, MesWmProductSalesLineDO::getEnterUnitMeasureId));
+        Map<Long, MdmUnitMeasureRespDTO> unitMeasureMap = mdmUnitMeasureApi.getUnitMeasureList(unitMeasureIds)
+                .getCheckedData().stream().collect(Collectors.toMap(MdmUnitMeasureRespDTO::getId, e -> e));
+        Map<Long, MdmItemModelRespDTO> itemModelMap = mdmItemModelApi.getItemModelMap(
+                convertSet(list, MesWmProductSalesLineDO::getItemModelId));
         // 2. 鏋勫缓缁撴灉
         return BeanUtils.toBean(list, MesWmProductSalesLineRespVO.class, vo -> {
             MapUtils.findAndThen(itemMap, vo.getItemId(), item -> {
                 vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification());
+                vo.setUnitMeasureId(item.getUnitMeasureId());
                 MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(),
                         unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName()));
             });
-
+            MapUtils.findAndThen(unitMeasureMap, vo.getEnterUnitMeasureId(),
+                    unitMeasure -> vo.setEnterUnitMeasureName(unitMeasure.getName()));
+            MapUtils.findAndThen(itemModelMap, vo.getItemModelId(),
+                    itemModel -> vo.setItemModel(itemModel.getModel()));
         });
     }
 
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLineRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLineRespVO.java
index 67e244b..adbe27a 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLineRespVO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLineRespVO.java
@@ -31,10 +31,28 @@
     @Schema(description = "瑙勬牸鍨嬪彿", example = "100g")
     private String specification;
 
-    @Schema(description = "鍗曚綅鍚嶇О", example = "涓�")
+    @Schema(description = "涓昏閲忓崟浣嶇紪鍙凤紙鐗╂枡涓诲崟浣嶏級", example = "1")
+    private Long unitMeasureId;
+
+    @Schema(description = "涓昏閲忓崟浣嶅悕绉�", example = "涓�")
     private String unitMeasureName;
 
-    @Schema(description = "鍑哄簱鏁伴噺", example = "100")
+    @Schema(description = "鐗╂枡鍨嬪彿缂栧彿", example = "1")
+    private Long itemModelId;
+
+    @Schema(description = "鐗╂枡鍨嬪彿鍚嶇О", example = "4绫�/鏍�")
+    private String itemModel;
+
+    @Schema(description = "褰曞叆鍗曚綅缂栧彿", example = "7")
+    private Long enterUnitMeasureId;
+
+    @Schema(description = "褰曞叆鍗曚綅鍚嶇О", example = "鏍�")
+    private String enterUnitMeasureName;
+
+    @Schema(description = "褰曞叆鏁伴噺锛堟寜褰曞叆鍗曚綅璁★級", example = "10.00")
+    private BigDecimal enterQuantity;
+
+    @Schema(description = "鍑哄簱鏁伴噺锛堢墿鏂欎富鍗曚綅鍙e緞锛�", example = "100")
     private BigDecimal quantity;
 
     @Schema(description = "鎵规ID", example = "1")
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLineSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLineSaveReqVO.java
index 67e7c3b..135fad0 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLineSaveReqVO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLineSaveReqVO.java
@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.line;
 
 import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.DecimalMin;
 import jakarta.validation.constraints.NotNull;
 import lombok.Data;
 
@@ -24,8 +25,18 @@
     @NotNull(message = "鐗╂枡涓嶈兘涓虹┖")
     private Long itemId;
 
-    @Schema(description = "鍑哄簱鏁伴噺", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
-    @NotNull(message = "鍑哄簱鏁伴噺涓嶈兘涓虹┖")
+    @Schema(description = "鐗╂枡鍨嬪彿缂栧彿锛堥�夋嫨鍨嬪彿鍚庢寜鍏跺崟浣嶄笌鎹㈢畻姣旂巼鎹㈢畻涓轰富鍗曚綅鏁伴噺锛�", example = "1")
+    private Long itemModelId;
+
+    @Schema(description = "褰曞叆鍗曚綅缂栧彿锛堜笉浼犳垨浼犵墿鏂欎富鍗曚綅鏃舵寜涓诲崟浣嶅綍鍏ワ級", example = "7")
+    private Long enterUnitMeasureId;
+
+    @Schema(description = "褰曞叆鏁伴噺锛堟寜褰曞叆鍗曚綅璁★紝绯荤粺鎹鎹㈢畻鍑哄簱鏁伴噺锛�", example = "10.00")
+    @DecimalMin(value = "0", inclusive = false, message = "褰曞叆鏁伴噺蹇呴』澶т簬 0")
+    private BigDecimal enterQuantity;
+
+    @Schema(description = "鍑哄簱鏁伴噺锛堢墿鏂欎富鍗曚綅鍙e緞锛涗紶浜嗗綍鍏ユ暟閲忔椂鐢辩郴缁熸崲绠楋紝鏃犻渶濉啓锛�", example = "100")
+    @DecimalMin(value = "0.01", message = "鍑哄簱鏁伴噺蹇呴』澶т簬 0")
     private BigDecimal quantity;
 
     @Schema(description = "鎵规ID", example = "1")
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/MesWmReturnVendorLineController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/MesWmReturnVendorLineController.java
index a03aaf6..3436279 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/MesWmReturnVendorLineController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/MesWmReturnVendorLineController.java
@@ -9,6 +9,8 @@
 import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.line.MesWmReturnVendorLineRespVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.line.MesWmReturnVendorLineSaveReqVO;
 import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
+import cn.iocoder.yudao.module.mdm.api.item.MdmItemModelApi;
+import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemModelRespDTO;
 import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO;
 
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor.MesWmReturnVendorLineDO;
@@ -26,8 +28,10 @@
 import org.springframework.web.bind.annotation.*;
 
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@@ -43,6 +47,8 @@
     private MesWmReturnVendorLineService returnVendorLineService;
     @Resource
     private MdmItemApi mdmItemApi;
+    @Resource
+    private MdmItemModelApi mdmItemModelApi;
     @Resource
     private MdmUnitMeasureApi mdmUnitMeasureApi;
 
@@ -110,18 +116,27 @@
         // 1. 鑾峰緱鍏宠仈鏁版嵁
         Map<Long, MdmItemRespDTO> itemMap = mdmItemApi.getItemMap(
                 convertSet(list, MesWmReturnVendorLineDO::getItemId));
-        Map<Long, MdmUnitMeasureRespDTO> unitMeasureMap = mdmUnitMeasureApi.getUnitMeasureList(
-                convertSet(itemMap.values(), MdmItemRespDTO::getUnitMeasureId)).getCheckedData()
-                .stream().collect(Collectors.toMap(MdmUnitMeasureRespDTO::getId, e -> e));
+        // 鐗╂枡涓诲崟浣嶄笌褰曞叆鍗曚綅閮借瑙f瀽鍚嶇О
+        Set<Long> unitMeasureIds = new HashSet<>(convertSet(itemMap.values(), MdmItemRespDTO::getUnitMeasureId));
+        unitMeasureIds.addAll(convertSet(list, MesWmReturnVendorLineDO::getEnterUnitMeasureId));
+        Map<Long, MdmUnitMeasureRespDTO> unitMeasureMap = mdmUnitMeasureApi.getUnitMeasureList(unitMeasureIds)
+                .getCheckedData().stream().collect(Collectors.toMap(MdmUnitMeasureRespDTO::getId, e -> e));
+        Map<Long, MdmItemModelRespDTO> itemModelMap = mdmItemModelApi.getItemModelMap(
+                convertSet(list, MesWmReturnVendorLineDO::getItemModelId));
         // 2. 鏋勫缓缁撴灉
         return BeanUtils.toBean(list, MesWmReturnVendorLineRespVO.class, vo -> {
             MapUtils.findAndThen(itemMap, vo.getItemId(), item -> {
                 vo.setItemCode(item.getCode());
                 vo.setItemName(item.getName());
                 vo.setSpecification(item.getSpecification());
+                vo.setUnitMeasureId(item.getUnitMeasureId());
                 MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(),
                         unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName()));
             });
+            MapUtils.findAndThen(unitMeasureMap, vo.getEnterUnitMeasureId(),
+                    unitMeasure -> vo.setEnterUnitMeasureName(unitMeasure.getName()));
+            MapUtils.findAndThen(itemModelMap, vo.getItemModelId(),
+                    itemModel -> vo.setItemModel(itemModel.getModel()));
         });
     }
 
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/line/MesWmReturnVendorLineRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/line/MesWmReturnVendorLineRespVO.java
index 2fb1a11..7e4a1f3 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/line/MesWmReturnVendorLineRespVO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/line/MesWmReturnVendorLineRespVO.java
@@ -28,10 +28,28 @@
     @Schema(description = "瑙勬牸鍨嬪彿", example = "10mm*100mm")
     private String specification;
 
-    @Schema(description = "璁¢噺鍗曚綅鍚嶇О", example = "鍗冨厠")
+    @Schema(description = "涓昏閲忓崟浣嶇紪鍙凤紙鐗╂枡涓诲崟浣嶏級", example = "1")
+    private Long unitMeasureId;
+
+    @Schema(description = "涓昏閲忓崟浣嶅悕绉�", example = "鍗冨厠")
     private String unitMeasureName;
 
-    @Schema(description = "閫�璐ф暟閲�", example = "100.00")
+    @Schema(description = "鐗╂枡鍨嬪彿缂栧彿", example = "1")
+    private Long itemModelId;
+
+    @Schema(description = "鐗╂枡鍨嬪彿鍚嶇О", example = "4绫�/鏍�")
+    private String itemModel;
+
+    @Schema(description = "褰曞叆鍗曚綅缂栧彿", example = "7")
+    private Long enterUnitMeasureId;
+
+    @Schema(description = "褰曞叆鍗曚綅鍚嶇О", example = "鏍�")
+    private String enterUnitMeasureName;
+
+    @Schema(description = "褰曞叆鏁伴噺锛堟寜褰曞叆鍗曚綅璁★級", example = "10.00")
+    private BigDecimal enterQuantity;
+
+    @Schema(description = "閫�璐ф暟閲忥紙鐗╂枡涓诲崟浣嶅彛寰勶級", example = "100.00")
     private BigDecimal quantity;
 
     @Schema(description = "鎵规ID", example = "1")
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/line/MesWmReturnVendorLineSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/line/MesWmReturnVendorLineSaveReqVO.java
index 78abd59..8a51c4a 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/line/MesWmReturnVendorLineSaveReqVO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/line/MesWmReturnVendorLineSaveReqVO.java
@@ -22,9 +22,18 @@
     @NotNull(message = "鐗╂枡ID涓嶈兘涓虹┖")
     private Long itemId;
 
-    @Schema(description = "閫�璐ф暟閲�", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
-    @NotNull(message = "閫�璐ф暟閲忎笉鑳戒负绌�")
-    @DecimalMin(value = "0", inclusive = false, message = "閫�璐ф暟閲忓繀椤诲ぇ浜� 0")
+    @Schema(description = "鐗╂枡鍨嬪彿缂栧彿锛堥�夋嫨鍨嬪彿鍚庢寜鍏跺崟浣嶄笌鎹㈢畻姣旂巼鎹㈢畻涓轰富鍗曚綅鏁伴噺锛�", example = "1")
+    private Long itemModelId;
+
+    @Schema(description = "褰曞叆鍗曚綅缂栧彿锛堜笉浼犳垨浼犵墿鏂欎富鍗曚綅鏃舵寜涓诲崟浣嶅綍鍏ワ級", example = "7")
+    private Long enterUnitMeasureId;
+
+    @Schema(description = "褰曞叆鏁伴噺锛堟寜褰曞叆鍗曚綅璁★紝绯荤粺鎹鎹㈢畻鍑哄簱鏁伴噺锛�", example = "10.00")
+    @DecimalMin(value = "0", inclusive = false, message = "褰曞叆鏁伴噺蹇呴』澶т簬 0")
+    private BigDecimal enterQuantity;
+
+    @Schema(description = "閫�璐ф暟閲忥紙鐗╂枡涓诲崟浣嶅彛寰勶紱浼犱簡褰曞叆鏁伴噺鏃剁敱绯荤粺鎹㈢畻锛屾棤闇�濉啓锛�", example = "100.00")
+    @DecimalMin(value = "0.01", message = "閫�璐ф暟閲忓繀椤诲ぇ浜� 0")
     private BigDecimal quantity;
 
     @Schema(description = "鎵规ID", example = "1")
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptLineDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptLineDO.java
index ae2d13e..8eba872 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptLineDO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptLineDO.java
@@ -55,7 +55,30 @@
      */
     private Long itemId;
     /**
-     * 鍏ュ簱鏁伴噺
+     * 鐗╂枡鍨嬪彿缂栧彿
+     *
+     * 鍏宠仈 {@link cn.iocoder.yudao.module.mdm.dal.dataobject.item.MdmItemModelDO#getId()}
+     */
+    private Long itemModelId;
+    /**
+     * 鐗╂枡鍨嬪彿鍚嶇О
+     */
+    private String itemModel;
+    /**
+     * 褰曞叆鍗曚綅缂栧彿
+     *
+     * 鍏宠仈 {@link cn.iocoder.yudao.module.mdm.dal.dataobject.unit.MdmUnitMeasureDO#getId()}
+     * 涓虹┖鎴栫瓑浜庣墿鏂欎富鍗曚綅鏃讹紝璇存槑鏈鎸変富鍗曚綅褰曞叆
+     */
+    private Long enterUnitMeasureId;
+    /**
+     * 褰曞叆鏁伴噺锛堟寜褰曞叆鍗曚綅璁★級
+     *
+     * 鎸変富鍗曚綅褰曞叆鏃朵笌 {@link #receivedQuantity} 鐩稿悓
+     */
+    private BigDecimal enterQuantity;
+    /**
+     * 鍏ュ簱鏁伴噺锛堢墿鏂欎富鍗曚綅鍙e緞锛屽簱瀛樹笌娴佹按鍧囦互璇ユ暟閲忎负鍑嗭級
      */
     private BigDecimal receivedQuantity;
     /**
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscissue/MesWmMiscIssueLineDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscissue/MesWmMiscIssueLineDO.java
index 9a05b50..23ce928 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscissue/MesWmMiscIssueLineDO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscissue/MesWmMiscIssueLineDO.java
@@ -52,7 +52,26 @@
      */
     private Long itemId;
     /**
-     * 鍑哄簱鏁伴噺
+     * 鐗╂枡鍨嬪彿缂栧彿
+     *
+     * 鍏宠仈 {@link cn.iocoder.yudao.module.mdm.dal.dataobject.item.MdmItemModelDO#getId()}
+     */
+    private Long itemModelId;
+    /**
+     * 褰曞叆鍗曚綅缂栧彿
+     *
+     * 鍏宠仈 {@link cn.iocoder.yudao.module.mdm.dal.dataobject.unit.MdmUnitMeasureDO#getId()}
+     * 涓虹┖鎴栫瓑浜庣墿鏂欎富鍗曚綅鏃讹紝璇存槑鏈鎸変富鍗曚綅褰曞叆
+     */
+    private Long enterUnitMeasureId;
+    /**
+     * 褰曞叆鏁伴噺锛堟寜褰曞叆鍗曚綅璁★級
+     *
+     * 鎸変富鍗曚綅褰曞叆鏃朵笌 {@link #quantity} 鐩稿悓
+     */
+    private BigDecimal enterQuantity;
+    /**
+     * 鍑哄簱鏁伴噺锛堢墿鏂欎富鍗曚綅鍙e緞锛屽簱瀛樹笌娴佹按鍧囦互璇ユ暟閲忎负鍑嗭級
      */
     private BigDecimal quantity;
     /**
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueLineDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueLineDO.java
index d363320..8c2f874 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueLineDO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueLineDO.java
@@ -46,7 +46,26 @@
      */
     private Long itemId;
     /**
-     * 鍙戞枡鏁伴噺
+     * 鐗╂枡鍨嬪彿缂栧彿
+     *
+     * 鍏宠仈 {@link cn.iocoder.yudao.module.mdm.dal.dataobject.item.MdmItemModelDO#getId()}
+     */
+    private Long itemModelId;
+    /**
+     * 褰曞叆鍗曚綅缂栧彿
+     *
+     * 鍏宠仈 {@link cn.iocoder.yudao.module.mdm.dal.dataobject.unit.MdmUnitMeasureDO#getId()}
+     * 涓虹┖鎴栫瓑浜庣墿鏂欎富鍗曚綅鏃讹紝璇存槑鏈鎸変富鍗曚綅褰曞叆
+     */
+    private Long enterUnitMeasureId;
+    /**
+     * 褰曞叆鏁伴噺锛堟寜褰曞叆鍗曚綅璁★級
+     *
+     * 鎸変富鍗曚綅褰曞叆鏃朵笌 {@link #quantity} 鐩稿悓
+     */
+    private BigDecimal enterQuantity;
+    /**
+     * 鍙戞枡鏁伴噺锛堢墿鏂欎富鍗曚綅鍙e緞锛屽簱瀛樹笌娴佹按鍧囦互璇ユ暟閲忎负鍑嗭級
      */
     private BigDecimal quantity;
     /**
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productissue/MesWmProductIssueLineDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productissue/MesWmProductIssueLineDO.java
index e789f1d..bc2ebc6 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productissue/MesWmProductIssueLineDO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productissue/MesWmProductIssueLineDO.java
@@ -47,7 +47,26 @@
      */
     private Long itemId;
     /**
-     * 棰嗘枡鏁伴噺
+     * 鐗╂枡鍨嬪彿缂栧彿
+     *
+     * 鍏宠仈 {@link cn.iocoder.yudao.module.mdm.dal.dataobject.item.MdmItemModelDO#getId()}
+     */
+    private Long itemModelId;
+    /**
+     * 褰曞叆鍗曚綅缂栧彿
+     *
+     * 鍏宠仈 {@link cn.iocoder.yudao.module.mdm.dal.dataobject.unit.MdmUnitMeasureDO#getId()}
+     * 涓虹┖鎴栫瓑浜庣墿鏂欎富鍗曚綅鏃讹紝璇存槑鏈鎸変富鍗曚綅褰曞叆
+     */
+    private Long enterUnitMeasureId;
+    /**
+     * 褰曞叆鏁伴噺锛堟寜褰曞叆鍗曚綅璁★級
+     *
+     * 鎸変富鍗曚綅褰曞叆鏃朵笌 {@link #quantity} 鐩稿悓
+     */
+    private BigDecimal enterQuantity;
+    /**
+     * 棰嗘枡鏁伴噺锛堢墿鏂欎富鍗曚綅鍙e緞锛屽簱瀛樹笌娴佹按鍧囦互璇ユ暟閲忎负鍑嗭級
      */
     private BigDecimal quantity;
     /**
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesLineDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesLineDO.java
index f76011b..663a20d 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesLineDO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesLineDO.java
@@ -58,7 +58,26 @@
      */
     private Long itemId;
     /**
-     * 鍑哄簱鏁伴噺
+     * 鐗╂枡鍨嬪彿缂栧彿
+     *
+     * 鍏宠仈 {@link cn.iocoder.yudao.module.mdm.dal.dataobject.item.MdmItemModelDO#getId()}
+     */
+    private Long itemModelId;
+    /**
+     * 褰曞叆鍗曚綅缂栧彿
+     *
+     * 鍏宠仈 {@link cn.iocoder.yudao.module.mdm.dal.dataobject.unit.MdmUnitMeasureDO#getId()}
+     * 涓虹┖鎴栫瓑浜庣墿鏂欎富鍗曚綅鏃讹紝璇存槑鏈鎸変富鍗曚綅褰曞叆
+     */
+    private Long enterUnitMeasureId;
+    /**
+     * 褰曞叆鏁伴噺锛堟寜褰曞叆鍗曚綅璁★級
+     *
+     * 鎸変富鍗曚綅褰曞叆鏃朵笌 {@link #quantity} 鐩稿悓
+     */
+    private BigDecimal enterQuantity;
+    /**
+     * 鍑哄簱鏁伴噺锛堢墿鏂欎富鍗曚綅鍙e緞锛屽簱瀛樹笌娴佹按鍧囦互璇ユ暟閲忎负鍑嗭級
      */
     private BigDecimal quantity;
     /**
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnvendor/MesWmReturnVendorLineDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnvendor/MesWmReturnVendorLineDO.java
index 8ef63bf..949d3fa 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnvendor/MesWmReturnVendorLineDO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnvendor/MesWmReturnVendorLineDO.java
@@ -41,7 +41,26 @@
      */
     private Long itemId;
     /**
-     * 閫�璐ф暟閲�
+     * 鐗╂枡鍨嬪彿缂栧彿
+     *
+     * 鍏宠仈 {@link cn.iocoder.yudao.module.mdm.dal.dataobject.item.MdmItemModelDO#getId()}
+     */
+    private Long itemModelId;
+    /**
+     * 褰曞叆鍗曚綅缂栧彿
+     *
+     * 鍏宠仈 {@link cn.iocoder.yudao.module.mdm.dal.dataobject.unit.MdmUnitMeasureDO#getId()}
+     * 涓虹┖鎴栫瓑浜庣墿鏂欎富鍗曚綅鏃讹紝璇存槑鏈鎸変富鍗曚綅褰曞叆
+     */
+    private Long enterUnitMeasureId;
+    /**
+     * 褰曞叆鏁伴噺锛堟寜褰曞叆鍗曚綅璁★級
+     *
+     * 鎸変富鍗曚綅褰曞叆鏃朵笌 {@link #quantity} 鐩稿悓
+     */
+    private BigDecimal enterQuantity;
+    /**
+     * 閫�璐ф暟閲忥紙鐗╂枡涓诲崟浣嶅彛寰勶紝搴撳瓨涓庢祦姘村潎浠ヨ鏁伴噺涓哄噯锛�
      */
     private BigDecimal quantity;
     /**
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 44b3741..552de15 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
@@ -395,6 +395,7 @@
     ErrorCode QC_IQC_CHECK_RESULT_EMPTY = new ErrorCode(1_040_603_007, "瀹屾垚妫�楠屽崟鍓嶏紝妫�娴嬬粨鏋滃繀椤诲~鍐�");
     ErrorCode QC_IQC_TEMPLATE_IS_DISABLE = new ErrorCode(1_040_603_009, "鎵�閫夎川妫�鏂规銆恵}銆戝凡绂佺敤锛岃閲嶆柊閫夋嫨宸插惎鐢ㄧ殑璐ㄦ鏂规");
     ErrorCode QC_IQC_TEMPLATE_TYPE_NOT_MATCH = new ErrorCode(1_040_603_010, "鎵�閫夎川妫�鏂规銆恵}銆戠殑妫�娴嬬绫讳笉鍖呭惈鏉ユ枡妫�楠岋紝璇烽噸鏂伴�夋嫨妫�娴嬬绫诲寘鍚潵鏂欐楠岀殑璐ㄦ鏂规");
+    ErrorCode QC_IQC_NO_ENABLED_TEMPLATE = new ErrorCode(1_040_603_011, "绯荤粺涓病鏈夊惎鐢ㄧ殑鏉ユ枡妫�楠岋紙IQC锛夎川妫�鏂规锛屾棤娉曡嚜鍔ㄧ敓鎴愭楠屽崟锛氳鍏堝湪銆愯川閲忕鐞�-璐ㄦ鏂规銆戜腑鏂板缓鎴栧惎鐢ㄤ竴涓娴嬬绫诲寘鍚潵鏂欐楠岀殑鏂规");
     // ========== MES 璐ㄩ噺绠$悊-鏉ユ枡妫�楠岃锛�1-040-603-100锛� ==========
     ErrorCode QC_IQC_LINE_NOT_EXISTS = new ErrorCode(1_040_603_100, "鏉ユ枡妫�楠岃涓嶅瓨鍦�");
 
@@ -514,6 +515,18 @@
     ErrorCode WM_MATERIAL_STOCK_IMPORT_OPERATION_INVALID = new ErrorCode(1_040_703_027, "鎿嶄綔绫诲瀷({})涓嶆敮鎸�");
     ErrorCode WM_MATERIAL_STOCK_IMPORT_STOCK_NOT_EXISTS = new ErrorCode(1_040_703_028, "搴撳瓨璁板綍涓嶅瓨鍦紝鏃犳硶鎵ц璇ユ搷浣�");
 
+    // ---- 涓昏緟鍗曚綅鎹㈢畻锛堢粨鍚堢墿鏂欏瀷鍙凤級 ----
+    ErrorCode WM_ITEM_UNIT_CONVERT_NOT_CONFIGURED = new ErrorCode(1_040_703_029,
+            "鐗╂枡銆恵}-{}銆戞病鏈夐厤缃閲忓崟浣嶃�恵}銆戝埌涓诲崟浣嶃�恵}銆戠殑鎹㈢畻姣旂巼锛屾棤娉曟崲绠楋紝璇峰厛鍒般�愬熀纭�鏁版嵁-鐗╂枡涓绘暟鎹�-鍨嬪彿銆戜负璇ョ墿鏂欐柊澧炲瀷鍙峰苟濉啓鎹㈢畻姣旂巼");
+    ErrorCode WM_ITEM_UNIT_CONVERT_MODEL_UNIT_MISMATCH = new ErrorCode(1_040_703_030,
+            "鎵�閫夊瀷鍙枫�恵}銆戠殑璁¢噺鍗曚綅鏄�恵}銆戯紝涓庢湰娆″綍鍏ュ崟浣嶃�恵}銆戜笉涓�鑷达紝璇烽噸鏂伴�夋嫨鍨嬪彿鎴栨敼鍥炲瀷鍙峰搴旂殑璁¢噺鍗曚綅");
+    ErrorCode WM_ITEM_UNIT_CONVERT_QUANTITY_REQUIRED = new ErrorCode(1_040_703_031,
+            "璁¢噺鍗曚綅銆恵}銆戜笉鏄墿鏂欍�恵}-{}銆戠殑涓诲崟浣嶏紝鎸夎鍗曚綅褰曞叆鏃跺綍鍏ユ暟閲忎笉鑳戒负绌猴紝璇峰~鍐欏綍鍏ユ暟閲忔垨鏀圭敤涓诲崟浣嶃�恵}銆�");
+    ErrorCode WM_ITEM_UNIT_CONVERT_MODEL_REQUIRED = new ErrorCode(1_040_703_032,
+            "璁¢噺鍗曚綅銆恵}銆戠殑鎹㈢畻姣旂巼鐢卞瀷鍙峰喅瀹氾紝璇峰厛閫夋嫨鐗╂枡銆恵}-{}銆戠殑鍨嬪彿鍚庡啀褰曞叆鏁伴噺");
+    ErrorCode WM_ITEM_UNIT_CONVERT_RATE_INVALID = new ErrorCode(1_040_703_033,
+            "鍨嬪彿銆恵}銆戠殑鎹㈢畻姣旂巼涓恒�恵}銆戜笉鍚堢悊锛�1 涓瀷鍙峰崟浣嶅繀椤诲搴斿ぇ浜� 0 鐨勪富鍗曚綅鏁伴噺锛岃鍒般�愬熀纭�鏁版嵁-鐗╂枡涓绘暟鎹�-鍨嬪彿銆戜慨姝h鍨嬪彿鐨勬崲绠楁瘮鐜�");
+
     // ========== MES 浠撳簱绠$悊-鍒拌揣閫氱煡鍗曪紙1-040-704-000锛� ==========
     ErrorCode WM_ARRIVAL_NOTICE_NOT_EXISTS = new ErrorCode(1_040_704_000, "鍒拌揣閫氱煡鍗曚笉瀛樺湪");
     ErrorCode WM_ARRIVAL_NOTICE_CODE_DUPLICATE = new ErrorCode(1_040_704_001, "鍒拌揣閫氱煡鍗曠紪鐮佸凡瀛樺湪");
@@ -543,6 +556,8 @@
             "鍏ュ簱鍗曞叧鑱斾簡鍒拌揣閫氱煡鍗曪紝蹇呴』閫夋嫨鍒拌揣閫氱煡鍗曡");
     ErrorCode WM_ITEM_RECEIPT_LINE_ARRIVAL_NOTICE_LINE_NOT_ALLOWED = new ErrorCode(1_040_705_102,
             "鍏ュ簱鍗曟湭鍏宠仈鍒拌揣閫氱煡鍗曪紝涓嶈兘閫夋嫨鍒拌揣閫氱煡鍗曡");
+    ErrorCode WM_ITEM_RECEIPT_LINE_QUANTITY_REQUIRED = new ErrorCode(1_040_705_103,
+            "璇峰~鍐欏叆搴撴暟閲忥紝鎴栭�夋嫨褰曞叆鍗曚綅骞跺~鍐欏綍鍏ユ暟閲忓悗鐢辩郴缁熻嚜鍔ㄦ崲绠�");
     ErrorCode WM_ITEM_RECEIPT_DETAIL_NOT_EXISTS = new ErrorCode(1_040_705_200, "閲囪喘鍏ュ簱鏄庣粏涓嶅瓨鍦�");
     ErrorCode WM_ITEM_RECEIPT_DETAIL_QUANTITY_EXCEED = new ErrorCode(1_040_705_202, "涓婃灦鏄庣粏鎬绘暟閲忎笉鑳借秴杩囪鍏ュ簱鏁伴噺");
     ErrorCode WM_ITEM_RECEIPT_BATCH_REQUIRED = new ErrorCode(1_040_705_203, "鐗╂枡銆恵}-{}銆戝凡寮�鍚壒娆$鐞嗭紝涓婃灦鏄庣粏鐨勬壒娆″彿涓嶈兘涓虹┖");
@@ -563,6 +578,8 @@
     ErrorCode WM_OUTSOURCE_ISSUE_CANCEL_NOT_ALLOWED = new ErrorCode(1_040_707_007, "宸插畬鎴愭垨宸插彇娑堢殑鍙戞枡鍗曚笉鍏佽鍙栨秷");
     ErrorCode WM_OUTSOURCE_ISSUE_LINE_NOT_EXISTS = new ErrorCode(1_040_707_100, "澶栧崗鍙戞枡鍗曡涓嶅瓨鍦�");
     ErrorCode WM_OUTSOURCE_ISSUE_LINE_ITEM_NOT_IN_BOM = new ErrorCode(1_040_707_101, "鍙戞枡鍗曡瀵瑰簲鐨勭墿鏂欎笉鍦ㄥ綋鍓嶅伐鍗曠殑 BOM 鍒楄〃涓�");
+    ErrorCode WM_OUTSOURCE_ISSUE_LINE_QUANTITY_REQUIRED = new ErrorCode(1_040_707_102,
+            "璇峰~鍐欏嚭搴撴暟閲忥紝鎴栭�夋嫨褰曞叆鍗曚綅骞跺~鍐欏綍鍏ユ暟閲忓悗鐢辩郴缁熻嚜鍔ㄦ崲绠�");
     ErrorCode WM_OUTSOURCE_ISSUE_DETAIL_NOT_EXISTS = new ErrorCode(1_040_707_200, "澶栧崗鍙戞枡鍗曟槑缁嗕笉瀛樺湪");
     ErrorCode WM_OUTSOURCE_ISSUE_DETAIL_LINE_NOT_MATCH = new ErrorCode(1_040_707_201, "鎷h揣鏄庣粏涓嶅睘浜庢寚瀹氱殑澶栧崗鍙戞枡鍗�");
     ErrorCode WM_OUTSOURCE_ISSUE_DETAIL_ITEM_MISMATCH = new ErrorCode(1_040_707_202, "鎷h揣鏄庣粏鐨勭墿鏂欎笌澶栧崗鍙戞枡鍗曡鐨勭墿鏂欎笉涓�鑷�");
@@ -579,6 +596,8 @@
     ErrorCode WM_PRODUCT_ISSUE_LINE_NOT_EXISTS = new ErrorCode(1_040_708_100, "鐢熶骇棰嗘枡鍑哄簱鍗曡涓嶅瓨鍦�");
     ErrorCode WM_PRODUCT_ISSUE_LINE_ITEM_NOT_IN_BOM = new ErrorCode(1_040_708_101, "褰撳墠鐗╂枡涓嶅湪鐢熶骇宸ュ崟鐨� BOM 鐗╂枡娓呭崟涓�");
     ErrorCode WM_PRODUCT_ISSUE_CODE_DUPLICATE = new ErrorCode(1_040_708_102, "棰嗘枡鍑哄簱鍗曠紪鐮佸凡瀛樺湪");
+    ErrorCode WM_PRODUCT_ISSUE_LINE_QUANTITY_REQUIRED = new ErrorCode(1_040_708_103,
+            "璇峰~鍐欏嚭搴撴暟閲忥紝鎴栭�夋嫨褰曞叆鍗曚綅骞跺~鍐欏綍鍏ユ暟閲忓悗鐢辩郴缁熻嚜鍔ㄦ崲绠�");
     ErrorCode WM_PRODUCT_ISSUE_DETAIL_NOT_EXISTS = new ErrorCode(1_040_708_200, "鐢熶骇棰嗘枡鍑哄簱鍗曟槑缁嗕笉瀛樺湪");
     ErrorCode WM_PRODUCT_ISSUE_DETAIL_ITEM_MISMATCH = new ErrorCode(1_040_708_201, "鎷h揣鏄庣粏鐨勭墿鏂欎笌棰嗘枡鍗曡鐨勭墿鏂欎笉涓�鑷�");
     ErrorCode WM_PRODUCT_ISSUE_DETAIL_LINE_NOT_MATCH = new ErrorCode(1_040_708_202, "鎷h揣鏄庣粏涓嶅睘浜庢寚瀹氱殑棰嗘枡鍑哄簱鍗�");
@@ -639,6 +658,8 @@
     ErrorCode WM_RETURN_VENDOR_NO_DETAIL = new ErrorCode(1_040_711_006, "渚涘簲鍟嗛��璐у崟娌℃湁鎷h揣鏄庣粏锛屾棤娉曟墽琛岄��璐�");
     ErrorCode WM_RETURN_VENDOR_DETAIL_ITEM_MISMATCH = new ErrorCode(1_040_711_007, "鎷h揣鏄庣粏鐨勭墿鏂欎笌閫�璐у崟琛岀殑鐗╂枡涓嶄竴鑷�");
     ErrorCode WM_RETURN_VENDOR_LINE_NOT_EXISTS = new ErrorCode(1_040_711_100, "渚涘簲鍟嗛��璐у崟琛屼笉瀛樺湪");
+    ErrorCode WM_RETURN_VENDOR_LINE_QUANTITY_REQUIRED = new ErrorCode(1_040_711_101,
+            "璇峰~鍐欓��璐ф暟閲忥紝鎴栭�夋嫨褰曞叆鍗曚綅骞跺~鍐欏綍鍏ユ暟閲忓悗鐢辩郴缁熻嚜鍔ㄦ崲绠�");
     ErrorCode WM_RETURN_VENDOR_DETAIL_NOT_EXISTS = new ErrorCode(1_040_711_200, "渚涘簲鍟嗛��璐у崟鏄庣粏涓嶅瓨鍦�");
     ErrorCode WM_RETURN_VENDOR_DETAIL_QUANTITY_INVALID = new ErrorCode(1_040_711_201, "閫�璐ф槑缁嗘暟閲忓繀椤诲ぇ浜� 0");
     ErrorCode WM_RETURN_VENDOR_DETAIL_LINE_NOT_MATCH = new ErrorCode(1_040_711_202, "鎷h揣鏄庣粏涓嶅睘浜庢寚瀹氱殑渚涘簲鍟嗛��璐у崟");
@@ -735,6 +756,8 @@
             "鍑哄簱琛屾壒娆″彿涓庡彂璐ч�氱煡鍗曡鎵规鍙蜂笉涓�鑷�");
     ErrorCode WM_PRODUCT_SALES_LINE_NOTICE_LINE_OQC_MISMATCH = new ErrorCode(1_040_714_033,
             "鍑哄簱琛� OQC 妫�楠屾爣璇嗕笌鍙戣揣閫氱煡鍗曡涓嶄竴鑷�");
+    ErrorCode WM_PRODUCT_SALES_LINE_QUANTITY_REQUIRED = new ErrorCode(1_040_714_034,
+            "璇峰~鍐欏嚭搴撴暟閲忥紝鎴栭�夋嫨褰曞叆鍗曚綅骞跺~鍐欏綍鍏ユ暟閲忓悗鐢辩郴缁熻嚜鍔ㄦ崲绠�");
 
     // ========== MES 浠撳簱绠$悊-鏉傞」鍑哄簱鍗曪紙1-040-715-000锛� ==========
     ErrorCode WM_MISC_ISSUE_NOT_EXISTS = new ErrorCode(1_040_715_000, "鏉傞」鍑哄簱鍗曚笉瀛樺湪");
@@ -744,6 +767,8 @@
     ErrorCode WM_MISC_ISSUE_CANCEL_NOT_ALLOWED = new ErrorCode(1_040_715_004, "鏉傞」鍑哄簱鍗曞凡瀹屾垚鎴栧凡鍙栨秷锛屾棤娉曞彇娑�");
     ErrorCode WM_MISC_ISSUE_DETAIL_QUANTITY_MISMATCH = new ErrorCode(1_040_715_005, "鏉傞」鍑哄簱鍗曡鏁伴噺涓庢槑缁嗘暟閲忎笉涓�鑷�");
     ErrorCode WM_MISC_ISSUE_LINE_NOT_EXISTS = new ErrorCode(1_040_715_100, "鏉傞」鍑哄簱鍗曡涓嶅瓨鍦�");
+    ErrorCode WM_MISC_ISSUE_LINE_QUANTITY_REQUIRED = new ErrorCode(1_040_715_101,
+            "璇峰~鍐欏嚭搴撴暟閲忥紝鎴栭�夋嫨褰曞叆鍗曚綅骞跺~鍐欏綍鍏ユ暟閲忓悗鐢辩郴缁熻嚜鍔ㄦ崲绠�");
     ErrorCode WM_MISC_ISSUE_DETAIL_NOT_EXISTS = new ErrorCode(1_040_715_200, "鏉傞」鍑哄簱鍗曟槑缁嗕笉瀛樺湪");
 
     // ========== MES 浠撳簱绠$悊-鏉傞」鍏ュ簱鍗曪紙1-040-716-000锛� ==========
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryService.java
index 06d1735..1423ac1 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryService.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryService.java
@@ -45,6 +45,13 @@
     void deleteMachinery(Long id);
 
     /**
+     * 鎵归噺鍒犻櫎璁惧
+     *
+     * @param ids 缂栧彿鏁扮粍
+     */
+    void deleteMachineryList(Collection<Long> ids);
+
+    /**
      * 鑾峰緱璁惧
      *
      * @param id 缂栧彿
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryServiceImpl.java
index 35ded24..792b4be 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryServiceImpl.java
@@ -4,6 +4,7 @@
 import cn.hutool.core.util.ObjUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+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.dv.machinery.vo.MesDvMachineryImportExcelVO;
@@ -109,26 +110,54 @@
     @Override
     public void deleteMachinery(Long id) {
         // 鏍¢獙瀛樺湪
-        validateMachineryExists(id);
+        MesDvMachineryDO machinery = machineryMapper.selectById(id);
+        if (machinery == null) {
+            throw exception(DV_MACHINERY_NOT_EXISTS);
+        }
         // 鏍¢獙鍏宠仈鏁版嵁
-        if (checkPlanMachineryService.getCheckPlanMachineryCountByMachineryId(id) > 0) {
-            throw exception(DV_MACHINERY_HAS_CHECK_PLAN);
-        }
-        if (checkRecordService.getCheckRecordCountByMachineryId(id) > 0) {
-            throw exception(DV_MACHINERY_HAS_CHECK_RECORD);
-        }
-        if (maintenRecordService.getMaintenRecordCountByMachineryId(id) > 0) {
-            throw exception(DV_MACHINERY_HAS_MAINTEN_RECORD);
-        }
-        if (repairService.getRepairCountByMachineryId(id) > 0) {
-            throw exception(DV_MACHINERY_HAS_REPAIR);
-        }
+        validateMachineryDeletable(machinery);
 
         // 鍒犻櫎
         machineryMapper.deleteById(id);
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void deleteMachineryList(Collection<Long> ids) {
+        if (CollUtil.isEmpty(ids)) {
+            return;
+        }
+        // 閫愪釜鍒犻櫎锛堝鐢ㄥ崟鏉″垹闄ら�昏緫锛屼繚鎸佹牎楠岋級锛屼换涓�澶辫触鍒欐暣浣撳洖婊�
+        ids.forEach(this::deleteMachinery);
+    }
+
+    /**
+     * 鏍¢獙璁惧鏄惁鍙垹闄わ紙鍏宠仈鐐规璁″垝/鐐规璁板綍/淇濆吇璁板綍/缁翠慨璁板綍浠讳竴瀛樺湪鍒欎笉鍏佽锛�
+     *
+     * @param machinery 璁惧
+     */
+    private void validateMachineryDeletable(MesDvMachineryDO machinery) {
+        Long id = machinery.getId();
+        String label = StrUtil.format("{}锛坽}锛�", machinery.getName(), machinery.getCode());
+        if (checkPlanMachineryService.getCheckPlanMachineryCountByMachineryId(id) > 0) {
+            throw new ServiceException(DV_MACHINERY_HAS_CHECK_PLAN.getCode(),
+                    StrUtil.format("璁惧{}宸插叧鑱旂偣妫�璁″垝锛屾棤娉曞垹闄わ紱璇峰厛鍦ㄧ偣妫�璁″垝涓Щ闄よ璁惧鍚庨噸璇�", label));
+        }
+        if (checkRecordService.getCheckRecordCountByMachineryId(id) > 0) {
+            throw new ServiceException(DV_MACHINERY_HAS_CHECK_RECORD.getCode(),
+                    StrUtil.format("璁惧{}宸插瓨鍦ㄧ偣妫�璁板綍锛屾棤娉曞垹闄わ紱濡傞渶鍒犻櫎璇峰厛澶勭悊璇ヨ澶囩殑鐐规璁板綍", label));
+        }
+        if (maintenRecordService.getMaintenRecordCountByMachineryId(id) > 0) {
+            throw new ServiceException(DV_MACHINERY_HAS_MAINTEN_RECORD.getCode(),
+                    StrUtil.format("璁惧{}宸插瓨鍦ㄤ繚鍏昏褰曪紝鏃犳硶鍒犻櫎锛涘闇�鍒犻櫎璇峰厛澶勭悊璇ヨ澶囩殑淇濆吇璁板綍", label));
+        }
+        if (repairService.getRepairCountByMachineryId(id) > 0) {
+            throw new ServiceException(DV_MACHINERY_HAS_REPAIR.getCode(),
+                    StrUtil.format("璁惧{}宸插瓨鍦ㄧ淮淇褰曪紝鏃犳硶鍒犻櫎锛涘闇�鍒犻櫎璇峰厛澶勭悊璇ヨ澶囩殑缁翠慨璁板綍", label));
+        }
+    }
+
+    @Override
     public void validateMachineryExists(Long id) {
         if (machineryMapper.selectById(id) == null) {
             throw exception(DV_MACHINERY_NOT_EXISTS);
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 1281815..d30aa6b 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
@@ -106,7 +106,7 @@
         // 1.2 鏍¢獙鏉ユ簮鍗曟嵁鍙傛暟锛屽苟楠岃瘉鏁版嵁瀛樺湪
         String sourceDocCode = validateAndGetSourceDocCode(
                 createReqVO.getSourceDocType(), createReqVO.getSourceDocId(), createReqVO.getSourceLineId());
-        // 1.3 纭畾璐ㄦ鏂规锛氭樉寮忔寚瀹氭椂鏍¢獙鏂规鏈韩鍙敤锛堜笉瑕佹眰涓庝骇鍝佺墿鏂欑粦瀹氾級锛涙湭鎸囧畾鏃舵寜鐗╂枡宸茬粦瀹氭柟妗堝厹搴�
+        // 1.3 纭畾璐ㄦ鏂规锛氳川妫�鏂规涓庝骇鍝佺墿鏂欎笉缁戝畾锛屾樉寮忔寚瀹氭椂鍙牎楠屾柟妗堟湰韬彲鐢紱鏈寚瀹氭椂璧伴粯璁ゆ柟妗堣В鏋�
         Long templateId;
         if (createReqVO.getTemplateId() != null) {
             MesQcTemplateDO template = templateService.getTemplate(createReqVO.getTemplateId());
@@ -122,8 +122,7 @@
             }
             templateId = template.getId();
         } else {
-            templateId = templateItemService.getRequiredTemplateByItemIdAndType(
-                    createReqVO.getItemId(), MesQcTypeEnum.IQC.getType()).getTemplateId();
+            templateId = resolveDefaultIqcTemplateId(createReqVO.getItemId());
         }
 
         // 2. 鎻掑叆涓昏〃
@@ -385,17 +384,8 @@
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Long createIqcFromArrivalNotice(Long noticeId, MesWmArrivalNoticeLineDO line, String noticeCode, Long vendorId) {
-        // 1. 鏍¢獙鐗╂枡鏄惁閰嶇疆浜� IQC 妫�楠屾ā鏉�
-        MesQcTemplateItemDO templateItem;
-        try {
-            templateItem = templateItemService.getRequiredTemplateByItemIdAndType(
-                    line.getItemId(), MesQcTypeEnum.IQC.getType());
-        } catch (Exception e) {
-            // 鑾峰彇鐗╂枡淇℃伅锛屾彁渚涙洿鏄庣‘鐨勯敊璇彁绀�
-            String itemInfo = getItemInfo(line.getItemId());
-            throw exception(QC_NO_TEMPLATE_FOR_ITEM, itemInfo);
-        }
-        Long templateId = templateItem.getTemplateId();
+        // 1. 纭畾璐ㄦ鏂规锛氳川妫�鏂规涓庝骇鍝佺墿鏂欎笉缁戝畾锛岀墿鏂欐湭缁戝畾鏂规鏃跺彇浠讳竴鍚敤鐨勬潵鏂欐楠屾柟妗�
+        Long templateId = resolveDefaultIqcTemplateId(line.getItemId());
 
         // 2. 鐢熸垚妫�楠屽崟缂栫爜
         String code = "IQC" + System.currentTimeMillis();
@@ -426,21 +416,28 @@
     }
 
     /**
-     * 鑾峰彇鐗╂枡淇℃伅锛堢紪鐮�+鍚嶇О锛�
+     * 瑙f瀽鏉ユ枡妫�楠岀殑榛樿璐ㄦ鏂规锛氳川妫�鏂规涓庝骇鍝佺墿鏂欎笉缁戝畾銆�
+     *
+     * 1. 鐗╂枡宸茬粦瀹氭潵鏂欐楠屾柟妗堟椂锛屼紭鍏堟部鐢紙鍏煎瀛橀噺閰嶇疆锛夛紱
+     * 2. 鐗╂枡鏈粦瀹氭椂锛屽彇浠讳竴鍚敤涓旀娴嬬绫诲寘鍚潵鏂欐楠岀殑鏂规锛堟寜缂栧彿鍙栨渶鏃╁垱寤虹殑涓�涓級銆�
+     *
+     * @param itemId 浜у搧鐗╂枡缂栧彿
+     * @return 璐ㄦ鏂规缂栧彿
      */
-    private String getItemInfo(Long itemId) {
-        if (itemId == null) {
-            return "鏈煡鐗╂枡";
+    private Long resolveDefaultIqcTemplateId(Long itemId) {
+        List<MesQcTemplateItemDO> boundList = templateItemService.getTemplateItemList(
+                itemId, MesQcTypeEnum.IQC.getType(), null, null);
+        if (CollUtil.isNotEmpty(boundList)) {
+            return boundList.get(0).getTemplateId();
         }
-        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) {
-            // 蹇界暐寮傚父
+        List<MesQcTemplateDO> enabledTemplates = templateService.getEnabledTemplateListByType(MesQcTypeEnum.IQC.getType());
+        if (CollUtil.isEmpty(enabledTemplates)) {
+            throw exception(QC_IQC_NO_ENABLED_TEMPLATE);
         }
-        return "鐗╂枡ID:" + itemId;
+        return enabledTemplates.stream()
+                .map(MesQcTemplateDO::getId)
+                .min(Comparator.naturalOrder())
+                .orElseThrow(() -> exception(QC_IQC_NO_ENABLED_TEMPLATE));
     }
 
     @Override
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptLineServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptLineServiceImpl.java
index 6450597..466db2a 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptLineServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptLineServiceImpl.java
@@ -12,12 +12,14 @@
 import cn.iocoder.yudao.module.mes.dal.mysql.wm.itemreceipt.MesWmItemReceiptLineMapper;
 import cn.iocoder.yudao.module.mes.service.wm.arrivalnotice.MesWmArrivalNoticeLineService;
 import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService;
+import cn.iocoder.yudao.module.mes.service.wm.unitconvert.MesWmItemUnitConvertService;
 import jakarta.annotation.Resource;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
+import java.math.BigDecimal;
 import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -44,6 +46,8 @@
     private MesWmArrivalNoticeLineService arrivalNoticeLineService;
     @Resource
     private MesWmBatchService batchService;
+    @Resource
+    private MesWmItemUnitConvertService itemUnitConvertService;
 
     @Override
     public Long createItemReceiptLine(MesWmItemReceiptLineSaveReqVO createReqVO) {
@@ -54,13 +58,15 @@
 
         // 3.1 鍒涘缓鍏ュ簱鍗曡
         MesWmItemReceiptLineDO line = BeanUtils.toBean(createReqVO, MesWmItemReceiptLineDO.class);
-        // 3.2 鐢熸垚鎴栬幏鍙栨壒娆�
+        // 3.2 鍙屽崟浣嶆崲绠�
+        fillReceivedQuantity(line, createReqVO);
+        // 3.3 鐢熸垚鎴栬幏鍙栨壒娆�
         MesWmBatchDO batch = generateOrGetBatch(receipt, createReqVO);
         if (batch != null) {
             line.setBatchId(batch.getId());
             line.setBatchCode(batch.getCode());
         }
-        // 3.3 鎻掑叆鏁版嵁搴�
+        // 3.4 鎻掑叆鏁版嵁搴�
         itemReceiptLineMapper.insert(line);
         return line.getId();
     }
@@ -76,15 +82,36 @@
 
         // 2.1 鏇存柊
         MesWmItemReceiptLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmItemReceiptLineDO.class);
-        // 2.2 鐢熸垚鎴栬幏鍙栨壒娆�
+        // 2.2 鍙屽崟浣嶆崲绠�
+        fillReceivedQuantity(updateObj, updateReqVO);
+        // 2.3 鐢熸垚鎴栬幏鍙栨壒娆�
         MesWmBatchDO batch = generateOrGetBatch(receipt, updateReqVO);
         if (batch != null) {
             updateObj.setBatchId(batch.getId()).setBatchCode(batch.getCode());
         }
-        // 2.3 鏇存柊鏁版嵁搴�
+        // 2.4 鏇存柊鏁版嵁搴�
         itemReceiptLineMapper.updateById(updateObj);
     }
 
+    /**
+     * 鍙屽崟浣嶆崲绠楋細鎸夊綍鍏ュ崟浣嶄笌鎵�閫夊瀷鍙凤紝鎶婂綍鍏ユ暟閲忔崲绠椾负鐗╂枡涓诲崟浣嶇殑鍏ュ簱鏁伴噺
+     *
+     * 鏈�夋嫨褰曞叆鍗曚綅鏃讹紝璇存槑鏈鎸夌墿鏂欎富鍗曚綅褰曞叆锛岀洿鎺ヤ娇鐢ㄤ紶鍏ョ殑鍏ュ簱鏁伴噺銆�
+     */
+    private void fillReceivedQuantity(MesWmItemReceiptLineDO line, MesWmItemReceiptLineSaveReqVO reqVO) {
+        if (reqVO.getEnterUnitMeasureId() != null) {
+            BigDecimal primaryQuantity = itemUnitConvertService.convertToPrimaryUnit(
+                    reqVO.getItemId(), reqVO.getItemModelId(),
+                    reqVO.getEnterUnitMeasureId(), reqVO.getEnterQuantity());
+            if (primaryQuantity != null) {
+                line.setReceivedQuantity(primaryQuantity);
+            }
+        }
+        if (line.getReceivedQuantity() == null) {
+            throw exception(WM_ITEM_RECEIPT_LINE_QUANTITY_REQUIRED);
+        }
+    }
+
     private void validateItemReceiptLineSaveData(MesWmItemReceiptDO receipt, MesWmItemReceiptLineSaveReqVO reqVO) {
         // 鏍¢獙鍏宠仈鍒拌揣閫氱煡鍗曡
         validateArrivalNoticeLine(receipt, reqVO.getArrivalNoticeLineId());
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueLineServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueLineServiceImpl.java
index 22b985d..20d39d4 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueLineServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueLineServiceImpl.java
@@ -7,6 +7,7 @@
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscissue.MesWmMiscIssueLineDO;
 import cn.iocoder.yudao.module.mes.dal.mysql.wm.miscissue.MesWmMiscIssueLineMapper;
 import cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService;
+import cn.iocoder.yudao.module.mes.service.wm.unitconvert.MesWmItemUnitConvertService;
 import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService;
 import jakarta.annotation.Resource;
 import org.springframework.context.annotation.Lazy;
@@ -14,10 +15,12 @@
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
+import java.math.BigDecimal;
 import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_MISC_ISSUE_LINE_NOT_EXISTS;
+import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_MISC_ISSUE_LINE_QUANTITY_REQUIRED;
 
 /**
  * MES 鏉傞」鍑哄簱鍗曡 Service 瀹炵幇绫�
@@ -39,6 +42,8 @@
     private MesMdmItemService mdmItemService;
     @Resource
     private MesWmWarehouseAreaService warehouseAreaService;
+    @Resource
+    private MesWmItemUnitConvertService itemUnitConvertService;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -46,11 +51,14 @@
         // 1. 鏍¢獙鏁版嵁
         validateMiscIssueLineSaveData(createReqVO.getIssueId(), createReqVO);
 
-        // 2. 鏂板琛�
+        // 2. 鍙屽崟浣嶆崲绠楋細鎸夊綍鍏ュ崟浣嶆崲绠椾负鐗╂枡涓诲崟浣嶆暟閲�
+        fillPrimaryQuantity(createReqVO);
+
+        // 3. 鏂板琛�
         MesWmMiscIssueLineDO line = BeanUtils.toBean(createReqVO, MesWmMiscIssueLineDO.class);
         miscIssueLineMapper.insert(line);
 
-        // 3.鑷姩鍒涘缓鏄庣粏
+        // 4.鑷姩鍒涘缓鏄庣粏
         createReqVO.setId(line.getId());
         miscIssueDetailService.createMiscIssueDetail(createReqVO);
         return line.getId();
@@ -64,14 +72,36 @@
         // 1.2 鏍¢獙鏁版嵁
         validateMiscIssueLineSaveData(line.getIssueId(), updateReqVO);
 
-        // 2. 鏇存柊琛�
+        // 2. 鍙屽崟浣嶆崲绠楋細鎸夊綍鍏ュ崟浣嶆崲绠椾负鐗╂枡涓诲崟浣嶆暟閲�
+        fillPrimaryQuantity(updateReqVO);
+
+        // 3. 鏇存柊琛�
         MesWmMiscIssueLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmMiscIssueLineDO.class);
         miscIssueLineMapper.updateById(updateObj);
 
-        // 3. 鏇存柊鏄庣粏锛堝熀浜庤淇℃伅锛�
+        // 4. 鏇存柊鏄庣粏锛堝熀浜庤淇℃伅锛�
         miscIssueDetailService.updateMiscIssueDetail(updateReqVO);
     }
 
+    /**
+     * 鍙屽崟浣嶆崲绠楋細閫夋嫨浜嗗綍鍏ュ崟浣嶆椂锛屾寜銆屽綍鍏ユ暟閲� 脳 鎹㈢畻姣旂巼銆嶅緱鍒扮墿鏂欎富鍗曚綅鍙e緞鐨勫嚭搴撴暟閲�
+     *
+     * 鎹㈢畻缁撴灉鍐欏洖璇锋眰鍙傛暟锛屼娇琛屼笌 1:1 鏄庣粏鐨勫彛寰勪繚鎸佷竴鑷达紱鏈寜杈呭崟浣嶅綍鍏ユ椂蹇呴』鐩存帴濉啓鍑哄簱鏁伴噺
+     */
+    private void fillPrimaryQuantity(MesWmMiscIssueLineSaveReqVO reqVO) {
+        if (reqVO.getEnterUnitMeasureId() != null) {
+            BigDecimal primaryQuantity = itemUnitConvertService.convertToPrimaryUnit(
+                    reqVO.getItemId(), reqVO.getItemModelId(),
+                    reqVO.getEnterUnitMeasureId(), reqVO.getEnterQuantity());
+            if (primaryQuantity != null) {
+                reqVO.setQuantity(primaryQuantity);
+            }
+        }
+        if (reqVO.getQuantity() == null) {
+            throw exception(WM_MISC_ISSUE_LINE_QUANTITY_REQUIRED);
+        }
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void deleteMiscIssueLine(Long id) {
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueLineServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueLineServiceImpl.java
index 93b369d..519185e 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueLineServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueLineServiceImpl.java
@@ -14,16 +14,19 @@
 import cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService;
 import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderBomService;
 import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService;
+import cn.iocoder.yudao.module.mes.service.wm.unitconvert.MesWmItemUnitConvertService;
 import jakarta.annotation.Resource;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
+import java.math.BigDecimal;
 import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_OUTSOURCE_ISSUE_LINE_NOT_EXISTS;
 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_OUTSOURCE_ISSUE_LINE_ITEM_NOT_IN_BOM;
+import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_OUTSOURCE_ISSUE_LINE_QUANTITY_REQUIRED;
 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_OUTSOURCE_ISSUE_NOT_EXISTS;
 
 /**
@@ -49,6 +52,8 @@
     private MesWmBatchService batchService;
     @Resource
     private MesProWorkOrderBomService workOrderBomService;
+    @Resource
+    private MesWmItemUnitConvertService itemUnitConvertService;
 
     @Override
     public Long createOutsourceIssueLine(MesWmOutsourceIssueLineSaveReqVO createReqVO) {
@@ -56,6 +61,8 @@
         validateOutsourceIssueLineSaveData(createReqVO);
         // 鏍规嵁 batchCode 瑙f瀽 batchId
         fillBatchId(createReqVO);
+        // 鍙屽崟浣嶆崲绠楋細鎸夊綍鍏ュ崟浣嶆崲绠椾负鐗╂枡涓诲崟浣嶆暟閲�
+        fillPrimaryQuantity(createReqVO);
 
         // 鎻掑叆
         MesWmOutsourceIssueLineDO line = BeanUtils.toBean(createReqVO, MesWmOutsourceIssueLineDO.class);
@@ -71,12 +78,33 @@
         validateOutsourceIssueLineSaveData(updateReqVO);
         // 鏍规嵁 batchCode 瑙f瀽 batchId
         fillBatchId(updateReqVO);
+        // 鍙屽崟浣嶆崲绠楋細鎸夊綍鍏ュ崟浣嶆崲绠椾负鐗╂枡涓诲崟浣嶆暟閲�
+        fillPrimaryQuantity(updateReqVO);
 
         // 鏇存柊
         MesWmOutsourceIssueLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmOutsourceIssueLineDO.class);
         outsourceIssueLineMapper.updateById(updateObj);
     }
 
+    /**
+     * 鍙屽崟浣嶆崲绠楋細閫夋嫨浜嗗綍鍏ュ崟浣嶆椂锛屾寜銆屽綍鍏ユ暟閲� 脳 鎹㈢畻姣旂巼銆嶅緱鍒扮墿鏂欎富鍗曚綅鍙e緞鐨勫彂鏂欐暟閲�
+     *
+     * 鏈寜杈呭崟浣嶅綍鍏ユ椂蹇呴』鐩存帴濉啓鍙戞枡鏁伴噺
+     */
+    private void fillPrimaryQuantity(MesWmOutsourceIssueLineSaveReqVO reqVO) {
+        if (reqVO.getEnterUnitMeasureId() != null) {
+            BigDecimal primaryQuantity = itemUnitConvertService.convertToPrimaryUnit(
+                    reqVO.getItemId(), reqVO.getItemModelId(),
+                    reqVO.getEnterUnitMeasureId(), reqVO.getEnterQuantity());
+            if (primaryQuantity != null) {
+                reqVO.setQuantity(primaryQuantity);
+            }
+        }
+        if (reqVO.getQuantity() == null) {
+            throw exception(WM_OUTSOURCE_ISSUE_LINE_QUANTITY_REQUIRED);
+        }
+    }
+
     @Override
     public void deleteOutsourceIssueLine(Long id) {
         // 鏍¢獙瀛樺湪
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueLineServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueLineServiceImpl.java
index 6b5141b..2b84d90 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueLineServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueLineServiceImpl.java
@@ -24,6 +24,7 @@
 import cn.iocoder.yudao.module.mes.service.wm.productissue.MesWmProductIssueLineService;
 import cn.iocoder.yudao.module.mes.service.wm.productissue.MesWmProductIssueService;
 import cn.iocoder.yudao.module.mes.service.wm.returnissue.MesWmReturnIssueLineService;
+import cn.iocoder.yudao.module.mes.service.wm.unitconvert.MesWmItemUnitConvertService;
 import jakarta.annotation.Resource;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
@@ -63,10 +64,14 @@
     private MesWmProductIssueDetailService issueDetailService;
     @Resource
     private MesProWorkOrderBomService workOrderBomService;
+    @Resource
+    private MesWmItemUnitConvertService itemUnitConvertService;
 
     @Override
     public Long createProductIssueLine(MesWmProductIssueLineSaveReqVO createReqVO) {
         validateProductIssueLineSaveData(createReqVO);
+        // 鍙屽崟浣嶆崲绠楋細鎸夊綍鍏ュ崟浣嶆崲绠椾负鐗╂枡涓诲崟浣嶆暟閲�
+        fillPrimaryQuantity(createReqVO);
 
         // 鎻掑叆
         MesWmProductIssueLineDO line = BeanUtils.toBean(createReqVO, MesWmProductIssueLineDO.class);
@@ -79,12 +84,33 @@
         // 鏍¢獙瀛樺湪
         validateProductIssueLineExists(updateReqVO.getId());
         validateProductIssueLineSaveData(updateReqVO);
+        // 鍙屽崟浣嶆崲绠楋細鎸夊綍鍏ュ崟浣嶆崲绠椾负鐗╂枡涓诲崟浣嶆暟閲�
+        fillPrimaryQuantity(updateReqVO);
 
         // 鏇存柊
         MesWmProductIssueLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmProductIssueLineDO.class);
         issueLineMapper.updateById(updateObj);
     }
 
+    /**
+     * 鍙屽崟浣嶆崲绠楋細閫夋嫨浜嗗綍鍏ュ崟浣嶆椂锛屾寜銆屽綍鍏ユ暟閲� 脳 鎹㈢畻姣旂巼銆嶅緱鍒扮墿鏂欎富鍗曚綅鍙e緞鐨勯鏂欐暟閲�
+     *
+     * 鏈寜杈呭崟浣嶅綍鍏ユ椂蹇呴』鐩存帴濉啓棰嗘枡鏁伴噺
+     */
+    private void fillPrimaryQuantity(MesWmProductIssueLineSaveReqVO reqVO) {
+        if (reqVO.getEnterUnitMeasureId() != null) {
+            BigDecimal primaryQuantity = itemUnitConvertService.convertToPrimaryUnit(
+                    reqVO.getItemId(), reqVO.getItemModelId(),
+                    reqVO.getEnterUnitMeasureId(), reqVO.getEnterQuantity());
+            if (primaryQuantity != null) {
+                reqVO.setQuantity(primaryQuantity);
+            }
+        }
+        if (reqVO.getQuantity() == null) {
+            throw exception(WM_PRODUCT_ISSUE_LINE_QUANTITY_REQUIRED);
+        }
+    }
+
     @Override
     public void deleteProductIssueLine(Long id) {
         // 鏍¢獙瀛樺湪
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 30303e7..373e12f 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
@@ -18,6 +18,7 @@
 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 cn.iocoder.yudao.module.mes.service.wm.unitconvert.MesWmItemUnitConvertService;
 import jakarta.annotation.Resource;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.context.annotation.Lazy;
@@ -25,6 +26,7 @@
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
+import java.math.BigDecimal;
 import java.util.List;
 import java.util.Objects;
 
@@ -60,9 +62,13 @@
     @Resource
     @Lazy
     private MesQcOqcService oqcService;
+    @Resource
+    private MesWmItemUnitConvertService itemUnitConvertService;
 
     @Override
     public Long createProductSalesLine(MesWmProductSalesLineSaveReqVO createReqVO) {
+        // 鍙屽崟浣嶆崲绠楋細鎸夊綍鍏ュ崟浣嶆崲绠椾负鐗╂枡涓诲崟浣嶆暟閲忥紙蹇呴』鍏堟崲绠楋紝鍐嶆牎楠屼笌鍙戣揣閫氱煡鍗曡鐨勬暟閲忎竴鑷存�э級
+        fillPrimaryQuantity(createReqVO);
         // 鏍¢獙鏁版嵁
         validateLineSaveData(createReqVO);
 
@@ -76,8 +82,10 @@
     public void updateProductSalesLine(MesWmProductSalesLineSaveReqVO updateReqVO) {
         // 鏍¢獙瀛樺湪
         MesWmProductSalesLineDO oldLine = validateProductSalesLineExists(updateReqVO.getId());
-        // 鏍¢獙鏁版嵁
         updateReqVO.setSalesId(oldLine.getSalesId());
+        // 鍙屽崟浣嶆崲绠楋細鎸夊綍鍏ュ崟浣嶆崲绠椾负鐗╂枡涓诲崟浣嶆暟閲忥紙蹇呴』鍏堟崲绠楋紝鍐嶆牎楠屼笌鍙戣揣閫氱煡鍗曡鐨勬暟閲忎竴鑷存�э級
+        fillPrimaryQuantity(updateReqVO);
+        // 鏍¢獙鏁版嵁
         validateLineSaveData(updateReqVO);
 
         // 鏇存柊
@@ -167,6 +175,25 @@
     }
 
     /**
+     * 鍙屽崟浣嶆崲绠楋細閫夋嫨浜嗗綍鍏ュ崟浣嶆椂锛屾寜銆屽綍鍏ユ暟閲� 脳 鎹㈢畻姣旂巼銆嶅緱鍒扮墿鏂欎富鍗曚綅鍙e緞鐨勫嚭搴撴暟閲�
+     *
+     * 鏈寜杈呭崟浣嶅綍鍏ユ椂蹇呴』鐩存帴濉啓鍑哄簱鏁伴噺
+     */
+    private void fillPrimaryQuantity(MesWmProductSalesLineSaveReqVO reqVO) {
+        if (reqVO.getEnterUnitMeasureId() != null) {
+            BigDecimal primaryQuantity = itemUnitConvertService.convertToPrimaryUnit(
+                    reqVO.getItemId(), reqVO.getItemModelId(),
+                    reqVO.getEnterUnitMeasureId(), reqVO.getEnterQuantity());
+            if (primaryQuantity != null) {
+                reqVO.setQuantity(primaryQuantity);
+            }
+        }
+        if (reqVO.getQuantity() == null) {
+            throw exception(WM_PRODUCT_SALES_LINE_QUANTITY_REQUIRED);
+        }
+    }
+
+    /**
      * 鏍规嵁 batchCode 瑙f瀽 batchId
      */
     private void fillBatchId(MesWmProductSalesLineSaveReqVO reqVO) {
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorLineServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorLineServiceImpl.java
index 39a10d4..27e61ea 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorLineServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorLineServiceImpl.java
@@ -18,18 +18,21 @@
 import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnvendor.MesWmReturnVendorLineMapper;
 import cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService;
 import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService;
+import cn.iocoder.yudao.module.mes.service.wm.unitconvert.MesWmItemUnitConvertService;
 import jakarta.annotation.Resource;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
+import java.math.BigDecimal;
 import java.util.List;
 import java.util.Set;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_RETURN_VENDOR_ITEM_NOT_IN_PURCHASE_ORDER;
 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_RETURN_VENDOR_LINE_NOT_EXISTS;
+import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_RETURN_VENDOR_LINE_QUANTITY_REQUIRED;
 
 /**
  * MES 渚涘簲鍟嗛��璐у崟琛� Service 瀹炵幇绫�
@@ -53,6 +56,8 @@
     private MesWmBatchService batchService;
     @Resource
     private ErpPurchaseOrderApi purchaseOrderApi;
+    @Resource
+    private MesWmItemUnitConvertService itemUnitConvertService;
 
     @Override
     public Long createReturnVendorLine(MesWmReturnVendorLineSaveReqVO createReqVO) {
@@ -60,6 +65,8 @@
         MesWmReturnVendorDO returnVendor = validateReturnVendorLineSaveData(createReqVO);
         // 閫�璐у崟鑻ュ凡鍏宠仈閲囪喘璁㈠崟锛岀墿鏂欏繀椤诲睘浜庤閲囪喘璁㈠崟锛岀姝㈣法璁㈠崟闅忔剰閫夋枡
         validateReturnVendorItemInPurchaseOrder(returnVendor, createReqVO.getItemId(), null);
+        // 鍙屽崟浣嶆崲绠楋細鎸夊綍鍏ュ崟浣嶆崲绠椾负鐗╂枡涓诲崟浣嶆暟閲�
+        fillPrimaryQuantity(createReqVO);
 
         // 鎻掑叆
         MesWmReturnVendorLineDO line = BeanUtils.toBean(createReqVO, MesWmReturnVendorLineDO.class);
@@ -77,6 +84,8 @@
         MesWmReturnVendorDO returnVendor = validateReturnVendorLineSaveData(updateReqVO);
         // 鍏宠仈閲囪喘璁㈠崟鏃讹紝涓嶅厑璁告妸琛岀墿鏂欐敼鎴愯鍗曞鐨勭墿鏂欙紱浠呮敼鏁伴噺绛夋搷浣滀笉鍙楀奖鍝�
         validateReturnVendorItemInPurchaseOrder(returnVendor, updateReqVO.getItemId(), oldLine.getItemId());
+        // 鍙屽崟浣嶆崲绠楋細鎸夊綍鍏ュ崟浣嶆崲绠椾负鐗╂枡涓诲崟浣嶆暟閲�
+        fillPrimaryQuantity(updateReqVO);
 
         // 鏇存柊
         MesWmReturnVendorLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmReturnVendorLineDO.class);
@@ -139,6 +148,25 @@
     }
 
     /**
+     * 鍙屽崟浣嶆崲绠楋細閫夋嫨浜嗗綍鍏ュ崟浣嶆椂锛屾寜銆屽綍鍏ユ暟閲� 脳 鎹㈢畻姣旂巼銆嶅緱鍒扮墿鏂欎富鍗曚綅鍙e緞鐨勯��璐ф暟閲�
+     *
+     * 鏈寜杈呭崟浣嶅綍鍏ユ椂蹇呴』鐩存帴濉啓閫�璐ф暟閲�
+     */
+    private void fillPrimaryQuantity(MesWmReturnVendorLineSaveReqVO reqVO) {
+        if (reqVO.getEnterUnitMeasureId() != null) {
+            BigDecimal primaryQuantity = itemUnitConvertService.convertToPrimaryUnit(
+                    reqVO.getItemId(), reqVO.getItemModelId(),
+                    reqVO.getEnterUnitMeasureId(), reqVO.getEnterQuantity());
+            if (primaryQuantity != null) {
+                reqVO.setQuantity(primaryQuantity);
+            }
+        }
+        if (reqVO.getQuantity() == null) {
+            throw exception(WM_RETURN_VENDOR_LINE_QUANTITY_REQUIRED);
+        }
+    }
+
+    /**
      * 鏍¢獙閫�璐ц鐗╂枡灞炰簬鎵�鍏宠仈閲囪喘璁㈠崟锛堥��璐у崟宸插叧鑱旈噰璐鍗曟椂锛夈��
      *
      * 閲囪喘閫�璐х殑鐗╂枡搴斿彇鑷叧鑱旈噰璐鍗曪紝姝ゅ涓哄悗绔厹搴曪紝闃叉閫氳繃鎺ュ彛璺ㄨ鍗曢殢鎰忛�夋枡銆�
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/unitconvert/MesWmItemUnitConvertService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/unitconvert/MesWmItemUnitConvertService.java
new file mode 100644
index 0000000..3d9f99e
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/unitconvert/MesWmItemUnitConvertService.java
@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.module.mes.service.wm.unitconvert;
+
+import java.math.BigDecimal;
+
+/**
+ * MES 鐗╂枡涓昏緟鍗曚綅鎹㈢畻 Service 鎺ュ彛
+ *
+ * 鍑哄叆搴撳崟鎹鐨勬暟閲忕粺涓�鎸夌墿鏂欎富鍗曚綅璁拌处锛屾湰鏈嶅姟璐熻矗鎶娿�屾寜杈呭崟浣�/鍨嬪彿鍗曚綅褰曞叆鐨勬暟閲忋��
+ * 鎹㈢畻鎴愪富鍗曚綅鏁伴噺銆傛崲绠楁瘮鐜囨潵婧愪紭鍏堢骇锛�
+ * 1. 琛屼笂鎸囧畾鐨勭墿鏂欏瀷鍙凤紙鍨嬪彿涓婇厤缃殑鍗曚綅 + 姣旂巼锛夛紱
+ * 2. 鐗╂枡涓绘暟鎹笂鐨勮緟鍗曚綅 1 / 杈呭崟浣� 2锛堝瓨閲忛厤缃級锛�
+ * 3. 鐗╂枡鍨嬪彿涓鍗曚綅涓嬪敮涓�鐨勬瘮鐜囥��
+ *
+ * @author 瓒呯骇绠$悊鍛�
+ */
+public interface MesWmItemUnitConvertService {
+
+    /**
+     * 瑙f瀽鎹㈢畻姣旂巼锛�1 涓寚瀹氬崟浣� = N 涓墿鏂欎富鍗曚綅
+     *
+     * @param itemId        鐗╂枡缂栧彿
+     * @param itemModelId   鐗╂枡鍨嬪彿缂栧彿锛堝彲涓虹┖锛�
+     * @param unitMeasureId 褰曞叆鍗曚綅缂栧彿锛堝彲涓虹┖锛屼负绌鸿涓轰富鍗曚綅锛�
+     * @return 鎹㈢畻姣旂巼锛屼富鍗曚綅鎴栨湭鎸囧畾鍗曚綅鏃惰繑鍥� 1
+     */
+    BigDecimal resolveRateToPrimaryUnit(Long itemId, Long itemModelId, Long unitMeasureId);
+
+    /**
+     * 灏嗗綍鍏ユ暟閲忔崲绠椾负鐗╂枡涓诲崟浣嶆暟閲�
+     *
+     * @param itemId        鐗╂枡缂栧彿
+     * @param itemModelId   鐗╂枡鍨嬪彿缂栧彿锛堝彲涓虹┖锛�
+     * @param unitMeasureId 褰曞叆鍗曚綅缂栧彿锛堝彲涓虹┖锛屼负绌鸿涓轰富鍗曚綅锛�
+     * @param enterQuantity 褰曞叆鏁伴噺
+     * @return 涓诲崟浣嶆暟閲忥紱褰曞叆鍗曚綅鍗充富鍗曚綅鏃跺師鏍疯繑鍥�
+     */
+    BigDecimal convertToPrimaryUnit(Long itemId, Long itemModelId, Long unitMeasureId, BigDecimal enterQuantity);
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/unitconvert/MesWmItemUnitConvertServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/unitconvert/MesWmItemUnitConvertServiceImpl.java
new file mode 100644
index 0000000..5a1b8c7
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/unitconvert/MesWmItemUnitConvertServiceImpl.java
@@ -0,0 +1,127 @@
+package cn.iocoder.yudao.module.mes.service.wm.unitconvert;
+
+import cn.hutool.core.util.ObjUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.common.exception.ServiceException;
+import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
+import cn.iocoder.yudao.module.mdm.api.item.MdmItemModelApi;
+import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemModelRespDTO;
+import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO;
+import cn.iocoder.yudao.module.mdm.api.unit.MdmUnitMeasureApi;
+import cn.iocoder.yudao.module.mdm.api.unit.dto.MdmUnitMeasureRespDTO;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
+
+/**
+ * MES 鐗╂枡涓昏緟鍗曚綅鎹㈢畻 Service 瀹炵幇绫�
+ *
+ * @author 瓒呯骇绠$悊鍛�
+ */
+@Service
+@Validated
+public class MesWmItemUnitConvertServiceImpl implements MesWmItemUnitConvertService {
+
+    @Resource
+    private MdmItemApi mdmItemApi;
+    @Resource
+    private MdmItemModelApi mdmItemModelApi;
+    @Resource
+    private MdmUnitMeasureApi mdmUnitMeasureApi;
+
+    @Override
+    public BigDecimal resolveRateToPrimaryUnit(Long itemId, Long itemModelId, Long unitMeasureId) {
+        MdmItemRespDTO item = mdmItemApi.validateItemExists(itemId).getCheckedData();
+        // 1. 鏈寚瀹氬綍鍏ュ崟浣嶏紝鎴栧綍鍏ュ崟浣嶅氨鏄墿鏂欎富鍗曚綅 鈫� 姣旂巼 1
+        if (unitMeasureId == null || ObjUtil.equal(item.getUnitMeasureId(), unitMeasureId)) {
+            return BigDecimal.ONE;
+        }
+        // 2. 鎸囧畾浜嗗瀷鍙� 鈫� 浠ュ瀷鍙蜂笂閰嶇疆鐨勫崟浣嶄笌姣旂巼涓哄噯
+        if (itemModelId != null) {
+            MdmItemModelRespDTO model = mdmItemModelApi.validateItemModelExistsAndEnable(itemModelId, itemId)
+                    .getCheckedData();
+            if (ObjUtil.notEqual(model.getUnitMeasureId(), unitMeasureId)) {
+                throw new ServiceException(WM_ITEM_UNIT_CONVERT_MODEL_UNIT_MISMATCH.getCode(), String.format(
+                        "鎵�閫夊瀷鍙枫��%s銆戠殑璁¢噺鍗曚綅鏄��%s銆戯紝涓庢湰娆″綍鍏ュ崟浣嶃��%s銆戜笉涓�鑷达紝璇烽噸鏂伴�夋嫨鍨嬪彿鎴栨敼鍥炲瀷鍙峰搴旂殑璁¢噺鍗曚綅",
+                        model.getModel(), unitName(model.getUnitMeasureId()), unitName(unitMeasureId)));
+            }
+            return validateRate(model);
+        }
+        // 3. 鏈寚瀹氬瀷鍙� 鈫� 鍏堝尮閰嶇墿鏂欎富鏁版嵁涓婄殑杈呭崟浣� 1 / 杈呭崟浣� 2
+        if (ObjUtil.equal(item.getUnitMeasureId2(), unitMeasureId) && item.getUnitMeasureRate1() != null) {
+            return item.getUnitMeasureRate1();
+        }
+        if (ObjUtil.equal(item.getUnitMeasureId3(), unitMeasureId) && item.getUnitMeasureRate2() != null) {
+            return item.getUnitMeasureRate2();
+        }
+        // 4. 鍐嶄粠鐗╂枡鍨嬪彿涓壘璇ュ崟浣嶏細姣旂巼鍞竴鍙洿鎺ヤ娇鐢紝姣旂巼鏈夊涓彇鍊煎垯蹇呴』鎸囧畾鍨嬪彿
+        List<MdmItemModelRespDTO> models = mdmItemModelApi.getItemModelListByItemId(itemId).getCheckedData().stream()
+                .filter(model -> ObjUtil.equal(model.getUnitMeasureId(), unitMeasureId))
+                .filter(model -> CommonStatusEnum.ENABLE.getStatus().equals(model.getStatus()))
+                .toList();
+        List<BigDecimal> distinctRates = models.stream()
+                .map(MdmItemModelRespDTO::getUnitMeasureRate)
+                .filter(java.util.Objects::nonNull)
+                .distinct()
+                .toList();
+        if (distinctRates.size() > 1) {
+            throw new ServiceException(WM_ITEM_UNIT_CONVERT_MODEL_REQUIRED.getCode(), String.format(
+                    "鐗╂枡銆�%s-%s銆戜笅浣跨敤璁¢噺鍗曚綅銆�%s銆戠殑鍨嬪彿鏈夊涓笖鎹㈢畻姣旂巼涓嶅悓锛岃鍏堥�夋嫨鍨嬪彿鍚庡啀褰曞叆鏁伴噺",
+                    item.getCode(), item.getName(), unitName(unitMeasureId)));
+        }
+        if (distinctRates.size() == 1) {
+            return validateRate(distinctRates.get(0), models.get(0).getModel());
+        }
+        // 5. 涓绘暟鎹笌鍨嬪彿鍧囨湭閰嶇疆璇ュ崟浣嶇殑鎹㈢畻姣旂巼
+        throw new ServiceException(WM_ITEM_UNIT_CONVERT_NOT_CONFIGURED.getCode(), String.format(
+                "鐗╂枡銆�%s-%s銆戞病鏈夐厤缃閲忓崟浣嶃��%s銆戝埌涓诲崟浣嶃��%s銆戠殑鎹㈢畻姣旂巼锛屾棤娉曟崲绠楋紝"
+                        + "璇峰厛鍒般�愬熀纭�鏁版嵁-鐗╂枡涓绘暟鎹�-鍨嬪彿銆戜负璇ョ墿鏂欐柊澧炲瀷鍙峰苟濉啓鎹㈢畻姣旂巼",
+                item.getCode(), item.getName(), unitName(unitMeasureId), unitName(item.getUnitMeasureId())));
+    }
+
+    @Override
+    public BigDecimal convertToPrimaryUnit(Long itemId, Long itemModelId, Long unitMeasureId, BigDecimal enterQuantity) {
+        BigDecimal rate = resolveRateToPrimaryUnit(itemId, itemModelId, unitMeasureId);
+        // 1. 褰曞叆鍗曚綅鍗充富鍗曚綅 鈫� 鏁伴噺鍘熸牱杩斿洖
+        if (BigDecimal.ONE.compareTo(rate) == 0) {
+            return enterQuantity;
+        }
+        // 2. 鎸夐潪涓诲崟浣嶅綍鍏ユ椂锛屽綍鍏ユ暟閲忓繀濉�
+        if (enterQuantity == null) {
+            MdmItemRespDTO item = mdmItemApi.validateItemExists(itemId).getCheckedData();
+            throw new ServiceException(WM_ITEM_UNIT_CONVERT_QUANTITY_REQUIRED.getCode(), String.format(
+                    "璁¢噺鍗曚綅銆�%s銆戜笉鏄墿鏂欍��%s-%s銆戠殑涓诲崟浣嶏紝鎸夎鍗曚綅褰曞叆鏃跺綍鍏ユ暟閲忎笉鑳戒负绌猴紝璇峰~鍐欏綍鍏ユ暟閲忔垨鏀圭敤涓诲崟浣嶃��%s銆�",
+                    unitName(unitMeasureId), item.getCode(), item.getName(), unitName(item.getUnitMeasureId())));
+        }
+        // 3. 杈呭崟浣嶆暟閲� 脳 鎹㈢畻姣旂巼 = 涓诲崟浣嶆暟閲�
+        return enterQuantity.multiply(rate);
+    }
+
+    private BigDecimal validateRate(MdmItemModelRespDTO model) {
+        return validateRate(model.getUnitMeasureRate(), model.getModel());
+    }
+
+    private BigDecimal validateRate(BigDecimal rate, String modelName) {
+        if (rate == null || rate.compareTo(BigDecimal.ZERO) <= 0) {
+            throw new ServiceException(WM_ITEM_UNIT_CONVERT_RATE_INVALID.getCode(), String.format(
+                    "鍨嬪彿銆�%s銆戠殑鎹㈢畻姣旂巼涓恒��%s銆戜笉鍚堢悊锛�1 涓瀷鍙峰崟浣嶅繀椤诲搴斿ぇ浜� 0 鐨勪富鍗曚綅鏁伴噺锛�"
+                            + "璇峰埌銆愬熀纭�鏁版嵁-鐗╂枡涓绘暟鎹�-鍨嬪彿銆戜慨姝h鍨嬪彿鐨勬崲绠楁瘮鐜�",
+                    modelName, rate));
+        }
+        return rate;
+    }
+
+    private String unitName(Long unitMeasureId) {
+        if (unitMeasureId == null) {
+            return "鏈寚瀹�";
+        }
+        MdmUnitMeasureRespDTO unit = mdmUnitMeasureApi.getUnitMeasure(unitMeasureId).getCheckedData();
+        return unit != null ? unit.getName() : "ID=" + unitMeasureId;
+    }
+
+}

--
Gitblit v1.9.3