cl
6 天以前 54794979fc9ad0aacf21f4e47a84c24e8f675251
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
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()));
    }
}