Browse Source

跨site调拨

clodop
常熟吴彦祖 2 months ago
parent
commit
7cad6afc6a
  1. 3
      .gitignore
  2. 2
      src/main/java/com/gaotao/modules/autoWareHourceHaian/HAIAN_AI_CONTEXT.md
  3. 8
      src/main/java/com/gaotao/modules/autoWareHourceHaian/api/controller/HaiAnWmsMessageController.java
  4. 25
      src/main/java/com/gaotao/modules/autoWareHourceHaian/api/entity/HaiAnAgvCallbackRequest.java
  5. 9
      src/main/java/com/gaotao/modules/autoWareHourceHaian/api/service/impl/HaiAnWmsMessageServiceImpl.java

3
.gitignore

@ -29,4 +29,5 @@ hs_err_pid*
# 本地行尾与编辑器配置仅用于开发机,不参与版本提交 - rqrq
.gitattributes
.editorconfig
.vscode/
.vscode/
.gitnexus

2
src/main/java/com/gaotao/modules/autoWareHourceHaian/HAIAN_AI_CONTEXT.md

@ -79,7 +79,7 @@
- 海安 `haian_ifs_pallet_move_queue.move_group_json.site` 存的是标签子site;自动任务执行时查询目标库位主数据必须先通过 `site_sub(subsiteid->siteid)` 反查大site,再按大site查询 `location`,禁止直接用子site查库位 - rqrq
- 海安 `HaianAutoTaskScheduler` 处理队列时必须先将 `serial_no_str` 对应标签回写到目标仓库/库位,再调用老IFS `MoveInventoryPartV2`;IFS失败要回滚标签更新,确保WMS与IFS库位一致性 - rqrq
- 海安自动任务开关使用 `scheduler.haianAutoTask.enabled`,P状态超时回收分钟数使用 `scheduler.haianAutoTask.ifsPalletMoveQueue.processing-timeout-minutes` - rqrq
- 海安 AGV 反馈接口 `POST /api/wms54/count/agvCallback` 新协议必填 `site/wmsId/taskId/palletId/targetPoint/targetArea/type`,`targetArea` 是下游 `wcs_area_code`,入库前必须按 `haian_area.wcs_area_code -> area_id` 转换后再写明细 `to_area`;`palletId` 在“下达任务”场景必须写入明细 `pallet_id`;`comment` 在“下达任务”场景写 `source_bill_no`、在 `RFID复核` 场景保存复核备注 - rqrq
- 海安 AGV 反馈接口 `POST /api/wms54/count/agvCallback` 新协议必填 `site/wmsId/taskId/托盘号/targetPoint/targetArea/type`;托盘号兼容 `palletId` 与对端协议字段 `pallet`,两者都有时优先 `palletId`,只传 `pallet` 也视为必填通过;`targetArea` 是下游 `wcs_area_code`,入库前必须按 `haian_area.wcs_area_code -> area_id` 转换后再写明细 `to_area`;解析后的托盘号在“下达任务”场景必须写入明细 `pallet_id`;`comment` 在“下达任务”场景写 `source_bill_no`、在 `RFID复核` 场景保存复核备注 - rqrq
- 海安 AGV 回调采用“两段式”:第一段接口仅写 `haian_wms_transport_task_detail(status=已录入)`;第二段由 `HaianWcsSchedule.scheduleAgvFeedback(3.1秒)` 乐观锁消费明细并驱动主任务/托盘状态(下达=calling_flag:Y并创建主任务含from_area、取货=托运中、送货=完成+按需移库+回写area/location、取消=已取消且calling_flag:N) - rqrq
- 海安 `wcsWareHouse` 回调同样采用“两段式”:第一段接口只写 `haian_wcs_callback_task(status=已录入)`;第二段由 `HaianWcsSchedule.scheduleHaianWcsTaskProcessing(2.6秒)` 乐观锁消费,并按 `入货架(原入库)/出货架(原出库)/离开入库口(原取走栈板)/到达异常位(原异常位处理)/到达出库口(原取货通知)/到达手工分拣区` 分流处理(到达出库口不再依赖transportTask分支,且不执行 `palletAutoGoToWCS.goToWCS` 回库逻辑;到达手工分拣区仅把 `haian_pallet.location_code` 改成回传点位,不改 calling_flag、不做移库) - rqrq
- 海安被分拣站点写死为 `R1/R2/R3/R4`(`HaiAnStationStaticData.SORTED_SOURCE_STATIONS`,与自动分拣 `J1/J2/J3/J4` 不是同一组)。到达手工分拣区会把 `haian_pallet.location_code` 改成回传点位,分拣页“放回标签”必须按当前 `location_code` 是否命中该数组判断被分拣源盘,禁止用“不是 J1-J4 就算被分拣”(会误放行货架/输送线)。现场编码不同时只改 `HaiAnStationStaticData` - rqrq

8
src/main/java/com/gaotao/modules/autoWareHourceHaian/api/controller/HaiAnWmsMessageController.java

