修改同步落库

This commit is contained in:
wuweihua
2026-10-27 00:04:21 +08:00
parent 2bae431e74
commit 7924450b89
7 changed files with 90 additions and 249 deletions
@@ -170,7 +170,7 @@ public class TabOrderMonitorController extends BaseController
customerKeywordResolver.resolve(query);
String asyncTaskId = UUID.randomUUID().toString().replace("-", "");
tabOrderCompareAsyncRunner.put(asyncTaskId, TabOrderCompareTask.STATUS_PENDING, 0, "queued",
0, 0, 0, 0, null, null, null);
0, 0, 0, null, null);
tabOrderCompareAsyncRunner.run(asyncTaskId, query);
Map<String, Object> data = new HashMap<String, Object>();
data.put("asyncTaskId", asyncTaskId);
@@ -7,8 +7,8 @@ import java.util.Map;
/**
* 订单比对异步任务进度(Redis)。
* missing = 上游有转单号、本地无;
* statusMismatch = 本地有转单号但 order_status 与上游不一致。
* missing = 上游有转单号、本地在指定状态集合中无对应单;
* statusMismatch 已废弃(恒为 0,不再比对状态)。
*/
public class TabOrderCompareTask implements Serializable
{
@@ -39,14 +39,16 @@ public interface PrcOrderBillMapper
List<String> selectExistingOrderIdentifiers(@Param("identifiers") List<String> identifiers,
@Param("customerCodes") List<String> customerCodes);
/** 订单比对:仅按转单号批量查本地已存在。 */
/** 订单比对:仅按转单号批量查本地已存在(可选 order_status 过滤)。 */
List<String> selectExistingTransferNos(@Param("transferNos") List<String> transferNos,
@Param("customerCodes") List<String> customerCodes);
@Param("customerCodes") List<String> customerCodes,
@Param("orderStatuses") List<Integer> orderStatuses);
/** 订单比对:按转单号批量查本地 transfer_no + order_status。 */
List<java.util.Map<String, Object>> selectTransferOrderStatuses(
@Param("transferNos") List<String> transferNos,
@Param("customerCodes") List<String> customerCodes);
@Param("customerCodes") List<String> customerCodes,
@Param("orderStatuses") List<Integer> orderStatuses);
/** 订单号下拉搜索(带数据权限) */
public List<String> selectOrderNoOptions(@Param("query") PrcOrderBill query, @Param("limit") int limit);
@@ -1,11 +1,14 @@
package com.bms.price.task;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -22,7 +25,8 @@ import com.bms.price.search.IBillSearchStore;
import com.bms.price.search.TabOrderSyncEsLog;
/**
* 订单比对异步任务:分页拉上游转单号+状态,与本地 transfer_no / order_status 比对。
* 订单比对异步任务:分页拉上游转单号,与本地 transfer_no 比对是否缺失。
* 上游扫描与本地匹配均使用列表「订单状态」筛选;不再比对/列出状态不一致。
*/
@Component
public class TabOrderCompareAsyncRunner
@@ -36,8 +40,12 @@ public class TabOrderCompareAsyncRunner
public static final int SCAN_HARD_LIMIT = 50000;
/** 进度/抽屉中保留的缺失转单号上限 */
public static final int MISSING_SAMPLE_LIMIT = 5000;
/** 状态不一致样本上限 */
public static final int STATUS_MISMATCH_SAMPLE_LIMIT = 5000;
/** Fallback when search orderStatuses empty (same as order-source list default). */
public static final List<Integer> COMPARE_LOCAL_ORDER_STATUSES =
Collections.unmodifiableList(Arrays.asList(
Integer.valueOf(3), Integer.valueOf(4), Integer.valueOf(5), Integer.valueOf(6),
Integer.valueOf(7), Integer.valueOf(8), Integer.valueOf(11)));
@Autowired
private TabOrderMonitorService tabOrderMonitorService;
@@ -63,14 +71,18 @@ public class TabOrderCompareAsyncRunner
query.setOrgOrderId(null);
query.setTransferOrderId(null);
}
// Use list filter orderStatuses for both upstream scan and local match (no hardcode).
List<Integer> compareStatuses = resolveCompareStatuses(query);
if (query != null)
{
query.setOrderStatuses(new ArrayList<Integer>(compareStatuses));
}
put(asyncTaskId, TabOrderCompareTask.STATUS_RUNNING, 0, "starting",
0, 0, 0, 0, null, null, null);
0, 0, 0, null, null);
int scanned = 0;
int matched = 0;
int missing = 0;
int statusMismatch = 0;
List<String> missingSample = new ArrayList<String>();
List<Map<String, Object>> statusMismatchSample = new ArrayList<Map<String, Object>>();
int pageNum = 1;
while (true)
{
@@ -96,8 +108,8 @@ public class TabOrderCompareAsyncRunner
transferNos.add(String.valueOf(tn).trim());
}
}
Map<String, Integer> localStatusByTn =
findLocalStatuses(transferNos, query == null ? null : query.getCustomerCodes());
Set<String> localTns = findLocalTransferNos(
transferNos, query == null ? null : query.getCustomerCodes(), compareStatuses);
for (Map<String, Object> row : pageRows)
{
if (row == null)
@@ -112,8 +124,7 @@ public class TabOrderCompareAsyncRunner
String tn = String.valueOf(tnObj).trim();
scanned++;
String key = tn.toUpperCase(Locale.ROOT);
Integer upstreamStatus = toInteger(row.get("orderStatus"));
if (!localStatusByTn.containsKey(key))
if (!localTns.contains(key))
{
missing++;
if (missingSample.size() < MISSING_SAMPLE_LIMIT)
@@ -123,19 +134,6 @@ public class TabOrderCompareAsyncRunner
continue;
}
matched++;
Integer localStatus = localStatusByTn.get(key);
if (!statusEquals(upstreamStatus, localStatus))
{
statusMismatch++;
if (statusMismatchSample.size() < STATUS_MISMATCH_SAMPLE_LIMIT)
{
Map<String, Object> one = new LinkedHashMap<String, Object>();
one.put("transferNo", tn);
one.put("upstreamStatus", upstreamStatus);
one.put("localStatus", localStatus);
statusMismatchSample.add(one);
}
}
}
int percent = Math.min(99, (int) ((scanned * 100L) / Math.max(scanned + pageSize, 1)));
if (pageRows.size() < pageSize)
@@ -143,9 +141,8 @@ public class TabOrderCompareAsyncRunner
percent = 99;
}
put(asyncTaskId, TabOrderCompareTask.STATUS_RUNNING, percent,
"scanning page=" + pageNum + " scanned=" + scanned
+ " missing=" + missing + " statusMismatch=" + statusMismatch,
scanned, matched, missing, statusMismatch, null, missingSample, statusMismatchSample);
"scanning page=" + pageNum + " scanned=" + scanned + " missing=" + missing,
scanned, matched, missing, null, missingSample);
if (pageRows.size() < pageSize)
{
break;
@@ -157,30 +154,19 @@ public class TabOrderCompareAsyncRunner
resp.put("scanned", Integer.valueOf(scanned));
resp.put("matched", Integer.valueOf(matched));
resp.put("missing", Integer.valueOf(missing));
resp.put("statusMismatch", Integer.valueOf(statusMismatch));
resp.put("statusMismatch", Integer.valueOf(0));
resp.put("missingTransferNos", missingSample);
resp.put("statusMismatchSamples", statusMismatchSample);
List<String> mismatchTns = new ArrayList<String>();
for (Map<String, Object> one : statusMismatchSample)
{
if (one == null) { continue; }
Object tn = one.get("transferNo");
if (tn != null && StringUtils.isNotEmpty(String.valueOf(tn).trim()))
{
mismatchTns.add(String.valueOf(tn).trim());
}
}
resp.put("statusMismatchTransferNos", mismatchTns);
resp.put("statusMismatchSamples", Collections.emptyList());
resp.put("statusMismatchTransferNos", Collections.emptyList());
resp.put("missingTruncated", Boolean.valueOf(missing > missingSample.size()));
resp.put("statusMismatchTruncated",
Boolean.valueOf(statusMismatch > statusMismatchSample.size()));
resp.put("statusMismatchTruncated", Boolean.FALSE);
put(asyncTaskId, TabOrderCompareTask.STATUS_SUCCESS, 100,
"done scanned=" + scanned + " missing=" + missing + " statusMismatch=" + statusMismatch,
scanned, matched, missing, statusMismatch, null, missingSample, statusMismatchSample);
"done scanned=" + scanned + " missing=" + missing,
scanned, matched, missing, null, missingSample);
TabOrderSyncEsLog.save(billSearchStore, asyncTaskId, "COMPARE_DONE", query, resp, "SUCCESS", null);
log.info("orderSource compare done asyncTaskId={} scanned={} matched={} missing={} statusMismatch={}",
log.info("orderSource compare done asyncTaskId={} scanned={} matched={} missing={}",
asyncTaskId, Integer.valueOf(scanned), Integer.valueOf(matched),
Integer.valueOf(missing), Integer.valueOf(statusMismatch));
Integer.valueOf(missing));
}
catch (Exception e)
{
@@ -191,100 +177,56 @@ public class TabOrderCompareAsyncRunner
msg = e.getClass().getSimpleName();
}
put(asyncTaskId, TabOrderCompareTask.STATUS_FAIL, 100, "failed",
0, 0, 0, 0, msg, null, null);
0, 0, 0, msg, null);
TabOrderSyncEsLog.save(billSearchStore, asyncTaskId, "COMPARE_DONE", query, null, "FAIL", msg);
}
}
/** transferNo(upper) -> local order_status (null value means local row exists with null status). */
private Map<String, Integer> findLocalStatuses(List<String> transferNos, List<String> customerCodes)
/**
* Prefer search filter orderStatuses; if empty, same default as order-source list
* (3/4/5/6/7/8/11) so SQL still has an IN list.
*/
private static List<Integer> resolveCompareStatuses(TabOrderMonitorQuery query)
{
Map<String, Integer> found = new HashMap<String, Integer>();
List<Integer> cleaned = new ArrayList<Integer>();
if (query != null && query.getOrderStatuses() != null)
{
for (Integer s : query.getOrderStatuses())
{
if (s != null)
{
cleaned.add(s);
}
}
}
return cleaned.isEmpty() ? new ArrayList<Integer>(COMPARE_LOCAL_ORDER_STATUSES) : cleaned;
}
/** transferNo(upper) present locally with the given order_status filter. */
private Set<String> findLocalTransferNos(List<String> transferNos, List<String> customerCodes,
List<Integer> orderStatuses)
{
Set<String> found = new HashSet<String>();
if (transferNos == null || transferNos.isEmpty())
{
return found;
}
List<Map<String, Object>> rows =
prcOrderBillMapper.selectTransferOrderStatuses(transferNos, cleanCodes(customerCodes));
List<String> rows = prcOrderBillMapper.selectExistingTransferNos(
transferNos, cleanCodes(customerCodes), orderStatuses);
if (rows == null)
{
return found;
}
for (Map<String, Object> row : rows)
for (String tn : rows)
{
if (row == null)
if (StringUtils.isNotEmpty(tn))
{
continue;
}
Object tn = first(row, "transferNo", "TRANSFERNO", "transfer_no");
if (tn == null || StringUtils.isEmpty(String.valueOf(tn).trim()))
{
continue;
}
String key = String.valueOf(tn).trim().toUpperCase(Locale.ROOT);
Integer st = toInteger(first(row, "orderStatus", "ORDERSTATUS", "order_status"));
// Keep first hit; duplicate transfer_no rare.
if (!found.containsKey(key))
{
found.put(key, st);
found.add(tn.trim().toUpperCase(Locale.ROOT));
}
}
return found;
}
private static Object first(Map<String, Object> row, String... keys)
{
if (row == null || keys == null)
{
return null;
}
for (String k : keys)
{
if (row.containsKey(k) && row.get(k) != null)
{
return row.get(k);
}
}
return null;
}
private static Integer toInteger(Object v)
{
if (v == null || "".equals(String.valueOf(v).trim()))
{
return null;
}
if (v instanceof Integer)
{
return (Integer) v;
}
if (v instanceof Number)
{
return Integer.valueOf(((Number) v).intValue());
}
try
{
return Integer.valueOf(String.valueOf(v).trim());
}
catch (Exception e)
{
return null;
}
}
private static boolean statusEquals(Integer a, Integer b)
{
if (a == null && b == null)
{
return true;
}
if (a == null || b == null)
{
return false;
}
return a.intValue() == b.intValue();
}
private static List<String> cleanCodes(List<String> codes)
{
if (codes == null || codes.isEmpty())
@@ -303,8 +245,7 @@ public class TabOrderCompareAsyncRunner
}
public void put(String taskId, String status, int percent, String message,
int scanned, int matched, int missing, int statusMismatch, String error,
List<String> missingSample, List<Map<String, Object>> statusMismatchSample)
int scanned, int matched, int missing, String error, List<String> missingSample)
{
TabOrderCompareTask task = new TabOrderCompareTask();
task.setTaskId(taskId);
@@ -314,27 +255,14 @@ public class TabOrderCompareAsyncRunner
task.setScanned(scanned);
task.setMatched(matched);
task.setMissing(missing);
task.setStatusMismatch(statusMismatch);
task.setStatusMismatch(0);
task.setError(error);
if (missingSample != null)
{
task.setMissingTransferNos(new ArrayList<String>(missingSample));
}
if (statusMismatchSample != null)
{
task.setStatusMismatchSamples(new ArrayList<Map<String, Object>>(statusMismatchSample));
List<String> tnList = new ArrayList<String>();
for (Map<String, Object> one : statusMismatchSample)
{
if (one == null) { continue; }
Object tn = one.get("transferNo");
if (tn != null && StringUtils.isNotEmpty(String.valueOf(tn).trim()))
{
tnList.add(String.valueOf(tn).trim());
}
}
task.setStatusMismatchTransferNos(tnList);
}
task.setStatusMismatchSamples(new ArrayList<Map<String, Object>>());
task.setStatusMismatchTransferNos(new ArrayList<String>());
redisCache.setCacheObject(CACHE_KEY_PREFIX + taskId, task, TTL_MINUTES, TimeUnit.MINUTES);
}
@@ -216,11 +216,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<foreach collection="customerCodes" item="ccode" open="(" separator="," close=")">
#{ccode}
</foreach>
</if>
<if test="orderStatuses != null and orderStatuses.size() > 0">
AND p.order_status IN
<foreach collection="orderStatuses" item="st" open="(" separator="," close=")">
#{st}
</foreach>
</if>
AND p.transfer_no IS NOT NULL AND p.transfer_no != ''
</select>
<!-- 订单比对:本地转单号 + 订单状态(用于状态一致性比对) -->
<!-- 订单比对:本地转单号 + 订单状态 -->
<select id="selectTransferOrderStatuses" resultType="java.util.HashMap">
SELECT p.transfer_no AS transferNo, p.order_status AS orderStatus
FROM prc_order_bill p
@@ -233,6 +239,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<foreach collection="customerCodes" item="ccode" open="(" separator="," close=")">
#{ccode}
</foreach>
</if>
<if test="orderStatuses != null and orderStatuses.size() > 0">
AND p.order_status IN
<foreach collection="orderStatuses" item="st" open="(" separator="," close=")">
#{st}
</foreach>
</if>
AND p.transfer_no IS NOT NULL AND p.transfer_no != ''
</select>