diff --git a/ruoyi-system/src/main/java/com/ruoyi/jarvis/service/goofish/GoofishOrderChangeLogger.java b/ruoyi-system/src/main/java/com/ruoyi/jarvis/service/goofish/GoofishOrderChangeLogger.java index fcd0813..2ee8324 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/jarvis/service/goofish/GoofishOrderChangeLogger.java +++ b/ruoyi-system/src/main/java/com/ruoyi/jarvis/service/goofish/GoofishOrderChangeLogger.java @@ -129,11 +129,55 @@ public class GoofishOrderChangeLogger { logParts.add("本地运单 " + str(b.localWaybillNo) + "→" + str(a.localWaybillNo)); } if (!logParts.isEmpty()) { + boolean notifyWecomLogistics = + !isLogisticsWecomMirroringShipWaybillFill(beforeSnap, afterRow, logParts); append(afterRow.getId(), afterRow.getAppKey(), afterRow.getOrderNo(), TYPE_LOGISTICS, source, - String.join(";", logParts)); + String.join(";", logParts), notifyWecomLogistics); } } + /** + * 详情/列表反拉:平台「运单号为 null→671…」并与本地 Redis 写入的运单一致、本地运单字段未在同一笔合并里改动时, + * 内容与刚发的「发货」通知重复 → 不写企微,仅保留事件日志。 + */ + private static boolean isLogisticsWecomMirroringShipWaybillFill(ErpGoofishOrder b, ErpGoofishOrder a, + List logParts) { + if (a == null) { + return false; + } + String lwAfter = trimEmpty(a.getLocalWaybillNo()); + if (lwAfter.isEmpty()) { + return false; + } + if (!eqStr(b == null ? null : b.getLocalWaybillNo(), a == null ? null : a.getLocalWaybillNo())) { + return false; + } + for (String p : logParts) { + if (p.startsWith("本地运单 ")) { + return false; + } + if (!(p.startsWith("平台运单 ") || p.startsWith("快递编码 ") || p.startsWith("快递名称 "))) { + return false; + } + } + String adb = trimEmpty(a.getDetailWaybillNo()); + String bdb = trimEmpty(b == null ? null : b.getDetailWaybillNo()); + if (!adb.equals(lwAfter)) { + return false; + } + // 平台侧从空补上运单号,与同单本地发货所用单号一致 + boolean detailWaybillJustFilled = + !eqStr(b == null ? null : b.getDetailWaybillNo(), a.getDetailWaybillNo()) && bdb.isEmpty(); + // 或运单早前已对齐,只差快递字段刷新,仍视作发货侧已知信息延伸 + boolean detailStableMatchesLocal = + eqStr(b == null ? null : b.getDetailWaybillNo(), a.getDetailWaybillNo()) && !adb.isEmpty(); + return detailWaybillJustFilled || detailStableMatchesLocal; + } + + private static String trimEmpty(String x) { + return x == null ? "" : x.trim(); + } + private static String str(Object o) { return o == null ? "null" : String.valueOf(o); }