You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
303 lines
14 KiB
303 lines
14 KiB
package com.gaotao.modules.autoWareHourceHaian.staticData;
|
|
|
|
import org.springframework.util.StringUtils;
|
|
|
|
import java.util.Arrays;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
import java.util.LinkedHashMap;
|
|
import java.util.Locale;
|
|
import java.util.Map;
|
|
|
|
/**
|
|
* @author rqrq
|
|
* @Description 海安物理站点/点位写死值:入库口、整托出库口、缓冲线、分拣位、异常位。PDA/回调认点位一律走本类,禁止业务侧再写站点字面量;WCS 回调 toBarcode 与业务站点同名,禁止数字码转 D1/D2。已确认入库口、整托出库口;其余立库站点实际编码待确认。 - rqrq
|
|
*/
|
|
public final class HaiAnStationStaticData {
|
|
|
|
private HaiAnStationStaticData() {
|
|
}
|
|
|
|
/**
|
|
* 海安唯一入库口。空托盘通知入库、直接组盘下发 WCS assemblyPosition 固定用此值,禁止再拆入库口1/2。 - rqrq
|
|
*/
|
|
public static final String INBOUND_PORT = "ST-INO1";
|
|
|
|
/**
|
|
* 主动叫料固定站点:Call料、合托、盘点拉板下发 WCS targetPosition。已确认为整托出库口,与普通出库口不是同一点。 - rqrq
|
|
*/
|
|
public static final String DIRECT_OUTBOUND_PORT = "ST-FO-01";
|
|
|
|
/**
|
|
* 普通出库口站点名。主动叫料本阶段不用;WCS「到达出库口」回传点位可能是此值,按回传原样落托盘。待确认站点实际编码。 - rqrq
|
|
*/
|
|
public static final String NORMAL_OUTBOUND_PORT = "ST-OUTO1";
|
|
|
|
/**
|
|
* 立库内允许人工移出/作为地面运输端点的三个口;区域均为A01,不包含货架、输送线、异常位或分拣位。 - rqrq
|
|
*/
|
|
public static final List<String> WAREHOUSE_PORT_STATIONS = Collections.unmodifiableList(
|
|
Arrays.asList(INBOUND_PORT, NORMAL_OUTBOUND_PORT, DIRECT_OUTBOUND_PORT)
|
|
);
|
|
|
|
/**
|
|
* 判断站点是否为入库口,去首尾空格后比较;空值返回否,不使用区域编码替代站点身份。 - rqrq
|
|
*/
|
|
public static boolean isInboundPort(String stationCode) {
|
|
return stationCode != null && INBOUND_PORT.equalsIgnoreCase(stationCode.trim());
|
|
}
|
|
|
|
/**
|
|
* 判断站点是否为普通出库口,空值返回否;与整托出库口分别识别以保留原出口分工。 - rqrq
|
|
*/
|
|
public static boolean isNormalOutboundPort(String stationCode) {
|
|
return stationCode != null && NORMAL_OUTBOUND_PORT.equalsIgnoreCase(stationCode.trim());
|
|
}
|
|
|
|
/**
|
|
* 判断站点是否为整托出库口,空值返回否;Call料、合托、盘点仍以此站点作为固定出口。 - rqrq
|
|
*/
|
|
public static boolean isDirectOutboundPort(String stationCode) {
|
|
return stationCode != null && DIRECT_OUTBOUND_PORT.equalsIgnoreCase(stationCode.trim());
|
|
}
|
|
|
|
/**
|
|
* 判断三个立库端口的站点集合;用于区域归一、地面权限及目标过滤,未知或空站点一律不放行。 - rqrq
|
|
*/
|
|
public static boolean isWarehousePortStation(String stationCode) {
|
|
// 调用同一站点白名单匹配,避免扫描、下发和回调各自维护不同的端口规则 - rqrq
|
|
return containsIgnoreCase(WAREHOUSE_PORT_STATIONS, stationCode);
|
|
}
|
|
|
|
/**
|
|
* 立库缓冲输送线站点。离开入库口、出货架都把 location_code 写成此值;禁止取消组盘/一键移出的判定之一。老模块写入 Virtual_AS,海安写入本常量,识别时两者都算输送线。待确认站点实际编码。 - rqrq
|
|
*/
|
|
public static final String BUFFER_CONVEYOR = "立库输送线";
|
|
|
|
/**
|
|
* 异常位白名单。到达异常位必须命中本数组才落托盘位置,禁止写死单一编码;1101 仅兼容历史托盘。待确认站点实际编码。 - rqrq
|
|
*/
|
|
public static final List<String> ERROR_STATIONS = Collections.unmodifiableList(
|
|
Arrays.asList("EXCP-01", "EXCP-02", "EXCP-03", "EXCP-04")
|
|
);
|
|
|
|
/**
|
|
* 地面点位清单只拉空闲点时传给立库的 status。组盘/换站选点必须用此值,避免拉到占用点。 - rqrq
|
|
*/
|
|
public static final String GROUND_LOCATION_IDLE = "IDLE";
|
|
|
|
/**
|
|
* 地面点占用状态同步:移入站点 type=1。人工绑站成功后必须调 update-ground-location-status。 - rqrq
|
|
*/
|
|
public static final Integer GROUND_LOCATION_BIND = 1;
|
|
|
|
/**
|
|
* 地面点占用状态同步:移出站点 type=2。人工解绑成功后必须调 update-ground-location-status。 - rqrq
|
|
*/
|
|
public static final Integer GROUND_LOCATION_REMOVE = 2;
|
|
|
|
/**
|
|
* 自动分拣组盘位白名单,仅 ST-RP-03/ST-RP-04 两个位置;pickingFeedback 命中记“自动分拣”,不包含自动被分拣源盘位和人工分拣位。 - rqrq
|
|
*/
|
|
public static final List<String> AUTO_SORT_STATIONS = Collections.unmodifiableList(
|
|
Arrays.asList("ST-RP-03", "ST-RP-04")
|
|
);
|
|
|
|
/**
|
|
* 自动被分拣源盘位白名单,仅 ST-RP-01/ST-RP-02 两个位置;用于识别自动分拣来源托盘,不并入人工被分拣白名单,避免放行 PDA 人工放回及回库操作。 - rqrq
|
|
*/
|
|
public static final List<String> AUTO_SORTED_SOURCE_STATIONS = Collections.unmodifiableList(
|
|
Arrays.asList("ST-RP-01", "ST-RP-02")
|
|
);
|
|
|
|
/**
|
|
* 手工分拣区站点白名单。原有人工分拣组盘工作盘点位,R1 属于本组,不是被分拣位。分拣页按工作盘逻辑:卡清单、扫回还原原托盘、无增量跳过、endFlag=N。 - rqrq
|
|
*/
|
|
public static final List<String> MANUAL_SORT_STATIONS = Collections.unmodifiableList(
|
|
Arrays.asList("ST-MP-05", "ST-MP-06", "ST-MP-07", "ST-MP-08")
|
|
);
|
|
|
|
/**
|
|
* 海安新增被分拣源盘站点白名单。老模块没有这个站点概念,禁止复用手工分拣 R1–R4。分拣页命中后按放回标签/通知回库处理。站点实际编码待现场确认后只改本数组。 - rqrq
|
|
*/
|
|
public static final List<String> SORTED_SOURCE_STATIONS = Collections.unmodifiableList(
|
|
Arrays.asList("ST-MP-01", "ST-MP-02", "ST-MP-03", "ST-MP-04")
|
|
);
|
|
|
|
/** 工作位到被分拣源盘位的一对一映射,仅用于清单查询和看板归属,不修改托盘位置或作业权限。 - rqrq */
|
|
private static final Map<String, String> SORTING_SOURCE_BY_WORK;
|
|
/** 历史看板编号到实际工作位映射,仅供看板入口与旧订阅兼容,不作为PDA站点白名单。 - rqrq */
|
|
private static final Map<String, String> BOARD_WORK_BY_ALIAS;
|
|
static {
|
|
// 显式登记六组现场配对,禁止依赖数组顺序或数字偏移生成业务关系 - rqrq
|
|
Map<String, String> sources = new LinkedHashMap<>();
|
|
sources.put("ST-MP-05", "ST-MP-01");
|
|
sources.put("ST-MP-06", "ST-MP-02");
|
|
sources.put("ST-MP-07", "ST-MP-03");
|
|
sources.put("ST-MP-08", "ST-MP-04");
|
|
sources.put("ST-RP-03", "ST-RP-01");
|
|
sources.put("ST-RP-04", "ST-RP-02");
|
|
SORTING_SOURCE_BY_WORK = Collections.unmodifiableMap(sources);
|
|
Map<String, String> aliases = new LinkedHashMap<>();
|
|
aliases.put("R1H", "ST-MP-05");
|
|
aliases.put("R2H", "ST-MP-06");
|
|
aliases.put("R3H", "ST-MP-07");
|
|
aliases.put("R4H", "ST-MP-08");
|
|
aliases.put("J1H", "ST-RP-03");
|
|
aliases.put("J2H", "ST-RP-04");
|
|
BOARD_WORK_BY_ALIAS = Collections.unmodifiableMap(aliases);
|
|
}
|
|
|
|
/** 按实际托盘站点取得WCS查询源盘位;已是源盘位则原样返回,空值/未知站点抛错阻止错误外呼。 - rqrq */
|
|
public static String requireSortingSourceStation(String stationCode) {
|
|
String station = stationCode == null ? "" : stationCode.trim().toUpperCase(Locale.ROOT);
|
|
String source = SORTING_SOURCE_BY_WORK.get(station);
|
|
if (source != null) {
|
|
return source;
|
|
}
|
|
if (SORTING_SOURCE_BY_WORK.containsValue(station)) {
|
|
return station;
|
|
}
|
|
throw new IllegalArgumentException("站点未配置分拣源盘对应关系:" + station);
|
|
}
|
|
|
|
/** 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(station)) {
|
|
return entry.getKey();
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
|
|
/** 看板请求工作位归一,兼容R1H–R4H/J1H/J2H;被分拣位、空值和未知编码拒绝,避免串屏。 - rqrq */
|
|
public static String requireSortingBoardWorkStation(String stationCode) {
|
|
String station = stationCode == null ? "" : stationCode.trim().toUpperCase(Locale.ROOT);
|
|
String work = BOARD_WORK_BY_ALIAS.get(station);
|
|
if (work != null) {
|
|
return work;
|
|
}
|
|
if (SORTING_SOURCE_BY_WORK.containsKey(station)) {
|
|
return station;
|
|
}
|
|
throw new IllegalArgumentException("不支持的海安看板分拣位:" + station);
|
|
}
|
|
|
|
/** 按工作位取得历史看板别名供兼容主题推送,未知编码返回空串表示无需额外推送。 - rqrq */
|
|
public static String resolveSortingBoardAlias(String workStation) {
|
|
for (Map.Entry<String, String> entry : BOARD_WORK_BY_ALIAS.entrySet()) {
|
|
if (entry.getValue().equalsIgnoreCase(workStation)) {
|
|
return entry.getKey();
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
|
|
/**
|
|
* @author rqrq
|
|
* @Description 判断当前站点是否为手工分拣区:命中 R1–R4 才算,空值否。用于和被分拣位区分,禁止把手工分拣站当成被分拣源盘。 - rqrq
|
|
*/
|
|
public static boolean isManualSortStation(String locationCode) {
|
|
return containsIgnoreCase(MANUAL_SORT_STATIONS, locationCode);
|
|
}
|
|
|
|
/**
|
|
* @author rqrq
|
|
* @Description 判断当前站点是否为海安被分拣源盘点:只对照 SORTED_SOURCE_STATIONS,空值否;忽略大小写。未配置站点时一律否,避免把 R1 手工分拣区误判成被分拣。 - rqrq
|
|
*/
|
|
public static boolean isSortedSourceStation(String locationCode) {
|
|
return containsIgnoreCase(SORTED_SOURCE_STATIONS, locationCode);
|
|
}
|
|
|
|
/**
|
|
* @author rqrq
|
|
* @Description 判断当前点位是否属于分拣作业站:手工分拣区或海安被分拣站都算。组盘入库/手工组盘必须拦截这类栈板,禁止和分拣页共用放行逻辑。 - rqrq
|
|
*/
|
|
public static boolean isSortingOperateStation(String locationCode) {
|
|
return isManualSortStation(locationCode) || isSortedSourceStation(locationCode);
|
|
}
|
|
|
|
/**
|
|
* @author rqrq
|
|
* @Description 返回分拣作业站中文角色,供组盘页拦截提示区分手工分拣区与被分拣站;未命中返回空串。 - rqrq
|
|
*/
|
|
public static String describeSortingOperateStation(String locationCode) {
|
|
if (isManualSortStation(locationCode)) {
|
|
return "手工分拣区";
|
|
}
|
|
if (isSortedSourceStation(locationCode)) {
|
|
return "被分拣站";
|
|
}
|
|
return "";
|
|
}
|
|
|
|
/**
|
|
* @author rqrq
|
|
* @Description 判断当前站点是否为异常位:命中 ERROR_STATIONS 才算,空值否。用于取消预定拦截与到达异常位校验。 - rqrq
|
|
*/
|
|
public static boolean isErrorStation(String locationCode) {
|
|
return containsIgnoreCase(ERROR_STATIONS, locationCode);
|
|
}
|
|
|
|
/**
|
|
* @author rqrq
|
|
* @Description 校验到达异常位回传点位必须落在异常位数组内,非法则抛错避免把非异常口写成异常落位。 - rqrq
|
|
*/
|
|
public static String requireErrorStation(String stationCode) {
|
|
if (!isErrorStation(stationCode)) {
|
|
throw new RuntimeException("到达异常位点位非法,不在异常位清单内:" + (stationCode == null ? "" : stationCode.trim()));
|
|
}
|
|
return stationCode.trim();
|
|
}
|
|
|
|
/**
|
|
* @author rqrq
|
|
* @Description 判断当前点位是否为自动分拣组盘位,供 pickingFeedback 动作类型分流。 - rqrq
|
|
*/
|
|
public static boolean isAutoSortStation(String assemblyPosition) {
|
|
return containsIgnoreCase(AUTO_SORT_STATIONS, assemblyPosition);
|
|
}
|
|
|
|
/**
|
|
* 判断业务站点是否为自动被分拣源盘位;输入站点编码去首尾空格并忽略大小写,空值或未知站点返回否,不授予 PDA 人工分拣权限。 - rqrq
|
|
*/
|
|
public static boolean isAutoSortedSourceStation(String locationCode) {
|
|
// 调用自动被分拣专用白名单匹配,未命中返回否,避免与自动组盘位或人工被分拣位混淆 - rqrq
|
|
return containsIgnoreCase(AUTO_SORTED_SOURCE_STATIONS, locationCode);
|
|
}
|
|
|
|
/**
|
|
* @author rqrq
|
|
* @Description 判断托盘是否位于输送线:Virtual_AS 或立库输送线都视为输送线态。 - rqrq
|
|
*/
|
|
public static boolean isConveyorStation(String locationCode) {
|
|
if (!StringUtils.hasText(locationCode)) {
|
|
return false;
|
|
}
|
|
String normalized = locationCode.trim();
|
|
return BUFFER_CONVEYOR.equals(normalized);
|
|
}
|
|
|
|
/**
|
|
* @author rqrq
|
|
* @Description 白名单忽略大小写匹配,空值直接否。 - rqrq
|
|
*/
|
|
private static boolean containsIgnoreCase(List<String> stations, String value) {
|
|
if (!StringUtils.hasText(value) || stations == null) {
|
|
return false;
|
|
}
|
|
String normalized = value.trim();
|
|
for (String station : stations) {
|
|
if (station.equalsIgnoreCase(normalized)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|