Browse Source

接口bug

clodop
常熟吴彦祖 1 month ago
parent
commit
e5c398a66f
  1. 4
      src/main/java/com/gaotao/modules/autoWareHourceHaian/HAIAN_AI_CONTEXT.md
  2. 2
      src/main/java/com/gaotao/modules/autoWareHourceHaian/api/entity/HaiAnAutoSortingInfoRequest.java
  3. 26
      src/main/java/com/gaotao/modules/autoWareHourceHaian/service/impl/HaiAnPdaAutoWarehouseServiceImpl.java
  4. 12
      src/main/java/com/gaotao/modules/autoWareHourceHaian/service/impl/HaiAnSortingBoardSource.java
  5. 12
      src/main/java/com/gaotao/modules/autoWareHourceHaian/staticData/HaiAnStationStaticData.java

4
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

2
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;
}

26
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()) {

12
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<String, HaiAnSortingBoardResult> 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<String, HaiAnSortingBoardResult> boards = unavailableBoards(site, "WCS未返回对应被分拣位,请核对位置配置");
Map<String, HaiAnSortingBoardResult> boards = unavailableBoards(site, "WCS未返回对应分拣位,请核对位置配置");
Map<String, Set<String>> 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<String> labels = new LinkedHashSet<>();
for (JsonNode material : materials) {

12
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<String, String> entry : SORTING_SOURCE_BY_WORK.entrySet()) {
if (entry.getValue().equals(source)) {
if (entry.getValue().equals(station)) {
return entry.getKey();
}
}

Loading…
Cancel
Save