From 2816415f539ef54839e331657edae7055c243ad8 Mon Sep 17 00:00:00 2001
From: chen.llin <1442464845@qq.comm>
Date: 星期六, 17 一月 2026 19:27:45 +0800
Subject: [PATCH] agv缓存库位清空和标记功能

---
 src/main/java/com/zy/asrs/task/handler/WorkMastHandler.java |  526 +++++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 460 insertions(+), 66 deletions(-)

diff --git a/src/main/java/com/zy/asrs/task/handler/WorkMastHandler.java b/src/main/java/com/zy/asrs/task/handler/WorkMastHandler.java
index bd754ab..399614d 100644
--- a/src/main/java/com/zy/asrs/task/handler/WorkMastHandler.java
+++ b/src/main/java/com/zy/asrs/task/handler/WorkMastHandler.java
@@ -5,6 +5,7 @@
 import com.core.exception.CoolException;
 import com.zy.asrs.entity.*;
 import com.zy.asrs.enums.LocStsType;
+import com.zy.asrs.mapper.BasDevpMapper;
 import com.zy.asrs.service.*;
 import com.zy.asrs.service.impl.BasStationServiceImpl;
 import com.zy.asrs.task.AbstractHandler;
@@ -19,11 +20,9 @@
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.interceptor.TransactionAspectSupport;
 
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
 
 /**
@@ -69,6 +68,18 @@
     
     @Autowired
     private AgvProperties agvProperties;
+    
+    @Autowired
+    private WrkMastLogService wrkMastLogService;
+    
+    @Autowired
+    private BasDevpMapper basDevpMapper;
+    
+    /**
+     * 绔欑偣杞璁℃暟鍣紝鐢ㄤ簬骞冲潎鍒嗛厤绔欑偣
+     * Key: 绔欑偣缁勬爣璇嗭紙濡� "east" 鎴� "west"锛夛紝Value: 褰撳墠杞绱㈠紩
+     */
+    private final Map<String, AtomicInteger> siteRoundRobinCounters = new ConcurrentHashMap<>();
 
     public ReturnT<String> start(WrkMast wrkMast) {
         // 4.鍏ュ簱瀹屾垚
@@ -727,20 +738,6 @@
         
         log.info("鍑哄簱浠诲姟瀹屾垚锛岀敓鎴恵}浠诲姟锛屼换鍔D锛歿}锛屾墭鐩樼爜锛歿}", isEmptyPallet ? "绌烘墭鍑哄簱" : "婊℃墭鍑哄簱", outTask.getId(), outTask.getBarcode());
         
-        // 鍒嗛厤缂撳瓨搴撲綅锛坵hs_type=2锛�
-        LocCache cacheLoc = locCacheService.selectOne(new EntityWrapper<LocCache>()
-                .eq("whs_type", agvProperties.getWhsTypeMapping().getCacheArea()) // whs_type=2 缂撳瓨鍖�
-                .eq("frozen", 0)
-                .eq("loc_sts", LocStsType.LOC_STS_TYPE_O.type) // O.闂茬疆
-                .ne("full_plt", isEmptyPallet ? "Y" : "N") // 绌烘墭涓嶉�夋弧鏉垮簱浣嶏紝婊℃墭涓嶉�夌┖鏉垮簱浣�
-                .orderAsc(Arrays.asList("row1", "bay1", "lev1"))
-                .last("OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY"));
-        
-        if (cacheLoc == null) {
-            log.warn("娌℃湁鍙敤鐨勭紦瀛樺簱浣嶏紝鏃犳硶鐢熸垚{}浠诲姟锛屼换鍔D锛歿}", isEmptyPallet ? "绌烘墭鍑哄簱" : "婊℃墭鍑哄簱", outTask.getId());
-            return;
-        }
-        
         // 鑾峰彇鍑哄簱绔欑偣锛堝嚭搴撲换鍔$殑staNo鏄嚭搴撶珯鐐癸紝灏嗕綔涓虹┖鎵�/婊℃墭鍑哄簱浠诲姟鐨勬簮绔欑偣锛�
         String outboundStaNo = outTask.getStaNo();
         if (outboundStaNo == null || outboundStaNo.isEmpty()) {
@@ -748,17 +745,112 @@
             return;
         }
         
-        // 鏍规嵁缂撳瓨鍖洪厤缃�夋嫨绔欑偣鍜屾満鍣ㄤ汉缁勶紙瑗夸晶锛�
-        List<String> cacheStations = agvProperties.getWestStations();
-        String robotGroup = agvProperties.getRobotGroupWest();
+        // 鏍规嵁鍑哄簱绔欑偣鍒ゆ柇鏄笢渚ц繕鏄タ渚�
+        Set<String> eastStations = new HashSet<>(agvProperties.getEastStations());
+        Set<String> westStations = new HashSet<>(agvProperties.getWestStations());
         
-        if (cacheStations.isEmpty()) {
-            log.warn("缂撳瓨鍖烘病鏈夐厤缃珯鐐癸紝鏃犳硶鐢熸垚{}浠诲姟锛屼换鍔D锛歿}", isEmptyPallet ? "绌烘墭鍑哄簱" : "婊℃墭鍑哄簱", outTask.getId());
+        List<String> cacheStations;
+        String robotGroup;
+        Long targetWhsType;
+        String sideName;
+        
+        if (eastStations.contains(outboundStaNo)) {
+            // 涓滀晶鍑哄簱绔欑偣锛屾煡鎵句笢渚A搴撲綅锛坵hs_type=1锛�
+            cacheStations = agvProperties.getEastStations();
+            robotGroup = agvProperties.getRobotGroupEast();
+            targetWhsType = agvProperties.getWhsTypeMapping().getInboundArea(); // whs_type=1
+            sideName = agvProperties.getEastDisplayName(); // 浠庨厤缃鍙栨樉绀哄悕绉�
+            log.info("鍑哄簱绔欑偣{}鍦▄}锛屾煡鎵緖}WA搴撲綅锛坵hs_type={}锛�", outboundStaNo, sideName, sideName, targetWhsType);
+        } else if (westStations.contains(outboundStaNo)) {
+            // 瑗夸晶鍑哄簱绔欑偣锛屾煡鎵捐タ渚A搴撲綅锛坵hs_type=2锛�
+            cacheStations = agvProperties.getWestStations();
+            robotGroup = agvProperties.getRobotGroupWest();
+            targetWhsType = agvProperties.getWhsTypeMapping().getCacheArea(); // whs_type=2
+            sideName = agvProperties.getWestDisplayName(); // 浠庨厤缃鍙栨樉绀哄悕绉�
+            log.info("鍑哄簱绔欑偣{}鍦▄}锛屾煡鎵緖}WA搴撲綅锛坵hs_type={}锛�", outboundStaNo, sideName, sideName, targetWhsType);
+        } else {
+            log.warn("鍑哄簱绔欑偣{}涓嶅湪閰嶇疆鐨勭珯鐐瑰垪琛ㄤ腑锛屾棤娉曞垽鏂瓄}/{}锛屼换鍔D锛歿}", 
+                outboundStaNo, agvProperties.getEastDisplayName(), agvProperties.getWestDisplayName(), outTask.getId());
             return;
         }
         
-        // 閫夋嫨缂撳瓨鍖虹洰鏍囩珯鐐癸紙浣跨敤绗竴涓彲鐢ㄧ珯鐐癸紝鎴栧彲浠ヤ紭鍖栦负閫夋嫨浠诲姟鏈�灏戠殑绔欑偣锛�
-        String cacheStaNo = cacheStations.get(0);
+        if (cacheStations.isEmpty()) {
+            log.warn("{}渚ф病鏈夐厤缃珯鐐癸紝鏃犳硶鐢熸垚{}浠诲姟锛屼换鍔D锛歿}", 
+                sideName, isEmptyPallet ? "绌烘墭鍑哄簱" : "婊℃墭鍑哄簱", outTask.getId());
+            return;
+        }
+        
+        // 鍒嗛厤缂撳瓨搴撲綅锛氬彧鏌ユ壘WA寮�澶寸殑搴撲綅锛圕A寮�澶村彧鍋氬叆搴擄紝WA寮�澶存墠浼氳鍑哄簱鍒嗛厤缂撳瓨鍖猴級
+        // 浣跨敤鏂扮殑鍒嗛厤閫昏緫锛氭寜鍒椾紭鍏堢骇锛堢涓夊垪鈫掔浜屽垪鈫掔涓�鍒楋級鍒嗛厤
+        String cacheAreaPrefix = agvProperties.getLocationPrefix().getCacheArea();
+        LocCache cacheLoc = allocateCacheLocationByPriority(targetWhsType, cacheAreaPrefix, isEmptyPallet);
+        
+        if (cacheLoc == null) {
+            log.warn("{}渚ф病鏈夊彲鐢ㄧ殑{}缂撳瓨搴撲綅锛屼笉鐢熸垚{}AGV浠诲姟锛屼换鍔D锛歿}", 
+                sideName, cacheAreaPrefix, isEmptyPallet ? "绌烘墭鍑哄簱" : "婊℃墭鍑哄簱", outTask.getId());
+            return;
+        }
+        
+        // 妫�鏌ュ伐浣滄。鏄惁宸插畬鎴愭垨宸茶浆鍘嗗彶妗�
+        boolean workCompleted = false;
+        if (outTask.getWrkNo() != null) {
+            // 妫�鏌ュ伐浣滄。鏄惁瀛樺湪涓斿凡瀹屾垚
+            WrkMast wrkMast = wrkMastService.selectOne(
+                new EntityWrapper<WrkMast>().eq("wrk_no", outTask.getWrkNo())
+            );
+            
+            if (wrkMast != null) {
+                Long wrkSts = wrkMast.getWrkSts();
+                // 鍑哄簱浠诲姟瀹屾垚鐘舵�侊細14锛堝凡鍑哄簱鏈‘璁わ級鎴�15锛堝嚭搴撴洿鏂板畬鎴愶級
+                if (wrkSts != null && (wrkSts == 14L || wrkSts == 15L)) {
+                    workCompleted = true;
+                    log.debug("宸ヤ綔妗}宸插畬鎴愶紝鐘舵�侊細{}", outTask.getWrkNo(), wrkSts);
+                }
+            } else {
+                // 濡傛灉宸ヤ綔妗d笉瀛樺湪锛屾鏌ュ巻鍙叉。
+                WrkMastLog wrkMastLog = wrkMastLogService.selectOne(
+                    new EntityWrapper<WrkMastLog>().eq("wrk_no", outTask.getWrkNo())
+                );
+                if (wrkMastLog != null) {
+                    long logWrkSts = wrkMastLog.getWrkSts();
+                    // 鍑哄簱浠诲姟鍘嗗彶妗e畬鎴愮姸鎬侊細15锛堝嚭搴撴洿鏂板畬鎴愶級
+                    if (logWrkSts == 15L) {
+                        workCompleted = true;
+                        log.debug("宸ヤ綔妗}宸茶浆鍘嗗彶妗e苟瀹岀粨锛屽巻鍙叉。鐘舵�侊細{}", outTask.getWrkNo(), logWrkSts);
+                    }
+                }
+            }
+        }
+        
+        // 妫�鏌ユ槸鍚︽湁浠庤鍑哄簱绔欑偣鍒扮紦瀛樺尯鐨勬鍦ㄦ惉杩愪换鍔★紙鐘舵��8锛氬凡鍛煎彨AGV锛屾鍦ㄦ惉杩愶級
+        // 鍑哄簱鍒扮紦瀛樺尯鐨勪换鍔$被鍨嬶細101锛堝叏鏉垮嚭搴擄級鎴�110锛堢┖鏉垮嚭搴擄級
+        List<Task> transportingTasks = taskService.selectList(
+            new EntityWrapper<Task>()
+                .eq("source_sta_no", outboundStaNo) // 婧愮珯鐐规槸鍑哄簱绔欑偣
+                .in("sta_no", cacheStations) // 鐩爣绔欑偣鏄紦瀛樺尯绔欑偣
+                .eq("task_type", "agv")
+                .eq("wrk_sts", 8L) // 鍙鏌ユ鍦ㄦ惉杩愮姸鎬佺殑浠诲姟
+                .in("io_type", 101, 110) // 鍑哄簱鍒扮紦瀛樺尯鐨勪换鍔$被鍨�
+        );
+        
+        // 濡傛灉鏈夋鍦ㄦ惉杩愮殑浠诲姟锛屼笖宸ヤ綔妗f湭瀹屾垚锛屽垯涓嶅垎閰嶇紦瀛樺簱浣�
+        if (!transportingTasks.isEmpty() && !workCompleted) {
+            log.info("鍑哄簱绔欑偣{}鍒扮紦瀛樺尯鏈墈}涓鍦ㄦ惉杩愮殑AGV浠诲姟锛屼笖宸ヤ綔妗f湭瀹屾垚锛屾殏涓嶅垎閰嶇紦瀛樺簱浣嶏紝绛夊緟鎼繍瀹屾垚銆傚嚭搴撲换鍔D锛歿}", 
+                outboundStaNo, transportingTasks.size(), outTask.getId());
+            return; // 鏈夋鍦ㄦ惉杩愮殑浠诲姟涓斿伐浣滄。鏈畬鎴愶紝涓嶅垎閰嶇紦瀛樺簱浣嶏紝绛夊緟涓嬫妫�鏌�
+        }
+        
+        if (!transportingTasks.isEmpty() && workCompleted) {
+            log.info("鍑哄簱绔欑偣{}鍒扮紦瀛樺尯鏈墈}涓鍦ㄦ惉杩愮殑AGV浠诲姟锛屼絾宸ヤ綔妗e凡瀹屾垚鎴栧凡杞巻鍙叉。锛屽厑璁稿垎閰嶇紦瀛樺簱浣嶃�傚嚭搴撲换鍔D锛歿}", 
+                outboundStaNo, transportingTasks.size(), outTask.getId());
+        }
+        
+        // 閫夋嫨缂撳瓨鍖虹洰鏍囩珯鐐癸紙浣跨敤鍜屽叆搴撲竴鏍风殑鍒嗛厤绛栫暐锛氳疆璇€�佹渶灏戜换鍔℃暟锛�
+        String cacheStaNo = allocateCacheStation(cacheStations, ioType);
+        if (cacheStaNo == null) {
+            log.warn("鏃犳硶涓哄嚭搴撲换鍔D锛歿}鍒嗛厤缂撳瓨鍖虹珯鐐癸紝鎵�鏈夌珯鐐归兘鍦ㄤ娇鐢ㄤ腑", outTask.getId());
+            return;
+        }
         
         // 鐢熸垚宸ヤ綔鍙�
         int workNo = commonService.getWorkNo(WorkNoType.PAKOUT.type);
@@ -805,58 +897,360 @@
         log.info("鎴愬姛鐢熸垚{}浠诲姟锛屼换鍔D锛歿}锛屽伐浣滃彿锛歿}锛屾簮绔欑偣锛歿}锛岀洰鏍囩珯鐐癸細{}锛岀紦瀛樺簱浣嶏細{}", 
                 isEmptyPallet ? "绌烘墭鍑哄簱" : "婊℃墭鍑哄簱", cacheTask.getId(), workNo, outboundStaNo, cacheStaNo, cacheLoc.getLocNo());
     }
+    
+    /**
+     * 鎸変紭鍏堢骇鍒嗛厤缂撳瓨搴撲綅
+     * 浼樺厛绾ц鍒欙細
+     * 1. 浼樺厛鍒嗛厤绗笁鍒楋紙bay1=3锛夛紝涓旇鎺掔殑1銆�2銆�3鍒楅兘鏄┖鐨�
+     * 2. 濡傛灉鎵�鏈夌涓夊垪閮芥湁璐э紝鍒欏垎閰嶇浜屽垪锛坆ay1=2锛夛紝涓旇鎺掔殑1銆�2鍒楅兘鏄┖鐨�
+     * 3. 濡傛灉鎵�鏈夋帓鐨勭浜岀涓夊垪閮芥弧浜嗭紝鍒欏垎閰嶇涓�鍒楋紙bay1=1锛�
+     * 4. 濡傛灉鎵�鏈夌涓�鍒楅兘婊′簡锛屽啀妫�鏌ョ浜屽垪鍜岀涓夊垪
+     * 5. 灞傦紙lev1锛変粠绗竴灞傚紑濮�
+     * 
+     * @param whsType 搴撳尯绫诲瀷
+     * @param cacheAreaPrefix 缂撳瓨鍖哄簱浣嶅墠缂�锛堝"WA"锛�
+     * @param isEmptyPallet 鏄惁绌烘墭
+     * @return 鍒嗛厤鐨勭紦瀛樺簱浣嶏紝濡傛灉鏃犳硶鍒嗛厤鍒欒繑鍥瀗ull
+     */
+    private LocCache allocateCacheLocationByPriority(Long whsType, String cacheAreaPrefix, boolean isEmptyPallet) {
+        // 鏌ヨ鎵�鏈夌鍚堟潯浠剁殑绌哄簱浣�
+        List<LocCache> allLocations = locCacheService.selectList(new EntityWrapper<LocCache>()
+                .eq("whs_type", whsType)
+                .like("loc_no", cacheAreaPrefix + "%")
+                .eq("frozen", 0)
+                .eq("loc_sts", LocStsType.LOC_STS_TYPE_O.type) // O.闂茬疆
+                .ne("full_plt", isEmptyPallet ? "Y" : "N") // 绌烘墭涓嶉�夋弧鏉垮簱浣嶏紝婊℃墭涓嶉�夌┖鏉垮簱浣�
+        );
+        
+        if (allLocations == null || allLocations.isEmpty()) {
+            return null;
+        }
+        
+        // 鎸塺ow1鍒嗙粍
+        Map<Integer, List<LocCache>> locationsByRow = allLocations.stream()
+                .filter(loc -> loc.getRow1() != null)
+                .collect(Collectors.groupingBy(LocCache::getRow1));
+        
+        if (locationsByRow.isEmpty()) {
+            return null;
+        }
+        
+        // 瀵规瘡涓帓锛屾鏌�1銆�2銆�3鍒楃殑鐘舵��
+        // 鍒楃姸鎬侊細true琛ㄧず璇ュ垪鏈夌┖搴撲綅锛宖alse琛ㄧず璇ュ垪宸叉弧
+        Map<Integer, Map<Integer, Boolean>> rowColumnStatus = new HashMap<>();
+        for (Map.Entry<Integer, List<LocCache>> entry : locationsByRow.entrySet()) {
+            Integer row = entry.getKey();
+            List<LocCache> rowLocs = entry.getValue();
+            
+            Map<Integer, Boolean> columnStatus = new HashMap<>();
+            // 妫�鏌ョ1銆�2銆�3鍒楁槸鍚︽湁绌哄簱浣�
+            for (int bay = 1; bay <= 3; bay++) {
+                final int bayFinal = bay;  // 鍒涘缓final鍓湰渚沴ambda浣跨敤
+                boolean hasEmpty = rowLocs.stream()
+                        .anyMatch(loc -> loc.getBay1() != null && loc.getBay1() == bayFinal);
+                columnStatus.put(bay, hasEmpty);
+            }
+            rowColumnStatus.put(row, columnStatus);
+        }
+        
+        // 浼樺厛绾�1锛氬垎閰嶇涓夊垪锛坆ay1=3锛夛紝涓旇鎺掔殑1銆�2銆�3鍒楅兘鏄┖鐨�
+        for (Map.Entry<Integer, List<LocCache>> entry : locationsByRow.entrySet()) {
+            Integer row = entry.getKey();
+            Map<Integer, Boolean> columnStatus = rowColumnStatus.get(row);
+            
+            // 妫�鏌ヨ鎺掔殑1銆�2銆�3鍒楁槸鍚﹂兘鏄┖鐨�
+            if (Boolean.TRUE.equals(columnStatus.get(1)) && 
+                Boolean.TRUE.equals(columnStatus.get(2)) && 
+                Boolean.TRUE.equals(columnStatus.get(3))) {
+                // 鍒嗛厤璇ユ帓鐨勭涓夊垪锛屼粠绗竴灞傚紑濮�
+                List<LocCache> bay3Locs = entry.getValue().stream()
+                        .filter(loc -> loc.getBay1() != null && loc.getBay1() == 3)
+                        .sorted(Comparator.comparing(loc -> loc.getLev1() != null ? loc.getLev1() : 0))
+                        .collect(Collectors.toList());
+                
+                if (!bay3Locs.isEmpty()) {
+                    log.debug("浼樺厛绾�1锛氬垎閰嶆帓{}鐨勭涓夊垪锛屽簱浣嶏細{}", row, bay3Locs.get(0).getLocNo());
+                    return bay3Locs.get(0);
+                }
+            }
+        }
+        
+        // 浼樺厛绾�2锛氬垎閰嶇浜屽垪锛坆ay1=2锛夛紝涓旇鎺掔殑1銆�2鍒楅兘鏄┖鐨勶紙绗笁鍒楀彲鑳藉凡婊★級
+        for (Map.Entry<Integer, List<LocCache>> entry : locationsByRow.entrySet()) {
+            Integer row = entry.getKey();
+            Map<Integer, Boolean> columnStatus = rowColumnStatus.get(row);
+            
+            // 妫�鏌ヨ鎺掔殑1銆�2鍒楁槸鍚﹂兘鏄┖鐨�
+            if (Boolean.TRUE.equals(columnStatus.get(1)) && 
+                Boolean.TRUE.equals(columnStatus.get(2))) {
+                // 鍒嗛厤璇ユ帓鐨勭浜屽垪锛屼粠绗竴灞傚紑濮�
+                List<LocCache> bay2Locs = entry.getValue().stream()
+                        .filter(loc -> loc.getBay1() != null && loc.getBay1() == 2)
+                        .sorted(Comparator.comparing(loc -> loc.getLev1() != null ? loc.getLev1() : 0))
+                        .collect(Collectors.toList());
+                
+                if (!bay2Locs.isEmpty()) {
+                    log.debug("浼樺厛绾�2锛氬垎閰嶆帓{}鐨勭浜屽垪锛屽簱浣嶏細{}", row, bay2Locs.get(0).getLocNo());
+                    return bay2Locs.get(0);
+                }
+            }
+        }
+        
+        // 浼樺厛绾�3锛氬垎閰嶇涓�鍒楋紙bay1=1锛夛紝鎵�鏈夋帓鐨勭浜岀涓夊垪閮芥弧浜�
+        for (Map.Entry<Integer, List<LocCache>> entry : locationsByRow.entrySet()) {
+            Integer row = entry.getKey();
+            Map<Integer, Boolean> columnStatus = rowColumnStatus.get(row);
+            
+            // 妫�鏌ヨ鎺掔殑绗竴鍒楁槸鍚︽湁绌哄簱浣�
+            if (Boolean.TRUE.equals(columnStatus.get(1))) {
+                // 鍒嗛厤璇ユ帓鐨勭涓�鍒楋紝浠庣涓�灞傚紑濮�
+                List<LocCache> bay1Locs = entry.getValue().stream()
+                        .filter(loc -> loc.getBay1() != null && loc.getBay1() == 1)
+                        .sorted(Comparator.comparing(loc -> loc.getLev1() != null ? loc.getLev1() : 0))
+                        .collect(Collectors.toList());
+                
+                if (!bay1Locs.isEmpty()) {
+                    log.debug("浼樺厛绾�3锛氬垎閰嶆帓{}鐨勭涓�鍒楋紝搴撲綅锛歿}", row, bay1Locs.get(0).getLocNo());
+                    return bay1Locs.get(0);
+                }
+            }
+        }
+        
+        // 浼樺厛绾�4锛氬鏋滄墍鏈夌涓�鍒楅兘婊′簡锛屽啀妫�鏌ョ浜屽垪鍜岀涓夊垪锛堜笉瑕佹眰璇ユ帓鐨�1銆�2鍒楅兘鏄┖鐨勶級
+        // 鍏堟鏌ョ浜屽垪
+        for (Map.Entry<Integer, List<LocCache>> entry : locationsByRow.entrySet()) {
+            Integer row = entry.getKey();
+            Map<Integer, Boolean> columnStatus = rowColumnStatus.get(row);
+            
+            // 妫�鏌ヨ鎺掔殑绗簩鍒楁槸鍚︽湁绌哄簱浣�
+            if (Boolean.TRUE.equals(columnStatus.get(2))) {
+                List<LocCache> bay2Locs = entry.getValue().stream()
+                        .filter(loc -> loc.getBay1() != null && loc.getBay1() == 2)
+                        .sorted(Comparator.comparing(loc -> loc.getLev1() != null ? loc.getLev1() : 0))
+                        .collect(Collectors.toList());
+                
+                if (!bay2Locs.isEmpty()) {
+                    log.debug("浼樺厛绾�4锛氬垎閰嶆帓{}鐨勭浜屽垪锛屽簱浣嶏細{}", row, bay2Locs.get(0).getLocNo());
+                    return bay2Locs.get(0);
+                }
+            }
+        }
+        
+        // 浼樺厛绾�5锛氭渶鍚庢鏌ョ涓夊垪锛堜笉瑕佹眰璇ユ帓鐨�1銆�2銆�3鍒楅兘鏄┖鐨勶級
+        for (Map.Entry<Integer, List<LocCache>> entry : locationsByRow.entrySet()) {
+            Integer row = entry.getKey();
+            Map<Integer, Boolean> columnStatus = rowColumnStatus.get(row);
+            
+            // 妫�鏌ヨ鎺掔殑绗笁鍒楁槸鍚︽湁绌哄簱浣�
+            if (Boolean.TRUE.equals(columnStatus.get(3))) {
+                List<LocCache> bay3Locs = entry.getValue().stream()
+                        .filter(loc -> loc.getBay1() != null && loc.getBay1() == 3)
+                        .sorted(Comparator.comparing(loc -> loc.getLev1() != null ? loc.getLev1() : 0))
+                        .collect(Collectors.toList());
+                
+                if (!bay3Locs.isEmpty()) {
+                    log.debug("浼樺厛绾�5锛氬垎閰嶆帓{}鐨勭涓夊垪锛屽簱浣嶏細{}", row, bay3Locs.get(0).getLocNo());
+                    return bay3Locs.get(0);
+                }
+            }
+        }
+        
+        // 濡傛灉鎵�鏈夊垪閮芥弧浜嗭紝杩斿洖null
+        return null;
+    }
+    
+    /**
+     * 涓哄嚭搴撳埌缂撳瓨鍖虹殑浠诲姟鍒嗛厤绔欑偣锛堜娇鐢ㄥ拰鍏ュ簱涓�鏍风殑鍒嗛厤绛栫暐锛�
+     * @param cacheStations 缂撳瓨鍖虹珯鐐瑰垪琛�
+     * @param ioType 浠诲姟绫诲瀷锛�101=鍏ㄦ澘鍑哄簱锛�110=绌烘澘鍑哄簱锛�
+     * @return 鍒嗛厤鐨勭珯鐐圭紪鍙凤紝濡傛灉鏃犳硶鍒嗛厤鍒欒繑鍥瀗ull
+     */
+    private String allocateCacheStation(List<String> cacheStations, Integer ioType) {
+        if (cacheStations == null || cacheStations.isEmpty()) {
+            log.warn("缂撳瓨鍖虹珯鐐瑰垪琛ㄤ负绌猴紝鏃犳硶鍒嗛厤绔欑偣");
+            return null;
+        }
+        
+        // 灏嗙珯鐐瑰瓧绗︿覆鍒楄〃杞崲涓烘暣鏁板垪琛�
+        List<Integer> siteIntList = cacheStations.stream()
+                .map(Integer::parseInt)
+                .collect(Collectors.toList());
+        
+        // 鏌ヨ鎵�鏈夌紦瀛樺尯绔欑偣鐨勮澶囦俊鎭紙鍖呭惈浠诲姟鏁帮級
+        List<BasDevp> devList = basDevpMapper.selectList(new EntityWrapper<BasDevp>()
+                .in("dev_no", siteIntList)
+        );
+        
+        if (devList.isEmpty()) {
+            log.warn("缂撳瓨鍖虹珯鐐箋}鍦ㄨ澶囪〃涓笉瀛樺湪", cacheStations);
+            return cacheStations.get(0); // 闄嶇骇锛氳繑鍥炵涓�涓珯鐐�
+        }
+        
+        // 鎸夊叆搴撲换鍔℃暟鎺掑簭锛堝嚭搴撳埌缂撳瓨鍖轰篃浣跨敤in_qty瀛楁锛�
+        devList.sort(Comparator.comparing(BasDevp::getInQty));
+        
+        // 鑾峰彇鏈�灏戜换鍔℃暟
+        int minInQty = devList.get(0).getInQty();
+        
+        // 绛涢�夊嚭浠诲姟鏁版渶灏戠殑绔欑偣鍒楄〃
+        List<BasDevp> minTaskSites = devList.stream()
+                .filter(dev -> dev.getInQty() == minInQty)
+                .collect(Collectors.toList());
+        
+        // 鏍规嵁閰嶇疆閫夋嫨鍒嗛厤绛栫暐
+        String strategy = agvProperties.getSiteAllocation().getStrategy();
+        boolean enableRoundRobin = agvProperties.getSiteAllocation().isEnableRoundRobin();
+        
+        List<BasDevp> orderedSites = new ArrayList<>();
+        String groupKey = "west"; // 缂撳瓨鍖轰娇鐢ㄨタ渚�
+        
+        if (minTaskSites.size() > 1 && enableRoundRobin && "round-robin".equals(strategy)) {
+            // 杞鍒嗛厤锛氬綋澶氫釜绔欑偣浠诲姟鏁扮浉鍚屾椂锛屼娇鐢ㄨ疆璇�
+            AtomicInteger counter = siteRoundRobinCounters.computeIfAbsent(groupKey, k -> new AtomicInteger(0));
+            int startIndex = counter.get() % minTaskSites.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("浣跨敤闅忔満鍒嗛厤绛栫暐");
+        } else {
+            // 榛樿锛氭寜鍏ュ簱浠诲姟鏁版帓搴忥紙宸茬粡鎺掑簭濂戒簡锛�
+            orderedSites = devList;
+        }
+        
+        // 渚濇妫�鏌ユ瘡涓珯鐐规槸鍚﹀湪鎼繍锛屾壘鍒扮涓�涓┖闂茬珯鐐瑰氨鍒嗛厤
+        String selectedSite = null;
+        List<Integer> checkIoTypes = Arrays.asList(101, 110); // 鍑哄簱鍒扮紦瀛樺尯鐨勪换鍔$被鍨�
+        
+        for (BasDevp dev : orderedSites) {
+            String staNo = String.valueOf(dev.getDevNo());
+            
+            // 妫�鏌ヨ绔欑偣鏄惁鏈夋鍦ㄦ惉杩愮殑鍚岀被鍨嬩换鍔�
+            List<Task> transportingTasks = taskService.selectList(
+                new EntityWrapper<Task>()
+                    .eq("sta_no", staNo)
+                    .eq("task_type", "agv")
+                    .eq("wrk_sts", 8L) // 鍙鏌ユ鍦ㄦ惉杩愮姸鎬佺殑浠诲姟
+                    .in("io_type", checkIoTypes)
+            );
+            
+            if (!transportingTasks.isEmpty()) {
+                log.debug("缂撳瓨鍖虹珯鐐箋}鏈墈}涓鍦ㄦ惉杩愮殑鍑哄簱AGV浠诲姟锛屾鏌ヤ笅涓�涓珯鐐�", 
+                    staNo, transportingTasks.size());
+                continue; // 璇ョ珯鐐规鍦ㄦ惉杩愶紝妫�鏌ヤ笅涓�涓珯鐐�
+            }
+            
+            // 鎵惧埌绗竴涓┖闂茬珯鐐癸紝鍒嗛厤
+            selectedSite = staNo;
+            log.info("鍑哄簱鍒扮紦瀛樺尯浠诲姟鎸夎鍒欏簲鍒嗛厤鍒扮珯鐐箋}锛岃绔欑偣绌洪棽锛屽垎閰嶆垚鍔�", staNo);
+            break;
+        }
+        
+        // 濡傛灉鎵�鏈夌珯鐐归兘鍦ㄦ惉杩愶紝鍒欎笉鍒嗛厤绔欑偣
+        if (selectedSite == null) {
+//            log.warn("鎵�鏈夌紦瀛樺尯绔欑偣閮芥湁姝e湪鎼繍鐨勫嚭搴撲换鍔★紝鏆備笉鍒嗛厤绔欑偣锛岀瓑寰呯┖闂�");
+            return null;
+        }
+        
+        // 鏇存柊绔欑偣浠诲姟鏁帮紙鍑哄簱鍒扮紦瀛樺尯涔熶娇鐢╥n_qty瀛楁锛�
+        basDevpMapper.incrementInQty(Integer.parseInt(selectedSite));
+        
+        return selectedSite;
+    }
 
     @Transactional(rollbackFor = Exception.class)
     public ReturnT<String> agvDoIn(Task wrkMast) {
-        if (wrkMast.getIoType().equals(1)) {
-            LocCache locCache = locCacheService.selectOne(new EntityWrapper<LocCache>().eq("loc_no", wrkMast.getLocNo()));
-            if (Objects.isNull(locCache)) {
-                throw new CoolException("鏁版嵁閿欒锛屽簱浣嶄笉瀛樺湪锛侊紒");
-            }
-            if (!locCache.getLocSts().equals(LocStsType.LOC_STS_TYPE_S.type)) {
-                throw new CoolException("褰撳墠搴撲綅鐘舵�佷负锛�" + LocStsType.LOC_STS_TYPE_S.type + "." + LocStsType.LOC_STS_TYPE_S.desc + "锛屼笉鏄嚭搴撻绾︾姸鎬�");
-            }
-            List<TaskDetl> taskDetls = taskDetlService.selectList(new EntityWrapper<TaskDetl>().eq("task_id", wrkMast.getId()));
-            if (Objects.isNull(taskDetls)) {
-                throw new CoolException("鏁版嵁閿欒锛氱粍鎵樻暟鎹笉瀛樺湪锛侊紒");
-            }
-            taskDetls.forEach(pakin -> {
-                LocCacheDetl detl = new LocCacheDetl();
-                BeanUtils.copyProperties(pakin, detl);
-                detl.setBarcode(pakin.getBarcode())
-                        .setLocId(locCache.getId())
-                        .setAnfme(pakin.getAnfme())
-                        .setBrand(pakin.getBrand())
-                        .setAppeTime(new Date())
-                        .setSpecs(pakin.getSpecs())
-                        .setColor(pakin.getColor())
-                        .setLocNo(locCache.getLocNo())
-                        .setAreaId(locCache.getAreaId())
-                        .setAreaName(locCache.getAreaName())
-                        .setUnit(pakin.getUnit())
-                        .setBatch(pakin.getBatch());
-                if (!locCacheDetlService.insert(detl)) {
-                    throw new CoolException("搴撲綅鏄庣粏淇濆瓨澶辫触锛侊紒");
+        Integer ioType = wrkMast.getIoType();
+        if (ioType == null) {
+            throw new CoolException("鏁版嵁閿欒锛歩oType涓虹┖锛侊紒");
+        }
+        
+        // 澶勭悊鍏ュ簱浠诲姟绫诲瀷锛�1锛堝疄鎵樺叆搴擄級銆�10锛堢┖鎵樺叆搴擄級銆�53銆�57
+        if (ioType == 1 || ioType == 10 || ioType == 53 || ioType == 57) {
+            // ioType == 1 闇�瑕佸鐞嗙粍鎵樻暟鎹�
+            if (ioType == 1) {
+                LocCache locCache = locCacheService.selectOne(new EntityWrapper<LocCache>().eq("loc_no", wrkMast.getLocNo()));
+                if (Objects.isNull(locCache)) {
+                    throw new CoolException("鏁版嵁閿欒锛屽簱浣嶄笉瀛樺湪锛侊紒");
                 }
-            });
+                if (!locCache.getLocSts().equals(LocStsType.LOC_STS_TYPE_S.type)) {
+                    throw new CoolException("褰撳墠搴撲綅鐘舵�佷负锛�" + LocStsType.LOC_STS_TYPE_S.type + "." + LocStsType.LOC_STS_TYPE_S.desc + "锛屼笉鏄嚭搴撻绾︾姸鎬�");
+                }
+                List<TaskDetl> taskDetls = taskDetlService.selectList(new EntityWrapper<TaskDetl>().eq("task_id", wrkMast.getId()));
+                if (Objects.isNull(taskDetls)) {
+                    throw new CoolException("鏁版嵁閿欒锛氱粍鎵樻暟鎹笉瀛樺湪锛侊紒");
+                }
+                taskDetls.forEach(pakin -> {
+                    LocCacheDetl detl = new LocCacheDetl();
+                    BeanUtils.copyProperties(pakin, detl);
+                    detl.setBarcode(pakin.getBarcode())
+                            .setLocId(locCache.getId())
+                            .setAnfme(pakin.getAnfme())
+                            .setBrand(pakin.getBrand())
+                            .setAppeTime(new Date())
+                            .setSpecs(pakin.getSpecs())
+                            .setColor(pakin.getColor())
+                            .setLocNo(locCache.getLocNo())
+                            .setAreaId(locCache.getAreaId())
+                            .setAreaName(locCache.getAreaName())
+                            .setUnit(pakin.getUnit())
+                            .setBatch(pakin.getBatch());
+                    if (!locCacheDetlService.insert(detl)) {
+                        throw new CoolException("搴撲綅鏄庣粏淇濆瓨澶辫触锛侊紒");
+                    }
+                });
 
-            locCache.setLocSts(LocStsType.LOC_STS_TYPE_F.type);
-            locCache.setModiTime(new Date());
-            locCache.setBarcode(wrkMast.getBarcode());
-            locCache.setModiTime(new Date());
-            locCache.setIoTime(new Date());
-            if (!locCacheService.updateById(locCache)) {
-                throw new CoolException("搴撲綅鐘舵�佷慨鏀瑰け璐ワ紒");
+                // 鏍规嵁fullPlt璁剧疆搴撲綅鐘舵�侊細婊℃墭璁剧疆涓�"F"锛堝湪搴擄級锛岀┖鎵樿缃负"D"锛堢┖妗�/绌烘爤鏉匡級
+                boolean isFullPlt = wrkMast.getFullPlt() != null && wrkMast.getFullPlt().equals("Y");
+                locCache.setLocSts(isFullPlt ? LocStsType.LOC_STS_TYPE_F.type : LocStsType.LOC_STS_TYPE_D.type);
+                locCache.setFullPlt(isFullPlt ? "Y" : "N");
+                locCache.setModiTime(new Date());
+                locCache.setBarcode(wrkMast.getBarcode());
+                locCache.setIoTime(new Date());
+                if (!locCacheService.updateById(locCache)) {
+                    throw new CoolException("搴撲綅鐘舵�佷慨鏀瑰け璐ワ紒");
+                }
+            } else if (ioType == 10 || ioType == 53 || ioType == 57) {
+                // 绌烘墭鍏ュ簱鎴栧叾浠栧叆搴撶被鍨嬶紝涔熼渶瑕佹洿鏂扮紦瀛樺簱浣嶇姸鎬�
+                LocCache locCache = locCacheService.selectOne(new EntityWrapper<LocCache>().eq("loc_no", wrkMast.getLocNo()));
+                if (locCache != null) {
+                    // 鏍规嵁fullPlt璁剧疆搴撲綅鐘舵�侊細婊℃墭璁剧疆涓�"F"锛堝湪搴擄級锛岀┖鎵樿缃负"D"锛堢┖妗�/绌烘爤鏉匡級
+                    // ioType == 10 鏄┖鎵樺叆搴擄紝榛樿璁剧疆涓�"D"
+                    boolean isFullPlt = (ioType != 10) && (wrkMast.getFullPlt() != null && wrkMast.getFullPlt().equals("Y"));
+                    locCache.setLocSts(isFullPlt ? LocStsType.LOC_STS_TYPE_F.type : LocStsType.LOC_STS_TYPE_D.type);
+                    locCache.setFullPlt(isFullPlt ? "Y" : "N");
+                    locCache.setModiTime(new Date());
+                    locCache.setBarcode(wrkMast.getBarcode());
+                    locCache.setIoTime(new Date());
+                    if (!locCacheService.updateById(locCache)) {
+                        throw new CoolException("搴撲綅鐘舵�佷慨鏀瑰け璐ワ紒");
+                    }
+                }
             }
+            
+            // 鏇存柊浠诲姟鐘舵�佷负5锛堝簱瀛樻洿鏂板畬鎴愶級
             wrkMast.setWrkSts(5L);
             wrkMast.setModiTime(new Date());
             if (!taskService.updateById(wrkMast)) {
                 throw new CoolException("浠诲姟鐘舵�佷慨鏀瑰け璐ワ紒锛�");
             }
-        }else {
-            throw new CoolException("鏁版嵁閿欒锛歩oType涓嶅瓨鍦紒锛�");
+        } else {
+            // 闈炲叆搴撲换鍔$被鍨嬶紝璁板綍鏃ュ織浣嗕笉鎶涘嚭寮傚父锛屽厑璁稿叾浠栫被鍨嬬殑浠诲姟閫氳繃
+            log.warn("agvDoIn鏂规硶鏀跺埌闈炲叆搴撲换鍔$被鍨嬶紝ioType锛歿}锛宼askId锛歿}锛岃烦杩囧鐞�", ioType, wrkMast.getId());
         }
-
 
         return SUCCESS;
     }

--
Gitblit v1.9.1