From 60f504b1f7308bcf8d1079a25d0db6922926ebae Mon Sep 17 00:00:00 2001
From: zwl <1051256694@qq.com>
Date: 星期二, 10 三月 2026 10:43:16 +0800
Subject: [PATCH] #
---
src/main/java/com/zy/asrs/task/WorkOutErpReportScheduler.java | 41 ++
src/main/java/com/zy/asrs/entity/param/ErpPakoutReportParam.java | 13
src/main/java/com/zy/api/controller/params/StopOutTaskParams.java | 40 ++
skills/build-asrs-solutions/agents/openai.yaml | 4
skills/build-asrs-solutions/SKILL.md | 75 ++++
skills/build-asrs-solutions/references/asrs-delivery-playbook.md | 92 +++++
src/main/java/com/zy/asrs/task/handler/WorkErpReportHandler.java | 334 ++++++++++++++++++++
src/main/java/com/zy/asrs/task/WorkErpReportScheduler.java | 41 ++
src/main/java/com/zy/asrs/entity/param/ErpPakinReportParam.java | 21 +
src/main/java/com/zy/asrs/entity/param/OpenOrderPakoutPauseParam.java | 11
src/main/java/com/zy/asrs/task/handler/WorkOutErpReportHandler.java | 281 +++++++++++++++++
11 files changed, 953 insertions(+), 0 deletions(-)
diff --git a/skills/build-asrs-solutions/SKILL.md b/skills/build-asrs-solutions/SKILL.md
new file mode 100644
index 0000000..585b981
--- /dev/null
+++ b/skills/build-asrs-solutions/SKILL.md
@@ -0,0 +1,75 @@
+---
+name: build-asrs-solutions
+description: Plan, design, implement, and communicate automated warehouse upper-level systems for ASRS projects, including WMS, WCS, ERP/MES integration, customer-facing requirement clarification, product scoping, interface definition, troubleshooting, and delivery coordination. Use when Codex supports 鑷姩鍖栫珛浣撲粨搴撲笂浣嶆満绯荤粺銆乄MS/WCS 鍔熻兘璁捐銆丒RP/MES/绗笁鏂圭郴缁熷鎺ャ�侀渶姹傛媶瑙c�佹帴鍙f枃妗c�佹祦绋嬫⒊鐞嗐�佸鎴锋矡閫氱邯瑕併�佸紓甯稿垎鏋愭垨椤圭洰浜や粯鎺ㄨ繘銆�
+---
+
+# Build ASRS Solutions
+
+## Overview
+
+浣滀负鑷姩鍖栫珛浣撲粨搴撻」鐩殑鏂规鍨嬪伐绋嬫惌妗o紝鍏堟妸涓氬姟娴併�佽澶囨祦鍜岀郴缁熻竟鐣岃娓咃紝鍐嶈緭鍑哄彲鎵ц鐨勮璁°�佹帴鍙c�佹帓鏈熷拰娌熼�氭潗鏂欍��
+濮嬬粓鎶婅繖涓妧鑳藉綋浣溾�滃叏鏍堝伐绋� + 浜у搧缁忕悊 + 瀹㈡埛闆嗘垚鎺ュ彛浜衡�濈殑宸ヤ綔杈呭姪锛岃�屼笉鏄崟绾殑浠g爜鐢熸垚鍣ㄣ��
+
+## Core Workflow
+
+1. 鍏堝缓绔嬩笂涓嬫枃
+
+- 鏄庣‘椤圭洰闃舵銆佽涓氬満鏅�佸簱鍖�/宸烽亾/宸ヤ綅缁撴瀯銆佽揣鐗╁睘鎬э紝浠ュ強鍏ュ簱銆佸嚭搴撱�佽ˉ璐с�佺Щ搴撱�佺洏鐐圭瓑浣滀笟绫诲瀷銆�
+- 鍒楀嚭鍙備笌绯荤粺鍜岃矗浠绘柟锛欵RP銆丮ES銆乄MS銆乄CS銆丳LC/璁惧灞傘�丳DA銆佹姤琛ㄥ钩鍙般�佺涓夋柟绯荤粺銆�
+- 纭涓绘暟鎹�佽鍗曘�佸簱瀛樸�佷换鍔°�佽澶囩姸鎬佸悇鑷殑 source of truth銆�
+
+2. 鍐嶅垝娓呯郴缁熻竟鐣�
+
+- 鏄庣‘鍝簺瑙勫垯灞炰簬 ERP/MES锛屽摢浜涘睘浜� WMS锛屽摢浜涘睘浜� WCS锛屽摢浜涘睘浜� PLC 鎴栬澶囨帶鍒跺櫒銆�
+- 鍖哄垎涓氬姟瀹屾垚銆佸簱瀛樺畬鎴愩�佷换鍔″畬鎴愩�佽澶囧畬鎴愶紝閬垮厤鎶婁笉鍚屽眰绾х姸鎬佸帇鎴愪竴涓姸鎬佸瓧娈点��
+- 涓烘瘡涓紓姝ユ帴鍙hˉ榻愯Е鍙戞椂鏈恒�佽姹�/鍥炴墽銆侀噸璇曘�佸箓绛夈�佽秴鏃躲�佽ˉ鍋裤�佸璐﹁鍒欍��
+
+3. 鎶婇棶棰樿浆鎹㈡垚浜や粯鐗�
+
+- 褰撻渶姹備笉娓呮櫚鏃讹紝鍏堣緭鍑烘緞娓呴棶棰樸�佽竟鐣屽亣璁俱�侀闄╃偣锛屼笉瑕佺洿鎺ヨ繘鍏ュ疄鐜般��
+- 褰撲换鍔″亸璁捐鏃讹紝杈撳嚭璐d换鐭╅樀銆佹椂搴忓浘銆佺姸鎬佹満銆佹帴鍙e崗璁�佸瓧娈垫槧灏勩�佹暟鎹ā鍨嬫垨 API 鑽夋銆�
+- 褰撲换鍔″亸鎵ц鏃讹紝杈撳嚭寮�鍙戞媶鍒嗐�佽仈璋冭鍒掋�佹祴璇曡寖鍥淬�佷笂绾垮垏鎹㈠拰楠屾敹娓呭崟銆�
+
+4. 鐢ㄥ満鏅弽鎺ㄦ柟妗堣川閲�
+
+- 璧伴�氭甯告祦绋嬨�侀珮宄版祦绋嬨�佸紓甯告祦绋嬨�佷汉宸ュ共棰勩�佸け璐ラ噸璇曘�佸洖婊氭仮澶嶃��
+- 妫�鏌ュ簱瀛樺樊寮傘�佽澶囨姤璀︺�佹秷鎭噸澶嶃�佸弽棣堝欢杩熴�佷笂娓搁樆濉炪�佷笅娓镐笉鍙敤鏃舵柟妗堟槸鍚︿粛鎴愮珛銆�
+
+## Working Rules
+
+- 鍏堢粦瀹氬叿浣撳璞★細浠撳簱銆佸簱鍖恒�佽澶囥�佽鍗曠被鍨嬨�佷换鍔$被鍨嬨�佺姸鎬佺爜銆佸紓甯哥爜銆佹帴鍙f柟鍚戙��
+- 浼樺厛鐢ㄨ〃鏍笺�佹椂搴忋�佺姸鎬佽縼绉汇�佽矗浠荤煩闃佃〃杈捐法绯荤粺閫昏緫锛屼笉瑕佸彧缁欐娊璞℃弿杩般��
+- 鎶婂垎鏋愰摼璺浐瀹氬埌涓氬姟鍗曞彿銆佷换鍔″彿銆佽澶囨寚浠ゅ彿銆佹秷鎭祦姘村彿銆�
+- 鍏堟毚闇插亣璁惧拰缂哄け杈撳叆锛屽啀缁欐柟妗堬紱涓嶈鎶婂叧閿笉纭畾鎬ц棌鍦ㄥ疄鐜扮粏鑺傞噷銆�
+- 榛樿杈撳嚭鍙互鐩存帴缁欑爺鍙戙�佹祴璇曘�佸疄鏂姐�佸鎴锋垨绗笁鏂瑰巶鍟嗚瘎瀹$殑鏉愭枡銆�
+
+## Default Output Shapes
+
+- 闇�姹傛緞娓咃細杈撳嚭 `鑳屾櫙/鑼冨洿/杈圭晫/鍏抽敭闂/寰呯‘璁ら」/椋庨櫓`銆�
+- 鎺ュ彛璁捐锛氳緭鍑� `鎺ュ彛鐩爣/璐d换褰掑睘/瑙﹀彂鏃舵満/瀛楁鏄犲皠/骞傜瓑涓庨噸璇�/寮傚父鍥炰紶/楠屾敹鍙e緞`銆�
+- 鏂规璇勫锛氳緭鍑� `鐜扮姸/闂鎷嗚В/鍊欓�夋柟妗�/鍙栬垗/椋庨櫓/鎺ㄨ崘鏂规`銆�
+- 鏁呴殰鍒嗘瀽锛氳緭鍑� `鐜拌薄/褰卞搷鑼冨洿/閾捐矾瀹氫綅/鎬�鐤戠偣/鍙栬瘉姝ラ/涓存椂姝㈣/姘镐箙淇/闃插洖褰掓帾鏂絗銆�
+- 瀹㈡埛娌熼�氾細杈撳嚭 `涓氬姟缁撹/绯荤粺杈圭晫/闇�瀵规柟鎻愪緵鍐呭/鎴戞柟鍔ㄤ綔/鏃堕棿鐐�/鏈喅闂`銆�
+
+## Common Deliverables
+
+- 闇�姹傛緞娓呮竻鍗�
+- WMS/WCS/ERP/MES 璐d换鐭╅樀
+- 鎺ュ彛鏂囨。鍜屽瓧娈垫槧灏勮〃
+- 涓氬姟娴佺▼鍥俱�佸紓甯告祦绋嬪浘銆佺姸鎬佹満
+- 鏁版嵁搴撹璁″缓璁�丼QL 鑽夋銆丄PI 鑽夋銆佷簨浠舵ā鍨�
+- 鑱旇皟璁″垝銆佹祴璇曟渚嬨�佷笂绾垮垏鎹㈡竻鍗�
+- 瀹㈡埛浼氳绾銆佽鍔ㄩ」銆佸澶栨緞娓呴偖浠惰崏绋�
+- 鏁呴殰澶嶇洏鍜屾牴鍥犲垎鏋愭姤鍛�
+
+## Default Heuristics
+
+- 鍏堟妸搴撳瓨宸紓鐪嬫垚鈥滃綊灞為敊璇�佹椂搴忛敊璇�佷汉宸ュ共棰勩�佸箓绛夊け鏁堛�佽ˉ鍋跨己澶扁�濋棶棰橈紝鑰屼笉鏄崟绾暟鎹敊銆�
+- 鍏堟妸閲嶅涓嬪彂銆佷换鍔″崱姝汇�佽澶囧弽澶嶆姤璀︾湅鎴愨�淲MS/WCS/璁惧鐘舵�佸垎鍙夆�濋棶棰橈紝鐩村埌璇佹嵁璇佹槑涓嶆槸銆�
+- 涓烘墍鏈夊閮ㄦ帴鍙i粯璁よ璁¢噸璇曘�佸幓閲嶃�佸洖鏌ャ�佸璐﹀拰浜哄伐鍏滃簳銆�
+- 鎶婂紓甯搁摼璺拰浜哄伐鎭㈠璁捐鎴愪骇鍝佽兘鍔涳紝涓嶈褰撲綔涓婄嚎鍚庝复鏃惰ˉ涓併��
+- 榛樿鐢ㄢ�淲MS 鍋忎笟鍔$瓥鐣ワ紝WCS 鍋忔墽琛岀紪鎺掆�濈殑鍘熷垯寤烘ā锛涢」鐩湁鍋忓樊鏃跺啀鏄惧紡鍐欐槑銆�
+
+## Reference
+
+褰撲换鍔¢渶瑕佹洿缁嗙殑璋冪爺鎻愮翰銆佽矗浠荤煩闃垫ā鏉裤�佹帴鍙f鏌ユ竻鍗曘�佹晠闅滄帓鏌ラ『搴忔垨浼氳绾楠ㄦ灦鏃讹紝璇诲彇 [references/asrs-delivery-playbook.md](references/asrs-delivery-playbook.md)銆�
diff --git a/skills/build-asrs-solutions/agents/openai.yaml b/skills/build-asrs-solutions/agents/openai.yaml
new file mode 100644
index 0000000..e25d9f8
--- /dev/null
+++ b/skills/build-asrs-solutions/agents/openai.yaml
@@ -0,0 +1,4 @@
+interface:
+ display_name: "ASRS Solutions"
+ short_description: "WMS/WCS and ERP/MES delivery playbook"
+ default_prompt: "Use $build-asrs-solutions to scope a warehouse-system request, map WMS/WCS and ERP/MES boundaries, and produce an actionable delivery plan."
diff --git a/skills/build-asrs-solutions/references/asrs-delivery-playbook.md b/skills/build-asrs-solutions/references/asrs-delivery-playbook.md
new file mode 100644
index 0000000..c4be6f7
--- /dev/null
+++ b/skills/build-asrs-solutions/references/asrs-delivery-playbook.md
@@ -0,0 +1,92 @@
+# ASRS Delivery Playbook
+
+## Table of Contents
+
+- Context checklist
+- Responsibility matrix template
+- Integration checklist
+- Scenario review set
+- Troubleshooting workflow
+- Communication templates
+
+## Context Checklist
+
+鍦ㄥ紑濮嬭璁℃垨鎺掓煡鍓嶏紝鍏堣ˉ榻愪笅闈㈢殑淇℃伅锛�
+
+- 椤圭洰闃舵锛氬敭鍓嶃�佽摑鍥俱�佸紑鍙戙�佽仈璋冦�佷笂绾裤�佽繍缁淬��
+- 鍦烘櫙杈圭晫锛氭暣搴撱�佸崟搴撳尯銆佸崟璁惧绾裤�佸崟瀹㈡埛銆佸崟宸ュ巶锛岃繕鏄泦鍥㈠鍩哄湴銆�
+- 璐х墿灞炴�э細鎵樼洏銆佹枡绠便�佸懆杞銆佸崟浠讹紝鏄惁鎵规銆佹晥鏈熴�佸簭鍒楀彿绠$悊銆�
+- 浣滀笟绫诲瀷锛氬叆搴撱�佸嚭搴撱�佽ˉ璐с�佺Щ搴撱�佽秺搴撱�佺洏鐐广�佸喕缁撱�佽В鍐汇�佺┖鎵樼鐞嗐��
+- 璁惧缁勬垚锛氬爢鍨涙満銆佺┛姊溅銆佹彁鍗囨満銆佽緭閫佺嚎銆佹満姊拌噦銆丄GV銆丷GV銆佺數瀛愭爣绛俱�佹壂鎻忓櫒銆�
+- 澶栭儴绯荤粺锛欵RP銆丮ES銆丱MS銆丼RM銆丵MS銆佽储鍔$郴缁熴�丅I銆佺涓夋柟浠撻厤骞冲彴銆�
+- 鏍稿績鎸囨爣锛氬悶鍚愩�佸簱瀛樺噯纭巼銆佷换鍔℃椂鏁堛�佹尝娆″畬鎴愮巼銆佽澶囧彲鐢ㄧ巼銆�
+- 褰撳墠闂锛氶渶姹傛柊澧炪�佷笂绾垮欢鏈熴�佸簱瀛樹笉鍑嗐�佷换鍔″崱姝汇�佹帴鍙e弽澶嶅け璐ャ�佸鎴峰彛寰勪笉涓�鑷淬��
+
+## Responsibility Matrix Template
+
+鐢ㄨ繖涓〃鍏堝仛璐d换褰掑睘锛屼笉瑕佺洿鎺ュ啓瀹炵幇銆�
+
+| Domain | ERP/MES | WMS | WCS | Device/PLC | Notes |
+| --- | --- | --- | --- | --- | --- |
+| 涓绘暟鎹� | 涓绘暟鎹潵婧�/瀹℃壒 | 涓绘暟鎹惤鍦板拰鏍¢獙 | 璁惧渚у繀瑕佹槧灏� | 鍙繚鐣欒澶囨墽琛屽繀闇�閰嶇疆 | 鏄庣‘缂栫爜銆佺増鏈�佸悓姝ラ鐜� |
+| 鍗曟嵁/鐢熶骇鎸囦护 | 涓嬪彂涓氬姟闇�姹� | 鎷嗗崟銆佸簱瀛樻牎楠屻�佹尝娆�/绛栫暐 | 鎺ユ敹鎵ц浠诲姟 | 鎺ユ敹鎺у埗鎸囦护 | 鏄庣‘璋佸彲浠ユ挙閿�鍜屾敼娲� |
+| 搴撳瓨鐪熷�� | 璐㈠姟鎴栫敓浜у彛寰� | 浠撳偍鐪熷�� | 缂撳瓨鎵ц鎬� | 涓嶄綔涓洪暱鏈熺湡鍊� | 鏄庣‘宸紓鍥炲啓璺緞 |
+| 浠诲姟鐘舵�� | 鍏虫敞涓氬姟缁撴灉 | 绠$悊涓氬姟浠诲姟鐘舵�� | 绠$悊鎵ц浠诲姟鐘舵�� | 杩斿洖鍔ㄤ綔缁撴灉 | 鍖哄垎瀹屾垚銆佸け璐ャ�佸彇娑堛�佹寕璧� |
+| 寮傚父澶勭悊 | 澶勭悊涓氬姟闃诲 | 澶勭悊搴撳瓨鍜屼笟鍔″紓甯� | 澶勭悊璁惧鍜屾墽琛屽紓甯� | 杈撳嚭鎶ヨ鍜屽弽棣� | 鏄庣‘浜哄伐浠嬪叆鐐� |
+
+## Integration Checklist
+
+姣忎釜鎺ュ彛閮芥鏌ヤ互涓嬮」鐩細
+
+- 鎺ュ彛鏂瑰悜锛氳皝鍙戣捣銆佽皝纭銆佽皝鍥炲啓銆佽皝閲嶈瘯銆�
+- 瑙﹀彂鏃舵満锛氬垱寤恒�佷笅鍙戙�佸紑濮嬨�侀儴鍒嗗畬鎴愩�佸畬鎴愩�佸彇娑堛�佸紓甯搞�佹仮澶嶃��
+- 鍞竴閿細璁㈠崟鍙枫�佽鍙枫�佷换鍔″彿銆佸鍣ㄥ彿銆佽澶囦换鍔″彿銆佹秷鎭祦姘村彿銆�
+- 瀛楁鏄犲皠锛氱紪鐮佷綋绯汇�佸崟浣嶃�佺姸鎬佺爜銆佹椂闂存牸寮忋�佹壒娆�/鏁堟湡/搴忓垪鍙峰彛寰勩��
+- 骞傜瓑鏈哄埗锛氬箓绛夐敭銆侀噸澶嶆姤鏂囪瘑鍒�佸幓閲嶇獥鍙c�侀噸澶嶅洖鎵у鐞嗐��
+- 閲嶈瘯绛栫暐锛氳秴鏃堕槇鍊笺�侀噸璇曟鏁般�侀��閬胯鍒欍�佷汉宸ヨˉ鍙戞柟寮忋��
+- 寮傚父闂幆锛氶敊璇爜銆侀敊璇弿杩般�侀�氱煡瀵硅薄銆佸崌绾ц矾寰勩�佹仮澶嶅姩浣溿��
+- 瀵硅处鏈哄埗锛氭棩鍒囥�佺彮娆°�佸閲忓洖鏌ャ�佸叏閲忔牎楠屻�佽ˉ鍋块�昏緫銆�
+- 瀹¤杩借釜锛氳姹傛棩蹇椼�佸洖鎵ф棩蹇椼�佺姸鎬佽縼绉绘棩蹇椼�佹搷浣滀汉銆佹椂闂存埑銆�
+- 鍒囨崲绛栫暐锛氬瓨閲忔暟鎹垵濮嬪寲銆佺伆搴﹁寖鍥淬�佸洖婊氭潯浠躲�佸弻鍐欐垨鍐荤粨绐楀彛銆�
+
+## Scenario Review Set
+
+鏂规鑷冲皯瑕嗙洊涓嬮潰杩欎簺鍦烘櫙锛�
+
+- 姝e父鍏ュ簱锛氶绾﹀埌璐с�佹敹璐с�佽川妫�銆佷笂鏋躲�佸簱瀛樼‘璁ゃ��
+- 姝e父鍑哄簱锛氭尝娆°�佸垎閰嶃�佹嫞閫夈�佸嚭搴撱�佽杞︺�佸洖鍐欍��
+- 搴撳瓨璋冩暣锛氱洏鐐瑰樊寮傘�佸喕缁撱�佽В鍐汇�佹姤鎹熴�佹姤婧€��
+- 浜哄伐骞查锛氬己鍒跺畬鎴愩�佸彇娑堜换鍔°�佹敼搴撲綅銆佹敼瀹瑰櫒銆佺嚎杈硅ˉ褰曘��
+- 寮傚父鎭㈠锛氳澶囨姤璀﹀悗閲嶄笅銆佷换鍔℃媶鍒嗐�佷换鍔″悎骞躲�佹柇鐐圭画浼犮��
+- 璺ㄧ郴缁熷け璐ワ細ERP 宸插洖鍐欎絾 WMS 鏈畬鎴愩�乄MS 宸插畬鎴愪絾 WCS 鏈洖鎵с�佽澶囧凡鍔ㄤ綔浣嗙姸鎬佹湭鍚屾銆�
+
+## Troubleshooting Workflow
+
+鎺掓煡鏃舵寜杩欎釜椤哄簭鎺ㄨ繘锛�
+
+1. 閿佸畾涓氬姟涓婚敭锛氳鍗曞彿銆佷换鍔″彿銆佸鍣ㄥ彿銆佽澶囨寚浠ゅ彿銆�
+2. 鎷夐綈鏃堕棿绾匡細ERP/MES銆乄MS銆乄CS銆佽澶囨棩蹇楃殑鏃堕棿鎴炽��
+3. 鎵炬渶鍚庝竴娆′竴鑷寸姸鎬侊紝纭闂鍙戠敓鍦ㄢ�滀笅鍙戝墠銆佹帴鍙d腑銆佹墽琛屼腑銆佸洖鍐欎腑鈥濈殑鍝竴娈点��
+4. 妫�鏌ユ槸鍚︽湁閲嶅娑堟伅銆佹紡鍥炴墽銆佷汉宸ユ敼鏁般�佹椂閽熸紓绉汇�佺姸鎬佸洖婊氬け璐ャ��
+5. 鍖哄垎涓存椂姝㈣鍜屾案涔呬慨澶嶏細鍏堟仮澶嶄綔涓氾紝鍐嶈ˉ鐩戞帶銆佽ˉ鏍¢獙銆佽ˉ琛ュ伩鏈哄埗銆�
+6. 杈撳嚭鍙獙璇佺粨璁猴細鐜拌薄銆佽瘉鎹�佹牴鍥犲亣璁俱�侀獙璇佺粨鏋溿�佷慨澶嶅姩浣溿�侀闃叉帾鏂姐��
+
+## Communication Templates
+
+### Requirement Clarification
+
+- 涓氬姟鐩爣鏄粈涔堬紝鎴愬姛鍙e緞鏄粈涔堛��
+- 鍝釜绯荤粺鍏堝彂璧凤紝鍝釜绯荤粺浣滀负鏈�缁堢‘璁ゅ彛寰勩��
+- 鍝簺鐘舵�侀渶瑕佸洖浼狅紝鍝簺鐘舵�佸彧鍦ㄦ湰绯荤粺鍐呴儴鍙銆�
+- 寮傚父鏃剁敱璋佸鐞嗭紝鍏佽鍝簺浜哄伐鎿嶄綔銆�
+- 瀹㈡埛蹇呴』鎻愪緵鍝簺涓绘暟鎹�佺紪鐮佽鍒欍�佹帴鍙f牱渚嬨�佹祴璇曠幆澧冦�侀獙鏀舵渚嬨��
+
+### Meeting Summary
+
+- 鑳屾櫙鍜岀洰鏍�
+- 宸茬‘璁よ寖鍥�
+- 鏈‘璁よ寖鍥�
+- 绯荤粺杈圭晫缁撹
+- 鍙屾柟琛屽姩椤�
+- 椋庨櫓鍜岄樆濉為」
+- 涓嬫妫�鏌ョ偣
diff --git a/src/main/java/com/zy/api/controller/params/StopOutTaskParams.java b/src/main/java/com/zy/api/controller/params/StopOutTaskParams.java
new file mode 100644
index 0000000..8c263e3
--- /dev/null
+++ b/src/main/java/com/zy/api/controller/params/StopOutTaskParams.java
@@ -0,0 +1,40 @@
+package com.zy.api.controller.params;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+@Data
+@ApiModel(value = "StopOutTaskParams", description = "pause out task params")
+public class StopOutTaskParams implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @ApiModelProperty("order no")
+ private String orderNo;
+
+ @ApiModelProperty("pause reason")
+ private String reason;
+
+ @ApiModelProperty("task list")
+ private List<TaskItem> tasks = new ArrayList<>();
+
+ @Data
+ public static class TaskItem implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @ApiModelProperty("task no")
+ private String taskNo;
+
+ @ApiModelProperty("station no")
+ private String staNo;
+
+ @ApiModelProperty("loc no")
+ private String locNo;
+ }
+}
diff --git a/src/main/java/com/zy/asrs/entity/param/ErpPakinReportParam.java b/src/main/java/com/zy/asrs/entity/param/ErpPakinReportParam.java
new file mode 100644
index 0000000..280c523
--- /dev/null
+++ b/src/main/java/com/zy/asrs/entity/param/ErpPakinReportParam.java
@@ -0,0 +1,21 @@
+package com.zy.asrs.entity.param;
+
+import lombok.Data;
+
+@Data
+public class ErpPakinReportParam {
+
+ private String palletId;
+
+ private Double anfme;
+
+ private String locId;
+
+ private Double weight;
+
+ private String createTime;
+
+ private String BizNo;
+
+ private String startTime;
+}
diff --git a/src/main/java/com/zy/asrs/entity/param/ErpPakoutReportParam.java b/src/main/java/com/zy/asrs/entity/param/ErpPakoutReportParam.java
new file mode 100644
index 0000000..79c5610
--- /dev/null
+++ b/src/main/java/com/zy/asrs/entity/param/ErpPakoutReportParam.java
@@ -0,0 +1,13 @@
+package com.zy.asrs.entity.param;
+
+import lombok.Data;
+
+@Data
+public class ErpPakoutReportParam {
+
+ private String palletId;
+
+ private String createTime;
+
+ private String startTime;
+}
diff --git a/src/main/java/com/zy/asrs/entity/param/OpenOrderPakoutPauseParam.java b/src/main/java/com/zy/asrs/entity/param/OpenOrderPakoutPauseParam.java
new file mode 100644
index 0000000..7e45467
--- /dev/null
+++ b/src/main/java/com/zy/asrs/entity/param/OpenOrderPakoutPauseParam.java
@@ -0,0 +1,11 @@
+package com.zy.asrs.entity.param;
+
+import lombok.Data;
+
+@Data
+public class OpenOrderPakoutPauseParam {
+
+ private String orderNo;
+
+ private String reason;
+}
diff --git a/src/main/java/com/zy/asrs/task/WorkErpReportScheduler.java b/src/main/java/com/zy/asrs/task/WorkErpReportScheduler.java
new file mode 100644
index 0000000..6caaf66
--- /dev/null
+++ b/src/main/java/com/zy/asrs/task/WorkErpReportScheduler.java
@@ -0,0 +1,41 @@
+package com.zy.asrs.task;
+
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.zy.asrs.entity.WrkMast;
+import com.zy.asrs.service.WrkMastService;
+import com.zy.asrs.task.core.ReturnT;
+import com.zy.asrs.task.handler.WorkErpReportHandler;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+@Slf4j
+@Component
+public class WorkErpReportScheduler {
+
+ @Autowired
+ private WrkMastService wrkMastService;
+
+ @Autowired
+ private WorkErpReportHandler workErpReportHandler;
+
+ @Scheduled(cron = "0/10 * * * * ? ")
+ private void execute() {
+ List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>()
+ .eq("wrk_sts", WorkErpReportHandler.ERP_REPORT_PENDING_WRK_STS)
+ .orderBy("io_time", true)
+ .orderBy("wrk_no", true));
+ if (wrkMasts.isEmpty()) {
+ return;
+ }
+ for (WrkMast wrkMast : wrkMasts) {
+ ReturnT<String> result = workErpReportHandler.start(wrkMast);
+ if (!result.isSuccess()) {
+ log.error("workNo={} erp report failed: {}", wrkMast.getWrkNo(), result.getMsg());
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/zy/asrs/task/WorkOutErpReportScheduler.java b/src/main/java/com/zy/asrs/task/WorkOutErpReportScheduler.java
new file mode 100644
index 0000000..d822a99
--- /dev/null
+++ b/src/main/java/com/zy/asrs/task/WorkOutErpReportScheduler.java
@@ -0,0 +1,41 @@
+package com.zy.asrs.task;
+
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.zy.asrs.entity.WrkMast;
+import com.zy.asrs.service.WrkMastService;
+import com.zy.asrs.task.core.ReturnT;
+import com.zy.asrs.task.handler.WorkOutErpReportHandler;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+@Slf4j
+@Component
+public class WorkOutErpReportScheduler {
+
+ @Autowired
+ private WrkMastService wrkMastService;
+
+ @Autowired
+ private WorkOutErpReportHandler workOutErpReportHandler;
+
+ @Scheduled(cron = "0/10 * * * * ? ")
+ private void execute() {
+ List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>()
+ .eq("wrk_sts", WorkOutErpReportHandler.ERP_REPORT_PENDING_WRK_STS)
+ .orderBy("io_time", true)
+ .orderBy("wrk_no", true));
+ if (wrkMasts.isEmpty()) {
+ return;
+ }
+ for (WrkMast wrkMast : wrkMasts) {
+ ReturnT<String> result = workOutErpReportHandler.start(wrkMast);
+ if (!result.isSuccess()) {
+ log.error("workNo={} outbound erp report failed: {}", wrkMast.getWrkNo(), result.getMsg());
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/zy/asrs/task/handler/WorkErpReportHandler.java b/src/main/java/com/zy/asrs/task/handler/WorkErpReportHandler.java
new file mode 100644
index 0000000..87043a6
--- /dev/null
+++ b/src/main/java/com/zy/asrs/task/handler/WorkErpReportHandler.java
@@ -0,0 +1,334 @@
+package com.zy.asrs.task.handler;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.core.common.Cools;
+import com.zy.asrs.entity.WaitPakin;
+import com.zy.asrs.entity.WrkDetl;
+import com.zy.asrs.entity.WrkMast;
+import com.zy.asrs.entity.param.ErpPakinReportParam;
+import com.zy.asrs.service.ApiLogService;
+import com.zy.asrs.service.WaitPakinService;
+import com.zy.asrs.service.WrkDetlService;
+import com.zy.asrs.service.WrkMastService;
+import com.zy.asrs.task.AbstractHandler;
+import com.zy.asrs.task.core.ReturnT;
+import com.zy.common.entity.Parameter;
+import com.zy.common.utils.HttpHandler;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+
+@Slf4j
+@Service
+public class WorkErpReportHandler extends AbstractHandler<String> {
+
+ public static final long ERP_REPORT_PENDING_WRK_STS = 16L;
+ public static final long ERP_REPORT_FINISHED_WRK_STS = 5L;
+ public static final int ERP_REPORT_MAX_RETRY_TIMES = 3;
+ public static final String ERP_REPORT_PENDING_FLAG = "P";
+ public static final String ERP_REPORT_SUCCESS_FLAG = "Y";
+ public static final String ERP_REPORT_FAIL_FLAG = "F";
+
+ private static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
+
+ @Autowired
+ private WrkMastService wrkMastService;
+ @Autowired
+ private WrkDetlService wrkDetlService;
+ @Autowired
+ private WaitPakinService waitPakinService;
+ @Autowired
+ private ApiLogService apiLogService;
+
+ @Value("${erp.switch.ErpReportOld}")
+ private boolean erpReportOld;
+
+ @Value("${erp.address.URL}")
+ private String erpUrl;
+
+ @Value("${erp.address.Inaddress}")
+ private String erpInAddress;
+
+ @Transactional(rollbackFor = Exception.class)
+ public ReturnT<String> start(WrkMast source) {
+ WrkMast wrkMast = wrkMastService.selectById(source.getWrkNo());
+ if (wrkMast == null || !Long.valueOf(ERP_REPORT_PENDING_WRK_STS).equals(wrkMast.getWrkSts())) {
+ return SUCCESS;
+ }
+
+ if (!isErpReportEnabled()) {
+ finishReport(wrkMast, false, getRetryTimes(wrkMast), "ERP reporting is disabled", false);
+ return FAIL.setMsg("ERP reporting is disabled");
+ }
+
+ List<WrkDetl> wrkDetls = wrkDetlService.selectByWrkNo(wrkMast.getWrkNo());
+ if (Cools.isEmpty(wrkDetls)) {
+ finishReport(wrkMast, false, getRetryTimes(wrkMast), "work details are empty", false);
+ return FAIL.setMsg("work details are empty");
+ }
+
+ WaitPakin waitPakin = findWaitPakin(wrkMast.getBarcode());
+ ErpPakinReportParam param = buildParam(wrkMast, wrkDetls, waitPakin);
+ String request = JSON.toJSONString(param);
+ String response = "";
+ boolean success = false;
+ String errorMsg = null;
+ String requestUrl = buildRequestUrl();
+
+ try {
+ response = new HttpHandler.Builder()
+ .setUri(erpUrl)
+ .setPath(erpInAddress)
+ .setJson(request)
+ .build()
+ .doPost();
+ success = isErpReportSuccess(response);
+ if (!success) {
+ errorMsg = extractErrorMsg(response);
+ }
+ finishReport(wrkMast, success, getRetryTimes(wrkMast), errorMsg, true);
+ } catch (Exception e) {
+ errorMsg = e.getMessage();
+ finishReport(wrkMast, false, getRetryTimes(wrkMast), errorMsg, true);
+ } finally {
+ try {
+ apiLogService.save(
+ "Inbound ERP Report",
+ requestUrl,
+ null,
+ "127.0.0.1",
+ request,
+ response,
+ success,
+ "workNo=" + wrkMast.getWrkNo()
+ );
+ } catch (Exception logEx) {
+ log.error("save erp api log failed", logEx);
+ }
+ }
+
+ if (success) {
+ return SUCCESS;
+ }
+ return FAIL.setMsg(errorMsg);
+ }
+
+ private boolean isErpReportEnabled() {
+ if (!erpReportOld) {
+ return false;
+ }
+ String erpReport = Parameter.get().getErpReport();
+ return Cools.isEmpty(erpReport) || "true".equalsIgnoreCase(erpReport);
+ }
+
+ private WaitPakin findWaitPakin(String barcode) {
+ if (Cools.isEmpty(barcode)) {
+ return null;
+ }
+ return waitPakinService.selectOne(new EntityWrapper<WaitPakin>().eq("zpallet", barcode));
+ }
+
+ private ErpPakinReportParam buildParam(WrkMast wrkMast, List<WrkDetl> wrkDetls, WaitPakin waitPakin) {
+ ErpPakinReportParam param = new ErpPakinReportParam();
+ param.setPalletId(resolvePalletId(wrkMast, wrkDetls));
+ param.setAnfme(sumAnfme(wrkDetls));
+ param.setLocId(wrkMast.getLocNo());
+ param.setWeight(sumWeight(wrkDetls));
+ param.setCreateTime(formatDate(resolveCreateTime(wrkMast)));
+ param.setBizNo(resolveBizNo(wrkDetls, waitPakin));
+ param.setStartTime(formatDate(resolveStartTime(wrkMast, waitPakin)));
+ return param;
+ }
+
+ private String resolvePalletId(WrkMast wrkMast, List<WrkDetl> wrkDetls) {
+ if (!Cools.isEmpty(wrkMast.getBarcode())) {
+ return wrkMast.getBarcode();
+ }
+ for (WrkDetl wrkDetl : wrkDetls) {
+ if (!Cools.isEmpty(wrkDetl.getZpallet())) {
+ return wrkDetl.getZpallet();
+ }
+ }
+ return null;
+ }
+
+ private Double sumAnfme(List<WrkDetl> wrkDetls) {
+ double total = 0D;
+ for (WrkDetl wrkDetl : wrkDetls) {
+ if (!Cools.isEmpty(wrkDetl.getAnfme())) {
+ total += wrkDetl.getAnfme();
+ }
+ }
+ return total;
+ }
+
+ private Double sumWeight(List<WrkDetl> wrkDetls) {
+ double total = 0D;
+ for (WrkDetl wrkDetl : wrkDetls) {
+ if (Cools.isEmpty(wrkDetl.getWeight())) {
+ continue;
+ }
+ double qty = Cools.isEmpty(wrkDetl.getAnfme()) ? 1D : wrkDetl.getAnfme();
+ total += wrkDetl.getWeight() * qty;
+ }
+ return total;
+ }
+
+ private Date resolveCreateTime(WrkMast wrkMast) {
+ if (!Cools.isEmpty(wrkMast.getCrnEndTime())) {
+ return wrkMast.getCrnEndTime();
+ }
+ if (!Cools.isEmpty(wrkMast.getModiTime())) {
+ return wrkMast.getModiTime();
+ }
+ if (!Cools.isEmpty(wrkMast.getIoTime())) {
+ return wrkMast.getIoTime();
+ }
+ return new Date();
+ }
+
+ private String resolveBizNo(List<WrkDetl> wrkDetls, WaitPakin waitPakin) {
+ for (WrkDetl wrkDetl : wrkDetls) {
+ if (!Cools.isEmpty(wrkDetl.getThreeCode())) {
+ return wrkDetl.getThreeCode();
+ }
+ }
+ return waitPakin == null ? null : waitPakin.getThreeCode();
+ }
+
+ private Date resolveStartTime(WrkMast wrkMast, WaitPakin waitPakin) {
+ if (waitPakin != null && !Cools.isEmpty(waitPakin.getAppeTime())) {
+ return waitPakin.getAppeTime();
+ }
+ if (!Cools.isEmpty(wrkMast.getAppeTime())) {
+ return wrkMast.getAppeTime();
+ }
+ if (!Cools.isEmpty(wrkMast.getIoTime())) {
+ return wrkMast.getIoTime();
+ }
+ return new Date();
+ }
+
+ private String formatDate(Date date) {
+ if (date == null) {
+ return null;
+ }
+ return new SimpleDateFormat(DATE_TIME_PATTERN).format(date);
+ }
+
+ private boolean isErpReportSuccess(String response) {
+ if (Cools.isEmpty(response)) {
+ return false;
+ }
+ try {
+ JSONObject jsonObject = JSON.parseObject(response);
+ if (jsonObject == null) {
+ return false;
+ }
+ Boolean success = jsonObject.getBoolean("success");
+ if (success != null) {
+ return success;
+ }
+ Integer code = jsonObject.getInteger("code");
+ if (code != null) {
+ return code == 200 || code == 0;
+ }
+ Integer status = jsonObject.getInteger("status");
+ if (status != null) {
+ return status == 200 || status == 0;
+ }
+ String result = jsonObject.getString("result");
+ if (!Cools.isEmpty(result)) {
+ return "success".equalsIgnoreCase(result) || "ok".equalsIgnoreCase(result) || "true".equalsIgnoreCase(result);
+ }
+ } catch (Exception ignore) {
+ return response.toLowerCase().contains("success") && response.toLowerCase().contains("true");
+ }
+ return false;
+ }
+
+ private String extractErrorMsg(String response) {
+ if (Cools.isEmpty(response)) {
+ return "empty erp response";
+ }
+ try {
+ JSONObject jsonObject = JSON.parseObject(response);
+ if (jsonObject == null) {
+ return response;
+ }
+ String[] keys = new String[]{"msg", "message", "error", "errMsg"};
+ for (String key : keys) {
+ String value = jsonObject.getString(key);
+ if (!Cools.isEmpty(value)) {
+ return value;
+ }
+ }
+ } catch (Exception ignore) {
+ }
+ return response;
+ }
+
+ private int getRetryTimes(WrkMast wrkMast) {
+ if (wrkMast.getExpTime() == null) {
+ return 0;
+ }
+ return wrkMast.getExpTime().intValue();
+ }
+
+ private void finishReport(WrkMast wrkMast, boolean success, int currentRetryTimes, String errorMsg, boolean countCurrentAttempt) {
+ int retryTimes = currentRetryTimes + (countCurrentAttempt ? 1 : 0);
+ Date now = new Date();
+ wrkMast.setExpTime((double) retryTimes);
+ wrkMast.setModiTime(now);
+ if (success) {
+ wrkMast.setWrkSts(ERP_REPORT_FINISHED_WRK_STS);
+ wrkMast.setLogMk(ERP_REPORT_SUCCESS_FLAG);
+ wrkMast.setLogErrMemo(null);
+ wrkMast.setLogErrTime(null);
+ } else {
+ wrkMast.setLogErrMemo(truncate(errorMsg, 500));
+ wrkMast.setLogErrTime(now);
+ if (retryTimes >= ERP_REPORT_MAX_RETRY_TIMES || !countCurrentAttempt) {
+ wrkMast.setWrkSts(ERP_REPORT_FINISHED_WRK_STS);
+ wrkMast.setLogMk(ERP_REPORT_FAIL_FLAG);
+ } else {
+ wrkMast.setWrkSts(ERP_REPORT_PENDING_WRK_STS);
+ wrkMast.setLogMk(ERP_REPORT_PENDING_FLAG);
+ }
+ }
+ if (!wrkMastService.updateById(wrkMast)) {
+ throw new IllegalStateException("update erp report status failed, workNo=" + wrkMast.getWrkNo());
+ }
+ }
+
+ private String truncate(String message, int maxLength) {
+ if (message == null || message.length() <= maxLength) {
+ return message;
+ }
+ return message.substring(0, maxLength);
+ }
+
+ private String buildRequestUrl() {
+ if (Cools.isEmpty(erpUrl)) {
+ return erpInAddress;
+ }
+ if (erpInAddress == null) {
+ return erpUrl;
+ }
+ if (erpUrl.endsWith("/") && erpInAddress.startsWith("/")) {
+ return erpUrl + erpInAddress.substring(1);
+ }
+ if (!erpUrl.endsWith("/") && !erpInAddress.startsWith("/")) {
+ return erpUrl + "/" + erpInAddress;
+ }
+ return erpUrl + erpInAddress;
+ }
+}
diff --git a/src/main/java/com/zy/asrs/task/handler/WorkOutErpReportHandler.java b/src/main/java/com/zy/asrs/task/handler/WorkOutErpReportHandler.java
new file mode 100644
index 0000000..433efdb
--- /dev/null
+++ b/src/main/java/com/zy/asrs/task/handler/WorkOutErpReportHandler.java
@@ -0,0 +1,281 @@
+package com.zy.asrs.task.handler;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.core.common.Cools;
+import com.zy.asrs.entity.WrkDetl;
+import com.zy.asrs.entity.WrkMast;
+import com.zy.asrs.entity.param.ErpPakoutReportParam;
+import com.zy.asrs.service.ApiLogService;
+import com.zy.asrs.service.WrkDetlService;
+import com.zy.asrs.service.WrkMastService;
+import com.zy.asrs.task.AbstractHandler;
+import com.zy.asrs.task.core.ReturnT;
+import com.zy.common.entity.Parameter;
+import com.zy.common.utils.HttpHandler;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+
+@Slf4j
+@Service
+public class WorkOutErpReportHandler extends AbstractHandler<String> {
+
+ public static final long ERP_REPORT_PENDING_WRK_STS = 17L;
+ public static final long ERP_REPORT_FINISHED_WRK_STS = 15L;
+ public static final int ERP_REPORT_MAX_RETRY_TIMES = 3;
+ public static final String ERP_REPORT_PENDING_FLAG = "P";
+ public static final String ERP_REPORT_SUCCESS_FLAG = "Y";
+ public static final String ERP_REPORT_FAIL_FLAG = "F";
+
+ private static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
+
+ @Autowired
+ private WrkMastService wrkMastService;
+ @Autowired
+ private WrkDetlService wrkDetlService;
+ @Autowired
+ private ApiLogService apiLogService;
+
+ @Value("${erp.switch.ErpReportOld}")
+ private boolean erpReportOld;
+
+ @Value("${erp.address.URL}")
+ private String erpUrl;
+
+ @Value("${erp.address.Outaddress}")
+ private String erpOutAddress;
+
+ @Transactional(rollbackFor = Exception.class)
+ public ReturnT<String> start(WrkMast source) {
+ WrkMast wrkMast = wrkMastService.selectById(source.getWrkNo());
+ if (wrkMast == null || !Long.valueOf(ERP_REPORT_PENDING_WRK_STS).equals(wrkMast.getWrkSts())) {
+ return SUCCESS;
+ }
+
+ if (!isErpReportEnabled()) {
+ finishReport(wrkMast, false, getRetryTimes(wrkMast), "ERP reporting is disabled", false);
+ return FAIL.setMsg("ERP reporting is disabled");
+ }
+
+ ErpPakoutReportParam param = buildParam(wrkMast);
+ String request = JSON.toJSONString(param);
+ String response = "";
+ boolean success = false;
+ String errorMsg = null;
+ String requestUrl = buildRequestUrl();
+
+ try {
+ response = new HttpHandler.Builder()
+ .setUri(erpUrl)
+ .setPath(erpOutAddress)
+ .setJson(request)
+ .build()
+ .doPost();
+ success = isErpReportSuccess(response);
+ if (!success) {
+ errorMsg = extractErrorMsg(response);
+ }
+ finishReport(wrkMast, success, getRetryTimes(wrkMast), errorMsg, true);
+ } catch (Exception e) {
+ errorMsg = e.getMessage();
+ finishReport(wrkMast, false, getRetryTimes(wrkMast), errorMsg, true);
+ } finally {
+ try {
+ apiLogService.save(
+ "Outbound ERP Report",
+ requestUrl,
+ null,
+ "127.0.0.1",
+ request,
+ response,
+ success,
+ "workNo=" + wrkMast.getWrkNo()
+ );
+ } catch (Exception logEx) {
+ log.error("save outbound erp api log failed", logEx);
+ }
+ }
+
+ if (success) {
+ return SUCCESS;
+ }
+ return FAIL.setMsg(errorMsg);
+ }
+
+ private boolean isErpReportEnabled() {
+ if (!erpReportOld) {
+ return false;
+ }
+ String erpReport = Parameter.get().getErpReport();
+ return Cools.isEmpty(erpReport) || "true".equalsIgnoreCase(erpReport);
+ }
+
+ private ErpPakoutReportParam buildParam(WrkMast wrkMast) {
+ ErpPakoutReportParam param = new ErpPakoutReportParam();
+ param.setPalletId(resolvePalletId(wrkMast));
+ param.setCreateTime(formatDate(resolveCreateTime(wrkMast)));
+ param.setStartTime(formatDate(resolveStartTime(wrkMast)));
+ return param;
+ }
+
+ private String resolvePalletId(WrkMast wrkMast) {
+ if (!Cools.isEmpty(wrkMast.getBarcode())) {
+ return wrkMast.getBarcode();
+ }
+ List<WrkDetl> wrkDetls = wrkDetlService.selectByWrkNo(wrkMast.getWrkNo());
+ for (WrkDetl wrkDetl : wrkDetls) {
+ if (!Cools.isEmpty(wrkDetl.getZpallet())) {
+ return wrkDetl.getZpallet();
+ }
+ }
+ return null;
+ }
+
+ private Date resolveCreateTime(WrkMast wrkMast) {
+ if (!Cools.isEmpty(wrkMast.getCrnEndTime())) {
+ return wrkMast.getCrnEndTime();
+ }
+ if (!Cools.isEmpty(wrkMast.getModiTime())) {
+ return wrkMast.getModiTime();
+ }
+ if (!Cools.isEmpty(wrkMast.getIoTime())) {
+ return wrkMast.getIoTime();
+ }
+ return new Date();
+ }
+
+ private Date resolveStartTime(WrkMast wrkMast) {
+ if (!Cools.isEmpty(wrkMast.getCrnStrTime())) {
+ return wrkMast.getCrnStrTime();
+ }
+ if (!Cools.isEmpty(wrkMast.getPlcStrTime())) {
+ return wrkMast.getPlcStrTime();
+ }
+ if (!Cools.isEmpty(wrkMast.getIoTime())) {
+ return wrkMast.getIoTime();
+ }
+ return new Date();
+ }
+
+ private String formatDate(Date date) {
+ if (date == null) {
+ return null;
+ }
+ return new SimpleDateFormat(DATE_TIME_PATTERN).format(date);
+ }
+
+ private boolean isErpReportSuccess(String response) {
+ if (Cools.isEmpty(response)) {
+ return false;
+ }
+ try {
+ JSONObject jsonObject = JSON.parseObject(response);
+ if (jsonObject == null) {
+ return false;
+ }
+ Boolean success = jsonObject.getBoolean("success");
+ if (success != null) {
+ return success;
+ }
+ Integer code = jsonObject.getInteger("code");
+ if (code != null) {
+ return code == 200 || code == 0;
+ }
+ Integer status = jsonObject.getInteger("status");
+ if (status != null) {
+ return status == 200 || status == 0;
+ }
+ String result = jsonObject.getString("result");
+ if (!Cools.isEmpty(result)) {
+ return "success".equalsIgnoreCase(result) || "ok".equalsIgnoreCase(result) || "true".equalsIgnoreCase(result);
+ }
+ } catch (Exception ignore) {
+ return response.toLowerCase().contains("success") && response.toLowerCase().contains("true");
+ }
+ return false;
+ }
+
+ private String extractErrorMsg(String response) {
+ if (Cools.isEmpty(response)) {
+ return "empty erp response";
+ }
+ try {
+ JSONObject jsonObject = JSON.parseObject(response);
+ if (jsonObject == null) {
+ return response;
+ }
+ String[] keys = new String[]{"msg", "message", "error", "errMsg"};
+ for (String key : keys) {
+ String value = jsonObject.getString(key);
+ if (!Cools.isEmpty(value)) {
+ return value;
+ }
+ }
+ } catch (Exception ignore) {
+ }
+ return response;
+ }
+
+ private int getRetryTimes(WrkMast wrkMast) {
+ if (wrkMast.getExpTime() == null) {
+ return 0;
+ }
+ return wrkMast.getExpTime().intValue();
+ }
+
+ private void finishReport(WrkMast wrkMast, boolean success, int currentRetryTimes, String errorMsg, boolean countCurrentAttempt) {
+ int retryTimes = currentRetryTimes + (countCurrentAttempt ? 1 : 0);
+ Date now = new Date();
+ wrkMast.setExpTime((double) retryTimes);
+ wrkMast.setModiTime(now);
+ if (success) {
+ wrkMast.setWrkSts(ERP_REPORT_FINISHED_WRK_STS);
+ wrkMast.setLogMk(ERP_REPORT_SUCCESS_FLAG);
+ wrkMast.setLogErrMemo(null);
+ wrkMast.setLogErrTime(null);
+ } else {
+ wrkMast.setLogErrMemo(truncate(errorMsg, 500));
+ wrkMast.setLogErrTime(now);
+ if (retryTimes >= ERP_REPORT_MAX_RETRY_TIMES || !countCurrentAttempt) {
+ wrkMast.setWrkSts(ERP_REPORT_FINISHED_WRK_STS);
+ wrkMast.setLogMk(ERP_REPORT_FAIL_FLAG);
+ } else {
+ wrkMast.setWrkSts(ERP_REPORT_PENDING_WRK_STS);
+ wrkMast.setLogMk(ERP_REPORT_PENDING_FLAG);
+ }
+ }
+ if (!wrkMastService.updateById(wrkMast)) {
+ throw new IllegalStateException("update outbound erp report status failed, workNo=" + wrkMast.getWrkNo());
+ }
+ }
+
+ private String truncate(String message, int maxLength) {
+ if (message == null || message.length() <= maxLength) {
+ return message;
+ }
+ return message.substring(0, maxLength);
+ }
+
+ private String buildRequestUrl() {
+ if (Cools.isEmpty(erpUrl)) {
+ return erpOutAddress;
+ }
+ if (erpOutAddress == null) {
+ return erpUrl;
+ }
+ if (erpUrl.endsWith("/") && erpOutAddress.startsWith("/")) {
+ return erpUrl + erpOutAddress.substring(1);
+ }
+ if (!erpUrl.endsWith("/") && !erpOutAddress.startsWith("/")) {
+ return erpUrl + "/" + erpOutAddress;
+ }
+ return erpUrl + erpOutAddress;
+ }
+}
--
Gitblit v1.9.1