修改同步落库
This commit is contained in:
+1
-1
@@ -170,7 +170,7 @@ public class TabOrderMonitorController extends BaseController
|
|||||||
customerKeywordResolver.resolve(query);
|
customerKeywordResolver.resolve(query);
|
||||||
String asyncTaskId = UUID.randomUUID().toString().replace("-", "");
|
String asyncTaskId = UUID.randomUUID().toString().replace("-", "");
|
||||||
tabOrderCompareAsyncRunner.put(asyncTaskId, TabOrderCompareTask.STATUS_PENDING, 0, "queued",
|
tabOrderCompareAsyncRunner.put(asyncTaskId, TabOrderCompareTask.STATUS_PENDING, 0, "queued",
|
||||||
0, 0, 0, 0, null, null, null);
|
0, 0, 0, null, null);
|
||||||
tabOrderCompareAsyncRunner.run(asyncTaskId, query);
|
tabOrderCompareAsyncRunner.run(asyncTaskId, query);
|
||||||
Map<String, Object> data = new HashMap<String, Object>();
|
Map<String, Object> data = new HashMap<String, Object>();
|
||||||
data.put("asyncTaskId", asyncTaskId);
|
data.put("asyncTaskId", asyncTaskId);
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import java.util.Map;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 订单比对异步任务进度(Redis)。
|
* 订单比对异步任务进度(Redis)。
|
||||||
* missing = 上游有转单号、本地无;
|
* missing = 上游有转单号、本地在指定状态集合中无对应单;
|
||||||
* statusMismatch = 本地有转单号但 order_status 与上游不一致。
|
* statusMismatch 已废弃(恒为 0,不再比对状态)。
|
||||||
*/
|
*/
|
||||||
public class TabOrderCompareTask implements Serializable
|
public class TabOrderCompareTask implements Serializable
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -39,14 +39,16 @@ public interface PrcOrderBillMapper
|
|||||||
List<String> selectExistingOrderIdentifiers(@Param("identifiers") List<String> identifiers,
|
List<String> selectExistingOrderIdentifiers(@Param("identifiers") List<String> identifiers,
|
||||||
@Param("customerCodes") List<String> customerCodes);
|
@Param("customerCodes") List<String> customerCodes);
|
||||||
|
|
||||||
/** 订单比对:仅按转单号批量查本地已存在。 */
|
/** 订单比对:仅按转单号批量查本地已存在(可选 order_status 过滤)。 */
|
||||||
List<String> selectExistingTransferNos(@Param("transferNos") List<String> transferNos,
|
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。 */
|
/** 订单比对:按转单号批量查本地 transfer_no + order_status。 */
|
||||||
List<java.util.Map<String, Object>> selectTransferOrderStatuses(
|
List<java.util.Map<String, Object>> selectTransferOrderStatuses(
|
||||||
@Param("transferNos") List<String> transferNos,
|
@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);
|
public List<String> selectOrderNoOptions(@Param("query") PrcOrderBill query, @Param("limit") int limit);
|
||||||
|
|||||||
+66
-138
@@ -1,11 +1,14 @@
|
|||||||
package com.bms.price.task;
|
package com.bms.price.task;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
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.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -22,7 +25,8 @@ import com.bms.price.search.IBillSearchStore;
|
|||||||
import com.bms.price.search.TabOrderSyncEsLog;
|
import com.bms.price.search.TabOrderSyncEsLog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 订单比对异步任务:分页拉上游转单号+状态,与本地 transfer_no / order_status 比对。
|
* 订单比对异步任务:分页拉上游转单号,与本地 transfer_no 比对是否缺失。
|
||||||
|
* 上游扫描与本地匹配均使用列表「订单状态」筛选;不再比对/列出状态不一致。
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class TabOrderCompareAsyncRunner
|
public class TabOrderCompareAsyncRunner
|
||||||
@@ -36,8 +40,12 @@ public class TabOrderCompareAsyncRunner
|
|||||||
public static final int SCAN_HARD_LIMIT = 50000;
|
public static final int SCAN_HARD_LIMIT = 50000;
|
||||||
/** 进度/抽屉中保留的缺失转单号上限 */
|
/** 进度/抽屉中保留的缺失转单号上限 */
|
||||||
public static final int MISSING_SAMPLE_LIMIT = 5000;
|
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
|
@Autowired
|
||||||
private TabOrderMonitorService tabOrderMonitorService;
|
private TabOrderMonitorService tabOrderMonitorService;
|
||||||
@@ -63,14 +71,18 @@ public class TabOrderCompareAsyncRunner
|
|||||||
query.setOrgOrderId(null);
|
query.setOrgOrderId(null);
|
||||||
query.setTransferOrderId(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",
|
put(asyncTaskId, TabOrderCompareTask.STATUS_RUNNING, 0, "starting",
|
||||||
0, 0, 0, 0, null, null, null);
|
0, 0, 0, null, null);
|
||||||
int scanned = 0;
|
int scanned = 0;
|
||||||
int matched = 0;
|
int matched = 0;
|
||||||
int missing = 0;
|
int missing = 0;
|
||||||
int statusMismatch = 0;
|
|
||||||
List<String> missingSample = new ArrayList<String>();
|
List<String> missingSample = new ArrayList<String>();
|
||||||
List<Map<String, Object>> statusMismatchSample = new ArrayList<Map<String, Object>>();
|
|
||||||
int pageNum = 1;
|
int pageNum = 1;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
@@ -96,8 +108,8 @@ public class TabOrderCompareAsyncRunner
|
|||||||
transferNos.add(String.valueOf(tn).trim());
|
transferNos.add(String.valueOf(tn).trim());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Map<String, Integer> localStatusByTn =
|
Set<String> localTns = findLocalTransferNos(
|
||||||
findLocalStatuses(transferNos, query == null ? null : query.getCustomerCodes());
|
transferNos, query == null ? null : query.getCustomerCodes(), compareStatuses);
|
||||||
for (Map<String, Object> row : pageRows)
|
for (Map<String, Object> row : pageRows)
|
||||||
{
|
{
|
||||||
if (row == null)
|
if (row == null)
|
||||||
@@ -112,8 +124,7 @@ public class TabOrderCompareAsyncRunner
|
|||||||
String tn = String.valueOf(tnObj).trim();
|
String tn = String.valueOf(tnObj).trim();
|
||||||
scanned++;
|
scanned++;
|
||||||
String key = tn.toUpperCase(Locale.ROOT);
|
String key = tn.toUpperCase(Locale.ROOT);
|
||||||
Integer upstreamStatus = toInteger(row.get("orderStatus"));
|
if (!localTns.contains(key))
|
||||||
if (!localStatusByTn.containsKey(key))
|
|
||||||
{
|
{
|
||||||
missing++;
|
missing++;
|
||||||
if (missingSample.size() < MISSING_SAMPLE_LIMIT)
|
if (missingSample.size() < MISSING_SAMPLE_LIMIT)
|
||||||
@@ -123,19 +134,6 @@ public class TabOrderCompareAsyncRunner
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
matched++;
|
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)));
|
int percent = Math.min(99, (int) ((scanned * 100L) / Math.max(scanned + pageSize, 1)));
|
||||||
if (pageRows.size() < pageSize)
|
if (pageRows.size() < pageSize)
|
||||||
@@ -143,9 +141,8 @@ public class TabOrderCompareAsyncRunner
|
|||||||
percent = 99;
|
percent = 99;
|
||||||
}
|
}
|
||||||
put(asyncTaskId, TabOrderCompareTask.STATUS_RUNNING, percent,
|
put(asyncTaskId, TabOrderCompareTask.STATUS_RUNNING, percent,
|
||||||
"scanning page=" + pageNum + " scanned=" + scanned
|
"scanning page=" + pageNum + " scanned=" + scanned + " missing=" + missing,
|
||||||
+ " missing=" + missing + " statusMismatch=" + statusMismatch,
|
scanned, matched, missing, null, missingSample);
|
||||||
scanned, matched, missing, statusMismatch, null, missingSample, statusMismatchSample);
|
|
||||||
if (pageRows.size() < pageSize)
|
if (pageRows.size() < pageSize)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
@@ -157,30 +154,19 @@ public class TabOrderCompareAsyncRunner
|
|||||||
resp.put("scanned", Integer.valueOf(scanned));
|
resp.put("scanned", Integer.valueOf(scanned));
|
||||||
resp.put("matched", Integer.valueOf(matched));
|
resp.put("matched", Integer.valueOf(matched));
|
||||||
resp.put("missing", Integer.valueOf(missing));
|
resp.put("missing", Integer.valueOf(missing));
|
||||||
resp.put("statusMismatch", Integer.valueOf(statusMismatch));
|
resp.put("statusMismatch", Integer.valueOf(0));
|
||||||
resp.put("missingTransferNos", missingSample);
|
resp.put("missingTransferNos", missingSample);
|
||||||
resp.put("statusMismatchSamples", statusMismatchSample);
|
resp.put("statusMismatchSamples", Collections.emptyList());
|
||||||
List<String> mismatchTns = new ArrayList<String>();
|
resp.put("statusMismatchTransferNos", Collections.emptyList());
|
||||||
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("missingTruncated", Boolean.valueOf(missing > missingSample.size()));
|
resp.put("missingTruncated", Boolean.valueOf(missing > missingSample.size()));
|
||||||
resp.put("statusMismatchTruncated",
|
resp.put("statusMismatchTruncated", Boolean.FALSE);
|
||||||
Boolean.valueOf(statusMismatch > statusMismatchSample.size()));
|
|
||||||
put(asyncTaskId, TabOrderCompareTask.STATUS_SUCCESS, 100,
|
put(asyncTaskId, TabOrderCompareTask.STATUS_SUCCESS, 100,
|
||||||
"done scanned=" + scanned + " missing=" + missing + " statusMismatch=" + statusMismatch,
|
"done scanned=" + scanned + " missing=" + missing,
|
||||||
scanned, matched, missing, statusMismatch, null, missingSample, statusMismatchSample);
|
scanned, matched, missing, null, missingSample);
|
||||||
TabOrderSyncEsLog.save(billSearchStore, asyncTaskId, "COMPARE_DONE", query, resp, "SUCCESS", null);
|
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),
|
asyncTaskId, Integer.valueOf(scanned), Integer.valueOf(matched),
|
||||||
Integer.valueOf(missing), Integer.valueOf(statusMismatch));
|
Integer.valueOf(missing));
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -191,100 +177,56 @@ public class TabOrderCompareAsyncRunner
|
|||||||
msg = e.getClass().getSimpleName();
|
msg = e.getClass().getSimpleName();
|
||||||
}
|
}
|
||||||
put(asyncTaskId, TabOrderCompareTask.STATUS_FAIL, 100, "failed",
|
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);
|
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())
|
if (transferNos == null || transferNos.isEmpty())
|
||||||
{
|
{
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
List<Map<String, Object>> rows =
|
List<String> rows = prcOrderBillMapper.selectExistingTransferNos(
|
||||||
prcOrderBillMapper.selectTransferOrderStatuses(transferNos, cleanCodes(customerCodes));
|
transferNos, cleanCodes(customerCodes), orderStatuses);
|
||||||
if (rows == null)
|
if (rows == null)
|
||||||
{
|
{
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
for (Map<String, Object> row : rows)
|
for (String tn : rows)
|
||||||
{
|
{
|
||||||
if (row == null)
|
if (StringUtils.isNotEmpty(tn))
|
||||||
{
|
{
|
||||||
continue;
|
found.add(tn.trim().toUpperCase(Locale.ROOT));
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return found;
|
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)
|
private static List<String> cleanCodes(List<String> codes)
|
||||||
{
|
{
|
||||||
if (codes == null || codes.isEmpty())
|
if (codes == null || codes.isEmpty())
|
||||||
@@ -303,8 +245,7 @@ public class TabOrderCompareAsyncRunner
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void put(String taskId, String status, int percent, String message,
|
public void put(String taskId, String status, int percent, String message,
|
||||||
int scanned, int matched, int missing, int statusMismatch, String error,
|
int scanned, int matched, int missing, String error, List<String> missingSample)
|
||||||
List<String> missingSample, List<Map<String, Object>> statusMismatchSample)
|
|
||||||
{
|
{
|
||||||
TabOrderCompareTask task = new TabOrderCompareTask();
|
TabOrderCompareTask task = new TabOrderCompareTask();
|
||||||
task.setTaskId(taskId);
|
task.setTaskId(taskId);
|
||||||
@@ -314,27 +255,14 @@ public class TabOrderCompareAsyncRunner
|
|||||||
task.setScanned(scanned);
|
task.setScanned(scanned);
|
||||||
task.setMatched(matched);
|
task.setMatched(matched);
|
||||||
task.setMissing(missing);
|
task.setMissing(missing);
|
||||||
task.setStatusMismatch(statusMismatch);
|
task.setStatusMismatch(0);
|
||||||
task.setError(error);
|
task.setError(error);
|
||||||
if (missingSample != null)
|
if (missingSample != null)
|
||||||
{
|
{
|
||||||
task.setMissingTransferNos(new ArrayList<String>(missingSample));
|
task.setMissingTransferNos(new ArrayList<String>(missingSample));
|
||||||
}
|
}
|
||||||
if (statusMismatchSample != null)
|
task.setStatusMismatchSamples(new ArrayList<Map<String, Object>>());
|
||||||
{
|
task.setStatusMismatchTransferNos(new ArrayList<String>());
|
||||||
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);
|
|
||||||
}
|
|
||||||
redisCache.setCacheObject(CACHE_KEY_PREFIX + taskId, task, TTL_MINUTES, TimeUnit.MINUTES);
|
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=")">
|
<foreach collection="customerCodes" item="ccode" open="(" separator="," close=")">
|
||||||
#{ccode}
|
#{ccode}
|
||||||
</foreach>
|
</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>
|
</if>
|
||||||
AND p.transfer_no IS NOT NULL AND p.transfer_no != ''
|
AND p.transfer_no IS NOT NULL AND p.transfer_no != ''
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!-- 订单比对:本地转单号 + 订单状态(用于状态一致性比对) -->
|
<!-- 订单比对:本地转单号 + 订单状态 -->
|
||||||
<select id="selectTransferOrderStatuses" resultType="java.util.HashMap">
|
<select id="selectTransferOrderStatuses" resultType="java.util.HashMap">
|
||||||
SELECT p.transfer_no AS transferNo, p.order_status AS orderStatus
|
SELECT p.transfer_no AS transferNo, p.order_status AS orderStatus
|
||||||
FROM prc_order_bill p
|
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=")">
|
<foreach collection="customerCodes" item="ccode" open="(" separator="," close=")">
|
||||||
#{ccode}
|
#{ccode}
|
||||||
</foreach>
|
</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>
|
</if>
|
||||||
AND p.transfer_no IS NOT NULL AND p.transfer_no != ''
|
AND p.transfer_no IS NOT NULL AND p.transfer_no != ''
|
||||||
</select>
|
</select>
|
||||||
|
|||||||
@@ -31,7 +31,6 @@
|
|||||||
已扫描 {{ progress.scanned || 0 }}
|
已扫描 {{ progress.scanned || 0 }}
|
||||||
/ 本地已有 {{ progress.matched || 0 }}
|
/ 本地已有 {{ progress.matched || 0 }}
|
||||||
/ 本地缺失 {{ progress.missing || 0 }}
|
/ 本地缺失 {{ progress.missing || 0 }}
|
||||||
/ 状态不一致 {{ progress.statusMismatch || 0 }}
|
|
||||||
</div>
|
</div>
|
||||||
<div v-if="progress.message" class="msg-line">{{ progress.message }}</div>
|
<div v-if="progress.message" class="msg-line">{{ progress.message }}</div>
|
||||||
<div v-if="progress.error" class="err-line">{{ progress.error }}</div>
|
<div v-if="progress.error" class="err-line">{{ progress.error }}</div>
|
||||||
@@ -41,34 +40,7 @@
|
|||||||
type="info"
|
type="info"
|
||||||
:closable="false"
|
:closable="false"
|
||||||
show-icon
|
show-icon
|
||||||
title="比对转单号 + 订单状态:1) 上游有转单号、本地没有;2) 两端都有但 order_status 不一致。异步分页扫描,结果已写入操作记录。"
|
title="仅比对转单号是否已落库:上游有、本地在当前「订单状态」筛选范围内没有。不再比对状态一致性。"
|
||||||
/>
|
|
||||||
|
|
||||||
<div class="json-panel__head">
|
|
||||||
<span>状态不一致(样本 {{ statusMismatchCount }})</span>
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
link
|
|
||||||
:disabled="!canFillMismatch"
|
|
||||||
@click="fillMismatchToSearch"
|
|
||||||
>回填到单号搜索</el-button>
|
|
||||||
</div>
|
|
||||||
<el-table
|
|
||||||
v-if="statusMismatchRows.length"
|
|
||||||
:data="statusMismatchRows"
|
|
||||||
border
|
|
||||||
size="small"
|
|
||||||
max-height="320"
|
|
||||||
class="mb12"
|
|
||||||
>
|
|
||||||
<el-table-column type="index" width="55" label="#" />
|
|
||||||
<el-table-column prop="transferNo" label="转单号" min-width="180" show-overflow-tooltip />
|
|
||||||
<el-table-column prop="upstreamStatusLabel" label="上游状态" width="110" />
|
|
||||||
<el-table-column prop="localStatusLabel" label="本地状态" width="110" />
|
|
||||||
</el-table>
|
|
||||||
<el-empty
|
|
||||||
v-else-if="!running"
|
|
||||||
description="暂无状态不一致"
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="json-panel__head">
|
<div class="json-panel__head">
|
||||||
@@ -159,65 +131,6 @@ const progressStatus = computed(() => {
|
|||||||
return undefined
|
return undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
const orderStatusMap = {
|
|
||||||
'0': '待提货',
|
|
||||||
'1': '已提货',
|
|
||||||
'2': '已收货',
|
|
||||||
'3': '运输中',
|
|
||||||
'4': '派送中',
|
|
||||||
'5': '已签收',
|
|
||||||
'6': '已完成',
|
|
||||||
'7': '已取消',
|
|
||||||
'8': '异常',
|
|
||||||
'9': '退件中',
|
|
||||||
'10': '已退件'
|
|
||||||
}
|
|
||||||
|
|
||||||
function labelStatus(v) {
|
|
||||||
const k = v == null ? '' : String(v).trim()
|
|
||||||
if (!k) return '-'
|
|
||||||
return orderStatusMap[k] || k
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizeMismatchList(raw) {
|
|
||||||
if (!Array.isArray(raw)) return []
|
|
||||||
return raw.map(row => {
|
|
||||||
if (row == null) return null
|
|
||||||
if (typeof row === 'string') {
|
|
||||||
return { transferNo: row, upstreamStatus: null, localStatus: null }
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
transferNo: row.transferNo || row.transfer_no || '',
|
|
||||||
upstreamStatus: row.upstreamStatus ?? row.upstream_status ?? null,
|
|
||||||
localStatus: row.localStatus ?? row.local_status ?? null
|
|
||||||
}
|
|
||||||
}).filter(Boolean)
|
|
||||||
}
|
|
||||||
|
|
||||||
const statusMismatchRows = computed(() => {
|
|
||||||
const samples = normalizeMismatchList(progress.value?.statusMismatchSamples)
|
|
||||||
if (samples.length) {
|
|
||||||
return samples.map(row => ({
|
|
||||||
transferNo: row.transferNo,
|
|
||||||
upstreamStatusLabel: labelStatus(row.upstreamStatus),
|
|
||||||
localStatusLabel: labelStatus(row.localStatus)
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
// fallback: flat transfer_no list when map samples missing
|
|
||||||
const flat = progress.value?.statusMismatchTransferNos || []
|
|
||||||
return (Array.isArray(flat) ? flat : []).map(tn => ({
|
|
||||||
transferNo: tn,
|
|
||||||
upstreamStatusLabel: '-',
|
|
||||||
localStatusLabel: '-'
|
|
||||||
}))
|
|
||||||
})
|
|
||||||
|
|
||||||
const statusMismatchCount = computed(() => {
|
|
||||||
const n = Number(progress.value?.statusMismatch)
|
|
||||||
if (!Number.isNaN(n) && n > 0) return n
|
|
||||||
return statusMismatchRows.value.length
|
|
||||||
})
|
|
||||||
|
|
||||||
const missingRows = computed(() => {
|
const missingRows = computed(() => {
|
||||||
const list = progress.value?.missingTransferNos || []
|
const list = progress.value?.missingTransferNos || []
|
||||||
return (Array.isArray(list) ? list : []).map(tn => ({ transferNo: tn }))
|
return (Array.isArray(list) ? list : []).map(tn => ({ transferNo: tn }))
|
||||||
@@ -233,9 +146,6 @@ const canFillSearch = computed(() => {
|
|||||||
return !running.value && missingRows.value.length > 0
|
return !running.value && missingRows.value.length > 0
|
||||||
})
|
})
|
||||||
|
|
||||||
const canFillMismatch = computed(() => {
|
|
||||||
return !running.value && statusMismatchRows.value.length > 0
|
|
||||||
})
|
|
||||||
|
|
||||||
function fillToSearch() {
|
function fillToSearch() {
|
||||||
const list = missingRows.value.map(r => String(r.transferNo || '').trim()).filter(Boolean)
|
const list = missingRows.value.map(r => String(r.transferNo || '').trim()).filter(Boolean)
|
||||||
@@ -248,17 +158,6 @@ function fillToSearch() {
|
|||||||
visible.value = false
|
visible.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
function fillMismatchToSearch() {
|
|
||||||
const list = statusMismatchRows.value.map(r => String(r.transferNo || '').trim()).filter(Boolean)
|
|
||||||
if (!list.length) {
|
|
||||||
ElMessage.warning('暂无可回填的状态不一致转单号')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const truncated = !!(progress.value?.statusMismatchTruncated)
|
|
||||||
|| (Number(progress.value?.statusMismatch || 0) > list.length)
|
|
||||||
emit('fill-search', { transferNos: list, truncated })
|
|
||||||
visible.value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearTimer() {
|
function clearTimer() {
|
||||||
if (timer) {
|
if (timer) {
|
||||||
@@ -291,7 +190,7 @@ function open(q) {
|
|||||||
ElMessage.error('启动比对任务失败')
|
ElMessage.error('启动比对任务失败')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
progress.value = { status: 'PENDING', percent: 0, message: 'queued', scanned: 0, matched: 0, missing: 0, statusMismatch: 0 }
|
progress.value = { status: 'PENDING', percent: 0, message: 'queued', scanned: 0, matched: 0, missing: 0 }
|
||||||
poll()
|
poll()
|
||||||
timer = setInterval(poll, 1500)
|
timer = setInterval(poll, 1500)
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
|
|||||||
@@ -421,7 +421,7 @@ function openOrderCompare() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
proxy.$modal.confirm(
|
proxy.$modal.confirm(
|
||||||
'将按当前客户与提货时间,异步分页比对上游转单号与订单状态(缺失转单号 + 状态不一致),确认继续?',
|
'将按当前客户、提货时间与订单状态筛选,异步分页比对上游转单号是否已落库,确认继续?',
|
||||||
'二次确认'
|
'二次确认'
|
||||||
).then(() => {
|
).then(() => {
|
||||||
// 比对只按客户+时间;不带单号框内容(回填后可能有数千转单号,带上会把比对拖死)
|
// 比对只按客户+时间;不带单号框内容(回填后可能有数千转单号,带上会把比对拖死)
|
||||||
|
|||||||
Reference in New Issue
Block a user