From e5c398a66fef57ce5d5c1b11bcb72582b47691a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B8=B8=E7=86=9F=E5=90=B4=E5=BD=A6=E7=A5=96?= Date: Fri, 2 Oct 2026 16:53:59 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8E=A5=E5=8F=A3bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../autoWareHourceHaian/HAIAN_AI_CONTEXT.md | 4 +-- .../entity/HaiAnAutoSortingInfoRequest.java | 2 +- .../HaiAnPdaAutoWarehouseServiceImpl.java | 26 +++++++++++-------- .../service/impl/HaiAnSortingBoardSource.java | 12 ++++----- .../staticData/HaiAnStationStaticData.java | 12 ++++++--- 5 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/gaotao/modules/autoWareHourceHaian/HAIAN_AI_CONTEXT.md b/src/main/java/com/gaotao/modules/autoWareHourceHaian/HAIAN_AI_CONTEXT.md index 92ee9e61..9a15ba98 100644 --- a/src/main/java/com/gaotao/modules/autoWareHourceHaian/HAIAN_AI_CONTEXT.md +++ b/src/main/java/com/gaotao/modules/autoWareHourceHaian/HAIAN_AI_CONTEXT.md @@ -160,8 +160,8 @@ ## 10. 立库开关与静态测试策略 -- 分拣清单协议按被分拣源盘位查询并返回该源盘位;手工工作位到源盘位为 `ST-MP-05→ST-MP-01、06→02、07→03、08→04`,自动为 `ST-RP-03→ST-RP-01、04→02`,映射集中在 `HaiAnStationStaticData`,不得按数字偏移推算。PDA 以实际托盘工作位解析查询源盘位,响应过滤使用源盘位,返回 `devCode` 保留实际托盘站点;未知站点拒绝外呼 - rqrq -- 看板继续共用 JSON 字符串 `ALL` 查询和5秒缓存,按返回的被分拣位反向归属到工作位;缺站保持不可用,空materials表示暂无任务。页面及推送使用工作位,旧 `R1H–R4H/J1H/J2H` 仅作看板入口及订阅兼容别名,返回站点与请求/主题一致;别名不得用于托盘实际位置或PDA权限判断。接口URL、页面URL保持兼容,WMS补字段仍按site+RFID查询 - rqrq +- 分拣清单协议按被分拣源盘位查询,但 WCS 响应 `sortingStation` 返回分拣工作位;手工工作位到源盘位为 `ST-MP-05→ST-MP-01、06→02、07→03、08→04`,自动为 `ST-RP-03→ST-RP-01、04→02`,映射集中在 `HaiAnStationStaticData`,不得按数字偏移推算。PDA 请求仍发送源盘位,响应按对应工作位过滤,返回 `devCode` 保留实际托盘站点;未知站点拒绝外呼 - rqrq +- 看板继续共用 JSON 字符串 `ALL` 查询和5秒缓存,按返回的分拣工作位归属到工作位缓存;兼容旧源盘位回传,缺站保持不可用,空materials表示暂无任务。页面及推送使用工作位,旧 `R1H–R4H/J1H/J2H` 仅作看板入口及订阅兼容别名,返回站点与请求/主题一致;别名不得用于托盘实际位置或PDA权限判断。接口URL、页面URL保持兼容,WMS补字段仍按site+RFID查询 - rqrq - 配置项 `application.yml -> interface.haianWarehouse` 作为海安立库总开关:`true` 表示真实 `HttpUtils.doPost`,`false` 表示无立库测试模式 - rqrq - 开关只允许注入 `HaiAnWcsApiServiceImpl`。业务 Service 必须走完整本地落库(WOT、calling_flag、组报文)再调 `HaiAnWcsApiService`,禁止再按开关提前 return - rqrq diff --git a/src/main/java/com/gaotao/modules/autoWareHourceHaian/api/entity/HaiAnAutoSortingInfoRequest.java b/src/main/java/com/gaotao/modules/autoWareHourceHaian/api/entity/HaiAnAutoSortingInfoRequest.java index 8fc55bae..93b86f55 100644 --- a/src/main/java/com/gaotao/modules/autoWareHourceHaian/api/entity/HaiAnAutoSortingInfoRequest.java +++ b/src/main/java/com/gaotao/modules/autoWareHourceHaian/api/entity/HaiAnAutoSortingInfoRequest.java @@ -20,7 +20,7 @@ public class HaiAnAutoSortingInfoRequest { private String palletId; /** - * 被分拣源盘位编码,由业务层按实际工作位配对取得(如ST-MP-05对应ST-MP-01),看板传ALL;不落库,WCS HTTP体序列化为JSON字符串,不是对象字段。 - rqrq + * 请求被分拣源盘位编码,由业务层按实际工作位配对取得(如ST-MP-05对应ST-MP-01),看板传ALL;WCS响应sortingStation按接口约定返回分拣工作位;不落库,HTTP体序列化为JSON字符串。 - rqrq */ private String locationCode; } diff --git a/src/main/java/com/gaotao/modules/autoWareHourceHaian/service/impl/HaiAnPdaAutoWarehouseServiceImpl.java b/src/main/java/com/gaotao/modules/autoWareHourceHaian/service/impl/HaiAnPdaAutoWarehouseServiceImpl.java index cbf18d30..10106d4a 100644 --- a/src/main/java/com/gaotao/modules/autoWareHourceHaian/service/impl/HaiAnPdaAutoWarehouseServiceImpl.java +++ b/src/main/java/com/gaotao/modules/autoWareHourceHaian/service/impl/HaiAnPdaAutoWarehouseServiceImpl.java @@ -357,7 +357,7 @@ public class HaiAnPdaAutoWarehouseServiceImpl implements HaiAnPdaAutoWarehouseSe /** * @author rqrq - * @Description 按实际工作位映射的被分拣源盘位查询清单并过滤rfidBarcode;devCode保留实际站点,未知站点拒绝外呼,接口失败回退空列表。 - rqrq + * @Description 按实际工作位映射的被分拣源盘位查询清单,并按WCS返回工作位过滤rfidBarcode;devCode保留实际站点,未知站点拒绝外呼,接口失败回退空列表。 - rqrq */ private HaiAnSortingListResult querySortingListFromWcs(String site, String palletId, String locationCode) { HaiAnSortingListResult result = new HaiAnSortingListResult(); @@ -371,6 +371,10 @@ public class HaiAnPdaAutoWarehouseServiceImpl implements HaiAnPdaAutoWarehouseSe // 根据实际托盘位置取得配对源盘位,未知站点直接报错,禁止向WCS发送工作位或历史看板别名 - rqrq String sourceStation = HaiAnStationStaticData.requireSortingSourceStation(locationCode); + String responseWorkStation = HaiAnStationStaticData.resolveSortingWorkStation(sourceStation); + if (!StringUtils.hasText(responseWorkStation)) { + throw new RuntimeException("未找到分拣清单响应工作位映射:" + sourceStation); + } HaiAnAutoSortingInfoRequest queryRequest = new HaiAnAutoSortingInfoRequest(); queryRequest.setSite(site); queryRequest.setPalletId(palletId); @@ -391,7 +395,7 @@ public class HaiAnPdaAutoWarehouseServiceImpl implements HaiAnPdaAutoWarehouseSe } ObjectMapper mapper = new ObjectMapper(); JsonNode rootNode = mapper.readTree(response); - // 兼容WCS根对象及resData包裹,统一在同一业务对象中按源盘位过滤,禁止混取其他站点标签 - rqrq + // 兼容WCS根对象及resData包裹,统一在同一业务对象中按返回工作位过滤,禁止混取其他站点标签 - rqrq if (!rootNode.has("sortingStations") && !rootNode.has("materials") && rootNode.path("resData").isObject()) { rootNode = rootNode.path("resData"); } @@ -403,24 +407,24 @@ public class HaiAnPdaAutoWarehouseServiceImpl implements HaiAnPdaAutoWarehouseSe throw new RuntimeException("WCS分拣清单sortingStations不是数组"); } if (sortingStations.isArray()) { - boolean matchedSource = false; + boolean matchedWorkStation = false; for (JsonNode stationNode : sortingStations) { String sortingStation = stationNode.path("sortingStation").asText(""); if (!StringUtils.hasText(sortingStation)) { sortingStation = stationNode.path("stationCode").asText(""); } - // WCS返回的是被分拣位,必须匹配本次查询源盘位;工作位只用于页面身份与业务权限 - rqrq - if (!StringUtils.hasText(sortingStation) || !sourceStation.equalsIgnoreCase(sortingStation.trim())) { + // WCS返回的是分拣工作位,必须匹配本次查询对应工作位;请求侧仍发送源盘位 - rqrq + if (!StringUtils.hasText(sortingStation) || !responseWorkStation.equalsIgnoreCase(sortingStation.trim())) { continue; } - // 配对源盘位只能出现一次,重复站点可能混入不同批次清单,拒绝后回退空列表以阻断错误扫码 - rqrq - if (matchedSource) { - throw new RuntimeException("WCS重复返回被分拣位:" + sourceStation); + // 配对工作位只能出现一次,重复站点可能混入不同批次清单,拒绝后回退空列表以阻断错误扫码 - rqrq + if (matchedWorkStation) { + throw new RuntimeException("WCS重复返回分拣位:" + responseWorkStation); } - matchedSource = true; + matchedWorkStation = true; JsonNode materials = stationNode.path("materials"); if (!materials.isArray()) { - throw new RuntimeException("WCS被分拣位materials不是数组:" + sourceStation); + throw new RuntimeException("WCS分拣位materials不是数组:" + responseWorkStation); } if (materials.isArray()) { for (JsonNode material : materials) { @@ -439,7 +443,7 @@ public class HaiAnPdaAutoWarehouseServiceImpl implements HaiAnPdaAutoWarehouseSe } } - // 仅缺少站点数组时兼容极简materials;有数组但未命中源盘位时保持空清单,禁止兜底混入别站标签 - rqrq + // 仅缺少站点数组时兼容极简materials;有数组但未命中工作位时保持空清单,禁止兜底混入别站标签 - rqrq if (sortingStations.isMissingNode() || sortingStations.isNull()) { JsonNode materials = rootNode.path("materials"); if (materials.isArray()) { diff --git a/src/main/java/com/gaotao/modules/autoWareHourceHaian/service/impl/HaiAnSortingBoardSource.java b/src/main/java/com/gaotao/modules/autoWareHourceHaian/service/impl/HaiAnSortingBoardSource.java index b6e036af..2464bf0b 100644 --- a/src/main/java/com/gaotao/modules/autoWareHourceHaian/service/impl/HaiAnSortingBoardSource.java +++ b/src/main/java/com/gaotao/modules/autoWareHourceHaian/service/impl/HaiAnSortingBoardSource.java @@ -91,7 +91,7 @@ public class HaiAnSortingBoardSource { return result; } - /** ALL返回被分拣源盘位RFID,反向归属到工作位缓存;缺站保留异常,空materials为正常空看板,未知源盘位跳过 - rqrq */ + /** ALL返回分拣工作位RFID,归属到工作位缓存;兼容源盘位旧报文,缺站保留异常,空materials为正常空看板 - rqrq */ private Map loadBoards(String site) throws Exception { HaiAnAutoSortingInfoRequest request = new HaiAnAutoSortingInfoRequest(); request.setSite(site); @@ -108,18 +108,18 @@ public class HaiAnSortingBoardSource { throw new IllegalStateException("WCS未返回sortingStations数组"); } // 预置六个分拣位,WCS没有返回的点位不能悄悄保留上轮数据 - rqrq - Map boards = unavailableBoards(site, "WCS未返回对应被分拣位,请核对位置配置"); + Map boards = unavailableBoards(site, "WCS未返回对应分拣位,请核对位置配置"); Map> stationLabels = new LinkedHashMap<>(); for (JsonNode stationNode : stations) { - String sourceStation = stationNode.path("sortingStation").asText("").trim().toUpperCase(Locale.ROOT); - // 按唯一配对将WCS源盘位归属到工作位;未知位置返回空串后跳过,不能将别站数据塞进六屏 - rqrq - String station = HaiAnStationStaticData.resolveSortingWorkStation(sourceStation); + String returnedStation = stationNode.path("sortingStation").asText("").trim().toUpperCase(Locale.ROOT); + // WCS当前返回工作位,兼容旧源盘位后统一归一到看板工作位;未知位置跳过,不能将别站数据塞进六屏 - rqrq + String station = HaiAnStationStaticData.resolveSortingWorkStation(returnedStation); if (!boards.containsKey(station)) { continue; } JsonNode materials = stationNode.get("materials"); if (stationLabels.containsKey(station) || materials == null || !materials.isArray()) { - throw new IllegalStateException("WCS被分拣位重复或materials不是数组:" + sourceStation); + throw new IllegalStateException("WCS分拣位重复或materials不是数组:" + returnedStation); } Set labels = new LinkedHashSet<>(); for (JsonNode material : materials) { diff --git a/src/main/java/com/gaotao/modules/autoWareHourceHaian/staticData/HaiAnStationStaticData.java b/src/main/java/com/gaotao/modules/autoWareHourceHaian/staticData/HaiAnStationStaticData.java index 9c59b3b3..ee9f7dcb 100644 --- a/src/main/java/com/gaotao/modules/autoWareHourceHaian/staticData/HaiAnStationStaticData.java +++ b/src/main/java/com/gaotao/modules/autoWareHourceHaian/staticData/HaiAnStationStaticData.java @@ -161,11 +161,15 @@ public final class HaiAnStationStaticData { throw new IllegalArgumentException("站点未配置分拣源盘对应关系:" + station); } - /** WCS返回源盘位反查实际工作位,供ALL快照归属;未知站点返回空串,由看板跳过非本组六屏数据。 - rqrq */ - public static String resolveSortingWorkStation(String sourceStation) { - String source = sourceStation == null ? "" : sourceStation.trim().toUpperCase(Locale.ROOT); + /** WCS返回工作位归属看板;兼容源盘位回传并反查工作位,未知站点返回空串,由看板跳过非本组六屏数据。 - rqrq */ + public static String resolveSortingWorkStation(String stationCode) { + String station = stationCode == null ? "" : stationCode.trim().toUpperCase(Locale.ROOT); + // 当前WCS返回分拣工作位,工作位本身就是看板身份;保留源盘位反查兼容旧报文 - rqrq + if (SORTING_SOURCE_BY_WORK.containsKey(station)) { + return station; + } for (Map.Entry entry : SORTING_SOURCE_BY_WORK.entrySet()) { - if (entry.getValue().equals(source)) { + if (entry.getValue().equals(station)) { return entry.getKey(); } }