From ac2545f3cd01f3061a107e4980fc6fa59eaeaa6b Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期五, 21 八月 2026 13:43:38 +0800
Subject: [PATCH] feat(mes): 新增袋码破损替换功能
---
.playwright-mcp/page-2026-08-21T03-59-08-154Z.yml | 1
.playwright-mcp/page-2026-08-21T04-00-37-255Z.yml | 1
.playwright-mcp/page-2026-08-21T04-00-18-943Z.yml | 1
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/bagcode/MesProBagCodeReplaceDO.java | 37 ++
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/vo/MesProBagCodeReplaceReqVO.java | 30 ++
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/MesProBagCodeController.java | 22 +
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/vo/MesProBagCodeReplaceItemRespVO.java | 51 +++
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/vo/MesProBagCodeRespVO.java | 8
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/bagcode/MesProBagCodeService.java | 14
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/bagcode/MesProBagCodeServiceImpl.java | 137 +++++++++
.playwright-mcp/page-2026-08-21T04-01-18-956Z.yml | 106 +++++++
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/bagcode/MesProBagCodeReplaceMapper.java | 27 +
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/vo/MesProBagCodeReplaceRespVO.java | 27 +
sql/mysql/mes_pro_bag_code_replacement.sql | 59 +++
sql/mysql/mes_pro_batch_bag_code_init.sql | 42 ++
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/bagcode/MesProBagCodeMapper.java | 18 +
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/vo/MesProBagCodeTraceRespVO.java | 15 +
docs/mes_pro_bag_code_replacement_integration.md | 150 ++++++++++
.playwright-mcp/page-2026-08-21T04-00-59-933Z.yml | 100 ++++++
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/batch/MesProBatchMapper.java | 4
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java | 5
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/bagcode/MesProBagCodeDO.java | 8
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/pallet/MesProPalletMapper.java | 3
.playwright-mcp/page-2026-08-21T03-59-21-224Z.yml | 1
24 files changed, 863 insertions(+), 4 deletions(-)
diff --git a/.playwright-mcp/page-2026-08-21T03-59-08-154Z.yml b/.playwright-mcp/page-2026-08-21T03-59-08-154Z.yml
new file mode 100644
index 0000000..6adf37e
--- /dev/null
+++ b/.playwright-mcp/page-2026-08-21T03-59-08-154Z.yml
@@ -0,0 +1 @@
+- generic [active]: 宸ヤ笟AI鏅洪�犲钩鍙�
\ No newline at end of file
diff --git a/.playwright-mcp/page-2026-08-21T03-59-21-224Z.yml b/.playwright-mcp/page-2026-08-21T03-59-21-224Z.yml
new file mode 100644
index 0000000..6adf37e
--- /dev/null
+++ b/.playwright-mcp/page-2026-08-21T03-59-21-224Z.yml
@@ -0,0 +1 @@
+- generic [active]: 宸ヤ笟AI鏅洪�犲钩鍙�
\ No newline at end of file
diff --git a/.playwright-mcp/page-2026-08-21T04-00-18-943Z.yml b/.playwright-mcp/page-2026-08-21T04-00-18-943Z.yml
new file mode 100644
index 0000000..6adf37e
--- /dev/null
+++ b/.playwright-mcp/page-2026-08-21T04-00-18-943Z.yml
@@ -0,0 +1 @@
+- generic [active]: 宸ヤ笟AI鏅洪�犲钩鍙�
\ No newline at end of file
diff --git a/.playwright-mcp/page-2026-08-21T04-00-37-255Z.yml b/.playwright-mcp/page-2026-08-21T04-00-37-255Z.yml
new file mode 100644
index 0000000..6adf37e
--- /dev/null
+++ b/.playwright-mcp/page-2026-08-21T04-00-37-255Z.yml
@@ -0,0 +1 @@
+- generic [active]: 宸ヤ笟AI鏅洪�犲钩鍙�
\ No newline at end of file
diff --git a/.playwright-mcp/page-2026-08-21T04-00-59-933Z.yml b/.playwright-mcp/page-2026-08-21T04-00-59-933Z.yml
new file mode 100644
index 0000000..a93d8dc
--- /dev/null
+++ b/.playwright-mcp/page-2026-08-21T04-00-59-933Z.yml
@@ -0,0 +1,100 @@
+- generic [ref=f3e7]:
+ - complementary [ref=f3e9]:
+ - generic [ref=f3e10]:
+ - generic [ref=f3e11] [cursor=pointer]
+ - link "宸ヤ笟AI鏅洪�犲钩鍙� 宸ヤ笟AI鏅洪�犲钩鍙�" [ref=f3e16] [cursor=pointer]:
+ - /url: javascript:void 0
+ - img "宸ヤ笟AI鏅洪�犲钩鍙�" [ref=f3e19]
+ - generic [ref=f3e20]: 宸ヤ笟AI鏅洪�犲钩鍙�
+ - menu [ref=f3e23]:
+ - menuitem "棣栭〉" [ref=f3e24] [cursor=pointer]
+ - listitem [ref=f3e29]:
+ - generic [ref=f3e30] [cursor=pointer]: 鍩虹鏁版嵁
+ - listitem [ref=f3e38]:
+ - generic [ref=f3e39] [cursor=pointer]: 涓�琚嬩竴鐮佺鐞�
+ - list [ref=f3e349]:
+ - menuitem "鎵规鐢熶骇绠$悊" [ref=f3e350] [cursor=pointer]
+ - menuitem "璧嬬爜绠$悊" [ref=f3e355] [cursor=pointer]
+ - menuitem "鎵樼洏鐮佺鐞�" [ref=f3e361] [cursor=pointer]
+ - menuitem "浜х嚎缁存姢" [ref=f3e368] [cursor=pointer]
+ - listitem [ref=f3e45]:
+ - generic [ref=f3e46] [cursor=pointer]: 绯荤粺绠$悊
+ - generic [ref=f3e53] [cursor=pointer]
+ - generic [ref=f3e58]:
+ - generic [ref=f3e59]:
+ - banner [ref=f3e60]:
+ - button [ref=f3e61] [cursor=pointer]
+ - button [ref=f3e64] [cursor=pointer]
+ - navigation "breadcrumb" [ref=f3e69]:
+ - list [ref=f3e70]:
+ - listitem [ref=f3e71]:
+ - link "棣栭〉" [disabled] [ref=f3e72]
+ - generic [ref=f3e77]:
+ - generic [ref=f3e79] [cursor=pointer]:
+ - generic [ref=f3e83]: 鎼滅储
+ - generic [ref=f3e84]: Ctrl K
+ - button [ref=f3e86] [cursor=pointer]
+ - button "dark" [ref=f3e91] [cursor=pointer]
+ - button [ref=f3e100] [cursor=pointer]
+ - button [ref=f3e106] [cursor=pointer]
+ - button [ref=f3e109] [cursor=pointer]
+ - button [ref=f3e115] [cursor=pointer]:
+ - button [ref=f3e117]
+ - button "宸ヤ綔鍙�" [ref=f3e121] [cursor=pointer]
+ - button [ref=f3e125] [cursor=pointer]:
+ - img "瓒呯骇绠$悊鍛�" [ref=f3e130]
+ - generic [ref=f3e132]:
+ - generic [ref=f3e133]: 棣栭〉
+ - generic [ref=f3e152]:
+ - button [ref=f3e153] [cursor=pointer]
+ - generic [ref=f3e160] [cursor=pointer]
+ - generic [ref=f3e164] [cursor=pointer]
+ - main [ref=f3e171]:
+ - generic [ref=f3e174]:
+ - generic [ref=f3e175]:
+ - generic [ref=f3e185] [cursor=pointer]:
+ - generic [ref=f3e186]: 鍝佺鎬绘暟
+ - generic [ref=f3e187]: "1"
+ - generic [ref=f3e198] [cursor=pointer]:
+ - generic [ref=f3e199]: MES 鍝佺
+ - generic [ref=f3e200]: "0"
+ - generic [ref=f3e211] [cursor=pointer]:
+ - generic [ref=f3e212]: 鍝佺鍒嗙被
+ - generic [ref=f3e213]: "1"
+ - generic [ref=f3e222] [cursor=pointer]:
+ - generic [ref=f3e223]: 璁¢噺鍗曚綅
+ - generic [ref=f3e224]: "1"
+ - generic [ref=f3e226]:
+ - generic [ref=f3e234] [cursor=pointer]:
+ - generic [ref=f3e235]: 浜х嚎
+ - generic [ref=f3e236]: "1"
+ - generic [ref=f3e248] [cursor=pointer]:
+ - generic [ref=f3e249]: 鐢熶骇鎵规
+ - generic [ref=f3e250]: "1"
+ - generic [ref=f3e259] [cursor=pointer]:
+ - generic [ref=f3e260]: 琚嬬爜
+ - generic [ref=f3e261]: "100"
+ - generic [ref=f3e272] [cursor=pointer]:
+ - generic [ref=f3e273]: 鎵樼洏鐮�
+ - generic [ref=f3e274]: "10"
+ - generic [ref=f3e276]:
+ - generic [ref=f3e280]:
+ - generic [ref=f3e281]: 琚嬬爜鐢熸垚瓒嬪娍
+ - generic [ref=f3e283]:
+ - generic [ref=f3e284] [cursor=pointer]:
+ - generic [ref=f3e285]:
+ - radio "杩� 7 澶�" [checked]
+ - generic [ref=f3e286]: 杩� 7 澶�
+ - generic [ref=f3e287] [cursor=pointer]:
+ - generic [ref=f3e288]:
+ - radio "杩� 30 澶�"
+ - generic [ref=f3e289]: 杩� 30 澶�
+ - generic [ref=f3e294]: 鎵规鐘舵�佸垎甯�
+ - generic [ref=f3e303]: 琚嬬爜鐘舵�佸垎甯�
+ - generic [ref=f3e312]:
+ - generic [ref=f3e313]: 蹇嵎鍏ュ彛
+ - generic [ref=f3e317]:
+ - generic [ref=f3e318]: 鍝佺绠$悊
+ - generic [ref=f3e326]: 鍝佺鍒嗙被
+ - generic [ref=f3e334]: 鎵规鐢熶骇
+ - generic [ref=f3e343]: 璧嬬爜绠$悊
\ No newline at end of file
diff --git a/.playwright-mcp/page-2026-08-21T04-01-18-956Z.yml b/.playwright-mcp/page-2026-08-21T04-01-18-956Z.yml
new file mode 100644
index 0000000..c98ec4f
--- /dev/null
+++ b/.playwright-mcp/page-2026-08-21T04-01-18-956Z.yml
@@ -0,0 +1,106 @@
+- generic [ref=f3e7]:
+ - complementary [ref=f3e9]:
+ - generic [ref=f3e10]:
+ - generic [ref=f3e11] [cursor=pointer]
+ - link "宸ヤ笟AI鏅洪�犲钩鍙� 宸ヤ笟AI鏅洪�犲钩鍙�" [ref=f3e16] [cursor=pointer]:
+ - /url: javascript:void 0
+ - img "宸ヤ笟AI鏅洪�犲钩鍙�" [ref=f3e19]
+ - generic [ref=f3e20]: 宸ヤ笟AI鏅洪�犲钩鍙�
+ - menu [ref=f3e23]:
+ - menuitem "棣栭〉" [ref=f3e24] [cursor=pointer]
+ - listitem [ref=f3e29]:
+ - generic [ref=f3e30] [cursor=pointer]: 鍩虹鏁版嵁
+ - listitem [ref=f3e38]:
+ - generic [ref=f3e39] [cursor=pointer]: 涓�琚嬩竴鐮佺鐞�
+ - list [ref=f3e349]:
+ - menuitem "鎵规鐢熶骇绠$悊" [ref=f3e350] [cursor=pointer]
+ - menuitem "璧嬬爜绠$悊" [active] [ref=f3e355] [cursor=pointer]
+ - menuitem "鎵樼洏鐮佺鐞�" [ref=f3e361] [cursor=pointer]
+ - menuitem "浜х嚎缁存姢" [ref=f3e368] [cursor=pointer]
+ - listitem [ref=f3e45]:
+ - generic [ref=f3e46] [cursor=pointer]: 绯荤粺绠$悊
+ - generic [ref=f3e53] [cursor=pointer]
+ - generic [ref=f3e58]:
+ - generic [ref=f3e59]:
+ - banner [ref=f3e60]:
+ - button [ref=f3e61] [cursor=pointer]
+ - button [ref=f3e64] [cursor=pointer]
+ - navigation "breadcrumb" [ref=f3e69]:
+ - list [ref=f3e70]:
+ - listitem [ref=f3e375]:
+ - link "涓�琚嬩竴鐮佺鐞�" [ref=f3e376] [cursor=pointer]:
+ - /url: javascript:void 0
+ - listitem [ref=f3e380]
+ - listitem [ref=f3e383]:
+ - link "璧嬬爜绠$悊" [disabled] [ref=f3e384]
+ - generic [ref=f3e77]:
+ - generic [ref=f3e79] [cursor=pointer]:
+ - generic [ref=f3e83]: 鎼滅储
+ - generic [ref=f3e84]: Ctrl K
+ - button [ref=f3e86] [cursor=pointer]
+ - button "dark" [ref=f3e91] [cursor=pointer]
+ - button [ref=f3e100] [cursor=pointer]
+ - button [ref=f3e106] [cursor=pointer]
+ - button [ref=f3e109] [cursor=pointer]
+ - button [ref=f3e115] [cursor=pointer]:
+ - button [ref=f3e117]
+ - button "宸ヤ綔鍙�" [ref=f3e121] [cursor=pointer]
+ - button [ref=f3e125] [cursor=pointer]:
+ - img "瓒呯骇绠$悊鍛�" [ref=f3e130]
+ - generic [ref=f3e132]:
+ - generic [ref=f3e137]:
+ - generic [ref=f3e138] [cursor=pointer]: 棣栭〉
+ - generic [ref=f3e392] [cursor=pointer]: 璧嬬爜绠$悊
+ - generic [ref=f3e152]:
+ - button [ref=f3e153] [cursor=pointer]
+ - generic [ref=f3e160] [cursor=pointer]
+ - generic [ref=f3e164] [cursor=pointer]
+ - main [ref=f3e171]:
+ - generic [ref=f3e174]:
+ - generic [ref=f3e175]:
+ - generic [ref=f3e185] [cursor=pointer]:
+ - generic [ref=f3e186]: 鍝佺鎬绘暟
+ - generic [ref=f3e187]: "1"
+ - generic [ref=f3e198] [cursor=pointer]:
+ - generic [ref=f3e199]: MES 鍝佺
+ - generic [ref=f3e200]: "0"
+ - generic [ref=f3e211] [cursor=pointer]:
+ - generic [ref=f3e212]: 鍝佺鍒嗙被
+ - generic [ref=f3e213]: "1"
+ - generic [ref=f3e222] [cursor=pointer]:
+ - generic [ref=f3e223]: 璁¢噺鍗曚綅
+ - generic [ref=f3e224]: "1"
+ - generic [ref=f3e226]:
+ - generic [ref=f3e234] [cursor=pointer]:
+ - generic [ref=f3e235]: 浜х嚎
+ - generic [ref=f3e236]: "1"
+ - generic [ref=f3e248] [cursor=pointer]:
+ - generic [ref=f3e249]: 鐢熶骇鎵规
+ - generic [ref=f3e250]: "1"
+ - generic [ref=f3e259] [cursor=pointer]:
+ - generic [ref=f3e260]: 琚嬬爜
+ - generic [ref=f3e261]: "100"
+ - generic [ref=f3e272] [cursor=pointer]:
+ - generic [ref=f3e273]: 鎵樼洏鐮�
+ - generic [ref=f3e274]: "10"
+ - generic [ref=f3e276]:
+ - generic [ref=f3e280]:
+ - generic [ref=f3e281]: 琚嬬爜鐢熸垚瓒嬪娍
+ - generic [ref=f3e283]:
+ - generic [ref=f3e284] [cursor=pointer]:
+ - generic [ref=f3e285]:
+ - radio "杩� 7 澶�" [checked]
+ - generic [ref=f3e286]: 杩� 7 澶�
+ - generic [ref=f3e287] [cursor=pointer]:
+ - generic [ref=f3e288]:
+ - radio "杩� 30 澶�"
+ - generic [ref=f3e289]: 杩� 30 澶�
+ - generic [ref=f3e294]: 鎵规鐘舵�佸垎甯�
+ - generic [ref=f3e303]: 琚嬬爜鐘舵�佸垎甯�
+ - generic [ref=f3e312]:
+ - generic [ref=f3e313]: 蹇嵎鍏ュ彛
+ - generic [ref=f3e317]:
+ - generic [ref=f3e318]: 鍝佺绠$悊
+ - generic [ref=f3e326]: 鍝佺鍒嗙被
+ - generic [ref=f3e334]: 鎵规鐢熶骇
+ - generic [ref=f3e343]: 璧嬬爜绠$悊
\ No newline at end of file
diff --git a/docs/mes_pro_bag_code_replacement_integration.md b/docs/mes_pro_bag_code_replacement_integration.md
new file mode 100644
index 0000000..9816c76
--- /dev/null
+++ b/docs/mes_pro_bag_code_replacement_integration.md
@@ -0,0 +1,150 @@
+# 涓�琚嬩竴鐮佺牬鎹熻鐮佹浛鎹� - 鍓嶇鑱旇皟鏂规
+
+## 娑夊強椤甸潰
+
+- 璧嬬爜绠$悊锛氳鐮佸垪琛ㄣ�佽鐮佽鎯呫�佹壂鐮佽拷婧�
+- 鎵规鐢熶骇绠$悊锛氭壒娆¤鎯呭強鏈夋晥琚嬬爜鏁伴噺灞曠ず
+- 鎵樼洏鐮佺鐞嗭細鎵樼洏璇︽儏鍙婄粦瀹氳鐮佸垪琛�
+
+鏈鍙柊澧炲悗绔帴鍙e拰瀛楁绾﹀畾锛屼笉淇敼鍓嶇椤圭洰浠g爜銆�
+
+## 涓氬姟娴佺▼涓庢暟鎹甫鍏�
+
+1. 鐢熶骇浜哄憳鍦ㄨ鐮佸垪琛ㄤ腑閫夋嫨鍚屼竴鎵规涓嬪寘瑁呯牬鎹熺殑琚嬬爜锛岃褰曞叾鏁版嵁搴撶紪鍙枫��
+2. 鍓嶇璋冪敤鐮存崯鏇挎崲鎺ュ彛锛屼紶鍏ユ壒娆$紪鍙枫�佹棫琚嬬爜缂栧彿鍒楄〃鍜岀牬鎹熷師鍥犮��
+3. 鍚庣鍦ㄤ竴涓簨鍔″唴灏嗘棫琚嬬爜鏀逛负鈥滃凡浣滃簾鈥濓紝鐢熸垚绛夐噺鏂拌鐮侊紝骞惰繑鍥炴棫鐮佷笌鏂扮爜涓�瀵逛竴鏄犲皠銆�
+4. 濡傛灉鏃ц鐮佸凡缁戝畾鍚敤鎵樼洏锛屾柊琚嬬爜鑷姩缁ф壙鍘熸墭鐩橈紱鏃х爜浠庢墭鐩樺綋鍓嶆湁鏁堣鐮佷腑绉婚櫎锛屾墭鐩樺凡缁戝畾鏁伴噺淇濇寔涓嶅彉銆�
+5. 鍓嶇鏍规嵁鍝嶅簲涓殑 `replaceUuid` 鎴栨柊琚嬬爜鍒楄〃鍒锋柊琚嬬爜鍒楄〃锛屽苟璋冪敤鐜版湁琚嬬爜瀵煎嚭鎺ュ彛瀹屾垚鏂版爣绛炬墦鍗般��
+6. 鏂拌鐮佸鍑哄悗鐘舵�佺敱鈥滃凡鐢熸垚鈥濆彉涓衡�滃凡瀵煎嚭鍗板埛鈥濓紱鏃ц鐮佷笉鍙備笌鎵撳嵃銆�
+7. 鎵弿鏃х爜浠嶅彲鏌ヨ鍘熸壒娆″拰浣滃簾淇℃伅锛涙壂鎻忔柊鐮佸彲鏌ヨ褰撳墠鎵规銆佹墭鐩樺拰鏇挎崲鏉ユ簮銆�
+
+## API
+
+### 1. 鐮存崯琚嬬爜鏇挎崲
+
+| 鏂规硶 | 璺緞 | 璇存槑 |
+|---|---|---|
+| POST | `/mes/pro/bag-code/replace` | 浣滃簾鐮存崯鏃ц鐮佸苟鍦ㄥ師鎵规鐢熸垚绛夐噺鏂拌鐮� |
+
+鏉冮檺锛歚mes:pro-bag-code:replace`
+
+**璇锋眰鍙傛暟锛�**
+
+| 鍙傛暟 | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+|---|---|---|---|
+| `batchId` | Long | 鏄� | 鐢熶骇鎵规缂栧彿 |
+| `oldIds` | Array<Long> | 鏄� | 寰呬綔搴熻鐮佺紪鍙凤紝鍘婚噸鍚庤嚦灏� 1 涓紝鍗曟鏈�澶� 200 涓� |
+| `reason` | String | 鏄� | 鏇挎崲鍘熷洜锛屼緥濡傗�滃寘瑁呯牬鎹熲�濓紝鏈�闀� 255 涓瓧绗� |
+
+**璇锋眰绀轰緥锛�**
+
+```json
+{
+ "batchId": 1001,
+ "oldIds": [5001, 5002],
+ "reason": "鍖呰鐮存崯"
+}
+```
+
+**鍝嶅簲瀛楁锛�**
+
+| 瀛楁 | 绫诲瀷 | 璇存槑 |
+|---|---|---|
+| `replaceUuid` | String | 鏈鏇挎崲缁� UUID锛屽彲鐢ㄤ簬璇嗗埆鏈鏂扮爜闆嗗悎 |
+| `batchId` | Long | 鐢熶骇鎵规缂栧彿 |
+| `batchCode` | String | 鐢熶骇鎵规鍙� |
+| `count` | Integer | 鏈鏇挎崲鏁伴噺 |
+| `items` | Array | 鏂版棫琚嬬爜鏄犲皠 |
+| `items.oldBagCodeId` | Long | 鏃ц鐮佺紪鍙� |
+| `items.oldCode` | String | 鏃ц鐮� |
+| `items.oldBagNo` | Integer | 鏃ц搴忓彿 |
+| `items.oldStatus` | Integer | 浣滃簾鍓嶇姸鎬� |
+| `items.oldPalletId` | Long | 鏃ц鐮佸師鎵樼洏缂栧彿锛屽彲涓虹┖ |
+| `items.oldPalletCode` | String | 鏃ц鐮佸師鎵樼洏鐮侊紝鍙负绌� |
+| `items.newBagCodeId` | Long | 鏂拌鐮佺紪鍙� |
+| `items.newCode` | String | 鏂拌鐮� |
+| `items.newBagNo` | Integer | 鏂拌搴忓彿 |
+| `items.newPalletId` | Long | 鏂拌鐮佸綋鍓嶆墭鐩樼紪鍙凤紝鍙负绌� |
+| `items.newPalletCode` | String | 鏂拌鐮佸綋鍓嶆墭鐩樼爜锛屽彲涓虹┖ |
+| `items.reason` | String | 鏇挎崲鍘熷洜 |
+| `items.replaceTime` | String | 鏇挎崲鏃堕棿 |
+
+**鍝嶅簲绀轰緥锛�**
+
+```json
+{
+ "code": 0,
+ "data": {
+ "replaceUuid": "9f6e4c4b2b2c4d5b8a8a8c0a0b0c0d0e",
+ "batchId": 1001,
+ "batchCode": "PC20260821L01ITEM001",
+ "count": 2,
+ "items": [
+ {
+ "oldBagCodeId": 5001,
+ "oldCode": "PC20260821L01ITEM001-0001",
+ "oldBagNo": 1,
+ "oldStatus": 20,
+ "oldPalletId": 3001,
+ "oldPalletCode": "PC20260821L01ITEM001-P01",
+ "newBagCodeId": 6001,
+ "newCode": "PC20260821L01ITEM001-1201",
+ "newBagNo": 1201,
+ "newPalletId": 3001,
+ "newPalletCode": "PC20260821L01ITEM001-P01",
+ "reason": "鍖呰鐮存崯",
+ "replaceTime": "2026-08-21 15:30:00"
+ }
+ ]
+ }
+}
+```
+
+## 瀛楁灞曠ず瑙勫垯
+
+| 瀛楁 | 灞曠ず浣嶇疆 | 璇存槑 |
+|---|---|---|
+| `status` | 琚嬬爜鍒楄〃銆佽鐮佽鎯呫�佹壂鐮佽拷婧� | 10 宸茬敓鎴愩��20 宸插鍑哄嵃鍒枫��30 宸蹭綔搴� |
+| `cancelTime` | 琚嬬爜璇︽儏銆佹壂鐮佽拷婧� | 浠呬綔搴熻鐮佽繑鍥� |
+| `cancelReason` | 琚嬬爜璇︽儏銆佹壂鐮佽拷婧� | 灞曠ず鐮存崯鎴栧叾浠栨浛鎹㈠師鍥� |
+| `replacementUuid` | 琚嬬爜璇︽儏銆佹壂鐮佽拷婧� | 鏍囪瘑鏇挎崲鎿嶄綔 |
+| `replacedByCode` | 浣滃簾鏃х爜杩芥函 | 灞曠ず鏇挎崲鍚庣殑鏂拌鐮� |
+| `replacementOfCode` | 鏂扮爜杩芥函 | 灞曠ず琚浛鎹㈢殑鏃ц鐮� |
+| `bagQuantity` | 鎵规鍒楄〃銆佹壒娆¤鎯� | 鎸夊綋鍓嶆湁鏁堣鐮佹暟閲忕粺璁★紝涓嶅寘鍚凡浣滃簾琚嬬爜 |
+| `palletCode` | 琚嬬爜鍒楄〃銆佹墭鐩樿鎯呫�佹壂鐮佽拷婧� | 宸茬粦瀹氬惎鐢ㄦ墭鐩樼殑鏇挎崲鏂扮爜缁ф壙鍘熸墭鐩� |
+
+## 涓氬姟瑙勫垯璇存槑
+
+| 鍦烘櫙 | 瑙勫垯 |
+|---|---|
+| 鏅�氱敓鎴� | 浠嶄粎鍏佽鐢熶骇涓壒娆★紝浣跨敤 `/mes/pro/bag-code/generate` |
+| 鐮存崯鏇挎崲 | 鍏佽鐢熶骇涓�佸凡瀹屾垚鎵规锛涜崏绋垮拰宸蹭綔搴熸壒娆′笉鍏佽 |
+| 鏃х爜鐘舵�� | 浠呭凡鐢熸垚銆佸凡瀵煎嚭鍗板埛鍙互鏇挎崲锛涘凡浣滃簾涓嶈兘閲嶅鏇挎崲 |
+| 鎵规褰掑睘 | `oldIds` 蹇呴』鍏ㄩ儴灞炰簬璇锋眰涓殑 `batchId` |
+| 鏂扮爜搴忓彿 | 浠庢壒娆″巻鍙叉渶澶ц搴忓彿缁х画閫掑锛屽凡浣滃簾鍜岄�昏緫鍒犻櫎搴忓彿涔熶笉澶嶇敤 |
+| 鏁伴噺 | 浣滃簾 N 涓苟鐢熸垚 N 涓紝鎵规鏈夋晥琚嬬爜鏁伴噺淇濇寔涓嶅彉 |
+| 鏈鎵樼洏 | 鏃х爜浣滃簾锛屾柊鐮佷繚鎸佹湭缁戝畾 |
+| 宸茶鎵樼洏 | 鍘熸墭鐩樺繀椤诲瓨鍦ㄤ笖鍚敤锛涙棫鐮佽В缁戝苟浣滃簾锛屾柊鐮佽嚜鍔ㄧ户鎵垮師鎵樼洏 |
+| 鎵樼洏鏁伴噺 | 鏇挎崲鍓嶅悗鎵樼洏鏈夋晥缁戝畾鏁伴噺淇濇寔涓嶅彉 |
+| 鎵撳嵃 | 鏂扮爜鍒濆涓哄凡鐢熸垚锛涘鍑哄悗鍙樹负宸插鍑哄嵃鍒凤紱鏃х爜涓嶅緱瀵煎嚭鎵撳嵃 |
+| 杩芥函 | 鏃х爜璁板綍淇濈暀骞舵樉绀哄凡浣滃簾锛屼笉杩斿洖琚嬬爜涓嶅瓨鍦紱鏂版棫鐮佸彲浜掔浉杩芥函 |
+| 鍘熷瓙鎬� | 浣滃簾銆佺敓鎴愩�佹墭鐩樼户鎵裤�佹浛鎹㈣褰曞啓鍏ヤ换涓�姝ュけ璐ワ紝鍏ㄩ儴浜嬪姟鍥炴粴 |
+
+## 鎺ュ彛璋冪敤鏃跺簭
+
+1. 鑾峰彇琚嬬爜鍒嗛〉锛屾寜鎵规鍜岀姸鎬佺瓫閫夋湁鏁堣鐮併��
+2. 鐢ㄦ埛鍕鹃�夌牬鎹熻鐮佸苟濉啓鍘熷洜銆�
+3. 璋冪敤 `/mes/pro/bag-code/replace`銆�
+4. 鎴愬姛鍚庡埛鏂拌鐮佸垪琛ㄥ拰鎵规鏁伴噺銆�
+5. 渚濇嵁鍝嶅簲鐨勬柊琚嬬爜闆嗗悎锛屾寜 `replaceUuid` 鏌ヨ鎴栧鍑烘柊鐮佽繘琛屾墦鍗般��
+6. 鎵撳嵃鎴愬姛鍚庡埛鏂扮姸鎬侊紱濡傞渶鎵爜纭锛屽垎鍒壂鎻忔棫鐮佸拰鏂扮爜鏍稿鏇挎崲鍏崇郴銆�
+
+## 娉ㄦ剰浜嬮」
+
+- `oldIds` 涓嶈娣峰叆涓嶅悓鎵规鐨勮鐮侊紱鏈嶅姟绔細鍐嶆鏍¢獙銆�
+- 涓嶈璋冪敤鏅�� `/generate` 瀹炵幇鐮存崯琛ョ爜锛屾櫘閫氱敓鎴愪細澧炲姞琚嬬爜鏁伴噺涓斾笉淇濆瓨鏇挎崲鍏崇郴銆�
+- 鏂拌鐮佷笉澶嶇敤鏃ц鐮佺殑 code 鎴栬搴忓彿锛�1200 琚嬫浛鎹� 2 琚嬫椂鏂扮爜閫氬父浠� 1201銆�1202 缁х画鐢熸垚銆�
+- 宸蹭綔搴熸棫鐮佷粛鍙拷婧紝浣嗕笉鍙粦瀹氭墭鐩樸�佷笉鍙啀娆℃浛鎹€�佷笉鍙墦鍗般��
+- 鍘熸墭鐩樺凡浣滃簾鎴栦笉瀛樺湪鏃讹紝宸茬粦瀹氳鐮佺殑鏇挎崲浼氬け璐ワ紝闇�瑕佸厛澶勭悊鎵樼洏鐘舵�併��
+- 鎵规杩芥函涓殑琚嬬爜瀵硅薄鍖呭惈鐘舵�佸瓧娈碉紱灞曠ず浣滃簾鏍囪瘑鏃朵笉瑕佸彧鏄剧ず `code` 瀛楃涓层��
+- 鏇挎崲鎺ュ彛杩斿洖鐨勬柊鐮佸垵濮嬫湭鎵撳嵃锛屽鍑烘垚鍔熷悗鎵嶅彉涓衡�滃凡瀵煎嚭鍗板埛鈥濄��
diff --git a/sql/mysql/mes_pro_bag_code_replacement.sql b/sql/mysql/mes_pro_bag_code_replacement.sql
new file mode 100644
index 0000000..af0dd54
--- /dev/null
+++ b/sql/mysql/mes_pro_bag_code_replacement.sql
@@ -0,0 +1,59 @@
+-- 涓�琚嬩竴鐮侊細鐮存崯琚嬬爜鏇挎崲杩佺Щ
+-- 璇存槑锛氭棫琚嬬爜淇濈暀骞舵爣璁板凡浣滃簾锛屾柊琚嬬爜涓庢棫琚嬬爜閫氳繃鏇挎崲璁板綍鍏宠仈銆�
+
+SET @cancel_time_exists = (
+ SELECT COUNT(*) FROM information_schema.columns
+ WHERE table_schema = DATABASE() AND table_name = 'mes_pro_bag_code' AND column_name = 'cancel_time'
+);
+SET @sql = IF(@cancel_time_exists = 0,
+ 'ALTER TABLE mes_pro_bag_code ADD COLUMN cancel_time DATETIME DEFAULT NULL COMMENT ''浣滃簾鏃堕棿'' AFTER print_time',
+ 'SELECT 1');
+PREPARE stmt FROM @sql;
+EXECUTE stmt;
+DEALLOCATE PREPARE stmt;
+
+SET @cancel_reason_exists = (
+ SELECT COUNT(*) FROM information_schema.columns
+ WHERE table_schema = DATABASE() AND table_name = 'mes_pro_bag_code' AND column_name = 'cancel_reason'
+);
+SET @sql = IF(@cancel_reason_exists = 0,
+ 'ALTER TABLE mes_pro_bag_code ADD COLUMN cancel_reason VARCHAR(255) DEFAULT NULL COMMENT ''浣滃簾鍘熷洜'' AFTER cancel_time',
+ 'SELECT 1');
+PREPARE stmt FROM @sql;
+EXECUTE stmt;
+DEALLOCATE PREPARE stmt;
+
+CREATE TABLE IF NOT EXISTS `mes_pro_bag_code_replace` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '缂栧彿',
+ `replace_uuid` VARCHAR(32) NOT NULL COMMENT '鏇挎崲缁� UUID',
+ `batch_id` BIGINT NOT NULL COMMENT '鐢熶骇鎵规缂栧彿',
+ `batch_code` VARCHAR(64) DEFAULT NULL COMMENT '鐢熶骇鎵规鍙�',
+ `old_bag_code_id` BIGINT NOT NULL COMMENT '鏃ц鐮佺紪鍙�',
+ `old_code` VARCHAR(64) NOT NULL COMMENT '鏃ц鐮�',
+ `old_bag_no` INT NOT NULL COMMENT '鏃ц搴忓彿',
+ `old_status` TINYINT NOT NULL COMMENT '鏃ц鐮佷綔搴熷墠鐘舵��',
+ `old_pallet_id` BIGINT DEFAULT NULL COMMENT '鏃ц鐮佸師鎵樼洏缂栧彿',
+ `old_pallet_code` VARCHAR(64) DEFAULT NULL COMMENT '鏃ц鐮佸師鎵樼洏鐮�',
+ `new_bag_code_id` BIGINT NOT NULL COMMENT '鏂拌鐮佺紪鍙�',
+ `new_code` VARCHAR(64) NOT NULL COMMENT '鏂拌鐮�',
+ `new_bag_no` INT NOT NULL COMMENT '鏂拌搴忓彿',
+ `reason` VARCHAR(255) NOT NULL COMMENT '鏇挎崲鍘熷洜',
+ `replace_time` DATETIME NOT NULL COMMENT '鏇挎崲鏃堕棿',
+ `creator` VARCHAR(64) DEFAULT '' COMMENT '鍒涘缓鑰�',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿',
+ `updater` VARCHAR(64) DEFAULT '' COMMENT '鏇存柊鑰�',
+ `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '鏇存柊鏃堕棿',
+ `deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '鏄惁鍒犻櫎',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_old_bag_code_id` (`old_bag_code_id`),
+ UNIQUE KEY `uk_new_bag_code_id` (`new_bag_code_id`),
+ KEY `idx_replace_uuid` (`replace_uuid`),
+ KEY `idx_batch_id` (`batch_id`),
+ KEY `idx_old_code` (`old_code`),
+ KEY `idx_new_code` (`new_code`)
+) ENGINE = InnoDB COMMENT = 'MES 琚嬬爜鏇挎崲璁板綍';
+
+INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`)
+SELECT 602629, '琚嬬爜鐮存崯鏇挎崲', 'mes:pro-bag-code:replace', 3, 6, 602618, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
+FROM DUAL
+WHERE NOT EXISTS (SELECT 1 FROM `system_menu` WHERE `id` = 602629 OR (`permission` = 'mes:pro-bag-code:replace' AND `deleted` = b'0'));
diff --git a/sql/mysql/mes_pro_batch_bag_code_init.sql b/sql/mysql/mes_pro_batch_bag_code_init.sql
index a3a1a03..8c7a86f 100644
--- a/sql/mysql/mes_pro_batch_bag_code_init.sql
+++ b/sql/mysql/mes_pro_batch_bag_code_init.sql
@@ -94,6 +94,8 @@
`pallet_code` VARCHAR(64) DEFAULT NULL COMMENT '鎵樼洏鐮侊紙鍐椾綑锛屼究浜庡睍绀猴級',
`status` TINYINT NOT NULL DEFAULT 10 COMMENT '鐘舵�侊紙瀛楀吀 mes_pro_bag_code_status锛�10 宸茬敓鎴� 20 宸插鍑哄嵃鍒� 30 宸蹭綔搴燂級',
`print_time` DATETIME DEFAULT NULL COMMENT '瀵煎嚭锛堜氦浠樺嵃鍒凤級鏃堕棿',
+ `cancel_time` DATETIME DEFAULT NULL COMMENT '浣滃簾鏃堕棿',
+ `cancel_reason` VARCHAR(255) DEFAULT NULL COMMENT '浣滃簾鍘熷洜',
`remark` VARCHAR(255) DEFAULT NULL COMMENT '澶囨敞',
`creator` VARCHAR(64) DEFAULT '' COMMENT '鍒涘缓鑰�',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿',
@@ -105,10 +107,43 @@
KEY `idx_batch_id` (`batch_id`),
KEY `idx_uuid` (`uuid`),
KEY `idx_pallet_id` (`pallet_id`)
-) ENGINE = InnoDB COMMENT = 'MES 琚嬬爜璧嬬爜锛堜竴琚嬩竴鐮侊級';
+ ) ENGINE = InnoDB COMMENT = 'MES 琚嬬爜璧嬬爜锛堜竴琚嬩竴鐮侊級';
-- ----------------------------
--- 5. 鎵规鍙疯嚜鍔ㄧ紪鐮佽鍒欙細PRO_BATCH_CODE
+-- 5. 琚嬬爜鏇挎崲璁板綍琛�
+-- ----------------------------
+CREATE TABLE IF NOT EXISTS `mes_pro_bag_code_replace` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '缂栧彿',
+ `replace_uuid` VARCHAR(32) NOT NULL COMMENT '鏇挎崲缁� UUID',
+ `batch_id` BIGINT NOT NULL COMMENT '鐢熶骇鎵规缂栧彿',
+ `batch_code` VARCHAR(64) DEFAULT NULL COMMENT '鐢熶骇鎵规鍙�',
+ `old_bag_code_id` BIGINT NOT NULL COMMENT '鏃ц鐮佺紪鍙�',
+ `old_code` VARCHAR(64) NOT NULL COMMENT '鏃ц鐮�',
+ `old_bag_no` INT NOT NULL COMMENT '鏃ц搴忓彿',
+ `old_status` TINYINT NOT NULL COMMENT '鏃ц鐮佷綔搴熷墠鐘舵��',
+ `old_pallet_id` BIGINT DEFAULT NULL COMMENT '鏃ц鐮佸師鎵樼洏缂栧彿',
+ `old_pallet_code` VARCHAR(64) DEFAULT NULL COMMENT '鏃ц鐮佸師鎵樼洏鐮�',
+ `new_bag_code_id` BIGINT NOT NULL COMMENT '鏂拌鐮佺紪鍙�',
+ `new_code` VARCHAR(64) NOT NULL COMMENT '鏂拌鐮�',
+ `new_bag_no` INT NOT NULL COMMENT '鏂拌搴忓彿',
+ `reason` VARCHAR(255) NOT NULL COMMENT '鏇挎崲鍘熷洜',
+ `replace_time` DATETIME NOT NULL COMMENT '鏇挎崲鏃堕棿',
+ `creator` VARCHAR(64) DEFAULT '' COMMENT '鍒涘缓鑰�',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿',
+ `updater` VARCHAR(64) DEFAULT '' COMMENT '鏇存柊鑰�',
+ `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '鏇存柊鏃堕棿',
+ `deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '鏄惁鍒犻櫎',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_old_bag_code_id` (`old_bag_code_id`),
+ UNIQUE KEY `uk_new_bag_code_id` (`new_bag_code_id`),
+ KEY `idx_replace_uuid` (`replace_uuid`),
+ KEY `idx_batch_id` (`batch_id`),
+ KEY `idx_old_code` (`old_code`),
+ KEY `idx_new_code` (`new_code`)
+) ENGINE = InnoDB COMMENT = 'MES 琚嬬爜鏇挎崲璁板綍';
+
+-- ----------------------------
+-- 6. 鎵规鍙疯嚜鍔ㄧ紪鐮佽鍒欙細PRO_BATCH_CODE
-- 缁撴瀯锛氬浐瀹氬瓧绗�(PC) + 鏃ユ湡(yyyyMMdd) + 杈撳叆瀛楃(浜х嚎缂栫爜+鍝佺缂栫爜) + 娴佹按鍙�(3浣嶏紝鎸夋棩寰幆)
-- 绀轰緥锛歅C20260818L01NY001
-- ----------------------------
@@ -189,7 +224,8 @@
(602620, '鐢熸垚浜岀淮鐮佹暟鎹寘', 'mes:pro-bag-code:generate', 3, 2, 602618, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'),
(602621, '琚嬬爜鍒犻櫎', 'mes:pro-bag-code:delete', 3, 3, 602618, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'),
(602622, '琚嬬爜瀵煎嚭', 'mes:pro-bag-code:export', 3, 4, 602618, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'),
-(602623, '琚嬬爜缁戝畾鎵樼洏', 'mes:pro-bag-code:bind', 3, 5, 602618, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0');
+(602623, '琚嬬爜缁戝畾鎵樼洏', 'mes:pro-bag-code:bind', 3, 5, 602618, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'),
+(602629, '琚嬬爜鐮存崯鏇挎崲', 'mes:pro-bag-code:replace', 3, 6, 602618, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0');
-- 鎵樼洏鐮佺鐞�
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`)
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/MesProBagCodeController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/MesProBagCodeController.java
index 61cb109..49cb688 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/MesProBagCodeController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/MesProBagCodeController.java
@@ -12,6 +12,8 @@
import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeBindReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeGenerateReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodePageReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeReplaceReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeReplaceRespVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeRespVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeTraceRespVO;
import cn.iocoder.yudao.module.mes.dal.dataobject.mdm.MesMdmItemDO;
@@ -73,6 +75,14 @@
@PreAuthorize("@ss.hasPermission('mes:pro-bag-code:create')")
public CommonResult<String> generateBagCodes(@Valid @RequestBody MesProBagCodeGenerateReqVO generateReqVO) {
return success(bagCodeService.generateBagCodes(generateReqVO));
+ }
+
+ @PostMapping("/replace")
+ @Operation(summary = "浣滃簾鐮存崯琚嬬爜骞剁敓鎴愮瓑閲忔浛鎹㈣鐮�")
+ @PreAuthorize("@ss.hasPermission('mes:pro-bag-code:replace')")
+ public CommonResult<MesProBagCodeReplaceRespVO> replaceBagCodes(
+ @Valid @RequestBody MesProBagCodeReplaceReqVO replaceReqVO) {
+ return success(bagCodeService.replaceBagCodes(replaceReqVO));
}
@DeleteMapping("/delete-by-uuid")
@@ -203,6 +213,18 @@
private MesProBagCodeTraceRespVO buildBagCodeTraceRespVO(MesProBagCodeDO bagCode) {
MesProBagCodeTraceRespVO respVO = BeanUtils.toBean(bagCode, MesProBagCodeTraceRespVO.class);
+ var replacement = bagCode.getStatus() != null
+ && bagCode.getStatus().equals(cn.iocoder.yudao.module.mes.enums.pro.MesProBagCodeStatusEnum.CANCELED.getStatus())
+ ? bagCodeService.getReplacementByOldBagCodeId(bagCode.getId())
+ : bagCodeService.getReplacementByNewBagCodeId(bagCode.getId());
+ if (replacement != null) {
+ respVO.setReplacementUuid(replacement.getReplaceUuid());
+ if (bagCode.getId().equals(replacement.getOldBagCodeId())) {
+ respVO.setReplacedByCode(replacement.getNewCode());
+ } else {
+ respVO.setReplacementOfCode(replacement.getOldCode());
+ }
+ }
// 鎵规淇℃伅
MesProBatchDO batch = batchService.getBatch(bagCode.getBatchId());
if (batch != null) {
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/vo/MesProBagCodeReplaceItemRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/vo/MesProBagCodeReplaceItemRespVO.java
new file mode 100644
index 0000000..4e38dc8
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/vo/MesProBagCodeReplaceItemRespVO.java
@@ -0,0 +1,51 @@
+package cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "绠$悊鍚庡彴 - MES 琚嬬爜鏇挎崲鏄庣粏 Response VO")
+@Data
+public class MesProBagCodeReplaceItemRespVO {
+
+ @Schema(description = "鏃ц鐮佺紪鍙�")
+ private Long oldBagCodeId;
+
+ @Schema(description = "鏃ц鐮�")
+ private String oldCode;
+
+ @Schema(description = "鏃ц搴忓彿")
+ private Integer oldBagNo;
+
+ @Schema(description = "鏃ц鐮佷綔搴熷墠鐘舵��")
+ private Integer oldStatus;
+
+ @Schema(description = "鏃ц鐮佸師鎵樼洏缂栧彿")
+ private Long oldPalletId;
+
+ @Schema(description = "鏃ц鐮佸師鎵樼洏鐮�")
+ private String oldPalletCode;
+
+ @Schema(description = "鏂拌鐮佺紪鍙�")
+ private Long newBagCodeId;
+
+ @Schema(description = "鏂拌鐮�")
+ private String newCode;
+
+ @Schema(description = "鏂拌搴忓彿")
+ private Integer newBagNo;
+
+ @Schema(description = "鏂拌鐮佸綋鍓嶆墭鐩樼紪鍙�")
+ private Long newPalletId;
+
+ @Schema(description = "鏂拌鐮佸綋鍓嶆墭鐩樼爜")
+ private String newPalletCode;
+
+ @Schema(description = "鏇挎崲鍘熷洜")
+ private String reason;
+
+ @Schema(description = "鏇挎崲鏃堕棿")
+ private LocalDateTime replaceTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/vo/MesProBagCodeReplaceReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/vo/MesProBagCodeReplaceReqVO.java
new file mode 100644
index 0000000..fd9cf6e
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/vo/MesProBagCodeReplaceReqVO.java
@@ -0,0 +1,30 @@
+package cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import lombok.Data;
+
+import java.util.List;
+
+@Schema(description = "绠$悊鍚庡彴 - MES 鐮存崯琚嬬爜鏇挎崲 Request VO")
+@Data
+public class MesProBagCodeReplaceReqVO {
+
+ @Schema(description = "鐢熶骇鎵规缂栧彿", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ @NotNull(message = "鐢熶骇鎵规缂栧彿涓嶈兘涓虹┖")
+ private Long batchId;
+
+ @Schema(description = "寰呬綔搴熺殑琚嬬爜缂栧彿鍒楄〃", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotEmpty(message = "寰呬綔搴熻鐮佷笉鑳戒负绌�")
+ @Size(max = 200, message = "鍗曟鏈�澶氭浛鎹� 200 涓鐮�")
+ private List<Long> oldIds;
+
+ @Schema(description = "鏇挎崲鍘熷洜", requiredMode = Schema.RequiredMode.REQUIRED, example = "鍖呰鐮存崯")
+ @NotBlank(message = "鏇挎崲鍘熷洜涓嶈兘涓虹┖")
+ @Size(max = 255, message = "鏇挎崲鍘熷洜闀垮害涓嶈兘瓒呰繃 255 涓瓧绗�")
+ private String reason;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/vo/MesProBagCodeReplaceRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/vo/MesProBagCodeReplaceRespVO.java
new file mode 100644
index 0000000..24210fc
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/vo/MesProBagCodeReplaceRespVO.java
@@ -0,0 +1,27 @@
+package cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Schema(description = "绠$悊鍚庡彴 - MES 鐮存崯琚嬬爜鏇挎崲 Response VO")
+@Data
+public class MesProBagCodeReplaceRespVO {
+
+ @Schema(description = "鏈鏇挎崲缁� UUID")
+ private String replaceUuid;
+
+ @Schema(description = "鐢熶骇鎵规缂栧彿")
+ private Long batchId;
+
+ @Schema(description = "鐢熶骇鎵规鍙�")
+ private String batchCode;
+
+ @Schema(description = "鏇挎崲鏁伴噺")
+ private Integer count;
+
+ @Schema(description = "鏇挎崲鏄庣粏")
+ private List<MesProBagCodeReplaceItemRespVO> items;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/vo/MesProBagCodeRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/vo/MesProBagCodeRespVO.java
index 900d5c5..07be109 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/vo/MesProBagCodeRespVO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/vo/MesProBagCodeRespVO.java
@@ -68,6 +68,14 @@
@ColumnWidth(20)
private LocalDateTime printTime;
+ @Schema(description = "浣滃簾鏃堕棿")
+ @ExcelIgnore
+ private LocalDateTime cancelTime;
+
+ @Schema(description = "浣滃簾鍘熷洜")
+ @ExcelIgnore
+ private String cancelReason;
+
@Schema(description = "澶囨敞")
@ExcelIgnore
private String remark;
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/vo/MesProBagCodeTraceRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/vo/MesProBagCodeTraceRespVO.java
index d049c46..4272372 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/vo/MesProBagCodeTraceRespVO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/vo/MesProBagCodeTraceRespVO.java
@@ -26,6 +26,21 @@
@Schema(description = "瀵煎嚭锛堜氦浠樺嵃鍒凤級鏃堕棿")
private LocalDateTime printTime;
+ @Schema(description = "浣滃簾鏃堕棿")
+ private LocalDateTime cancelTime;
+
+ @Schema(description = "浣滃簾鍘熷洜")
+ private String cancelReason;
+
+ @Schema(description = "鏇挎崲缁� UUID")
+ private String replacementUuid;
+
+ @Schema(description = "鏇挎崲鍚庣殑鏂拌鐮�")
+ private String replacedByCode;
+
+ @Schema(description = "琚浛鎹㈢殑鏃ц鐮�")
+ private String replacementOfCode;
+
// ========== 鎵规淇℃伅 ==========
@Schema(description = "鐢熶骇鎵规缂栧彿", example = "1024")
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/bagcode/MesProBagCodeDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/bagcode/MesProBagCodeDO.java
index feb8e98..be7f025 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/bagcode/MesProBagCodeDO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/bagcode/MesProBagCodeDO.java
@@ -79,6 +79,14 @@
*/
private LocalDateTime printTime;
/**
+ * 浣滃簾鏃堕棿
+ */
+ private LocalDateTime cancelTime;
+ /**
+ * 浣滃簾鍘熷洜
+ */
+ private String cancelReason;
+ /**
* 澶囨敞
*/
private String remark;
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/bagcode/MesProBagCodeReplaceDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/bagcode/MesProBagCodeReplaceDO.java
new file mode 100644
index 0000000..5e0749b
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/bagcode/MesProBagCodeReplaceDO.java
@@ -0,0 +1,37 @@
+package cn.iocoder.yudao.module.mes.dal.dataobject.pro.bagcode;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import java.time.LocalDateTime;
+
+@TableName("mes_pro_bag_code_replace")
+@KeySequence("mes_pro_bag_code_replace_seq")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class MesProBagCodeReplaceDO extends BaseDO {
+
+ @TableId
+ private Long id;
+ private String replaceUuid;
+ private Long batchId;
+ private String batchCode;
+ private Long oldBagCodeId;
+ private String oldCode;
+ private Integer oldBagNo;
+ private Integer oldStatus;
+ private Long oldPalletId;
+ private String oldPalletCode;
+ private Long newBagCodeId;
+ private String newCode;
+ private Integer newBagNo;
+ private String reason;
+ private LocalDateTime replaceTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/bagcode/MesProBagCodeMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/bagcode/MesProBagCodeMapper.java
index 4a4906d..ca31481 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/bagcode/MesProBagCodeMapper.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/bagcode/MesProBagCodeMapper.java
@@ -98,6 +98,24 @@
@Select("SELECT IFNULL(MAX(bag_no), 0) FROM mes_pro_bag_code WHERE batch_id = #{batchId}")
Integer selectMaxBagNo(@Param("batchId") Long batchId);
+ default List<MesProBagCodeDO> selectListByIdsForUpdate(Collection<Long> ids) {
+ return selectList(new LambdaQueryWrapperX<MesProBagCodeDO>()
+ .in(MesProBagCodeDO::getId, ids)
+ .orderByAsc(MesProBagCodeDO::getId)
+ .last("FOR UPDATE"));
+ }
+
+ @Update("<script>UPDATE mes_pro_bag_code SET status = #{toStatus}, cancel_time = #{cancelTime}, " +
+ "cancel_reason = #{cancelReason}, pallet_id = NULL, pallet_code = NULL, update_time = NOW() " +
+ "WHERE deleted = 0 AND id = #{id} AND status = #{fromStatus}</script>")
+ int cancelById(@Param("id") Long id, @Param("fromStatus") Integer fromStatus,
+ @Param("toStatus") Integer toStatus, @Param("cancelTime") LocalDateTime cancelTime,
+ @Param("cancelReason") String cancelReason);
+
+ @Select("SELECT COUNT(*) FROM mes_pro_bag_code WHERE batch_id = #{batchId} " +
+ "AND deleted = 0 AND status <> 30")
+ int selectEffectiveCountByBatchId(@Param("batchId") Long batchId);
+
/**
* 鎵归噺鏍囪涓哄凡瀵煎嚭鍗板埛锛堜粎鏇存柊澶勪簬鐩爣鍘熺姸鎬佺殑璁板綍锛�
*
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/bagcode/MesProBagCodeReplaceMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/bagcode/MesProBagCodeReplaceMapper.java
new file mode 100644
index 0000000..5fce030
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/bagcode/MesProBagCodeReplaceMapper.java
@@ -0,0 +1,27 @@
+package cn.iocoder.yudao.module.mes.dal.mysql.pro.bagcode;
+
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.bagcode.MesProBagCodeReplaceDO;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.Collection;
+import java.util.List;
+
+@Mapper
+public interface MesProBagCodeReplaceMapper extends BaseMapperX<MesProBagCodeReplaceDO> {
+
+ default List<MesProBagCodeReplaceDO> selectListByOldBagCodeIds(Collection<Long> oldBagCodeIds) {
+ return selectList(new LambdaQueryWrapper<MesProBagCodeReplaceDO>()
+ .in(MesProBagCodeReplaceDO::getOldBagCodeId, oldBagCodeIds));
+ }
+
+ default MesProBagCodeReplaceDO selectByOldBagCodeId(Long oldBagCodeId) {
+ return selectOne(MesProBagCodeReplaceDO::getOldBagCodeId, oldBagCodeId);
+ }
+
+ default MesProBagCodeReplaceDO selectByNewBagCodeId(Long newBagCodeId) {
+ return selectOne(MesProBagCodeReplaceDO::getNewBagCodeId, newBagCodeId);
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/batch/MesProBatchMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/batch/MesProBatchMapper.java
index 64d0121..f35a1e4 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/batch/MesProBatchMapper.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/batch/MesProBatchMapper.java
@@ -6,6 +6,7 @@
import cn.iocoder.yudao.module.mes.controller.admin.pro.batch.vo.MesProBatchPageReqVO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.batch.MesProBatchDO;
import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Select;
/**
* MES 鐢熶骇鎵规 Mapper
@@ -23,6 +24,9 @@
return selectCount(MesProBatchDO::getLineId, lineId);
}
+ @Select("SELECT * FROM mes_pro_batch WHERE id = #{id} AND deleted = 0 FOR UPDATE")
+ MesProBatchDO selectByIdForUpdate(@org.apache.ibatis.annotations.Param("id") Long id);
+
default PageResult<MesProBatchDO> selectPage(MesProBatchPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<MesProBatchDO>()
.likeIfPresent(MesProBatchDO::getCode, reqVO.getCode())
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/pallet/MesProPalletMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/pallet/MesProPalletMapper.java
index b2b6512..8e2b856 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/pallet/MesProPalletMapper.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/pallet/MesProPalletMapper.java
@@ -23,6 +23,9 @@
return selectOne(MesProPalletDO::getCode, code);
}
+ @Select("SELECT * FROM mes_pro_pallet WHERE id = #{id} AND deleted = 0 FOR UPDATE")
+ MesProPalletDO selectByIdForUpdate(@Param("id") Long id);
+
default List<MesProPalletDO> selectListByBatchId(Long batchId) {
return selectList(MesProPalletDO::getBatchId, batchId);
}
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 41c8c20..02e4dab 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
@@ -818,6 +818,11 @@
ErrorCode PRO_BAG_CODE_BIND_PALLET_BOUND = new ErrorCode(1_040_752_004, "瀛樺湪宸茬粦瀹氭墭鐩樼殑琚嬬爜锛岃鍏堣В缁�");
ErrorCode PRO_BAG_CODE_UUID_NOT_EXISTS = new ErrorCode(1_040_752_005, "琚嬬爜鐢熸垚缁勪笉瀛樺湪");
ErrorCode PRO_BAG_CODE_BIND_PALLET_OVER_CAPACITY = new ErrorCode(1_040_752_006, "缁戝畾鍚庤鐮佹暟閲忚秴杩囨墭鐩樺彲瑁呰鏁�");
+ ErrorCode PRO_BAG_CODE_REPLACE_BATCH_STATUS_INVALID = new ErrorCode(1_040_752_007, "鐢熶骇鎵规鐘舵�佷笉鍏佽鐮存崯琚嬬爜鏇挎崲");
+ ErrorCode PRO_BAG_CODE_REPLACE_BATCH_MISMATCH = new ErrorCode(1_040_752_008, "寰呮浛鎹㈣鐮佷笉灞炰簬鎸囧畾鐢熶骇鎵规");
+ ErrorCode PRO_BAG_CODE_REPLACE_ALREADY_REPLACED = new ErrorCode(1_040_752_009, "琚嬬爜宸插畬鎴愭浛鎹紝涓嶅厑璁搁噸澶嶆浛鎹�");
+ ErrorCode PRO_BAG_CODE_REPLACE_STATUS_INVALID = new ErrorCode(1_040_752_010, "琚嬬爜鐘舵�佷笉鍏佽鐮存崯鏇挎崲");
+ ErrorCode PRO_BAG_CODE_REPLACE_PALLET_INVALID = new ErrorCode(1_040_752_011, "琚嬬爜鍘熸墭鐩樹笉瀛樺湪鎴栧凡浣滃簾锛屼笉鍏佽缁ф壙");
// ========== MES 鐢熶骇绠$悊-鎵樼洏鐮侊紙1-040-753-000锛� ==========
ErrorCode PRO_PALLET_NOT_EXISTS = new ErrorCode(1_040_753_000, "鎵樼洏鐮佷笉瀛樺湪");
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/bagcode/MesProBagCodeService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/bagcode/MesProBagCodeService.java
index 5608218..c75dadf 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/bagcode/MesProBagCodeService.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/bagcode/MesProBagCodeService.java
@@ -4,6 +4,8 @@
import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeBindReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeGenerateReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodePageReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeReplaceReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeReplaceRespVO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.bagcode.MesProBagCodeDO;
import jakarta.validation.Valid;
@@ -26,6 +28,11 @@
* @return 鐢熸垚缁� UUID锛堟爣璁板悓涓�娆$敓鎴愮殑鏁版嵁鍖咃級
*/
String generateBagCodes(@Valid MesProBagCodeGenerateReqVO generateReqVO);
+
+ /**
+ * 浣滃簾鐮存崯琚嬬爜骞跺湪鍘熸壒娆$敓鎴愮瓑閲忔浛鎹㈣鐮�
+ */
+ MesProBagCodeReplaceRespVO replaceBagCodes(@Valid MesProBagCodeReplaceReqVO replaceReqVO);
/**
* 鍒犻櫎鐢熸垚缁勶紙浠�"宸茬敓鎴�"鐘舵�佷笖鏈粦瀹氭墭鐩樼殑琚嬬爜鍏佽鍒犻櫎锛�
@@ -80,6 +87,13 @@
MesProBagCodeDO getBagCodeByCode(String code);
/**
+ * 鏌ヨ琚嬬爜鏇挎崲璁板綍
+ */
+ cn.iocoder.yudao.module.mes.dal.dataobject.pro.bagcode.MesProBagCodeReplaceDO getReplacementByOldBagCodeId(Long oldBagCodeId);
+
+ cn.iocoder.yudao.module.mes.dal.dataobject.pro.bagcode.MesProBagCodeReplaceDO getReplacementByNewBagCodeId(Long newBagCodeId);
+
+ /**
* 鑾峰緱琚嬬爜鍒嗛〉
*
* @param pageReqVO 鍒嗛〉鏌ヨ
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/bagcode/MesProBagCodeServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/bagcode/MesProBagCodeServiceImpl.java
index 3ac2f9d..d346513 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/bagcode/MesProBagCodeServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/bagcode/MesProBagCodeServiceImpl.java
@@ -7,13 +7,20 @@
import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeBindReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeGenerateReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodePageReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeReplaceItemRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeReplaceReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeReplaceRespVO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.bagcode.MesProBagCodeDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.bagcode.MesProBagCodeReplaceDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.batch.MesProBatchDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.pallet.MesProPalletDO;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.bagcode.MesProBagCodeMapper;
+import cn.iocoder.yudao.module.mes.dal.mysql.pro.bagcode.MesProBagCodeReplaceMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.batch.MesProBatchMapper;
+import cn.iocoder.yudao.module.mes.dal.mysql.pro.pallet.MesProPalletMapper;
import cn.iocoder.yudao.module.mes.enums.pro.MesProBagCodeStatusEnum;
import cn.iocoder.yudao.module.mes.enums.pro.MesProBatchStatusEnum;
+import cn.iocoder.yudao.module.mes.enums.pro.MesProPalletStatusEnum;
import cn.iocoder.yudao.module.mes.service.pro.pallet.MesProPalletService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
@@ -24,7 +31,9 @@
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
@@ -43,6 +52,10 @@
private MesProBagCodeMapper bagCodeMapper;
@Resource
private MesProBatchMapper batchMapper;
+ @Resource
+ private MesProBagCodeReplaceMapper replaceMapper;
+ @Resource
+ private MesProPalletMapper palletMapper;
@Resource
private MesProPalletService palletService;
@@ -51,7 +64,7 @@
@Transactional(rollbackFor = Exception.class)
public String generateBagCodes(MesProBagCodeGenerateReqVO generateReqVO) {
// 1. 鏍¢獙鎵规瀛樺湪涓斿浜庣敓浜т腑鐘舵��
- MesProBatchDO batch = batchMapper.selectById(generateReqVO.getBatchId());
+ MesProBatchDO batch = batchMapper.selectByIdForUpdate(generateReqVO.getBatchId());
if (batch == null) {
throw exception(PRO_BATCH_NOT_EXISTS);
}
@@ -86,6 +99,118 @@
.setBagQuantity((batch.getBagQuantity() == null ? 0 : batch.getBagQuantity())
+ generateReqVO.getCount()));
return uuid;
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public MesProBagCodeReplaceRespVO replaceBagCodes(MesProBagCodeReplaceReqVO replaceReqVO) {
+ MesProBatchDO batch = batchMapper.selectByIdForUpdate(replaceReqVO.getBatchId());
+ if (batch == null) {
+ throw exception(PRO_BATCH_NOT_EXISTS);
+ }
+ if (!MesProBatchStatusEnum.PRODUCING.getStatus().equals(batch.getStatus())
+ && !MesProBatchStatusEnum.FINISHED.getStatus().equals(batch.getStatus())) {
+ throw exception(PRO_BAG_CODE_REPLACE_BATCH_STATUS_INVALID);
+ }
+
+ List<Long> oldIds = replaceReqVO.getOldIds().stream()
+ .distinct().sorted().toList();
+ List<MesProBagCodeDO> oldBagCodes = bagCodeMapper.selectListByIdsForUpdate(oldIds);
+ if (oldBagCodes.size() != oldIds.size()) {
+ throw exception(PRO_BAG_CODE_NOT_EXISTS);
+ }
+ for (MesProBagCodeDO oldBagCode : oldBagCodes) {
+ if (!batch.getId().equals(oldBagCode.getBatchId())) {
+ throw exception(PRO_BAG_CODE_REPLACE_BATCH_MISMATCH);
+ }
+ if (!MesProBagCodeStatusEnum.GENERATED.getStatus().equals(oldBagCode.getStatus())
+ && !MesProBagCodeStatusEnum.PRINTED.getStatus().equals(oldBagCode.getStatus())) {
+ throw exception(PRO_BAG_CODE_REPLACE_STATUS_INVALID);
+ }
+ if (replaceMapper.selectByOldBagCodeId(oldBagCode.getId()) != null) {
+ throw exception(PRO_BAG_CODE_REPLACE_ALREADY_REPLACED);
+ }
+ }
+
+ Map<Long, MesProPalletDO> palletMap = new LinkedHashMap<>();
+ oldBagCodes.stream().map(MesProBagCodeDO::getPalletId).filter(id -> id != null)
+ .distinct().sorted().forEach(palletId -> {
+ MesProPalletDO pallet = palletMapper.selectByIdForUpdate(palletId);
+ if (pallet == null || !MesProPalletStatusEnum.IN_USE.getStatus().equals(pallet.getStatus())) {
+ throw exception(PRO_BAG_CODE_REPLACE_PALLET_INVALID);
+ }
+ palletMap.put(palletId, pallet);
+ });
+
+ String replaceUuid = IdUtil.fastSimpleUUID();
+ LocalDateTime replaceTime = LocalDateTime.now();
+ int startNo = bagCodeMapper.selectMaxBagNo(batch.getId()) + 1;
+ List<MesProBagCodeDO> newBagCodes = new ArrayList<>(oldBagCodes.size());
+ List<MesProBagCodeReplaceDO> replacements = new ArrayList<>(oldBagCodes.size());
+ List<MesProBagCodeReplaceItemRespVO> items = new ArrayList<>(oldBagCodes.size());
+ for (int i = 0; i < oldBagCodes.size(); i++) {
+ MesProBagCodeDO oldBagCode = oldBagCodes.get(i);
+ if (bagCodeMapper.cancelById(oldBagCode.getId(), oldBagCode.getStatus(),
+ MesProBagCodeStatusEnum.CANCELED.getStatus(), replaceTime, replaceReqVO.getReason()) != 1) {
+ throw exception(PRO_BAG_CODE_REPLACE_STATUS_INVALID);
+ }
+ int newBagNo = startNo + i;
+ MesProPalletDO pallet = oldBagCode.getPalletId() == null ? null : palletMap.get(oldBagCode.getPalletId());
+ MesProBagCodeDO newBagCode = new MesProBagCodeDO()
+ .setUuid(replaceUuid)
+ .setCode(batch.getCode() + "-" + StrUtil.padPre(String.valueOf(newBagNo), 4, '0'))
+ .setBagNo(newBagNo)
+ .setBatchId(batch.getId())
+ .setBatchCode(batch.getCode())
+ .setPalletId(pallet == null ? null : pallet.getId())
+ .setPalletCode(pallet == null ? null : pallet.getCode())
+ .setStatus(MesProBagCodeStatusEnum.GENERATED.getStatus())
+ .setRemark(replaceReqVO.getReason());
+ newBagCodes.add(newBagCode);
+
+ replacements.add(new MesProBagCodeReplaceDO()
+ .setReplaceUuid(replaceUuid)
+ .setBatchId(batch.getId())
+ .setBatchCode(batch.getCode())
+ .setOldBagCodeId(oldBagCode.getId())
+ .setOldCode(oldBagCode.getCode())
+ .setOldBagNo(oldBagCode.getBagNo())
+ .setOldStatus(oldBagCode.getStatus())
+ .setOldPalletId(oldBagCode.getPalletId())
+ .setOldPalletCode(oldBagCode.getPalletCode())
+ .setNewCode(newBagCode.getCode())
+ .setNewBagNo(newBagNo)
+ .setReason(replaceReqVO.getReason())
+ .setReplaceTime(replaceTime));
+ items.add(new MesProBagCodeReplaceItemRespVO()
+ .setOldBagCodeId(oldBagCode.getId())
+ .setOldCode(oldBagCode.getCode())
+ .setOldBagNo(oldBagCode.getBagNo())
+ .setOldStatus(oldBagCode.getStatus())
+ .setOldPalletId(oldBagCode.getPalletId())
+ .setOldPalletCode(oldBagCode.getPalletCode())
+ .setNewCode(newBagCode.getCode())
+ .setNewBagNo(newBagNo)
+ .setNewPalletId(newBagCode.getPalletId())
+ .setNewPalletCode(newBagCode.getPalletCode())
+ .setReason(replaceReqVO.getReason())
+ .setReplaceTime(replaceTime));
+ }
+ bagCodeMapper.insertBatch(newBagCodes);
+ for (int i = 0; i < replacements.size(); i++) {
+ replacements.get(i).setNewBagCodeId(newBagCodes.get(i).getId());
+ items.get(i).setNewBagCodeId(newBagCodes.get(i).getId());
+ }
+ replaceMapper.insertBatch(replacements);
+ batchMapper.updateById(new MesProBatchDO().setId(batch.getId())
+ .setBagQuantity(bagCodeMapper.selectEffectiveCountByBatchId(batch.getId())));
+
+ return new MesProBagCodeReplaceRespVO()
+ .setReplaceUuid(replaceUuid)
+ .setBatchId(batch.getId())
+ .setBatchCode(batch.getCode())
+ .setCount(newBagCodes.size())
+ .setItems(items);
}
@Override
@@ -180,6 +305,16 @@
}
@Override
+ public MesProBagCodeReplaceDO getReplacementByOldBagCodeId(Long oldBagCodeId) {
+ return replaceMapper.selectByOldBagCodeId(oldBagCodeId);
+ }
+
+ @Override
+ public MesProBagCodeReplaceDO getReplacementByNewBagCodeId(Long newBagCodeId) {
+ return replaceMapper.selectByNewBagCodeId(newBagCodeId);
+ }
+
+ @Override
public PageResult<MesProBagCodeDO> getBagCodePage(MesProBagCodePageReqVO pageReqVO) {
return bagCodeMapper.selectPage(pageReqVO);
}
--
Gitblit v1.9.3