From 9611dc686299be640ce5e5f5990c747765161ec7 Mon Sep 17 00:00:00 2001
From: chen.llin <1442464845@qq.comm>
Date: 星期三, 21 一月 2026 10:59:38 +0800
Subject: [PATCH] agv逻辑调整2

---
 src/main/java/com/zy/asrs/task/handler/AgvHandler.java | 1005 +++++++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 742 insertions(+), 263 deletions(-)

diff --git a/src/main/java/com/zy/asrs/task/handler/AgvHandler.java b/src/main/java/com/zy/asrs/task/handler/AgvHandler.java
index 69db13d..c346977 100644
--- a/src/main/java/com/zy/asrs/task/handler/AgvHandler.java
+++ b/src/main/java/com/zy/asrs/task/handler/AgvHandler.java
@@ -3,6 +3,7 @@
 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.Task;
 import com.zy.asrs.entity.TaskLog;
 import com.zy.asrs.entity.WrkMast;
@@ -15,6 +16,9 @@
 import com.zy.asrs.service.LocCacheService;
 import com.zy.asrs.service.TaskLogService;
 import com.zy.asrs.service.TaskService;
+import com.zy.asrs.service.WrkMastService;
+import com.zy.asrs.service.WrkMastLogService;
+import com.zy.asrs.entity.WrkMastLog;
 import com.zy.common.constant.ApiInterfaceConstant;
 import com.zy.common.properties.AgvProperties;
 import com.zy.common.utils.HttpHandler;
@@ -62,6 +66,12 @@
     @Resource
     private AgvProperties agvProperties;
 
+    @Resource
+    private WrkMastService wrkMastService;
+
+    @Resource
+    private WrkMastLogService wrkMastLogService;
+
     /**
      * 绔欑偣杞璁℃暟鍣紝鐢ㄤ簬骞冲潎鍒嗛厤绔欑偣
      * Key: 绔欑偣缁勬爣璇嗭紙濡� "east" 鎴� "west"锛夛紝Value: 褰撳墠杞绱㈠紩
@@ -69,128 +79,266 @@
     private final Map<String, AtomicInteger> siteRoundRobinCounters = new ConcurrentHashMap<>();
 
     /**
-     * 鍛煎彨agv鎼繍
+     * 鍛煎彨AGV
+     * 
+     * 閲嶈锛氭鏂规硶鍙兘浠� AgvScheduler.callAgv() 瀹氭椂浠诲姟涓皟鐢紒
+     * 鎵�鏈堿GV鍛煎彨璇锋眰蹇呴』閫氳繃瀹氭椂浠诲姟缁熶竴澶勭悊锛岀‘淇濓細
+     * 1. 浠诲姟鎸夐『搴忓鐞嗭紝閬垮厤骞跺彂鍐茬獊
+     * 2. 绔欑偣鍒嗛厤鍜孉GV鍛煎彨鍒嗙锛岃亴璐f竻鏅�
+     * 3. 缁熶竴鐨勯敊璇鐞嗗拰閲嶈瘯鏈哄埗
+     * 
+     * @param taskList 浠诲姟鍒楄〃锛堥�氬父鍙寘鍚竴涓换鍔★級
+     * @return 鏄惁鎴愬姛澶勭悊浜嗕换鍔★紙鎴愬姛鍛煎彨AGV锛岀姸鎬佷粠7鍙樹负8锛�
      */
