|
|
@ -24,7 +24,6 @@ import com.gaotao.modules.autoWareHourceHaian.api.entity.HaiAnRobotErrorRequest; |
|
|
import com.gaotao.modules.autoWareHourceHaian.api.entity.HaiAnWcsInboundCallbackRequest; |
|
|
import com.gaotao.modules.autoWareHourceHaian.api.entity.HaiAnWcsInboundCallbackRequest; |
|
|
import com.gaotao.modules.autoWareHourceHaian.api.service.HaiAnWmsMessageService; |
|
|
import com.gaotao.modules.autoWareHourceHaian.api.service.HaiAnWmsMessageService; |
|
|
import com.gaotao.modules.autoWareHourceHaian.entity.HaiAnCountResultInsertData; |
|
|
import com.gaotao.modules.autoWareHourceHaian.entity.HaiAnCountResultInsertData; |
|
|
import com.gaotao.modules.autoWareHourceHaian.entity.HaiAnTransportTaskDetailLockParam; |
|
|
|
|
|
import com.gaotao.modules.autoWareHourceHaian.entity.pda.HaiAnAreaOption; |
|
|
import com.gaotao.modules.autoWareHourceHaian.entity.pda.HaiAnAreaOption; |
|
|
import com.gaotao.modules.autoWareHourceHaian.entity.pda.HaiAnHandlingUnitLabelRow; |
|
|
import com.gaotao.modules.autoWareHourceHaian.entity.pda.HaiAnHandlingUnitLabelRow; |
|
|
import com.gaotao.modules.autoWareHourceHaian.entity.pda.HaiAnPalletDetailRow; |
|
|
import com.gaotao.modules.autoWareHourceHaian.entity.pda.HaiAnPalletDetailRow; |
|
|
@ -184,7 +183,7 @@ public class HaiAnWmsMessageServiceImpl implements HaiAnWmsMessageService { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* @Description 立库同步RFID复核:同site+taskNo只认首次结果;首次比对后先写已录入明细,再提交并返回原立库报文。- rqrq |
|
|
|
|
|
|
|
|
* @Description 立库同步RFID复核:在线表同site+taskNo+RFID复核动作已有记录时复用首次结果,否则比对并写入已录入明细后返回立库报文。- rqrq |
|
|
* @param data site、搬运taskNo、palletId必填;rfidBarcodes空值按空盘比对,不要求运输主表已存在。- rqrq |
|
|
* @param data site、搬运taskNo、palletId必填;rfidBarcodes空值按空盘比对,不要求运输主表已存在。- rqrq |
|
|
* @return 首次响应的完整字段;重复调用返回已保存的首次响应,不因再次扫描改变运输动作。- rqrq |
|
|
* @return 首次响应的完整字段;重复调用返回已保存的首次响应,不因再次扫描改变运输动作。- rqrq |
|
|
*/ |
|
|
*/ |
|
|
@ -206,9 +205,7 @@ public class HaiAnWmsMessageServiceImpl implements HaiAnWmsMessageService { |
|
|
throw new RuntimeException("RFID复核taskNo或palletId超过运输明细字段长度"); |
|
|
throw new RuntimeException("RFID复核taskNo或palletId超过运输明细字段长度"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 与AGV回调共用事务级任务锁;锁失败中断首次复核写入,不查询或要求运输主表存在。- rqrq |
|
|
|
|
|
acquireTransportTaskDetailInsertLock(site, taskNo); |
|
|
|
|
|
// 锁内先读取历史及在线首条;重复请求直接返回首轮响应,禁止用本次扫描覆盖复核事实。- rqrq |
|
|
|
|
|
|
|
|
// 仅按请求site+taskNo+RFID复核动作查询在线首条;已存在则返回首次响应,查询失败中断,不申请应用锁。- rqrq |
|
|
HaiAnWmsTransportTaskDetail firstDetail = haiAnAgvTaskMapper.getFirstRfidVerifyDetail( |
|
|
HaiAnWmsTransportTaskDetail firstDetail = haiAnAgvTaskMapper.getFirstRfidVerifyDetail( |
|
|
site, taskNo, HaiAnAgvCallbackTypeStaticData.RFID_CHECK); |
|
|
site, taskNo, HaiAnAgvCallbackTypeStaticData.RFID_CHECK); |
|
|
if (firstDetail != null) { |
|
|
if (firstDetail != null) { |
|
|
@ -265,7 +262,7 @@ public class HaiAnWmsMessageServiceImpl implements HaiAnWmsMessageService { |
|
|
+ differenceType + "," + differenceDetail); |
|
|
+ differenceType + "," + differenceDetail); |
|
|
result.setActionDirective("EXIT_TO_INBOUND_PORT"); |
|
|
result.setActionDirective("EXIT_TO_INBOUND_PORT"); |
|
|
} |
|
|
} |
|
|
// 锁内按本任务现有步骤分配序号;失败回滚复核事务,避免只返回立库结果而无待消费明细。- rqrq |
|
|
|
|
|
|
|
|
// 按在线任务现有步骤分配序号;失败回滚复核事务,避免只返回立库结果而无待消费明细。- rqrq |
|
|
Integer nextSeqNo = haiAnAgvTaskMapper.getNextSeqNoForTaskDetail(site, taskNo); |
|
|
Integer nextSeqNo = haiAnAgvTaskMapper.getNextSeqNoForTaskDetail(site, taskNo); |
|
|
if (nextSeqNo == null || nextSeqNo <= 0) { |
|
|
if (nextSeqNo == null || nextSeqNo <= 0) { |
|
|
throw new RuntimeException("RFID复核生成运输明细序号失败,taskNo=" + taskNo); |
|
|
throw new RuntimeException("RFID复核生成运输明细序号失败,taskNo=" + taskNo); |
|
|
@ -285,6 +282,7 @@ public class HaiAnWmsMessageServiceImpl implements HaiAnWmsMessageService { |
|
|
// 首次响应和RFID业务错误同事务写入海安运输明细;重复保护返回0时回读首条,绝不返回未落库的新判定。- rqrq |
|
|
// 首次响应和RFID业务错误同事务写入海安运输明细;重复保护返回0时回读首条,绝不返回未落库的新判定。- rqrq |
|
|
int insertedRows = haiAnAgvTaskMapper.insertTransportTaskDetail(detail); |
|
|
int insertedRows = haiAnAgvTaskMapper.insertTransportTaskDetail(detail); |
|
|
if (insertedRows <= 0) { |
|
|
if (insertedRows <= 0) { |
|
|
|
|
|
// 插入前已出现相同在线业务键时回读首次响应;未找到记录则回滚,禁止返回未保存的扫描结果。- rqrq |
|
|
HaiAnWmsTransportTaskDetail concurrentFirst = haiAnAgvTaskMapper.getFirstRfidVerifyDetail( |
|
|
HaiAnWmsTransportTaskDetail concurrentFirst = haiAnAgvTaskMapper.getFirstRfidVerifyDetail( |
|
|
site, taskNo, HaiAnAgvCallbackTypeStaticData.RFID_CHECK); |
|
|
site, taskNo, HaiAnAgvCallbackTypeStaticData.RFID_CHECK); |
|
|
if (concurrentFirst == null) { |
|
|
if (concurrentFirst == null) { |
|
|
@ -315,7 +313,7 @@ public class HaiAnWmsMessageServiceImpl implements HaiAnWmsMessageService { |
|
|
} |
|
|
} |
|
|
return saved; |
|
|
return saved; |
|
|
} |
|
|
} |
|
|
// 历史AGV回调不具备首次同步响应;仅从首条comment恢复通过/失败,避免重复扫描改变定时任务既定动作。- rqrq |
|
|
|
|
|
|
|
|
// 旧AGV在线明细不具备首次同步响应;仅从首条comment恢复通过/失败,避免重复扫描改变定时任务既定动作。- rqrq |
|
|
boolean passed = HaiAnRfidCheckResultStaticData.PASS.equals( |
|
|
boolean passed = HaiAnRfidCheckResultStaticData.PASS.equals( |
|
|
detail.getComment() == null ? null : detail.getComment().trim()); |
|
|
detail.getComment() == null ? null : detail.getComment().trim()); |
|
|
HaiAnInboundRfidVerifyResult result = new HaiAnInboundRfidVerifyResult(); |
|
|
HaiAnInboundRfidVerifyResult result = new HaiAnInboundRfidVerifyResult(); |
|
|
@ -331,25 +329,6 @@ public class HaiAnWmsMessageServiceImpl implements HaiAnWmsMessageService { |
|
|
return result; |
|
|
return result; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* @Description 通过单次Callable取得同site+taskNo的事务级应用锁;两入口共用锁键并在锁内分配明细序号。- rqrq |
|
|
|
|
|
* @param site 请求大site,必须已按入口规则校验,不能取登录态。- rqrq |
|
|
|
|
|
* @param taskNo 搬运任务号,直接对应明细task_no,不要求主任务存在。- rqrq |
|
|
|
|
|
*/ |
|
|
|
|
|
private void acquireTransportTaskDetailInsertLock(String site, String taskNo) { |
|
|
|
|
|
if (!StringUtils.hasText(site) || !StringUtils.hasText(taskNo)) { |
|
|
|
|
|
throw new RuntimeException("运输明细写入锁缺少site或taskNo"); |
|
|
|
|
|
} |
|
|
|
|
|
HaiAnTransportTaskDetailLockParam lockParam = new HaiAnTransportTaskDetailLockParam(site, taskNo); |
|
|
|
|
|
// 单次调用SQL Server sp_getapplock并读取返回码;数据库异常或负码须回滚,禁止无锁写入首次复核。- rqrq |
|
|
|
|
|
haiAnAgvTaskMapper.lockTransportTaskDetailInsert(lockParam); |
|
|
|
|
|
Integer lockResult = lockParam.getLockResult(); |
|
|
|
|
|
if (lockResult == null || lockResult < 0) { |
|
|
|
|
|
throw new RuntimeException("取得运输明细写入锁失败,site=" + site + ",taskNo=" + taskNo |
|
|
|
|
|
+ ",lockResult=" + lockResult); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* @author rqrq |
|
|
* @author rqrq |
|
|
* @Description 处理海安立库出入库回调:按事务类型分流落库,到达出库口(原取货通知)执行幂等校验,目标区域固定A01并映射仓库/库位;仅认新中文 - rqrq |
|
|
* @Description 处理海安立库出入库回调:按事务类型分流落库,到达出库口(原取货通知)执行幂等校验,目标区域固定A01并映射仓库/库位;仅认新中文 - rqrq |
|
|
@ -1523,22 +1502,18 @@ public class HaiAnWmsMessageServiceImpl implements HaiAnWmsMessageService { |
|
|
// 托盘号兼容对端pallet与内部palletId,两者都有时取palletId,避免协议字段名不一致导致下达任务落空托盘 - rqrq |
|
|
// 托盘号兼容对端pallet与内部palletId,两者都有时取palletId,避免协议字段名不一致导致下达任务落空托盘 - rqrq |
|
|
String palletId = data.resolvePalletId(); |
|
|
String palletId = data.resolvePalletId(); |
|
|
String targetPoint = data.getTargetPoint().trim(); |
|
|
String targetPoint = data.getTargetPoint().trim(); |
|
|
// 按目标站点先识别立库三个口,再解析其它区域;缺少映射时保留WCS原码,仍须保存回调轨迹。- rqrq |
|
|
|
|
|
String targetArea = convertAgvTargetAreaToBusinessArea(site, data.getTargetArea(), targetPoint); |
|
|
|
|
|
String normalizedType = normalizeAgvCallbackType(data.getType()); |
|
|
String normalizedType = normalizeAgvCallbackType(data.getType()); |
|
|
|
|
|
|
|
|
// 2. 只写haian_wms_transport_task_detail:task_no用wmsId,状态统一“已录入”,targetArea落to_area,不校验主记录存在 - rqrq |
|
|
// 2. 只写haian_wms_transport_task_detail:task_no用wmsId,状态统一“已录入”,targetArea落to_area,不校验主记录存在 - rqrq |
|
|
// 与同步RFID复核共用事务级任务锁;失败中断,避免两入口并发分到同一seqNo或产生两条首次复核。- rqrq |
|
|
|
|
|
acquireTransportTaskDetailInsertLock(site, wmsId); |
|
|
|
|
|
// 旧AGV接口的RFID动作也须遵守首次结果;历史或在线已有复核时直接幂等返回,不在归档后补写第二条。- rqrq |
|
|
|
|
|
if (HaiAnAgvCallbackTypeStaticData.RFID_CHECK.equals(normalizedType)) { |
|
|
|
|
|
HaiAnWmsTransportTaskDetail firstRfidDetail = haiAnAgvTaskMapper.getFirstRfidVerifyDetail( |
|
|
|
|
|
site, wmsId, HaiAnAgvCallbackTypeStaticData.RFID_CHECK); |
|
|
|
|
|
if (firstRfidDetail != null) { |
|
|
|
|
|
updateSuccessLog(logId, messageId + " | RFID复核已按首次结果录入,跳过重复回调", startTime); |
|
|
|
|
|
return messageId; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 仅按请求site+wmsId(taskNo)+归一化type查询在线明细;任意状态已有记录即幂等跳过,查询失败回滚,不申请应用锁。- rqrq |
|
|
|
|
|
Integer existingCount = haiAnAgvTaskMapper.countTaskDetailByType(site, wmsId, normalizedType); |
|
|
|
|
|
if (existingCount != null && existingCount > 0) { |
|
|
|
|
|
// 重复回调仅补齐本次接口成功日志,不覆盖在线明细及其首次业务结果。- rqrq |
|
|
|
|
|
updateSuccessLog(logId, messageId + " | 同site+taskNo+type在线明细已存在,跳过重复回调", startTime); |
|
|
|
|
|
return messageId; |
|
|
} |
|
|
} |
|
|
|
|
|
// 在线无同动作记录才解析目标区域;按site与站点识别立库口,其它区域缺少映射时保留WCS原码供消费重试。- rqrq |
|
|
|
|
|
String targetArea = convertAgvTargetAreaToBusinessArea(site, data.getTargetArea(), targetPoint); |
|
|
// 序号仍按当前最大步骤+1;插入语句内按动作去重,已存在则返回0。- rqrq |
|
|
// 序号仍按当前最大步骤+1;插入语句内按动作去重,已存在则返回0。- rqrq |
|
|
Integer nextSeqNo = haiAnAgvTaskMapper.getNextSeqNoForTaskDetail(site, wmsId); |
|
|
Integer nextSeqNo = haiAnAgvTaskMapper.getNextSeqNoForTaskDetail(site, wmsId); |
|
|
if (nextSeqNo == null || nextSeqNo <= 0) { |
|
|
if (nextSeqNo == null || nextSeqNo <= 0) { |
|
|
|