package com.vincent.rsf.server.manager.service.impl;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.vincent.rsf.framework.common.R;
|
import com.vincent.rsf.server.api.controller.erp.params.InOutResultBatchPayload;
|
import com.vincent.rsf.server.api.controller.erp.params.InOutResultReportParam;
|
import com.vincent.rsf.server.manager.entity.AsnOrderLog;
|
import com.vincent.rsf.server.manager.entity.CloudWmsNotifyLog;
|
import com.vincent.rsf.server.manager.enums.OrderType;
|
import com.vincent.rsf.server.manager.service.AsnOrderLogService;
|
import com.vincent.rsf.server.manager.service.CloudWmsFeedbackResendService;
|
import com.vincent.rsf.server.manager.service.CloudWmsNotifyLogService;
|
import lombok.extern.slf4j.Slf4j;
|
import org.apache.commons.lang3.StringUtils;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
|
import java.util.*;
|
|
/**
|
* 历史单触发云仓入出库上报:优先放行该单暂缓待办;若无则从历史云仓上报记录复制请求体入队。
|
*/
|
@Slf4j
|
@Service
|
public class CloudWmsFeedbackResendServiceImpl implements CloudWmsFeedbackResendService {
|
|
private static final int MAX_SCAN = 500;
|
|
@Autowired
|
private AsnOrderLogService asnOrderLogService;
|
@Autowired
|
private CloudWmsNotifyLogService cloudWmsNotifyLogService;
|
@Autowired
|
private ObjectMapper objectMapper;
|
|
@Override
|
public R submitInOutCloudWmsByAsnOrderLogId(Long asnOrderLogId) {
|
if (asnOrderLogId == null) {
|
return R.error("参数不能为空");
|
}
|
AsnOrderLog orderLog = asnOrderLogService.getById(asnOrderLogId);
|
if (orderLog == null) {
|
return R.error("历史单据不存在");
|
}
|
String code = orderLog.getCode();
|
if (StringUtils.isBlank(code)) {
|
return R.error("单据号为空");
|
}
|
boolean inbound = inboundFromOrderType(orderLog.getType());
|
R flushR = cloudWmsNotifyLogService.manualFlushToNotifyByOrderCode(code.trim(), inbound);
|
Object flushCode = flushR.get("code");
|
if (flushCode instanceof Number && ((Number) flushCode).intValue() == 200) {
|
return flushR;
|
}
|
return enqueueFromHistoricalNotifyLogs(asnOrderLogId, orderLog, code);
|
}
|
|
private R enqueueFromHistoricalNotifyLogs(Long asnOrderLogId, AsnOrderLog orderLog, String code) {
|
String reportType = cloudWmsNotifyLogService.getReportTypeInOutResult();
|
LambdaQueryWrapper<CloudWmsNotifyLog> qw = new LambdaQueryWrapper<CloudWmsNotifyLog>()
|
.eq(CloudWmsNotifyLog::getReportType, reportType)
|
.and(w -> w.like(CloudWmsNotifyLog::getRequestBody, "\"orderNo\":\"" + code + "\"")
|
.or()
|
.like(CloudWmsNotifyLog::getBizRef, "orderNo=" + code))
|
.orderByDesc(CloudWmsNotifyLog::getId)
|
.last("LIMIT " + MAX_SCAN);
|
List<CloudWmsNotifyLog> candidates = cloudWmsNotifyLogService.list(qw);
|
Map<String, CloudWmsNotifyLog> latestByLine = new LinkedHashMap<>();
|
for (CloudWmsNotifyLog row : candidates) {
|
if (StringUtils.isBlank(row.getRequestBody())) {
|
continue;
|
}
|
try {
|
JsonNode root = objectMapper.readTree(row.getRequestBody());
|
if (root.has("lines") && root.get("lines").isArray() && root.get("lines").size() > 0) {
|
InOutResultBatchPayload batch = objectMapper.readValue(row.getRequestBody(), InOutResultBatchPayload.class);
|
if (batch.getLines() == null || batch.getLines().isEmpty()) {
|
continue;
|
}
|
InOutResultReportParam first = batch.getLines().get(0);
|
if (!code.equals(first.getOrderNo()) || !matchOrderType(orderLog.getType(), first.getInbound())) {
|
continue;
|
}
|
latestByLine.putIfAbsent("batch_" + row.getId(), row);
|
continue;
|
}
|
InOutResultReportParam p = objectMapper.readValue(row.getRequestBody(), InOutResultReportParam.class);
|
if (p == null || !code.equals(p.getOrderNo())) {
|
continue;
|
}
|
if (!matchOrderType(orderLog.getType(), p.getInbound())) {
|
continue;
|
}
|
String sig = lineSignature(p);
|
latestByLine.putIfAbsent(sig, row);
|
} catch (Exception e) {
|
continue;
|
}
|
}
|
if (latestByLine.isEmpty()) {
|
return R.error("未找到该单号对应的云仓入出库上报记录");
|
}
|
Date now = new Date();
|
int n = 0;
|
for (CloudWmsNotifyLog src : latestByLine.values()) {
|
CloudWmsNotifyLog copy = new CloudWmsNotifyLog()
|
.setReportType(reportType)
|
.setRequestBody(src.getRequestBody())
|
.setNotifyStatus(cloudWmsNotifyLogService.getNotifyStatusPending())
|
.setRetryCount(0)
|
.setBizRef("manualResend,asnOrderLogId=" + asnOrderLogId + ",fromNotifyLogId=" + src.getId() + ",orderNo=" + code)
|
.setCreateTime(now)
|
.setUpdateTime(now)
|
.setSendHold(0)
|
.setSending(0);
|
if (StringUtils.isNotBlank(src.getSourceOrderNo())) {
|
copy.setSourceOrderNo(src.getSourceOrderNo())
|
.setInboundFlag(src.getInboundFlag())
|
.setWareHouseCode(src.getWareHouseCode());
|
} else {
|
fillInOutRoutingFromBody(copy, src.getRequestBody());
|
}
|
if (saveOrRefreshResendRow(copy, now)) {
|
n++;
|
}
|
}
|
return R.ok("已加入云仓上报队列 " + n + " 条,将由定时任务发送").add(n);
|
}
|
|
private static boolean inboundFromOrderType(String type) {
|
if (StringUtils.isBlank(type)) {
|
return true;
|
}
|
return OrderType.ORDER_IN.type.equalsIgnoreCase(type.trim());
|
}
|
|
/**
|
* 同请求体已有待发送或失败记录:更新为可自动调度;否则插入新待办。
|
*/
|
private boolean saveOrRefreshResendRow(CloudWmsNotifyLog copy, Date now) {
|
int pending = cloudWmsNotifyLogService.getNotifyStatusPending();
|
int fail = cloudWmsNotifyLogService.getNotifyStatusFail();
|
LambdaQueryWrapper<CloudWmsNotifyLog> existQw = new LambdaQueryWrapper<CloudWmsNotifyLog>()
|
.eq(CloudWmsNotifyLog::getReportType, copy.getReportType())
|
.eq(CloudWmsNotifyLog::getRequestBody, copy.getRequestBody())
|
.in(CloudWmsNotifyLog::getNotifyStatus, pending, fail)
|
.orderByDesc(CloudWmsNotifyLog::getId)
|
.last("LIMIT 1");
|
CloudWmsNotifyLog existing = cloudWmsNotifyLogService.getOne(existQw);
|
if (existing != null && existing.getId() != null) {
|
CloudWmsNotifyLog row = new CloudWmsNotifyLog().setId(existing.getId());
|
cloudWmsNotifyLogService.fillFromConfig(row);
|
LambdaUpdateWrapper<CloudWmsNotifyLog> u = new LambdaUpdateWrapper<CloudWmsNotifyLog>()
|
.eq(CloudWmsNotifyLog::getId, existing.getId())
|
.set(CloudWmsNotifyLog::getNotifyStatus, row.getNotifyStatus())
|
.set(CloudWmsNotifyLog::getMaxRetryCount, row.getMaxRetryCount())
|
.set(CloudWmsNotifyLog::getRetryIntervalSeconds, row.getRetryIntervalSeconds())
|
.set(CloudWmsNotifyLog::getSendHold, 0)
|
.set(CloudWmsNotifyLog::getSending, 0)
|
.set(CloudWmsNotifyLog::getRetryCount, 0)
|
.set(CloudWmsNotifyLog::getBizRef, copy.getBizRef())
|
.set(CloudWmsNotifyLog::getUpdateTime, now)
|
.set(CloudWmsNotifyLog::getLastNotifyTime, null)
|
.set(CloudWmsNotifyLog::getLastResponseBody, null);
|
if (StringUtils.isNotBlank(copy.getSourceOrderNo())) {
|
u.set(CloudWmsNotifyLog::getSourceOrderNo, copy.getSourceOrderNo())
|
.set(CloudWmsNotifyLog::getInboundFlag, copy.getInboundFlag())
|
.set(CloudWmsNotifyLog::getWareHouseCode, copy.getWareHouseCode());
|
}
|
return cloudWmsNotifyLogService.update(u);
|
}
|
cloudWmsNotifyLogService.fillFromConfig(copy);
|
return cloudWmsNotifyLogService.save(copy);
|
}
|
|
private void fillInOutRoutingFromBody(CloudWmsNotifyLog copy, String body) {
|
if (StringUtils.isBlank(body)) {
|
return;
|
}
|
try {
|
JsonNode root = objectMapper.readTree(body);
|
if (root.has("lines") && root.get("lines").isArray() && root.get("lines").size() > 0) {
|
InOutResultReportParam first = objectMapper.treeToValue(root.get("lines").get(0), InOutResultReportParam.class);
|
if (first != null) {
|
boolean inb = first.getInbound() == null || Boolean.TRUE.equals(first.getInbound());
|
copy.setSourceOrderNo(first.getOrderNo())
|
.setInboundFlag(inb ? 1 : 0)
|
.setWareHouseCode(first.getWareHouseId());
|
}
|
return;
|
}
|
InOutResultReportParam p = objectMapper.readValue(body, InOutResultReportParam.class);
|
if (p != null) {
|
boolean inb = p.getInbound() == null || Boolean.TRUE.equals(p.getInbound());
|
copy.setSourceOrderNo(p.getOrderNo())
|
.setInboundFlag(inb ? 1 : 0)
|
.setWareHouseCode(p.getWareHouseId());
|
}
|
} catch (Exception ignored) {
|
}
|
}
|
|
private static boolean matchOrderType(String asnType, Boolean inbound) {
|
if (StringUtils.isBlank(asnType)) {
|
return true;
|
}
|
boolean wantIn = "in".equalsIgnoreCase(asnType.trim());
|
if (inbound == null) {
|
return true;
|
}
|
return wantIn == inbound;
|
}
|
|
private static String lineSignature(InOutResultReportParam p) {
|
return String.join("|",
|
String.valueOf(p.getOrderNo()),
|
String.valueOf(p.getLineId()),
|
String.valueOf(p.getMatNr()),
|
String.valueOf(p.getLocId()),
|
String.valueOf(p.getWareHouseId()),
|
String.valueOf(p.getInbound()),
|
String.valueOf(p.getQty()),
|
String.valueOf(p.getBatch()));
|
}
|
}
|