From 66db7b279d35f23cab775bf91e22215e61cc37ee Mon Sep 17 00:00:00 2001 From: yeuimu <2197651308@qq.com> Date: Fri, 28 Aug 2026 03:50:24 +0000 Subject: [PATCH] =?UTF-8?q?style:=20=E6=97=A5=E6=8A=A5=E6=94=B9=E7=BB=93?= =?UTF-8?q?=E8=AE=BA=E5=BC=8F=E6=9E=81=E7=AE=80=E6=8E=92=E7=89=88(?= =?UTF-8?q?=E5=8E=BB=E6=8E=89=E8=A1=A5=E6=8B=89=E7=AD=89=E5=86=85=E9=83=A8?= =?UTF-8?q?=E6=9C=AF=E8=AF=AD=E5=92=8C=E9=80=90=E7=8A=B6=E6=80=81=E6=98=8E?= =?UTF-8?q?=E7=BB=86)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- flows/monitor/daily_report.py | 88 +++++++++++++++++------------------ 1 file changed, 43 insertions(+), 45 deletions(-) diff --git a/flows/monitor/daily_report.py b/flows/monitor/daily_report.py index f3bc9bd..a618893 100644 --- a/flows/monitor/daily_report.py +++ b/flows/monitor/daily_report.py @@ -21,77 +21,72 @@ from flows.sds.verify import sds_verify from flows.shared import SyncDB, emit_sync_summary, send_markdown, start_of_day -def _fmt_diff(diff: dict) -> str: - return " ".join(f"{k}{v:+d}" for k, v in (diff or {}).items()) or "—" - - -_TOTALS_LABELS = { - "ordersAdded": "订单新增", "ordersUpdated": "订单更新", "ordersRemoved": "订单移除", - "goodsAdded": "商品新增", "goodsUpdated": "商品更新", "goodsRemoved": "商品移除", -} - - -def _fmt_totals(summary: dict) -> str: - parts = [f"{_TOTALS_LABELS.get(k, k)} {v:,}" for k, v in summary.items() - if k not in ("totalDays", "daysWithDiff") and v] - return " · ".join(parts) - def _short_date(date_str: str) -> str: return date_str[5:] if len(date_str) == 10 and date_str[:4].isdigit() else date_str +def _affected_units(diff: dict) -> int: + """状态不符单数 ≈ 本地比远程多的状态计数之和(远程改了状态的单)。""" + return sum(v for v in (diff or {}).values() if v > 0) + + def build_daily_message( days: int, window: str, riin: dict, sds: dict, goods: dict, ocr: dict, failures: list[dict], ) -> tuple[str, bool]: - """拼装日报 markdown,返回 (消息, 是否需关注)。独立成函数便于预览/测试。""" + """拼装日报 markdown,返回 (消息, 是否需关注)。结论式极简排版,不暴露内部术语。""" lines = [f"📊 **数据核验日报** {datetime.now().strftime('%m-%d %H:%M')}" f"(近 {days} 天,{window})", ""] attention = False + diff_names: list[str] = [] for name, report in (("RIIN", riin), ("SDS", sds)): try: days_r = (report.get("verifyReport") or {}).get("days") or [] summary = (report.get("verifyReport") or {}).get("summary") or {} diff_days = [d for d in days_r if not d.get("ok")] - total, n_diff = summary.get("totalDays", len(days_r)), summary.get("daysWithDiff", len(diff_days)) - if diff_days: - lines.append(f"**{name}** {total - n_diff}/{total} 天一致,**{n_diff} 天有差异(已补拉)**⚠️") - for d in diff_days[:8]: - lines.append(f"> {_short_date(d['date'])} {_fmt_diff(d.get('diff'))}(补拉 {d.get('orders', 0):,} 单)") - if len(diff_days) > 8: - lines.append(f"> …共 {len(diff_days)} 天") - totals = _fmt_totals(summary) - if totals: - lines.append(f"> 补拉量合计 {totals}") - lines.append("> 注:同一差异长期存在多为统计口径/状态映射问题(如发货后退款未同步)") - attention = True + total = summary.get("totalDays", len(days_r)) + if not diff_days: + lines.append(f"**{name}** {total}/{total} 天与远程一致 ✅") else: - lines.append(f"**{name}** {total}/{total} 天一致 ✅") + diff_names.append(name) + attention = True + lines.append(f"**{name}** {total - len(diff_days)}/{total} 天与远程一致 ⚠️") + if len(diff_days) <= 4: + per_day = " · ".join( + f"{_short_date(d['date'])} {_affected_units(d.get('diff'))}单" for d in diff_days) + lines.append(f"> {per_day}状态不符,已自动重新同步") + else: + total_affected = sum(_affected_units(d.get("diff")) for d in diff_days) + lines.append(f"> {len(diff_days)} 天共约 {total_affected:,} 单状态不符,已自动重新同步") except Exception as err: # noqa: BLE001 lines.append(f"**{name}** 核验结果解析失败:{err}") attention = True - lines.append("") - lines.append("**商品完整性**") - for sys in ("RIIN", "SDS"): - g = goods[sys] - zero = f"**{g['zeroGoodsOrders']}**⚠️" if g["zeroGoodsOrders"] else "0" - lines.append(f"> {sys} 订单 {g['orders']:,} · 商品 {g['goods']:,} · 零商品订单 {zero} · 无名称 {g['goodsNoName']:,}") - attention = attention or g["zeroGoodsOrders"] > 0 - lines.append(f"> 全库孤儿商品 {goods['RIIN']['orphanGoods']:,}") - lines.append("") - - lines.append(f"**OCR** 完成 {ocr.get('done', 0):,} · 失败 {ocr.get('error', 0):,}" - f" · 不支持 {ocr.get('unsupported', 0):,} · 待处理 {ocr.get('pending', 0):,}") - lines.append(f"**失败 runs(24h)** {len(failures)} 个" + (" ✅" if not failures else "")) - for f in failures[:5]: - lines.append(f"> 🔴 {f['name']}({f['state']}){f['start']}") + zero_total = sum(g["zeroGoodsOrders"] for g in goods.values()) + lines += ["", f"**商品** RIIN {goods['RIIN']['orders']:,} 单/{goods['RIIN']['goods']:,} 行" + f" · SDS {goods['SDS']['orders']:,} 单/{goods['SDS']['goods']:,} 行" + + (" ⚠️" if zero_total else " ✅")] + if zero_total: + lines.append(f"> 有 {zero_total} 单缺商品数据") + attention = True + lines.append(f"**OCR** 已完成 {ocr.get('done', 0):,} · 待处理 {ocr.get('pending', 0):,}" + f" · 失败 {ocr.get('error', 0):,}") if failures: attention = True + names = "、".join(f"{f['name']}({f['state']})" for f in failures[:4]) + lines.append(f"**失败任务(24h)** {len(failures)} 个:{names}") + else: + lines.append("**失败任务(24h)** 0 个 ✅") - lines += ["", ("⚠️ **存在需关注项,见上**" if attention else "✅ **数据全部一致,无异常**")] + lines.append("") + if attention: + lines.append("⚠️ **存在需关注项,见上**") + if diff_names: + lines.append("> 每天都出现的相同差异属远程统计口径问题,非数据丢失") + else: + lines.append("✅ **数据全部一致,无异常**") return "\n".join(lines), attention @@ -117,7 +112,10 @@ def daily_report(days: int = 7) -> dict: emit_sync_summary("数据核验日报", [ ("核验窗口", f"近{days}天"), ("需关注", "是" if attention else "否"), ("RIIN 零商品订单", goods["RIIN"]["zeroGoodsOrders"]), + ("RIIN 商品无名称", goods["RIIN"]["goodsNoName"]), ("SDS 零商品订单", goods["SDS"]["zeroGoodsOrders"]), + ("SDS 商品无名称", goods["SDS"]["goodsNoName"]), + ("全库孤儿商品", goods["RIIN"]["orphanGoods"]), ("OCR 待处理", ocr.get("pending", 0)), ("失败 runs(24h)", len(failures)), ("已发企微", "是" if sent else "否"), ])