match_calls_by_time.py 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import sqlite3
  2. from datetime import datetime
  3. DB = "data/telephony.sqlite3"
  4. def parse(value):
  5. if not value:
  6. return None
  7. return datetime.fromisoformat(value.replace("Z", "+00:00"))
  8. def norm_phone(value):
  9. if not value:
  10. return None
  11. return "".join(c for c in value if c.isdigit() or c == "+")
  12. con = sqlite3.connect(DB)
  13. con.row_factory = sqlite3.Row
  14. calls = con.execute("""
  15. SELECT *
  16. FROM calls
  17. WHERE started_at IS NOT NULL
  18. ORDER BY started_at
  19. """).fetchall()
  20. cdrs = con.execute("""
  21. SELECT *
  22. FROM cdr_calls
  23. WHERE start_time IS NOT NULL
  24. ORDER BY start_time
  25. """).fetchall()
  26. print("=== ZEITLICHE CALL-ZUORDNUNG ===")
  27. print()
  28. for call in calls:
  29. ct = parse(call["started_at"])
  30. candidates = []
  31. for cdr in cdrs:
  32. dt = parse(cdr["start_time"])
  33. if not dt:
  34. continue
  35. delta = abs((ct - dt).total_seconds())
  36. if delta <= 120:
  37. score = delta
  38. call_phone = norm_phone(call["phone"])
  39. cdr_phone = norm_phone(cdr["source_caller_id"])
  40. # Gleiche Rufnummer stark bevorzugen.
  41. if call_phone and cdr_phone:
  42. if call_phone == cdr_phone:
  43. score -= 60
  44. else:
  45. score += 30
  46. candidates.append((score, delta, cdr))
  47. candidates.sort(key=lambda x: x[0])
  48. print(
  49. f"CALL {call['id']:>3} | "
  50. f"{call['started_at']} | "
  51. f"phone={call['phone']} | "
  52. f"duration={call['duration_seconds']}"
  53. )
  54. if not candidates:
  55. print(" -> KEIN CDR innerhalb 120s")
  56. continue
  57. for rank, (score, delta, cdr) in enumerate(candidates[:3], 1):
  58. print(
  59. f" {rank}. "
  60. f"CDR={cdr['id']} "
  61. f"delta={delta:.2f}s "
  62. f"phone={cdr['source_caller_id']} "
  63. f"recId={cdr['src_rec_id'] or cdr['dst_rec_id']} "
  64. f"cdr={cdr['cdr_id']}"
  65. )
  66. best = candidates[0]
  67. print(
  68. f" => BEST MATCH: cdr_calls.id={best[2]['id']} "
  69. f"(Abweichung {best[1]:.2f}s)"
  70. )
  71. print()
  72. print("=== FERTIG ===")
  73. con.close()