retest_fixes.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. # -*- coding: utf-8 -*-
  2. """F-01/F-01B/F-03B/F-05/F-07 真实链路复测(F-06 由单测覆盖)。"""
  3. import json
  4. import os
  5. import sys
  6. import time
  7. import requests
  8. BASE = os.path.dirname(os.path.abspath(__file__))
  9. FIXTURES = os.path.dirname(BASE)
  10. sys.path.insert(0, FIXTURES)
  11. import run_tests as rt # noqa: E402
  12. CASE_ID = 27
  13. rt.CASE_ID = CASE_ID
  14. sys.stdout.reconfigure(encoding="utf-8")
  15. def log(msg):
  16. print(msg, flush=True)
  17. FILES = [
  18. # (测试点, 文件名)
  19. ("F-01", "RT_F01_BILL-09_交行同义.xlsx"),
  20. ("F-01B", "RT_F01B_CALL-09_导出话单同义.xlsx"),
  21. ("F-01B", "RT_F01B_CALL-17_日期时间同义.xlsx"),
  22. ("F-01B", "RT_F01B_CALL-19_时长格式.xlsx"),
  23. ("F-01B", "RT_F01B_IND-03_开户同义.xlsx"),
  24. ("F-03B/F-05", "RT_F03B_F05_CALL-18_方向_新增列.xlsx"),
  25. ("F-03B/F-07", "RT_F03B_F07_BILL-方向_新增列.xlsx"),
  26. ]
  27. def ai_data_page(c, tpl_id, size=30):
  28. r = c.request("GET", "/aiClean/data/page",
  29. params={"aiTemplateId": tpl_id, "page": 1, "size": size}, timeout=60)
  30. j = r.json() or {}
  31. return (j.get("data") or {})
  32. def main():
  33. c = rt.Client()
  34. c.open_case()
  35. batch_id = None
  36. roots = []
  37. recs = []
  38. log("== 上传 ==")
  39. for point, name in FILES:
  40. path = os.path.join(BASE, name)
  41. with open(path, "rb") as f:
  42. r = c.request("POST", "/dm/preFileUpload", params=({"batchId": batch_id} if batch_id else {}),
  43. files={"file": (name, f)}, timeout=120)
  44. data = (r.json() or {}).get("data")
  45. if not data:
  46. log(f" {name}: DATA_NULL {(r.json() or {}).get('message')}")
  47. recs.append(dict(point=point, file=name, upload="DATA_NULL"))
  48. continue
  49. batch_id = batch_id or data.get("batchId")
  50. roots.append(data)
  51. sheets = []
  52. for ch in data.get("children") or []:
  53. sheets.append(dict(sheet_id=ch.get("id"), sheet_name=ch.get("sheetName"),
  54. status=ch.get("fileStatus"), template_id=ch.get("templateId"),
  55. data_num=ch.get("dataNum")))
  56. log(f" {name}: {[(s['sheet_name'], s['status'], s['template_id']) for s in sheets]}")
  57. recs.append(dict(point=point, file=name, file_id=data.get("id"),
  58. batch_id=data.get("batchId"), sheets=sheets))
  59. log(f"batch={batch_id}; 发起智能清洗")
  60. sc = c.smart_clean(roots)
  61. log(f"smartClean: {sc.get('code')} {sc.get('message')} data={sc.get('data')}")
  62. if sc.get("code") != 200 or not sc.get("data"):
  63. json.dump(recs, open(os.path.join(BASE, "retest_result.json"), "w", encoding="utf-8"),
  64. ensure_ascii=False, indent=1, default=str)
  65. return
  66. t0 = time.time()
  67. final = None
  68. while time.time() - t0 < 1800:
  69. st = c.status(batch_id)
  70. if st and st.get("stage") in ("DONE", "PARTIAL", "FAILED"):
  71. final = st
  72. break
  73. time.sleep(3)
  74. log(f"batch final={final}")
  75. sheet_ids = [s["sheet_id"] for r in recs for s in r.get("sheets") or []]
  76. jobs = rt.db_jobs(sheet_ids)
  77. for rec in recs:
  78. rec["jobs"] = []
  79. for s in rec.get("sheets") or []:
  80. job = jobs.get(int(s["sheet_id"])) if s.get("sheet_id") else None
  81. s["job"] = job
  82. if job:
  83. rec["jobs"].append(job)
  84. rec["ai_templates"] = []
  85. for j in rec["jobs"]:
  86. tid = j.get("ai_template_id")
  87. if tid:
  88. rec["ai_templates"].append(rt.db_ai_template(tid))
  89. log(f"\n[{rec['point']}] {rec['file']}")
  90. for j in rec["jobs"]:
  91. log(f" job={j['job_id']} status={j['status']} exit={j['exit_code']} by={j['matched_by']} "
  92. f"tier={j['match_tier']} ref={j['ref_template_id']} ai={j['ai_template_id']} "
  93. f"llm={j['llm_calls']} conf={j['confidence']} rows={j['row_total']}/{j['row_loaded']} "
  94. f"fail={j['fail_reason']}")
  95. tpl_id = j.get("ai_template_id")
  96. tpl = next((t for t in rec["ai_templates"] if t and str(t["id"]) == str(tpl_id)), None)
  97. if tpl:
  98. log(f" AI表名={tpl['table_name_cn']!r} headers={tpl['headers'][:80]!r}")
  99. # 方向字段核验
  100. dir_cols = [f for f in tpl.get("fields") or []
  101. if f.get("field_type") in ("CALL_DIRECTION", "DEBIT_CREDIT_FLAG")]
  102. if dir_cols:
  103. data = ai_data_page(c, tpl["id"], 30)
  104. recs_data = (data.get("pages") or {}).get("records") or []
  105. for f in dir_cols:
  106. vals = sorted({str(r.get(f["column_name"])) for r in recs_data if r.get(f["column_name"]) is not None})
  107. log(f" direction field {f['field_name_cn']} ({f['field_type']}) distinct={vals[:10]}")
  108. rec.setdefault("direction_values", {})[f["field_name_cn"]] = vals[:10]
  109. json.dump(recs, open(os.path.join(BASE, "retest_result.json"), "w", encoding="utf-8"),
  110. ensure_ascii=False, indent=1, default=str)
  111. log("\nresult -> retest_result.json")
  112. if __name__ == "__main__":
  113. main()