-    public void callAgv(List<Task> taskList) {
-
-        if (!agvProperties.isSendTask()) {
-            return;
+    public boolean callAgv(List<Task> taskList) {
+        // 璁板綍璋冪敤鍫嗘爤锛岀‘淇濆彧鑳戒粠瀹氭椂浠诲姟璋冪敤
+        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
+        boolean calledFromScheduler = false;
+        for (StackTraceElement element : stackTrace) {
+            if (element.getClassName().contains("AgvScheduler") && 
+                element.getMethodName().equals("callAgv")) {
+                calledFromScheduler = true;
+                break;
+            }
+        }
+        
+        if (!calledFromScheduler) {
+            log.error("涓ラ噸閿欒锛歝allAgv鏂规硶鍙兘浠嶢gvScheduler.callAgv()瀹氭椂浠诲姟涓皟鐢紒褰撳墠璋冪敤鍫嗘爤锛歿}", 
+                Arrays.stream(stackTrace).limit(5).map(StackTraceElement::toString).collect(Collectors.joining("\n")));
+            return false;
         }
 
-        for (Task task : taskList) {
-            // 濡傛灉浠诲姟鐘舵�佸凡缁忔槸8锛堝凡鍛煎彨AGV锛屾鍦ㄦ惉杩愶級锛屽垯涓嶅啀鍙戦�佹寚浠�
-            if (task.getWrkSts() != null && task.getWrkSts() == 8L) {
-                // log.debug("浠诲姟ID锛歿}鐘舵�佸凡鏄�8锛堟鍦ㄦ惉杩愶級锛岃烦杩囧彂閫�", task.getId());
-                continue;
+        if (!agvProperties.isSendTask()) {
+            log.warn("AGV鍛煎彨锛氶厤缃甶sSendTask=false锛屼笉鍙戦�丄GV浠诲姟");
+            return false;
+        }
+
+        // 姣忔鍙鐞嗕竴涓换鍔★紝閬垮厤楂樺苟鍙戞墽琛�
+        if (taskList == null || taskList.isEmpty()) {
+            return false;
+        }
+        
+        // 鍙鐞嗙涓�涓换鍔�
+        Task task = taskList.get(0);
+        
+        // 鍛煎彨AGV瀹氭椂浠诲姟鍙鐞嗗凡鍒嗛厤绔欑偣鐨勪换鍔★紝绔欑偣鍒嗛厤鐢卞崟鐙殑瀹氭椂浠诲姟澶勭悊
+        String staNo = task.getStaNo();
+        String displayTaskId = (task.getWrkNo() != null) ? String.valueOf(task.getWrkNo()) : String.valueOf(task.getId());
+        
+        // 妫�鏌ョ珯鐐规槸鍚︽湁鏁堬紙涓嶄负绌恒�佷笉涓虹┖瀛楃涓层�佷笉涓�0锛�
+        if (staNo == null || staNo.isEmpty() || staNo.equals("0")) {
+            // 娌℃湁鏈夋晥绔欑偣锛岃烦杩囷紙绔欑偣鍒嗛厤鐢盿llocateSite瀹氭椂浠诲姟澶勭悊锛�
+            log.warn("瀹氭椂浠诲姟callAgv锛氫换鍔D锛歿}娌℃湁鏈夋晥绔欑偣鍒嗛厤锛坰ta_no={}锛夛紝璺宠繃鍙戦�侊紝绛夊緟鍒嗛厤绔欑偣瀹氭椂浠诲姟澶勭悊", displayTaskId, staNo);
+            return false; // 杩斿洖false锛岃〃绀烘湭鎴愬姛澶勭悊
+        }
+        
+        // 妫�鏌ョ珯鐐规槸鍚︽湁鏁堬紙涓嶄负0涓斿瓨鍦級
+        try {
+            Integer siteNo = Integer.parseInt(staNo);
+            if (siteNo == null || siteNo == 0) {
+                log.warn("瀹氭椂浠诲姟callAgv锛氫换鍔D锛歿}鐨勭洰鏍囩珯鐐箋}鏃犳晥锛堜负0锛夛紝娓呯┖绔欑偣鍒嗛厤锛屽皢閲嶆柊鍒嗛厤", displayTaskId, staNo);
+                task.setStaNo(null);
+                taskService.updateById(task);
+                return false; // 杩斿洖false锛岃鍒嗛厤绔欑偣瀹氭椂浠诲姟閲嶆柊鍒嗛厤
+            }
+            // 妫�鏌ョ珯鐐规槸鍚﹀瓨鍦�
+            List<BasDevp> basDevpList = basDevpMapper.selectList(new EntityWrapper<BasDevp>().eq("dev_no", siteNo));
+            if (basDevpList == null || basDevpList.isEmpty()) {
+                log.warn("瀹氭椂浠诲姟callAgv锛氫换鍔D锛歿}鐨勭洰鏍囩珯鐐箋}涓嶅瓨鍦紝娓呯┖绔欑偣鍒嗛厤锛屽皢閲嶆柊鍒嗛厤", displayTaskId, staNo);
+                task.setStaNo(null);
+                taskService.updateById(task);
+                return false; // 杩斿洖false锛岃鍒嗛厤绔欑偣瀹氭椂浠诲姟閲嶆柊鍒嗛厤
+            }
+        } catch (NumberFormatException e) {
+            // 绔欑偣鏍煎紡閿欒锛屾竻绌虹珯鐐癸紝璁╁垎閰嶇珯鐐瑰畾鏃朵换鍔¢噸鏂板垎閰�
+            log.warn("瀹氭椂浠诲姟callAgv锛氫换鍔D锛歿}鐨勭洰鏍囩珯鐐箋}鏍煎紡閿欒锛屾竻绌虹珯鐐瑰垎閰嶏紝灏嗛噸鏂板垎閰�", displayTaskId, staNo);
+            task.setStaNo(null);
+            taskService.updateById(task);
+            return false; // 杩斿洖false锛岃鍒嗛厤绔欑偣瀹氭椂浠诲姟閲嶆柊鍒嗛厤
+        }
+        
+        log.info("瀹氭椂浠诲姟callAgv锛氫换鍔D锛歿}宸叉湁绔欑偣鍒嗛厤锛歿}锛屽噯澶囧彂閫丄GV鍛戒护", displayTaskId, staNo);
+        
+        
+        // 妫�鏌ョ珯鐐规槸鍚︽湁鐘舵��8鐨勫悓绫诲瀷浠诲姟锛屾湁鍒欒烦杩囷紙涓嶆竻绌虹珯鐐癸級
+        // 瑙勫垯锛氭渶澶氱粰姣忎釜绔欑偣鍒嗛厤1鏉′换鍔★紝鏈畬鎴愬垯绛夊緟
+        // 鍒ゆ柇浠诲姟鏄惁瀹屾垚锛氶�氳繃鏌ヨagv宸ヤ綔妗o紙wrk_mast锛夛紝濡傛灉鏌ヤ笉鍒板氨鏄畬鎴愪簡
+        if (staNo != null && !staNo.isEmpty() && task.getIoType() != null) {
+            // 鏍规嵁褰撳墠浠诲姟绫诲瀷锛屽彧妫�鏌ュ悓绫诲瀷鐨勬鍦ㄦ惉杩愪换鍔★紙鐘舵��8锛�
+            // 鍏ュ簱浠诲姟锛坕oType < 100锛夛細鍙鏌ュ叆搴撶被鍨嬬殑姝e湪鎼繍浠诲姟
+            // 鍑哄簱浠诲姟锛坕oType >= 100锛夛細鍙鏌ュ嚭搴撶被鍨嬬殑姝e湪鎼繍浠诲姟
+            List<Integer> ioTypes;
+            String taskType;
+            if (task.getIoType() < 100) {
+                // 鍏ュ簱浠诲姟锛氬彧妫�鏌ュ叆搴撶被鍨嬶紙1, 10, 53, 57锛�
+                ioTypes = Arrays.asList(1, 10, 53, 57);
+                taskType = "鍏ュ簱";
+            } else {
+                // 鍑哄簱浠诲姟锛氬彧妫�鏌ュ嚭搴撶被鍨嬶紙101, 110, 103, 107锛�
+                ioTypes = Arrays.asList(101, 110, 103, 107);
+                taskType = "鍑哄簱";
             }
             
-            // 濡傛灉浠诲姟娌℃湁鍒嗛厤绔欑偣锛屽厛鍒嗛厤绔欑偣锛堝彧鏈変负绌烘椂鎵嶅垎閰嶏紝宸茬粡鍒嗛厤浜嗕笉瑕佹竻绌猴級
-            String staNo = task.getStaNo();
-            if (staNo == null || staNo.isEmpty()) {
-                String errorMsg = allocateSiteForTask(task);
-                if (errorMsg != null) {
-                    // 鏃犳硶鍒嗛厤绔欑偣锛屽彧鍦ㄦ棩蹇椾腑璁板綍锛屼笉璁板綍鍒颁换鍔′腑锛坅pp涓嶉渶瑕佺煡閬擄級
-                    // log.warn("浠诲姟ID锛歿}鏃犳硶鍒嗛厤绔欑偣锛歿}", task.getId(), errorMsg);
-                    continue;
-                }
-                // 妫�鏌ユ槸鍚︽垚鍔熷垎閰嶄簡绔欑偣锛堝鏋滆繑鍥瀗ull涓攕taNo浠嶄负绌猴紝璇存槑鎵�鏈夌珯鐐归兘鍦ㄦ惉杩愶紝绛夊緟涓嬫鍐嶈瘯锛�
-                staNo = task.getStaNo();
-                if (staNo == null || staNo.isEmpty()) {
-                    // 鎵�鏈夌珯鐐归兘鍦ㄦ惉杩愶紝鏆備笉鍒嗛厤锛岀瓑寰呬笅娆″畾鏃朵换鍔″啀灏濊瘯
-                    continue;
-                }
-                // log.info("浠诲姟ID锛歿}宸插垎閰嶇珯鐐癸細{}", task.getId(), staNo);
-            }
+            // 閫氳繃SQL鏌ヨ璇ョ珯鐐规墍鏈堿GV浠诲姟锛堝寘鎷姸鎬�7鍜�8锛�
+            // 瑙勫垯锛氭渶澶氱粰姣忎釜绔欑偣鍒嗛厤1鏉′换鍔★紝鏈畬鎴愬垯绛夊緟
+            // 鍒ゆ柇浠诲姟鏄惁瀹屾垚锛氶�氳繃鏌ヨagv宸ヤ綔妗o紙wrk_mast锛夛紝濡傛灉鏌ヤ笉鍒板氨鏄畬鎴愪簡
+            List<Task> allTasks = taskService.selectList(
+                new EntityWrapper<Task>()
+                    .eq("sta_no", staNo)
+                    .eq("task_type", "agv")
+                    .in("wrk_sts", 7L, 8L)
+                    .in("io_type", ioTypes)
+                    .ne("id", task.getId()) // 鎺掗櫎褰撳墠浠诲姟鏈韩
+                    .andNew("(is_deleted = 0)")
+            );
             
-            // 妫�鏌ョ洰鏍囩珯鐐规槸鍚︽湁鏁堬紙涓嶄负0涓斿瓨鍦級
-            if (staNo != null && !staNo.isEmpty()) {
-                try {
-                    Integer siteNo = Integer.parseInt(staNo);
-                    // 妫�鏌ョ珯鐐规槸鍚︿负0锛堟棤鏁堢珯鐐癸級锛屽鏋滄槸0鍒欎笉鍙戦�侊紝浣嗕笉娓呯┖绔欑偣
-                    if (siteNo == null || siteNo == 0) {
-                        // log.warn("浠诲姟ID锛歿}鐨勭洰鏍囩珯鐐箋}鏃犳晥锛堜负0锛夛紝璺宠繃鍙戦�侊紝淇濈暀绔欑偣鍒嗛厤", task.getId(), staNo);
-                        continue;
+            int taskCount = allTasks != null ? allTasks.size() : 0;
+            log.info("瀹氭椂浠诲姟锛氫换鍔D锛歿}锛岀珯鐐箋}鏌ヨ鍒皗}涓狝GV浠诲姟锛堟帓闄ゅ綋鍓嶄换鍔★級锛屽紑濮嬫鏌ユ槸鍚︽湁鏈畬鎴愮殑浠诲姟", 
+                displayTaskId, staNo, taskCount);
+            
+            // 妫�鏌ユ槸鍚︽湁鏈夋晥鐨勬湭瀹屾垚浠诲姟锛堥�氳繃鏌ヨagv宸ヤ綔妗e垽鏂級
+            boolean hasValidTask = false;
+            if (taskCount > 0) {
+                for (Task agvTask : allTasks) {
+                    if (agvTask.getWrkNo() != null) {
+                        // 鏌ヨ宸ヤ綔妗o紝濡傛灉鏌ヤ笉鍒板氨鏄畬鎴愪簡
+                        WrkMast wrkMast = wrkMastService.selectOne(
+                            new EntityWrapper<WrkMast>().eq("wrk_no", agvTask.getWrkNo())
+                        );
+                        if (wrkMast != null) {
+                            // 宸ヤ綔妗e瓨鍦紝妫�鏌ユ槸鍚﹀凡瀹屾垚
+                            Long wrkSts = wrkMast.getWrkSts();
+                            Integer ioType = agvTask.getIoType();
+                            
+                            if (wrkSts != null && ioType != null) {
+                                // 鍏ュ簱浠诲姟锛氱姸鎬�4鎴�5琛ㄧず瀹屾垚
+                                boolean isCompleted = false;
+                                if ((ioType == 1 || ioType == 10 || ioType == 53 || ioType == 57) &&
+                                    (wrkSts == 4L || wrkSts == 5L)) {
+                                    isCompleted = true;
+                                }
+                                // 鍑哄簱浠诲姟锛氱姸鎬�14鎴�15琛ㄧず瀹屾垚
+                                else if ((ioType == 101 || ioType == 110 || ioType == 103 || ioType == 107) &&
+                                         (wrkSts == 14L || wrkSts == 15L)) {
+                                    isCompleted = true;
+                                }
+                                
+                                if (!isCompleted) {
+                                    // 宸ヤ綔妗e瓨鍦ㄤ笖鏈畬鎴愶紝瑙嗕负鏈夋晥浠诲姟
+                                    hasValidTask = true;
+                                    log.info("瀹氭椂浠诲姟锛氫换鍔D锛歿}锛岀珯鐐箋}宸叉湁1鏉℃湭瀹屾垚鐨剓}AGV浠诲姟锛堝伐浣滃彿锛歿}锛屽伐浣滄。鐘舵�侊細{}锛夛紝璺宠繃褰撳墠浠诲姟锛岀瓑寰呭畬鎴�", 
+                                        displayTaskId, staNo, taskType, agvTask.getWrkNo(), wrkSts);
+                                    break;
+                                } else {
+                                    log.info("瀹氭椂浠诲姟锛氫换鍔D锛歿}锛岀珯鐐箋}鐨勪换鍔}锛堝伐浣滃彿锛歿}锛夊凡瀹屾垚锛堝伐浣滄。鐘舵�侊細{}锛夛紝涓嶇畻鏈夋晥浠诲姟", 
+                                        displayTaskId, staNo, agvTask.getId(), agvTask.getWrkNo(), wrkSts);
+                                }
+                            } else {
+                                // 宸ヤ綔妗e瓨鍦ㄤ絾鐘舵�佹湭鐭ワ紝瑙嗕负鏈夋晥浠诲姟
+                                hasValidTask = true;
+                                log.info("瀹氭椂浠诲姟锛氫换鍔D锛歿}锛岀珯鐐箋}宸叉湁1鏉}AGV浠诲姟锛堝伐浣滃彿锛歿}锛屽伐浣滄。鐘舵�佹湭鐭ワ級锛岃烦杩囧綋鍓嶄换鍔★紝绛夊緟瀹屾垚", 
+                                    displayTaskId, staNo, taskType, agvTask.getWrkNo());
+                                break;
+                            }
+                        } else {
+                            // 濡傛灉宸ヤ綔妗f煡涓嶅埌锛岃涓哄凡瀹屾垚锛屼笉绠楁湁鏁堜换鍔�
+                            log.info("瀹氭椂浠诲姟锛氫换鍔D锛歿}锛岀珯鐐箋}鐨勪换鍔}锛堝伐浣滃彿锛歿}锛夊伐浣滄。鏌ヤ笉鍒帮紝瑙嗕负宸插畬鎴愶紝涓嶇畻鏈夋晥浠诲姟", 
+                                displayTaskId, staNo, agvTask.getId(), agvTask.getWrkNo());
+                        }
                     }
-                    List<BasDevp> basDevpList = basDevpMapper.selectList(new EntityWrapper<BasDevp>().eq("dev_no", siteNo));
-                    if (basDevpList == null || basDevpList.isEmpty()) {
-                        // 绔欑偣涓嶅瓨鍦紝璺宠繃鍙戦�侊紝涓嶆竻绌虹珯鐐�
-                        // log.warn("浠诲姟ID锛歿}鐨勭洰鏍囩珯鐐箋}涓嶅瓨鍦紝璺宠繃鍙戦�侊紝淇濈暀绔欑偣鍒嗛厤", task.getId(), staNo);
-                        continue;
-                    }
-                } catch (NumberFormatException e) {
-                    // 绔欑偣鏍煎紡閿欒锛岃烦杩囧彂閫侊紝涓嶆竻绌虹珯鐐�
-                    // log.warn("浠诲姟ID锛歿}鐨勭洰鏍囩珯鐐箋}鏍煎紡閿欒锛岃烦杩囧彂閫侊紝淇濈暀绔欑偣鍒嗛厤", task.getId(), staNo);
-                    continue;
                 }
             } else {
-                // 娌℃湁绔欑偣锛岃烦杩�
-                continue;
+                log.info("瀹氭椂浠诲姟锛氫换鍔D锛歿}锛岀珯鐐箋}娌℃湁鍏朵粬AGV浠诲姟锛屽彲浠ュ垎閰�", displayTaskId, staNo);
             }
             
-            // 妫�鏌ョ珯鐐规槸鍚︽湁鐘舵��8鐨勫悓绫诲瀷浠诲姟锛屾湁鍒欒烦杩囷紙涓嶆竻绌虹珯鐐癸級
-            if (staNo != null && !staNo.isEmpty() && task.getIoType() != null) {
-                // 鏍规嵁褰撳墠浠诲姟绫诲瀷锛屽彧妫�鏌ュ悓绫诲瀷鐨勬鍦ㄦ惉杩愪换鍔★紙鐘舵��8锛�
-                // 鍏ュ簱浠诲姟锛坕oType < 100锛夛細鍙鏌ュ叆搴撶被鍨嬬殑姝e湪鎼繍浠诲姟
-                // 鍑哄簱浠诲姟锛坕oType >= 100锛夛細鍙鏌ュ嚭搴撶被鍨嬬殑姝e湪鎼繍浠诲姟
-                List<Integer> ioTypes;
-                String taskType;
-                if (task.getIoType() < 100) {
-                    // 鍏ュ簱浠诲姟锛氬彧妫�鏌ュ叆搴撶被鍨嬶紙1, 10, 53, 57锛�
-                    ioTypes = Arrays.asList(1, 10, 53, 57);
-                    taskType = "鍏ュ簱";
-                } else {
-                    // 鍑哄簱浠诲姟锛氬彧妫�鏌ュ嚭搴撶被鍨嬶紙101, 110, 103, 107锛�
-                    ioTypes = Arrays.asList(101, 110, 103, 107);
-                    taskType = "鍑哄簱";
+            // 濡傛灉绔欑偣鏈夋湁鏁堢殑鏈畬鎴愪换鍔★紝璺宠繃褰撳墠浠诲姟
+            if (hasValidTask) {
+                log.warn("瀹氭椂浠诲姟锛氫换鍔D锛歿}锛岀珯鐐箋}鏈夋湭瀹屾垚鐨剓}AGV浠诲姟锛岃烦杩囧綋鍓嶄换鍔★紝绛夊緟瀹屾垚銆備笅娆″皢閲嶆柊灏濊瘯澶勭悊姝や换鍔�", 
+                    displayTaskId, staNo, taskType);
+                return false; // 杩斿洖false锛岃〃绀烘湭鎴愬姛澶勭悊锛屼笅娆′細閲嶆柊灏濊瘯
+            }
+            
+            // 妫�鏌ユ槸鍚︽湁鐘舵��8涓斿凡鏀跺埌AGV纭鐨勪换鍔★紙鐢ㄤ簬鏃ュ織璁板綍锛�
+            List<Task> transportingTasks = taskService.selectList(
+                new EntityWrapper<Task>()
+                    .eq("sta_no", staNo)
+                    .eq("task_type", "agv")
+                    .eq("wrk_sts", 8L) // 鍙鏌ユ鍦ㄦ惉杩愶紙8锛夌殑浠诲姟
+                    .isNotNull("plc_str_time") // 鍙鏌ュ凡鏀跺埌AGV纭鐨勪换鍔★紙plc_str_time涓嶄负绌猴級
+                    .in("io_type", ioTypes)
+                    .ne("id", task.getId()) // 鎺掗櫎褰撳墠浠诲姟鏈韩
+                    .andNew("(is_deleted = 0)")
+            );
+            
+            // 妫�鏌ュ苟鑷姩缁撴潫宸插畬鎴愬伐浣滄。鐨凙GV浠诲姟
+            int originalCount = transportingTasks.size();
+            List<Task> validTransportingTasks = checkAndCompleteFinishedTasks(transportingTasks, taskType);
+            int completedCount = originalCount - validTransportingTasks.size();
+            
+            if (completedCount > 0) {
+                log.info("瀹氭椂浠诲姟锛氱珯鐐箋}鑷姩缁撴潫浜唟}涓凡瀹屾垚宸ヤ綔妗g殑AGV浠诲姟锛屽墿浣檣}涓鍦ㄦ惉杩愮殑浠诲姟", 
+                    staNo, completedCount, validTransportingTasks.size());
+            }
+            
+            if (!validTransportingTasks.isEmpty()) {
+                List<Integer> transportingTaskIds = validTransportingTasks.stream()
+                        .map(Task::getWrkNo)
+                        .filter(wrkNo -> wrkNo != null) // 杩囨护鎺塶ull鍊�
+                        .collect(Collectors.toList());
+                // 璁板綍琚崰鐢ㄤ换鍔$殑璇︾粏淇℃伅
+                StringBuilder taskDetailInfo = new StringBuilder();
+                for (Task t : validTransportingTasks) {
+                    if (taskDetailInfo.length() > 0) {
+                        taskDetailInfo.append("; ");
+                    }
+                    String tDisplayTaskId = (t.getWrkNo() != null) ? String.valueOf(t.getWrkNo()) : String.valueOf(t.getId());
+                    taskDetailInfo.append("浠诲姟").append(tDisplayTaskId)
+                            .append("(wrk_no=").append(t.getWrkNo())
+                            .append(",纭鏃堕棿=").append(t.getPlcStrTime() != null ? t.getPlcStrTime().toString() : "鏈‘璁�")
+                            .append(",鍒涘缓鏃堕棿=").append(t.getAppeTime() != null ? t.getAppeTime().toString() : "鏈煡")
+                            .append(")");
                 }
-                
-                // 妫�鏌ョ姸鎬佷负8锛堝凡鍛煎彨AGV锛屾鍦ㄦ惉杩愶級鐨勫悓绫诲瀷浠诲姟
-                List<Task> transportingTasks = taskService.selectList(
-                    new EntityWrapper<Task>()
-                        .eq("sta_no", staNo)
-                        .eq("task_type", "agv")
-                        .eq("wrk_sts", 8L) // 鍙鏌ユ鍦ㄦ惉杩愮姸鎬佺殑浠诲姟
-                        .in("io_type", ioTypes)
-                        .ne("id", task.getId()) // 鎺掗櫎褰撳墠浠诲姟鏈韩
-                );
-                
-                if (!transportingTasks.isEmpty()) {
-                    // log.info("绔欑偣{}鏈墈}涓鍦ㄦ惉杩愮殑{}AGV浠诲姟锛岃烦杩囧綋鍓嶄换鍔D锛歿}", 
-                    //         staNo, transportingTasks.size(), taskType, task.getId());
-                    continue;
-                }
+                log.info("瀹氭椂浠诲姟锛氱珯鐐箋}鏈墈}涓鍦ㄦ惉杩愮殑{}AGV浠诲姟锛堝伐浣滃彿锛歿}锛夛紝璺宠繃褰撳墠浠诲姟ID锛歿}锛屼笅娆″皢閲嶆柊灏濊瘯銆備换鍔¤鎯咃細{}", 
+                        staNo, validTransportingTasks.size(), taskType, transportingTaskIds, displayTaskId, taskDetailInfo.toString());
+                return false; // 杩斿洖false锛岃〃绀烘湭鎴愬姛澶勭悊锛屼笅娆′細閲嶆柊灏濊瘯
+            } else if (completedCount > 0) {
+                // 鎵�鏈夊崰鐢ㄤ换鍔¢兘宸茬粨鏉燂紝绔欑偣宸查噴鏀撅紝鍙互缁х画澶勭悊褰撳墠浠诲姟
+                log.info("瀹氭椂浠诲姟锛氱珯鐐箋}鐨勬墍鏈夊崰鐢ㄤ换鍔″凡鑷姩缁撴潫锛岀珯鐐瑰凡閲婃斁锛屽彲浠ュ垎閰嶇粰褰撳墠浠诲姟ID锛歿}", staNo, task.getId());
             }
-            
-            // 鍛煎彨agv
-            String response = "";
-            boolean success = false;
-            String url = ApiInterfaceConstant.AGV_IP + ApiInterfaceConstant.AGV_CREATE_TASK_PATH;
-            String namespace = "";
-            switch (task.getIoType()) {
-                case 1:
-                case 10:
-                case 53:
-                case 57:
-                    namespace = "鍏ュ簱";
-                    break;
-                case 3:
-                    namespace = "杞Щ";
-                    break;
-                case 101:
-                case 110:
-                case 103:
-                case 107:
-                    namespace = "鍑哄簱";
-                    break;
-                default:
-            }
-            String body = getRequest(task,namespace);
-            
-            // 鑾峰彇褰撳墠閲嶈瘯娆℃暟
-            int currentRetryCount = getRetryCount(task);
-            int maxRetryCount = agvProperties.getCallRetry().getMaxRetryCount();
-            boolean retryEnabled = agvProperties.getCallRetry().isEnabled();
-            
+        }
+        
+        log.info("瀹氭椂浠诲姟锛氫换鍔D锛歿}锛岀珯鐐箋}妫�鏌ラ�氳繃锛屽噯澶囧彂閫丄GV鍛戒护", displayTaskId, staNo);
+        
+        // 鍛煎彨agv
+        String response = "";
+        boolean success = false;
+        String url = ApiInterfaceConstant.AGV_IP + ApiInterfaceConstant.AGV_CREATE_TASK_PATH;
+        String namespace = "";
+        switch (task.getIoType()) {
+            case 1:
+            case 10:
+            case 53:
+            case 57:
+                namespace = "鍏ュ簱";
+                break;
+            case 3:
+                namespace = "杞Щ";
+                break;
+            case 101:
+            case 110:
+            case 103:
+            case 107:
+                namespace = "鍑哄簱";
+                break;
+            default:
+        }
+        String body = getRequest(task,namespace);
+        
+        // 鑾峰彇褰撳墠閲嶈瘯娆℃暟
+        int currentRetryCount = getRetryCount(task);
+        int maxRetryCount = agvProperties.getCallRetry().getMaxRetryCount();
+        boolean retryEnabled = agvProperties.getCallRetry().isEnabled();
+        
             // 濡傛灉閲嶈瘯娆℃暟宸茶揪鍒版渶澶у�硷紝璺宠繃鏈鍙戦��
             if (retryEnabled && currentRetryCount >= maxRetryCount) {
                 // log.warn("{}鍛煎彨agv鎼繍 - 浠诲姟ID锛歿}宸茶揪鍒版渶澶ч噸璇曟鏁帮紙{}锛夛紝鍋滄閲嶈瘯", 
@@ -199,82 +347,191 @@
                 task.setErrorTime(new Date());
                 task.setErrorMemo(String.format("AGV鍛煎彨澶辫触锛屽凡杈惧埌鏈�澶ч噸璇曟鏁帮紙%d娆★級", maxRetryCount));
                 taskService.updateById(task);
-                continue;
+                return true; // 宸茶揪鍒版渶澶ч噸璇曟鏁帮紝涓嶅啀閲嶈瘯锛岃繑鍥瀟rue琛ㄧず宸插鐞嗭紙铏界劧澶辫触锛�
             }
+        
+        // 鎵撳嵃璇锋眰淇℃伅锛堝寘鍚噸璇曟鏁帮級
+        // if (currentRetryCount > 0) {
+        //     log.info("{}鍛煎彨agv鎼繍锛堢{}娆¢噸璇曪級 - 璇锋眰鍦板潃锛歿}", namespace, currentRetryCount + 1, url);
+        // } else {
+        //     log.info("{}鍛煎彨agv鎼繍 - 璇锋眰鍦板潃锛歿}", namespace, url);
+        // }
+        // log.info("{}鍛煎彨agv鎼繍 - 璇锋眰鍙傛暟锛歿}", namespace, body);
+        
+        boolean result = false; // 榛樿杩斿洖false锛岃〃绀烘湭鎴愬姛澶勭悊
+        try {
+            // 浣跨敤浠欏伐M4鎺ュ彛
+            response = new HttpHandler.Builder()
+                    .setUri(ApiInterfaceConstant.AGV_IP)
+                    .setPath(ApiInterfaceConstant.AGV_CREATE_TASK_PATH)
+                    .setJson(body)
+                    .build()
+                    .doPost();
+            // 鎵撳嵃杩斿洖鍙傛暟
+            // log.info("{}鍛煎彨agv鎼繍 - 杩斿洖鍙傛暟锛歿}", namespace, response);
             
-            // 鎵撳嵃璇锋眰淇℃伅锛堝寘鍚噸璇曟鏁帮級
-            // if (currentRetryCount > 0) {
-            //     log.info("{}鍛煎彨agv鎼繍锛堢{}娆¢噸璇曪級 - 璇锋眰鍦板潃锛歿}", namespace, currentRetryCount + 1, url);
-            // } else {
-            //     log.info("{}鍛煎彨agv鎼繍 - 璇锋眰鍦板潃锛歿}", namespace, url);
-            // }
-            // log.info("{}鍛煎彨agv鎼繍 - 璇锋眰鍙傛暟锛歿}", namespace, body);
-            
-            try {
-                // 浣跨敤浠欏伐M4鎺ュ彛
-                response = new HttpHandler.Builder()
-                        .setUri(ApiInterfaceConstant.AGV_IP)
-                        .setPath(ApiInterfaceConstant.AGV_CREATE_TASK_PATH)
-                        .setJson(body)
-                        .build()
-                        .doPost();
-                // 鎵撳嵃杩斿洖鍙傛暟
-                // log.info("{}鍛煎彨agv鎼繍 - 杩斿洖鍙傛暟锛歿}", namespace, response);
-                
-                // 妫�鏌ュ搷搴旀槸鍚︿负绌�
-                if (response == null || response.trim().isEmpty()) {
-                    String errorMsg = "AGV鎺ュ彛杩斿洖涓虹┖";
-                    // log.error("{}鍛煎彨agv鎼繍澶辫触 - 浠诲姟ID锛歿}锛寋}", namespace, task.getId(), errorMsg);
-                    handleCallFailure(task, namespace, errorMsg, retryEnabled, maxRetryCount, currentRetryCount);
-                    continue;
-                }
-                
-                JSONObject jsonObject = JSON.parseObject(response);
-                if (jsonObject == null) {
-                    String errorMsg = "鍝嶅簲JSON瑙f瀽澶辫触锛屽搷搴斿唴瀹癸細" + response;
-                    // log.error("{}鍛煎彨agv鎼繍澶辫触 - 浠诲姟ID锛歿}锛寋}", namespace, task.getId(), errorMsg);
-                    handleCallFailure(task, namespace, errorMsg, retryEnabled, maxRetryCount, currentRetryCount);
-                    continue;
-                }
-                
-                Integer code = jsonObject.getInteger("code");
-                if (code != null && code.equals(200)) {
-                    // 鍛煎彨鎴愬姛锛屾竻闄ら噸璇曟鏁板拰閿欒淇℃伅
-                    success = true;
-                    task.setWrkSts(8L);
-                    task.setMemo(clearRetryInfo(task.getMemo())); // 娓呴櫎閲嶈瘯淇℃伅
-                    task.setErrorTime(null);
-                    task.setErrorMemo(null);
-                    taskService.updateById(task);
-                    // log.info("{}鍛煎彨agv鎼繍鎴愬姛 - 浠诲姟ID锛歿}", namespace, task.getId());
-                } else {
-                    String message = jsonObject.getString("message");
-                    String errorMsg = String.format("閿欒鐮侊細%s锛岄敊璇俊鎭細%s", code, message);
-                    // log.error("{}鍛煎彨agv鎼繍澶辫触 - 浠诲姟ID锛歿}锛寋}", namespace, task.getId(), errorMsg);
-                    handleCallFailure(task, namespace, errorMsg, retryEnabled, maxRetryCount, currentRetryCount);
-                }
-            } catch (Exception e) {
-                String errorMsg = "寮傚父淇℃伅锛�" + e.getMessage();
-                // log.error("{}鍛煎彨agv鎼繍寮傚父 - 浠诲姟ID锛歿}锛岃姹傚湴鍧�锛歿}锛岃姹傚弬鏁帮細{}锛寋}", 
-                //         namespace, task.getId(), url, body, errorMsg, e);
+            // 妫�鏌ュ搷搴旀槸鍚︿负绌�
+            if (response == null || response.trim().isEmpty()) {
+                String errorMsg = "AGV鎺ュ彛杩斿洖涓虹┖";
+                log.warn("瀹氭椂浠诲姟锛歿}鍛煎彨agv鎼繍澶辫触 - 浠诲姟ID锛歿}锛寋}", namespace, displayTaskId, errorMsg);
                 handleCallFailure(task, namespace, errorMsg, retryEnabled, maxRetryCount, currentRetryCount);
-            } finally {
-                try {
-                    // 淇濆瓨鎺ュ彛鏃ュ織
-                    apiLogService.save(
-                            namespace + "鍛煎彨agv鎼繍",
-                            url,
-                            null,
-                            "127.0.0.1",
-                            body,
-                            response,
-                            success
-                    );
-                } catch (Exception e) {
-                    // log.error(namespace + "鍛煎彨agv淇濆瓨鎺ュ彛鏃ュ織寮傚父:", e);
+                // 濡傛灉杈惧埌鏈�澶ч噸璇曟鏁帮紝杩斿洖true琛ㄧず宸插鐞嗭紙铏界劧澶辫触锛�
+                // 鍚﹀垯杩斿洖false锛岃瀹氭椂浠诲姟閲嶆柊灏濊瘯
+                if (retryEnabled && currentRetryCount >= maxRetryCount) {
+                    result = true; // 宸茶揪鍒版渶澶ч噸璇曟鏁帮紝杩斿洖true琛ㄧず宸插鐞嗭紙铏界劧澶辫触锛�
+                    log.info("瀹氭椂浠诲姟锛氫换鍔D锛歿}锛孉GV鍛煎彨澶辫触涓斿凡杈惧埌鏈�澶ч噸璇曟鏁帮紙{}娆★級锛屾爣璁颁负宸插鐞嗭紝涓嶅啀閲嶈瘯", 
+                        displayTaskId, maxRetryCount);
+                } else {
+                    result = false; // 杩斿洖false锛岃瀹氭椂浠诲姟閲嶆柊灏濊瘯
+                    log.info("瀹氭椂浠诲姟锛氫换鍔D锛歿}锛屼笅娆″皢閲嶆柊灏濊瘯鍙戦�丄GV鍛戒护", displayTaskId);
                 }
+            } else {
+                // 灏濊瘯瑙f瀽JSON鍝嶅簲锛屾崟鑾稪SON瑙f瀽寮傚父
+                JSONObject jsonObject = null;
+                try {
+                    jsonObject = JSON.parseObject(response);
+                } catch (com.alibaba.fastjson.JSONException e) {
+                    // JSON瑙f瀽澶辫触锛屽搷搴斿彲鑳戒笉鏄湁鏁堢殑JSON鏍煎紡锛堝"Server Error"绛夛級
+                    String errorMsg = String.format("AGV鎺ュ彛杩斿洖闈濲SON鏍煎紡鍝嶅簲锛屽搷搴斿唴瀹癸細%s锛岃В鏋愰敊璇細%s", response, e.getMessage());
+                    log.error("瀹氭椂浠诲姟锛歿}鍛煎彨agv鎼繍澶辫触 - 浠诲姟ID锛歿}锛寋}", namespace, displayTaskId, errorMsg);
+                    
+                    // 鏈嶅姟鍣ㄩ敊璇椂锛屾爣璁扮珯鐐逛负涓嶅彲鐢紝娓呯┖绔欑偣鍒嗛厤锛屼笉鍐嶄负褰撳墠浠诲姟鍒嗛厤绔欑偣
+                    try {
+                        Integer siteNo = Integer.parseInt(staNo);
+                        // 鏌ヨ绔欑偣淇℃伅
+                        List<BasDevp> basDevpList = basDevpMapper.selectList(new EntityWrapper<BasDevp>().eq("dev_no", siteNo));
+                        if (basDevpList != null && !basDevpList.isEmpty()) {
+                            BasDevp basDevp = basDevpList.get(0);
+                            // 鏍囪绔欑偣涓轰笉鍙敤锛堣缃甤anining='N'锛�
+                            basDevp.setCanining("N");
+                            basDevpMapper.updateById(basDevp);
+                            log.warn("瀹氭椂浠诲姟锛氫换鍔D锛歿}锛孉GV鎺ュ彛杩斿洖鏈嶅姟鍣ㄩ敊璇紝宸叉爣璁扮珯鐐箋}涓轰笉鍙敤锛坈anining='N'锛�", 
+                                displayTaskId, siteNo);
+                            
+                            // 鍑忓皯绔欑偣鐨勫叆搴撲换鍔℃暟锛堜箣鍓嶅垎閰嶇珯鐐规椂宸茬粡澧炲姞浜唅n_qty锛�
+                            basDevpMapper.decrementInQty(siteNo);
+                            log.debug("瀹氭椂浠诲姟锛氫换鍔D锛歿}锛岀珯鐐箋}鐨刬n_qty宸插噺灏�", displayTaskId, siteNo);
+                        }
+                    } catch (Exception ex) {
+                        log.error("瀹氭椂浠诲姟锛氫换鍔D锛歿}锛屾爣璁扮珯鐐箋}涓轰笉鍙敤鏃跺彂鐢熷紓甯革細{}", displayTaskId, staNo, ex.getMessage());
+                    }
+                    
+                    // 娓呯┖褰撳墠浠诲姟鐨勭珯鐐瑰垎閰�
+                    log.warn("瀹氭椂浠诲姟锛氫换鍔D锛歿}锛孉GV鎺ュ彛杩斿洖鏈嶅姟鍣ㄩ敊璇紝娓呯┖绔欑偣鍒嗛厤锛歿}锛屼笉鍐嶄负褰撳墠浠诲姟鍒嗛厤绔欑偣", 
+                        displayTaskId, staNo);
+                    task.setStaNo(null);
+                    taskService.updateById(task);
+                    
+                    // 鏍囪浠诲姟涓哄け璐ワ紝涓嶅啀灏濊瘯鍒嗛厤
+                    task.setErrorTime(new Date());
+                    task.setErrorMemo(String.format("AGV鎺ュ彛杩斿洖鏈嶅姟鍣ㄩ敊璇紝绔欑偣宸叉爣璁颁负涓嶅彲鐢細%s", errorMsg));
+                    taskService.updateById(task);
+                    
+                    handleCallFailure(task, namespace, errorMsg, retryEnabled, maxRetryCount, currentRetryCount);
+                    // 鏈嶅姟鍣ㄩ敊璇椂锛屼笉鍐嶅皾璇曞垎閰嶏紝鐩存帴鏍囪涓哄凡澶勭悊
+                    result = true; // 杩斿洖true琛ㄧず宸插鐞嗭紙铏界劧澶辫触锛夛紝涓嶅啀灏濊瘯鍒嗛厤
+                    log.info("瀹氭椂浠诲姟锛氫换鍔D锛歿}锛孉GV鍛煎彨澶辫触锛堟湇鍔″櫒閿欒锛夛紝绔欑偣宸叉爣璁颁负涓嶅彲鐢紝浠诲姟宸叉爣璁颁负澶辫触锛屼笉鍐嶅皾璇曞垎閰�", 
+                        displayTaskId);
+                }
+                
+                // 濡傛灉JSON瑙f瀽鎴愬姛锛岀户缁鐞�
+                if (jsonObject != null) {
+                    Integer code = jsonObject.getInteger("code");
+                    if (code != null && code.equals(200)) {
+                        // 鍛煎彨鎴愬姛锛屾竻闄ら噸璇曟鏁板拰閿欒淇℃伅
+                        success = true;
+                        // 濡傛灉褰撳墠鐘舵�佷笉鏄�8锛屾洿鏂颁负8锛涘鏋滃凡缁忔槸8锛屼繚鎸佷笉鍙橈紙鍙兘鏄噸璇曟垚鍔燂級
+                        Long currentStatus = task.getWrkSts();
+                        if (currentStatus == null || currentStatus != 8L) {
+                            task.setWrkSts(8L);
+                            log.info("瀹氭椂浠诲姟锛歿}鍛煎彨agv鎼繍鎴愬姛 - 浠诲姟ID锛歿}锛岀姸鎬佷粠{}鏇存柊涓�8", namespace, displayTaskId, currentStatus);
+                        } else {
+                            log.info("瀹氭椂浠诲姟锛歿}鍛煎彨agv鎼繍鎴愬姛锛堥噸璇曪級 - 浠诲姟ID锛歿}锛岀姸鎬佷繚鎸佷负8", namespace, displayTaskId);
+                        }
+                        task.setMemo(clearRetryInfo(task.getMemo())); // 娓呴櫎閲嶈瘯淇℃伅
+                        task.setErrorTime(null);
+                        task.setErrorMemo(null);
+                        taskService.updateById(task);
+                        log.info("瀹氭椂浠诲姟锛歿}鍛煎彨agv鎼繍鎴愬姛 - 浠诲姟ID锛歿}", namespace, displayTaskId);
+                        result = true; // 杩斿洖true锛岃〃绀烘垚鍔熷鐞�
+                    } else {
+                        String message = jsonObject.getString("message");
+                        String errorMsg = String.format("閿欒鐮侊細%s锛岄敊璇俊鎭細%s", code, message);
+                        log.warn("瀹氭椂浠诲姟锛歿}鍛煎彨agv鎼繍澶辫触 - 浠诲姟ID锛歿}锛寋}", namespace, displayTaskId, errorMsg);
+                        
+                        // 妫�鏌ユ槸鍚︽槸绔欑偣鎴栧簱浣嶇浉鍏崇殑閿欒锛屽鏋滄槸锛屾竻绌虹珯鐐瑰垎閰嶏紝璁╁畾鏃朵换鍔¢噸鏂板垎閰�
+                        boolean shouldReallocateSite = false;
+                        if (message != null) {
+                            String lowerMessage = message.toLowerCase();
+                            // 搴撲綅涓嶅瓨鍦ㄣ�佺珯鐐逛笉瀛樺湪绛夐敊璇紝搴旇閲嶆柊鍒嗛厤绔欑偣
+                            if (lowerMessage.contains("搴撲綅涓嶅瓨鍦�") || 
+                                lowerMessage.contains("绔欑偣涓嶅瓨鍦�") || 
+                                lowerMessage.contains("浣嶇疆涓嶅瓨鍦�") ||
+                                lowerMessage.contains("搴撲綅鏃犳晥") ||
+                                lowerMessage.contains("绔欑偣鏃犳晥")) {
+                                shouldReallocateSite = true;
+                            }
+                        }
+                        
+                        if (shouldReallocateSite) {
+                            // 娓呯┖绔欑偣鍒嗛厤锛岃瀹氭椂浠诲姟閲嶆柊鍒嗛厤绔欑偣
+                            log.warn("瀹氭椂浠诲姟锛氫换鍔D锛歿}锛孉GV鍛煎彨澶辫触锛坽}锛夛紝娓呯┖绔欑偣鍒嗛厤锛歿}锛屼笅娆″皢閲嶆柊鍒嗛厤绔欑偣", 
+                                displayTaskId, errorMsg, staNo);
+                            task.setStaNo(null);
+                            taskService.updateById(task);
+                        }
+                        
+                        handleCallFailure(task, namespace, errorMsg, retryEnabled, maxRetryCount, currentRetryCount);
+                        
+                        // 濡傛灉杈惧埌鏈�澶ч噸璇曟鏁帮紝杩斿洖true琛ㄧず宸插鐞嗭紙铏界劧澶辫触锛�
+                        // 鍚﹀垯杩斿洖false锛岃瀹氭椂浠诲姟閲嶆柊灏濊瘯锛堝鏋滅珯鐐硅娓呯┖锛屼細閲嶆柊鍒嗛厤绔欑偣锛涘鏋滅珯鐐规湭娓呯┖锛屼細閲嶆柊鍙戦�丄GV锛�
+                        if (retryEnabled && currentRetryCount >= maxRetryCount) {
+                            result = true; // 宸茶揪鍒版渶澶ч噸璇曟鏁帮紝杩斿洖true琛ㄧず宸插鐞嗭紙铏界劧澶辫触锛�
+                            log.info("瀹氭椂浠诲姟锛氫换鍔D锛歿}锛孉GV鍛煎彨澶辫触涓斿凡杈惧埌鏈�澶ч噸璇曟鏁帮紙{}娆★級锛屾爣璁颁负宸插鐞嗭紝涓嶅啀閲嶈瘯", 
+                                displayTaskId, maxRetryCount);
+                        } else {
+                            result = false; // 杩斿洖false锛岃瀹氭椂浠诲姟閲嶆柊灏濊瘯锛堥噸鏂板垎閰嶇珯鐐规垨閲嶆柊鍙戦�丄GV锛�
+                            if (shouldReallocateSite) {
+                                log.info("瀹氭椂浠诲姟锛氫换鍔D锛歿}锛岀珯鐐瑰凡娓呯┖锛屼笅娆″皢閲嶆柊鍒嗛厤绔欑偣", displayTaskId);
+                            } else {
+                                log.info("瀹氭椂浠诲姟锛氫换鍔D锛歿}锛屼笅娆″皢閲嶆柊灏濊瘯鍙戦�丄GV鍛戒护", displayTaskId);
+                            }
+                        }
+                    }
+                }
+            }
+        } catch (Exception e) {
+            String errorMsg = "寮傚父淇℃伅锛�" + e.getMessage();
+            log.error("瀹氭椂浠诲姟锛歿}鍛煎彨agv鎼繍寮傚父 - 浠诲姟ID锛歿}锛岃姹傚湴鍧�锛歿}锛岃姹傚弬鏁帮細{}锛寋}", 
+                    namespace, displayTaskId, url, body, errorMsg, e);
+            handleCallFailure(task, namespace, errorMsg, retryEnabled, maxRetryCount, currentRetryCount);
+            // 濡傛灉杈惧埌鏈�澶ч噸璇曟鏁帮紝杩斿洖true琛ㄧず宸插鐞嗭紙铏界劧澶辫触锛�
+            // 鍚﹀垯杩斿洖false锛岃瀹氭椂浠诲姟閲嶆柊灏濊瘯
+            if (retryEnabled && currentRetryCount >= maxRetryCount) {
+                result = true; // 宸茶揪鍒版渶澶ч噸璇曟鏁帮紝杩斿洖true琛ㄧず宸插鐞嗭紙铏界劧澶辫触锛�
+                log.info("瀹氭椂浠诲姟锛氫换鍔D锛歿}锛孉GV鍛煎彨寮傚父涓斿凡杈惧埌鏈�澶ч噸璇曟鏁帮紙{}娆★級锛屾爣璁颁负宸插鐞嗭紝涓嶅啀閲嶈瘯", 
+                    displayTaskId, maxRetryCount);
+            } else {
+                result = false; // 杩斿洖false锛岃瀹氭椂浠诲姟閲嶆柊灏濊瘯
+                log.info("瀹氭椂浠诲姟锛氫换鍔D锛歿}锛屼笅娆″皢閲嶆柊灏濊瘯鍙戦�丄GV鍛戒护", displayTaskId);
+            }
+        } finally {
+            try {
+                // 淇濆瓨鎺ュ彛鏃ュ織
+                apiLogService.save(
+                        namespace + "鍛煎彨agv鎼繍",
+                        url,
+                        null,
+                        "127.0.0.1",
+                        body,
+                        response,
+                        success
+                );
+            } catch (Exception e) {
+                // log.error(namespace + "鍛煎彨agv淇濆瓨鎺ュ彛鏃ュ織寮傚父:", e);
             }
         }
+        return result;
     }
 
     /**
@@ -309,6 +566,114 @@
             // log.warn("{}鍛煎彨agv鎼繍澶辫触 - 浠诲姟ID锛歿}锛屽仠姝㈤噸璇曘�傞敊璇俊鎭細{}", 
             //         namespace, task.getId(), errorMsg);
         }
+    }
+
+    /**
+     * 妫�鏌ュ苟鑷姩缁撴潫宸插畬鎴愬伐浣滄。鐨凙GV浠诲姟
+     * 濡傛灉浠诲姟瀵瑰簲鐨勫伐浣滄。宸茬粡瀹屾垚锛堝叆搴撴垚鍔燂級锛屽垯鑷姩缁撴潫璇GV浠诲姟
+     * @param transportingTasks 姝e湪鎼繍鐨勪换鍔″垪琛�
+     * @param taskTypeName 浠诲姟绫诲瀷鍚嶇О锛堢敤浜庢棩蹇楋級
+     * @return 浠嶇劧鏈夋晥鐨勬鍦ㄦ惉杩愮殑浠诲姟鍒楄〃锛堝凡瀹屾垚鐨勫凡琚Щ闄わ級
+     */
+    private List<Task> checkAndCompleteFinishedTasks(List<Task> transportingTasks, String taskTypeName) {
+        if (transportingTasks == null || transportingTasks.isEmpty()) {
+            return transportingTasks;
+        }
+        
+        List<Task> validTasks = new ArrayList<>();
+        Date now = new Date();
+        
+        for (Task agvTask : transportingTasks) {
+            boolean isCompleted = false;
+            String reason = "";
+            
+            // 妫�鏌ュ伐浣滄。鏄惁瀛樺湪
+            WrkMast wrkMast = null;
+            if (agvTask.getWrkNo() != null) {
+                wrkMast = wrkMastService.selectOne(
+                    new EntityWrapper<WrkMast>().eq("wrk_no", agvTask.getWrkNo())
+                );
+            }
+            
+            // 妫�鏌ュ巻鍙叉。鏄惁瀛樺湪
+            WrkMastLog wrkMastLog = null;
+            if (agvTask.getWrkNo() != null) {
+                wrkMastLog = wrkMastLogService.selectOne(
+                    new EntityWrapper<WrkMastLog>().eq("wrk_no", agvTask.getWrkNo())
+                );
+            }
+            // 濡傛灉閫氳繃wrk_no娌℃壘鍒帮紝涓旀湁鏉$爜锛屽垯閫氳繃鏉$爜鏌ヨ
+            if (wrkMastLog == null && !Cools.isEmpty(agvTask.getBarcode())) {
+                List<WrkMastLog> logList = wrkMastLogService.selectList(
+                    new EntityWrapper<WrkMastLog>().eq("barcode", agvTask.getBarcode())
+                );
+                if (!logList.isEmpty()) {
+                    wrkMastLog = logList.get(0);
+                }
+            }
+            
+            // 濡傛灉宸ヤ綔妗e瓨鍦紝妫�鏌ユ槸鍚﹀凡瀹屾垚
+            if (wrkMast != null) {
+                Long wrkSts = wrkMast.getWrkSts();
+                Integer ioType = agvTask.getIoType();
+                
+                if (wrkSts != null && ioType != null) {
+                    // 鍏ュ簱浠诲姟锛氱姸鎬�4锛堝叆搴撳畬鎴愶級鎴�5锛堝簱瀛樻洿鏂板畬鎴愶級
+                    if ((ioType == 1 || ioType == 10 || ioType == 53 || ioType == 57) &&
+                        (wrkSts == 4L || wrkSts == 5L)) {
+                        isCompleted = true;
+                        reason = String.format("宸ヤ綔妗e凡瀹屾垚锛岀姸鎬侊細%d", wrkSts);
+                    }
+                    // 鍑哄簱浠诲姟锛氱姸鎬�14锛堝凡鍑哄簱鏈‘璁わ級鎴�15锛堝嚭搴撴洿鏂板畬鎴愶級
+                    else if ((ioType == 101 || ioType == 110 || ioType == 103 || ioType == 107) &&
+                             (wrkSts == 14L || wrkSts == 15L)) {
+                        isCompleted = true;
+                        reason = String.format("宸ヤ綔妗e凡瀹屾垚锛岀姸鎬侊細%d", wrkSts);
+                    }
+                }
+            }
+            
+            // 1. 濡傛灉宸ヤ綔妗h繘鍏ュ巻鍙叉。锛岀珛鍗崇粨鏉烝GV浠诲姟锛堝彧瑕佸巻鍙叉。瀛樺湪灏辩粨鏉燂級
+            if (!isCompleted && wrkMastLog != null) {
+                isCompleted = true;
+                reason = String.format("宸ヤ綔妗e凡杞巻鍙叉。锛岀珛鍗崇粨鏉烝GV浠诲姟锛屽巻鍙叉。鐘舵�侊細%d", wrkMastLog.getWrkSts());
+            }
+            
+            // 濡傛灉宸插畬鎴愶紝鏇存柊AGV浠诲姟鐘舵�佷负瀹屾垚
+            if (isCompleted) {
+                agvTask.setWrkSts(9L);
+                agvTask.setModiTime(now);
+                if (taskService.updateById(agvTask)) {
+                    // taskId浣跨敤宸ヤ綔鍙凤紙wrk_no锛夛紝濡傛灉宸ヤ綔鍙蜂负绌哄垯浣跨敤浠诲姟ID
+                    String displayTaskId = (agvTask.getWrkNo() != null) ? String.valueOf(agvTask.getWrkNo()) : String.valueOf(agvTask.getId());
+                    log.info("{}锛岃嚜鍔ㄧ粨鏉烝GV浠诲姟锛宼askId锛歿}锛寃rkNo锛歿}锛宐arcode锛歿}锛岀珯鐐癸細{}锛岄噴鏀剧珯鐐逛緵鏂颁换鍔′娇鐢�", 
+                        reason, displayTaskId, agvTask.getWrkNo(), agvTask.getBarcode(), agvTask.getStaNo());
+                    // 杞Щ鍒板巻鍙茶〃锛堜細鑷姩鍑忓皯绔欑偣鐨刬n_qty锛�
+                    try {
+                        moveTaskToHistory(Collections.singletonList(agvTask));
+                        log.info("鑷姩缁撴潫AGV浠诲姟鍚庡凡杞Щ鍒板巻鍙茶〃锛宼askId锛歿}锛岀珯鐐癸細{}宸查噴鏀�", displayTaskId, agvTask.getStaNo());
+                    } catch (Exception e) {
+                        log.error("鑷姩缁撴潫AGV浠诲姟鍚庤浆绉诲巻鍙茶〃澶辫触锛宼askId锛歿}", displayTaskId, e);
+                    }
+                } else {
+                    log.error("鑷姩缁撴潫AGV浠诲姟澶辫触锛屾洿鏂颁换鍔$姸鎬佸け璐ワ紝taskId锛歿}", 
+                        (agvTask.getWrkNo() != null) ? String.valueOf(agvTask.getWrkNo()) : String.valueOf(agvTask.getId()));
+                }
+            } else {
+                // 浠诲姟浠嶇劧鏈夋晥锛屼繚鐣欏湪鍒楄〃涓�
+                // 璁板綍浠诲姟浠嶇劧鏈夋晥鐨勫師鍥狅紙鐢ㄤ簬璋冭瘯锛�
+                String displayTaskId = (agvTask.getWrkNo() != null) ? String.valueOf(agvTask.getWrkNo()) : String.valueOf(agvTask.getId());
+                if (wrkMast == null && wrkMastLog == null) {
+                    log.debug("浠诲姟ID锛歿}锛堢珯鐐癸細{}锛変粛鐒舵湁鏁堬細宸ヤ綔妗e拰鍘嗗彶妗i兘涓嶅瓨鍦紝鍙兘宸ヤ綔妗h繕鏈垱寤�", displayTaskId, agvTask.getStaNo());
+                } else if (wrkMast != null) {
+                    log.debug("浠诲姟ID锛歿}锛堢珯鐐癸細{}锛変粛鐒舵湁鏁堬細宸ヤ綔妗g姸鎬�={}锛屼换鍔$被鍨�={}锛屾湭杈惧埌瀹屾垚鏉′欢", 
+                        displayTaskId, agvTask.getStaNo(), wrkMast.getWrkSts(), agvTask.getIoType());
+                }
+                validTasks.add(agvTask);
+            }
+        }
+        
+        return validTasks;
     }
 
     /**
@@ -382,8 +747,10 @@
      */
     private String getRequest(Task task, String nameSpace) {
         JSONObject object = new JSONObject();
-        // taskId浣跨敤浠诲姟ID锛屾牸寮忥細T + 浠诲姟ID
-        object.put("taskId", "T" + task.getId());
+        // taskId浣跨敤宸ヤ綔鍙凤紙wrk_no锛夛紝鏍煎紡锛歍 + 宸ヤ綔鍙�
+        // 濡傛灉宸ヤ綔鍙蜂负绌猴紝鍒欎娇鐢ㄤ换鍔D浣滀负澶囬��
+        String taskIdValue = (task.getWrkNo() != null) ? "T" + task.getWrkNo() : "T" + task.getId();
+        object.put("taskId", taskIdValue);
         // fromBin浣跨敤婧愬簱浣嶇紪鍙凤紙sourceLocNo锛夛紝濡傛灉涓虹┖鍒欎娇鐢ㄦ簮绔欑偣缂栧彿锛坰ourceStaNo锛変綔涓哄閫�
         String fromBin = task.getSourceLocNo();
         if (fromBin == null || fromBin.isEmpty()) {
@@ -428,10 +795,16 @@
 
     /**
      * 涓轰换鍔″垎閰嶇珯鐐癸紙瀹氭椂浠诲姟涓皟鐢級
+     * 娉ㄦ剰锛氬彧浼氬垎閰嶄竴涓珯鐐癸紝鎵惧埌绗竴涓鍚堟潯浠剁殑绔欑偣灏卞垎閰嶅苟閫�鍑�
      * @param task 浠诲姟瀵硅薄
      * @return 濡傛灉鏃犳硶鍒嗛厤绔欑偣锛岃繑鍥為敊璇俊鎭紱濡傛灉鍒嗛厤鎴愬姛锛岃繑鍥瀗ull骞舵洿鏂皌ask鐨剆taNo
      */
-    private String allocateSiteForTask(Task task) {
+    @Transactional(rollbackFor = Exception.class)
+    public String allocateSiteForTask(Task task) {
+        // taskId浣跨敤宸ヤ綔鍙凤紙wrk_no锛夛紝濡傛灉宸ヤ綔鍙蜂负绌哄垯浣跨敤浠诲姟ID
+        String displayTaskId = (task.getWrkNo() != null) ? String.valueOf(task.getWrkNo()) : String.valueOf(task.getId());
+        log.debug("寮�濮嬩负浠诲姟ID锛歿}鍒嗛厤绔欑偣锛屼换鍔$被鍨嬶細{}锛屾満鍣ㄤ汉缁勶細{}", 
+            displayTaskId, task.getIoType(), task.getInvWh());
         // 鏍规嵁浠诲姟鐨刬nvWh锛堟満鍣ㄤ汉缁勶級鍒ゆ柇鏄笢渚ц繕鏄タ渚�
         String robotGroup = task.getInvWh();
         List<String> targetStations;
@@ -449,12 +822,12 @@
             // 榛樿浣跨敤涓滀晶
             targetStations = agvProperties.getEastStations();
             groupKey = "east";
-            // log.warn("浠诲姟ID锛歿}鐨勬満鍣ㄤ汉缁剓}鏈瘑鍒紝浣跨敤榛樿涓滀晶绔欑偣", task.getId(), robotGroup);
+            log.warn("浠诲姟ID锛歿}鐨勬満鍣ㄤ汉缁剓}鏈瘑鍒紝浣跨敤榛樿涓滀晶绔欑偣", displayTaskId, robotGroup);
         }
         
         if (targetStations.isEmpty()) {
             String errorMsg = "娌℃湁鍙敤鐨勭洰鏍囩珯鐐归厤缃�";
-            // log.warn("浠诲姟ID锛歿}", errorMsg, task.getId());
+            log.warn("浠诲姟ID锛歿}锛寋}", displayTaskId, errorMsg);
             return errorMsg;
         }
         
@@ -463,20 +836,46 @@
                 .map(Integer::parseInt)
                 .collect(Collectors.toList());
         
+        log.info("浠诲姟ID锛歿}锛寋}绔欑偣缁勯厤缃殑绔欑偣锛歿}锛屽叡{}涓珯鐐�", 
+            displayTaskId, groupKey.equals("east") ? agvProperties.getEastDisplayName() : agvProperties.getWestDisplayName(),
+            targetStations, targetStations.size());
+        
         // 鍒ゆ柇鑳藉叆绔欑偣锛坕n_enable="Y"琛ㄧず鑳藉叆锛夛紝鎺掗櫎dev_no=0鐨勬棤鏁堢珯鐐�
-        List<Integer> sites = basDevpMapper.selectList(
+        List<BasDevp> allDevList = basDevpMapper.selectList(
                 new EntityWrapper<BasDevp>()
-                        .eq("in_enable", "Y")
                         .in("dev_no", siteIntList)
                         .ne("dev_no", 0) // 鎺掗櫎dev_no=0鐨勬棤鏁堢珯鐐�
-        ).stream()
+        );
+        // 璁板綍鎵�鏈夌珯鐐圭殑鐘舵�佷俊鎭�
+        StringBuilder siteStatusInfo = new StringBuilder();
+        for (BasDevp dev : allDevList) {
+            if (siteStatusInfo.length() > 0) {
+                siteStatusInfo.append("; ");
+            }
+            siteStatusInfo.append("绔欑偣").append(dev.getDevNo())
+                    .append("(in_enable=").append(dev.getInEnable())
+                    .append(",canining=").append(dev.getCanining()).append(")");
+        }
+        log.info("浠诲姟ID锛歿}锛屽�欓�夌珯鐐圭姸鎬侊細{}", displayTaskId, siteStatusInfo.toString());
+        
+        List<Integer> sites = allDevList.stream()
+                .filter(dev -> "Y".equals(dev.getInEnable()))
                 .map(BasDevp::getDevNo)
                 .filter(devNo -> devNo != null && devNo != 0) // 鍐嶆杩囨护锛岀‘淇濅笉涓簄ull鎴�0
                 .collect(Collectors.toList());
         
+        // 妫�鏌ユ槸鍚︽湁绔欑偣涓嶅彲鐢紝濡傛灉鏈夛紝璇存槑闇�瑕佸湪鍙敤鐨勭珯鐐逛箣闂村钩鍧囧垎閰�
+        List<Integer> unavailableSites = new ArrayList<>(siteIntList);
+        unavailableSites.removeAll(sites);
+        if (!unavailableSites.isEmpty()) {
+            log.info("浠诲姟ID锛歿}锛寋}绔欑偣缁勪腑鏈墈}涓珯鐐逛笉鍙敤锛坕n_enable!='Y'锛夛細{}锛屽皢鍦▄}涓彲鐢ㄧ珯鐐逛箣闂村钩鍧囧垎閰�", 
+                displayTaskId, groupKey.equals("east") ? agvProperties.getEastDisplayName() : agvProperties.getWestDisplayName(),
+                unavailableSites.size(), unavailableSites, sites.size());
+        }
+        
         if (sites.isEmpty()) {
-            String errorMsg = "娌℃湁鑳藉叆绔欑偣";
-            // log.warn("浠诲姟ID锛歿}", errorMsg, task.getId());
+            String errorMsg = "娌℃湁鑳藉叆绔欑偣锛坕n_enable='Y'锛�";
+            log.warn("浠诲姟ID锛歿}锛寋}锛屽�欓�夌珯鐐瑰垪琛細{}锛岀珯鐐圭姸鎬侊細{}", displayTaskId, errorMsg, targetStations, siteStatusInfo.toString());
             return errorMsg;
         }
         
@@ -486,13 +885,27 @@
                 .eq("in_enable", "Y")
                 .eq("canining", "Y")
                 .ne("dev_no", 0) // 鎺掗櫎dev_no=0鐨勬棤鏁堢珯鐐�
-        ).stream()
-                .filter(dev -> dev.getDevNo() != null && dev.getDevNo() != 0) // 鍐嶆杩囨护锛岀‘淇濅笉涓簄ull鎴�0
-                .collect(Collectors.toList());
+        );
         
         if (devListWithConfig.isEmpty()) {
             // 绔欑偣閰嶇疆涓嶅厑璁稿叆搴擄紙canining != "Y"锛夛紝鏆備笉鍒嗛厤锛岀瓑寰呴厤缃紑閫氾紙鍙湪瀹氭椂浠诲姟涓褰曟棩蹇楋級
-            // log.warn("浠诲姟ID锛歿}娌℃湁鍙叆绔欑偣锛堢珯鐐规湭寮�閫氬彲鍏ュ厑璁革細canining='Y'锛夛紝鏆備笉鍒嗛厤绔欑偣锛岀瓑寰呴厤缃紑閫�", task.getId());
+            // 璁板綍姣忎釜绔欑偣鐨刢anining鐘舵��
+            StringBuilder caniningStatusInfo = new StringBuilder();
+            for (Integer siteNo : sites) {
+                BasDevp dev = allDevList.stream()
+                        .filter(d -> d.getDevNo().equals(siteNo))
+                        .findFirst()
+                        .orElse(null);
+                if (dev != null) {
+                    if (caniningStatusInfo.length() > 0) {
+                        caniningStatusInfo.append("; ");
+                    }
+                    caniningStatusInfo.append("绔欑偣").append(siteNo)
+                            .append("(canining=").append(dev.getCanining()).append(")");
+                }
+            }
+            log.warn("浠诲姟ID锛歿}娌℃湁鍙叆绔欑偣锛堢珯鐐规湭寮�閫氬彲鍏ュ厑璁革細canining='Y'锛夛紝鏆備笉鍒嗛厤绔欑偣锛岀瓑寰呴厤缃紑閫氥�傝兘鍏ョ珯鐐瑰垪琛細{}锛宑anining鐘舵�侊細{}", 
+                    displayTaskId, sites, caniningStatusInfo.toString());
             return null; // 杩斿洖null锛岃〃绀烘殏涓嶅垎閰嶏紝绛夊緟閰嶇疆寮�閫�
         }
         
@@ -500,12 +913,14 @@
         List<Integer> configuredSites = devListWithConfig.stream()
                 .map(BasDevp::getDevNo)
                 .collect(Collectors.toList());
+        log.info("浠诲姟ID锛歿}锛屽凡閰嶇疆鍙叆绔欑偣鍒楄〃锛歿}", displayTaskId, configuredSites);
         List<Integer> canInSites = basDevpMapper.getCanInSites(configuredSites);
         if (canInSites.isEmpty()) {
             // 鎵�鏈夊凡閰嶇疆鍙叆鐨勭珯鐐归兘鏈夊嚭搴撲换鍔★紝鏆備笉鍒嗛厤锛岀瓑寰呬笅娆″畾鏃朵换鍔″啀灏濊瘯锛堝彧鍦ㄥ畾鏃朵换鍔′腑璁板綍鏃ュ織锛�
-            // log.warn("浠诲姟ID锛歿}娌℃湁鍙叆绔欑偣锛堣绛夊緟鍑哄簱瀹屾垚锛夛紝鏆備笉鍒嗛厤绔欑偣锛岀瓑寰呬笅娆″畾鏃朵换鍔″啀灏濊瘯", task.getId());
+            log.warn("浠诲姟ID锛歿}娌℃湁鍙叆绔欑偣锛堣绛夊緟鍑哄簱瀹屾垚锛夛紝鏆備笉鍒嗛厤绔欑偣锛岀瓑寰呬笅娆″畾鏃朵换鍔″啀灏濊瘯銆傚凡閰嶇疆鍙叆绔欑偣鍒楄〃锛歿}", displayTaskId, configuredSites);
             return null; // 杩斿洖null锛岃〃绀烘殏涓嶅垎閰嶏紝绛夊緟涓嬫瀹氭椂浠诲姟鍐嶅皾璇�
         }
+        log.info("浠诲姟ID锛歿}锛屾病鏈夊嚭搴撲换鍔$殑绔欑偣鍒楄〃锛歿}", displayTaskId, canInSites);
         
         // 瀵绘壘鍏ュ簱浠诲姟鏈�灏戠殑绔欑偣锛堜笖蹇呴』in_enable="Y"鑳藉叆 鍜� canining="Y"鍙叆锛夛紝鎺掗櫎dev_no=0鐨勬棤鏁堢珯鐐�
         List<BasDevp> devList = basDevpMapper.selectList(new EntityWrapper<BasDevp>()
@@ -520,9 +935,20 @@
         if (devList.isEmpty()) {
             // 鐞嗚涓婁笉搴旇鍒拌繖閲岋紝鍥犱负鍓嶉潰宸茬粡妫�鏌ヨ繃浜嗭紝浣嗕负浜嗗畨鍏ㄨ捣瑙佽繕鏄繚鐣�
             String errorMsg = "娌℃湁鍙叆绔欑偣锛坕n_enable='Y'涓攃anining='Y'锛�";
-            // log.warn("浠诲姟ID锛歿}", errorMsg, task.getId());
+            log.warn("浠诲姟ID锛歿}锛寋}锛屽彲鍏ョ珯鐐瑰垪琛細{}", displayTaskId, errorMsg, canInSites);
             return errorMsg;
         }
+        
+        // 璁板綍姣忎釜绔欑偣鐨勫叆搴撲换鍔℃暟
+        StringBuilder siteInQtyInfo = new StringBuilder();
+        for (BasDevp dev : devList) {
+            if (siteInQtyInfo.length() > 0) {
+                siteInQtyInfo.append("; ");
+            }
+            siteInQtyInfo.append("绔欑偣").append(dev.getDevNo())
+                    .append("(鍏ュ簱浠诲姟鏁�=").append(dev.getInQty()).append(")");
+        }
+        log.info("浠诲姟ID锛歿}锛屽彲鍏ョ珯鐐瑰強鍏跺叆搴撲换鍔℃暟锛歿}", displayTaskId, siteInQtyInfo.toString());
         
         // 鍏堟寜瑙勫垯鎺掑簭锛堝叆搴撲换鍔℃暟鎺掑簭锛�
         devList.sort(Comparator.comparing(BasDevp::getInQty));
@@ -543,98 +969,123 @@
             }
         }
         
-        // 绛涢�夊嚭浠诲姟鏁版渶灏戠殑绔欑偣鍒楄〃锛堟寜瑙勫垯鎺掑簭鍚庣殑鍊欓�夌珯鐐癸級
-        int minInQty = devList.get(0).getInQty();
-        List<BasDevp> minTaskSites = devList.stream()
-                .filter(dev -> dev.getInQty() == minInQty)
+        // 鍏堟煡璇gv宸ヤ綔妗d腑鏈鍒嗛厤绔欑偣鐨勭珯鐐�
+        // 鏌ヨagv宸ヤ綔妗d腑鎵�鏈夊凡鍒嗛厤绔欑偣鐨勪换鍔★紙sta_no涓嶄负绌恒�佷笉涓虹┖瀛楃涓层�佷笉涓�0锛�
+        final List<String> allocatedSiteNos;
+        if (checkIoTypes != null && !checkIoTypes.isEmpty()) {
+            List<Task> allocatedTasks = taskService.selectList(
+                new EntityWrapper<Task>()
+                    .eq("task_type", "agv")
+                    .in("wrk_sts", 7L, 8L) // 寰呭懠鍙獳GV鍜屾鍦ㄦ惉杩愮殑浠诲姟
+                    .in("io_type", checkIoTypes)
+                    .isNotNull("sta_no")
+                    .ne("sta_no", "")
+                    .ne("sta_no", "0")
+                    .andNew("(is_deleted = 0)")
+            );
+            // 鑾峰彇宸插垎閰嶇殑绔欑偣缂栧彿鍒楄〃
+            allocatedSiteNos = allocatedTasks.stream()
+                    .map(Task::getStaNo)
+                    .filter(staNo -> staNo != null && !staNo.isEmpty() && !staNo.equals("0"))
+                    .distinct()
+                    .collect(Collectors.toList());
+        } else {
+            allocatedSiteNos = new ArrayList<>();
+        }
+        
+        // 浠庡彲鐢ㄧ珯鐐逛腑绛涢�夊嚭鏈鍒嗛厤鐨勭珯鐐�
+        List<BasDevp> unallocatedSites = devList.stream()
+                .filter(dev -> {
+                    String staNo = String.valueOf(dev.getDevNo());
+                    return !allocatedSiteNos.contains(staNo);
+                })
                 .collect(Collectors.toList());
+        
+        // 鍙娇鐢ㄦ湭鍒嗛厤绔欑偣
+        if (unallocatedSites.isEmpty()) {
+            // 鏈垎閰嶇珯鐐逛负绌猴細涓嶅垎閰嶇珯鐐�
+            StringBuilder allocatedSitesInfo = new StringBuilder();
+            for (String staNo : allocatedSiteNos) {
+                if (allocatedSitesInfo.length() > 0) {
+                    allocatedSitesInfo.append("; ");
+                }
+                allocatedSitesInfo.append("绔欑偣").append(staNo).append("宸茶鍒嗛厤");
+            }
+            log.warn("浠诲姟ID锛歿}锛屾墍鏈夊彲鐢ㄧ珯鐐归兘宸茶鍒嗛厤锛屾殏涓嶅垎閰嶇珯鐐癸紝绛夊緟涓嬫瀹氭椂浠诲姟鍐嶅皾璇曘�傚凡鍒嗛厤绔欑偣锛歿}", 
+                displayTaskId, allocatedSitesInfo.length() > 0 ? allocatedSitesInfo.toString() : "鏃犺缁嗕俊鎭�");
+            return null; // 杩斿洖null锛岃〃绀烘殏涓嶅垎閰嶏紝绛夊緟涓嬫瀹氭椂浠诲姟鍐嶅皾璇�
+        }
+        
+        // 瀛樺湪鏈垎閰嶇珯鐐癸細鏍规嵁閰嶇疆鐨勫垎閰嶇瓥鐣ラ�夋嫨鍏蜂綋绔欑偣
+        // 鍏堟寜瑙勫垯鎺掑簭锛堝叆搴撲换鍔℃暟鎺掑簭锛�
+        unallocatedSites.sort(Comparator.comparing(BasDevp::getInQty));
         
         // 鏍规嵁閰嶇疆閫夋嫨鍒嗛厤绛栫暐锛岀‘瀹氫紭鍏堝垎閰嶇殑绔欑偣椤哄簭
         List<BasDevp> orderedSites = new ArrayList<>();
         String strategy = agvProperties.getSiteAllocation().getStrategy();
         boolean enableRoundRobin = agvProperties.getSiteAllocation().isEnableRoundRobin();
         
-        if (minTaskSites.size() > 1 && enableRoundRobin && "round-robin".equals(strategy)) {
+        // 璁板綍鏄惁浣跨敤杞绛栫暐锛屼互鍙婅疆璇㈣鏁板櫒锛堢敤浜庡湪鎴愬姛鍒嗛厤绔欑偣鍚庨�掑锛�
+        AtomicInteger roundRobinCounter = null;
+        int roundRobinStartIndex = 0;
+        if (unallocatedSites.size() > 1 && enableRoundRobin && "round-robin".equals(strategy)) {
             // 杞鍒嗛厤锛氬厛鎸夎疆璇㈢瓥鐣ユ帓搴�
-            AtomicInteger counter = siteRoundRobinCounters.computeIfAbsent(groupKey, k -> new AtomicInteger(0));
-            int startIndex = counter.get() % minTaskSites.size();
+            roundRobinCounter = siteRoundRobinCounters.computeIfAbsent(groupKey, k -> new AtomicInteger(0));
+            roundRobinStartIndex = roundRobinCounter.get() % unallocatedSites.size(); // 鑾峰彇褰撳墠绱㈠紩锛屼絾涓嶉�掑锛堟垚鍔熷垎閰嶅悗鍐嶉�掑锛�
             // 灏嗚疆璇㈤�変腑鐨勭珯鐐规斁鍦ㄦ渶鍓嶉潰
-            orderedSites.addAll(minTaskSites.subList(startIndex, minTaskSites.size()));
-            orderedSites.addAll(minTaskSites.subList(0, startIndex));
-            // 娣诲姞鍏朵粬绔欑偣锛堜换鍔℃暟鏇村鐨勶級
-            orderedSites.addAll(devList.stream()
-                    .filter(dev -> dev.getInQty() > minInQty)
-                    .collect(Collectors.toList()));
-            log.debug("浣跨敤杞鍒嗛厤绛栫暐锛岀珯鐐圭粍锛歿}锛岃疆璇㈣捣濮嬬储寮曪細{}", groupKey, startIndex);
-        } else if (minTaskSites.size() > 1 && enableRoundRobin && "random".equals(strategy)) {
-            // 闅忔満鍒嗛厤锛氬厛闅忔満鎺掑簭浠诲姟鏁版渶灏戠殑绔欑偣
-            List<BasDevp> shuffledMinSites = new ArrayList<>(minTaskSites);
-            Collections.shuffle(shuffledMinSites);
-            orderedSites.addAll(shuffledMinSites);
-            // 娣诲姞鍏朵粬绔欑偣锛堜换鍔℃暟鏇村鐨勶級
-            orderedSites.addAll(devList.stream()
-                    .filter(dev -> dev.getInQty() > minInQty)
-                    .collect(Collectors.toList()));
-            log.debug("浣跨敤闅忔満鍒嗛厤绛栫暐");
+            orderedSites.addAll(unallocatedSites.subList(roundRobinStartIndex, unallocatedSites.size()));
+            orderedSites.addAll(unallocatedSites.subList(0, roundRobinStartIndex));
+            log.info("浠诲姟ID锛歿}锛屼娇鐢ㄨ疆璇㈠垎閰嶇瓥鐣ワ紝绔欑偣缁勶細{}锛岃疆璇㈣捣濮嬬储寮曪細{}锛屽�欓�夌珯鐐癸細{}锛堝叡{}涓湭鍒嗛厤绔欑偣锛�", 
+                displayTaskId, groupKey, roundRobinStartIndex, 
+                unallocatedSites.stream().map(d -> String.valueOf(d.getDevNo())).collect(Collectors.joining(",")), 
+                unallocatedSites.size());
+        } else if (unallocatedSites.size() > 1 && enableRoundRobin && "random".equals(strategy)) {
+            // 闅忔満鍒嗛厤锛氬厛闅忔満鎺掑簭鏈垎閰嶇珯鐐�
+            List<BasDevp> shuffledSites = new ArrayList<>(unallocatedSites);
+            Collections.shuffle(shuffledSites);
+            orderedSites.addAll(shuffledSites);
+            log.info("浠诲姟ID锛歿}锛屼娇鐢ㄩ殢鏈哄垎閰嶇瓥鐣ワ紝鍊欓�夌珯鐐癸細{}", 
+                displayTaskId, unallocatedSites.stream().map(d -> String.valueOf(d.getDevNo())).collect(Collectors.joining(",")));
         } else {
             // 榛樿锛氭寜鍏ュ簱浠诲姟鏁版帓搴忥紙宸茬粡鎺掑簭濂戒簡锛�
-            orderedSites = devList;
+            orderedSites = unallocatedSites;
         }
         
-        // 渚濇妫�鏌ユ瘡涓珯鐐规槸鍚﹀湪鎼繍锛屾壘鍒扮涓�涓┖闂茬珯鐐瑰氨鍒嗛厤
-        BasDevp selectedSite = null;
-        for (BasDevp dev : orderedSites) {
-            String staNo = String.valueOf(dev.getDevNo());
-            
-            // 濡傛灉浠诲姟绫诲瀷涓嶄负绌猴紝妫�鏌ヨ绔欑偣鏄惁鏈夋鍦ㄦ惉杩愮殑鍚岀被鍨嬩换鍔�
-            boolean isTransporting = false;
-            if (checkIoTypes != null && !checkIoTypes.isEmpty()) {
-                List<Task> transportingTasks = taskService.selectList(
-                    new EntityWrapper<Task>()
-                        .eq("sta_no", staNo)
-                        .eq("task_type", "agv")
-                        .eq("wrk_sts", 8L) // 鍙鏌ユ鍦ㄦ惉杩愮姸鎬佺殑浠诲姟
-                        .in("io_type", checkIoTypes)
-                );
-                isTransporting = !transportingTasks.isEmpty();
-                
-                if (isTransporting) {
-                    // log.debug("绔欑偣{}鏈墈}涓鍦ㄦ惉杩愮殑{}AGV浠诲姟锛屾鏌ヤ笅涓�涓珯鐐�", 
-                    //     staNo, transportingTasks.size(), taskTypeName);
-                    continue; // 璇ョ珯鐐规鍦ㄦ惉杩愶紝妫�鏌ヤ笅涓�涓珯鐐�
-                }
-            }
-            
-            // 鎵惧埌绗竴涓┖闂茬珯鐐癸紝鍒嗛厤
-            selectedSite = dev;
-            // log.info("浠诲姟ID锛歿}鎸夎鍒欏簲鍒嗛厤鍒扮珯鐐箋}锛岃绔欑偣绌洪棽锛屽垎閰嶆垚鍔�", task.getId(), staNo);
-            break;
-        }
-        
-        // 濡傛灉鎵�鏈夌珯鐐归兘鍦ㄦ惉杩愶紝鍒欎笉鍒嗛厤绔欑偣锛堝彧鍦ㄥ畾鏃朵换鍔′腑璁板綍鏃ュ織锛屼笉杩斿洖閿欒淇℃伅锛�
-        if (selectedSite == null) {
-//            log.warn("浠诲姟ID锛歿}锛屾殏涓嶅垎閰嶇珯鐐癸紝绛夊緟绌洪棽 - 鎵�鏈夊�欓�夌珯鐐归兘鏈夋鍦ㄦ惉杩愮殑{}浠诲姟",
-//                task.getId(), taskIoType != null && taskIoType < 100 ? "鍏ュ簱" : "鍑哄簱");
-            return null; // 杩斿洖null锛岃〃绀烘殏涓嶅垎閰嶏紝绛夊緟涓嬫瀹氭椂浠诲姟鍐嶅皾璇�
-        }
-        
+        // 鏃㈢劧宸茬粡绛涢�夊嚭浜嗘湭鍒嗛厤绔欑偣锛岀洿鎺ユ牴鎹垎閰嶇瓥鐣ラ�夋嫨绗竴涓珯鐐瑰嵆鍙�
+        // 鏈垎閰嶇珯鐐瑰湪AGV宸ヤ綔妗d腑閮芥病鏈夊凡鍒嗛厤鐨勪换鍔★紝鍙互鐩存帴鍒嗛厤
+        BasDevp selectedSite = orderedSites.get(0);
         Integer endSite = selectedSite.getDevNo();
+        String staNo = String.valueOf(endSite);
+        
+        log.info("浠诲姟ID锛歿}锛屼粠{}涓湭鍒嗛厤绔欑偣涓�夋嫨绔欑偣{}锛堝叆搴撲换鍔℃暟锛歿}锛夛紝鍊欓�夌珯鐐癸細{}", 
+            displayTaskId, orderedSites.size(), staNo, selectedSite.getInQty(),
+            orderedSites.stream().map(d -> String.valueOf(d.getDevNo())).collect(Collectors.joining(",")));
+        
+        // 濡傛灉浣跨敤杞绛栫暐涓旀垚鍔熷垎閰嶇珯鐐癸紝閫掑杞璁℃暟鍣紙纭繚涓嬫浠庝笅涓�涓珯鐐瑰紑濮嬶級
+        if (roundRobinCounter != null && unallocatedSites.size() > 1) {
+            roundRobinCounter.getAndIncrement();
+            log.debug("浠诲姟ID锛歿}鎴愬姛鍒嗛厤鍒扮珯鐐箋}锛岃疆璇㈣鏁板櫒宸查�掑锛屼笅娆″皢浠庝笅涓�涓珯鐐瑰紑濮嬭疆璇�", displayTaskId, staNo);
+        }
         
         // 妫�鏌ョ珯鐐规槸鍚︽湁鏁堬紙涓嶈兘涓�0鎴杗ull锛�
         if (endSite == null || endSite == 0) {
             String errorMsg = String.format("鍒嗛厤鐨勭珯鐐规棤鏁堬紙dev_no=%s锛�", endSite);
-            // log.error("浠诲姟ID锛歿}锛寋}", task.getId(), errorMsg);
+            log.error("浠诲姟ID锛歿}锛寋}", displayTaskId, errorMsg);
             return errorMsg;
         }
         
         // 鍏ュ簱鏆傚瓨+1
         basDevpMapper.incrementInQty(endSite);
         
-        // 鏇存柊浠诲姟鐨勭珯鐐圭紪鍙�
+        // 鏇存柊浠诲姟鐨勭珯鐐圭紪鍙凤紝骞剁‘淇濈姸鎬佷负7锛堝緟鍛煎彨AGV锛�
         task.setStaNo(String.valueOf(endSite));
+        if (task.getWrkSts() == null || task.getWrkSts() != 7L) {
+            task.setWrkSts(7L); // 纭繚鐘舵�佷负7锛堝緟鍛煎彨AGV锛�
+            log.debug("浠诲姟ID锛歿}鍒嗛厤绔欑偣鏃讹紝鐘舵�佷笉鏄�7锛屽凡鏇存柊涓�7锛堝緟鍛煎彨AGV锛�", displayTaskId);
+        }
         taskService.updateById(task);
         
-        // log.info("浠诲姟ID锛歿}宸插垎閰嶇珯鐐癸細{}", task.getId(), endSite);
+        log.info("浠诲姟ID锛歿}宸插垎閰嶇珯鐐癸細{}锛屾満鍣ㄤ汉缁勶細{}锛屼换鍔$被鍨嬶細{}", displayTaskId, endSite, robotGroup, taskTypeName);
         return null; // 鍒嗛厤鎴愬姛锛岃繑鍥瀗ull
     }
 
@@ -643,7 +1094,7 @@
      * @param staNo 绔欑偣缂栧彿
      * @return 鏈哄櫒浜虹粍鍚嶇О
      */
-    private String determineRobotGroupByStation(String staNo) {
+        private String determineRobotGroupByStation(String staNo) {
         if (staNo == null || staNo.isEmpty()) {
             return agvProperties.getRobotGroupEast(); // 榛樿浣跨敤涓滀晶鏈哄櫒浜虹粍
         }
@@ -684,6 +1135,8 @@
         // 鎵归噺鏇存柊鏆傚瓨鐐圭姸鎬�
         List<String> locOList = new ArrayList<>();
         List<String> locFList = new ArrayList<>();
+        // 鏀堕泦闇�瑕佸噺灏慽n_qty鐨勭珯鐐癸紙鍏ュ簱浠诲姟锛�
+        Set<Integer> sitesToDecrement = new HashSet<>();
         for (Task task : taskList) {
             String sourceStaNo = task.getSourceStaNo();
             String staNo = task.getStaNo();
@@ -691,9 +1144,30 @@
                 locOList.add(sourceStaNo);
                 locFList.add(staNo);
             } else if (task.getIoType() < 100) {
+                // 鍏ュ簱浠诲姟锛氬噺灏戠洰鏍囩珯鐐圭殑in_qty
                 locOList.add(sourceStaNo);
+                if (staNo != null && !staNo.isEmpty()) {
+                    try {
+                        Integer siteNo = Integer.parseInt(staNo);
+                        if (siteNo != null && siteNo > 0) {
+                            sitesToDecrement.add(siteNo);
+                        }
+                    } catch (NumberFormatException e) {
+                        log.warn("浠诲姟ID锛歿}鐨勭珯鐐圭紪鍙锋牸寮忛敊璇細{}锛岃烦杩囧噺灏慽n_qty", task.getId(), staNo);
+                    }
+                }
             } else {
                 locFList.add(staNo);
+            }
+        }
+
+        // 鍑忓皯绔欑偣鐨勫叆搴撲换鍔℃暟锛坕n_qty锛�
+        for (Integer siteNo : sitesToDecrement) {
+            try {
+                basDevpMapper.decrementInQty(siteNo);
+                log.debug("浠诲姟杞Щ鍒板巻鍙茶〃锛岀珯鐐箋}鐨刬n_qty宸插噺灏�", siteNo);
+            } catch (Exception e) {
+                log.error("浠诲姟杞Щ鍒板巻鍙茶〃锛屽噺灏戠珯鐐箋}鐨刬n_qty澶辫触", siteNo, e);
             }
         }
 
@@ -778,7 +1252,10 @@
 
         // 鏋勯�犲彇娑堜换鍔¤姹�
         JSONObject cancelRequest = new JSONObject();
-        cancelRequest.put("taskId", "T" + task.getId());
+        // taskId浣跨敤宸ヤ綔鍙凤紙wrk_no锛夛紝鏍煎紡锛歍 + 宸ヤ綔鍙�
+        // 濡傛灉宸ヤ綔鍙蜂负绌猴紝鍒欎娇鐢ㄤ换鍔D浣滀负澶囬��
+        String taskIdValue = (task.getWrkNo() != null) ? "T" + task.getWrkNo() : "T" + task.getId();
+        cancelRequest.put("taskId", taskIdValue);
         cancelRequest.put("kind", kind);
         String body = cancelRequest.toJSONString();
 
@@ -793,7 +1270,9 @@
             JSONObject jsonObject = JSON.parseObject(response);
             if (jsonObject.getInteger("code") != null && jsonObject.getInteger("code").equals(200)) {
                 success = true;
-                log.info(namespace + "鍙栨秷AGV浠诲姟鎴愬姛锛歿}", task.getId());
+                // taskId浣跨敤宸ヤ綔鍙凤紙wrk_no锛夛紝濡傛灉宸ヤ綔鍙蜂负绌哄垯浣跨敤浠诲姟ID
+                String displayTaskId = (task.getWrkNo() != null) ? String.valueOf(task.getWrkNo()) : String.valueOf(task.getId());
+                log.info(namespace + "鍙栨秷AGV浠诲姟鎴愬姛锛歿}", displayTaskId);
             } else {
                 log.error(namespace + "鍙栨秷AGV浠诲姟澶辫触锛侊紒锛乽rl锛歿}锛況equest锛歿}锛況esponse锛歿}", url, body, response);
             }

--
Gitblit v1.9.1