@ -140,14 +140,14 @@ public class HaiAnWmsMessageController extends AbstractController {
/**
* @author rqrq
* @Description AGV任务反馈入口,确保任务定位参数有效后交给Service编排处理 - rqrq
* @param data AGV回调实体(site/wmsId/taskId/palletId/targetPoint/targetArea(type为WCS区域编码)/type/comment) - rqrq
* @param data AGV回调实体(site/wmsId/taskId/palletId或pallet/targetPoint/targetArea(type为WCS区域编码)/type/comment) - rqrq
* @return ResponseData 统一响应对象,成功返回messageId,失败返回错误原因 - rqrq
*/
@PostMapping("/count/agvCallback")
public ResponseData agvCallback(@RequestBody HaiAnAgvCallbackRequest data) {
try {
if (!validateAgvCallbackData(data)) {
return errorResponse("参数验证失败:site/wmsId/taskId/palletId/targetPoint/targetArea/type为必填项,type需为约定动作类型");
return errorResponse("参数验证失败:site/wmsId/taskId/托盘号(palletId或pallet)/targetPoint/targetArea/type为必填项,type需为约定动作类型");
}
String messageId = haiAnWmsMessageService.handleAgvCallback(data);
log.info("海安AGV任务反馈已接收 - rqrq,messageId={}, wmsId={}, taskId={}",
@ -232,14 +232,14 @@ public class HaiAnWmsMessageController extends AbstractController {
/**
* @author rqrq
* @Description 验证AGV任务反馈参数,确保主任务键与动作语义完整,避免状态串写 - rqrq
* @Description 验证AGV任务反馈参数,确保主任务键与动作语义完整,避免状态串写;托盘号走resolvePalletId兼容pallet/palletId - rqrq
*/
private boolean validateAgvCallbackData(HaiAnAgvCallbackRequest data) {
if (data == null
|| !StringUtils.hasText(data.getSite())
|| !StringUtils.hasText(data.getWmsId())
|| !StringUtils.hasText(data.getTaskId())
|| !StringUtils.hasText(data.getPalletId())
|| !StringUtils.hasText(data.resolvePalletId())
|| !StringUtils.hasText(data.getTargetPoint())
|| !StringUtils.hasText(data.getTargetArea())
|| !StringUtils.hasText(data.getType())) {

25
src/main/java/com/gaotao/modules/autoWareHourceHaian/api/entity/HaiAnAgvCallbackRequest.java

@ -1,6 +1,7 @@
package com.gaotao.modules.autoWareHourceHaian.api.entity;
import lombok.Data;
import org.springframework.util.StringUtils;
/**
* @author rqrq
@ -25,10 +26,17 @@ public class HaiAnAgvCallbackRequest {
private String taskId;
/**
* 托盘编号(必填):用于标识本次AGV反馈作用托盘,下达任务场景需落库到任务明细 - rqrq
* 托盘编号(优先取值):海安内部字段名;用于标识本次AGV反馈作用托盘,下达任务场景需落库到任务明细。
* 与 pallet 都有值时业务一律取本字段;不落请求表,仅回调入参。 - rqrq
*/
private String palletId;
/**
* 托盘编号兼容字段(对端协议名pallet):不落库、仅请求解析。
* 对端文档传 pallet 而不是 palletId 时由此接收;palletId 为空才使用本字段,避免双字段同时到达时口径漂移。 - rqrq
*/
private String pallet;
/**
* AGV设备号(可选) - rqrq
*/
@ -53,5 +61,20 @@ public class HaiAnAgvCallbackRequest {
* 回调备注(选填):RFID复核场景传复核结果文本,其它类型忽略 - rqrq
*/
private String comment;
/**
* @author rqrq
* @Description 解析AGV回调托盘号:palletId优先,缺省回退pallet;都空返回null,避免对端两种字段名导致必填校验误杀 - rqrq
* @return 去空格后的托盘号,两者都空时为null - rqrq
*/
public String resolvePalletId() {
if (StringUtils.hasText(palletId)) {
return palletId.trim();
}
if (StringUtils.hasText(pallet)) {
return pallet.trim();
}
return null;
}
}

9
src/main/java/com/gaotao/modules/autoWareHourceHaian/api/service/impl/HaiAnWmsMessageServiceImpl.java

@ -1338,7 +1338,8 @@ public class HaiAnWmsMessageServiceImpl implements HaiAnWmsMessageService {
validateAgvCallbackRequest(data);
String wmsId = data.getWmsId().trim();
String xjTaskId = data.getTaskId().trim();
String palletId = data.getPalletId().trim();
// 托盘号兼容对端pallet与内部palletId,两者都有时取palletId,避免协议字段名不一致导致下达任务落空托盘 - rqrq
String palletId = data.resolvePalletId();
String targetPoint = data.getTargetPoint().trim();
String targetArea = convertAgvTargetAreaToBusinessArea(site, data.getTargetArea());
String normalizedType = normalizeAgvCallbackType(data.getType());
@ -1405,18 +1406,18 @@ public class HaiAnWmsMessageServiceImpl implements HaiAnWmsMessageService {
/**
* @author rqrq
* @Description 校验AGV回调核心字段:site/wmsId/taskId/palletId/targetPoint/targetArea/type均必填且type必须在白名单内 - rqrq
* @Description 校验AGV回调核心字段:site/wmsId/taskId/托盘号(palletId优先否则pallet)/targetPoint/targetArea/type均必填且type必须在白名单内 - rqrq
*/
private void validateAgvCallbackRequest(HaiAnAgvCallbackRequest data) {
if (data == null
|| !StringUtils.hasText(data.getSite())
|| !StringUtils.hasText(data.getWmsId())
|| !StringUtils.hasText(data.getTaskId())
|| !StringUtils.hasText(data.getPalletId())
|| !StringUtils.hasText(data.resolvePalletId())
|| !StringUtils.hasText(data.getTargetPoint())
|| !StringUtils.hasText(data.getTargetArea())
|| !StringUtils.hasText(data.getType())) {
throw new RuntimeException("AGV反馈参数缺失:site/wmsId/taskId/palletId/targetPoint/targetArea/type为必填项");
throw new RuntimeException("AGV反馈参数缺失:site/wmsId/taskId/托盘号(palletId或pallet)/targetPoint/targetArea/type为必填项");
}
String normalizedType = normalizeAgvCallbackType(data.getType());
if (!isSupportedAgvCallbackType(normalizedType)) {

Loading…
Cancel
Save