summary.py 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. import csv
  2. import xml.etree.ElementTree as ET
  3. from collections import defaultdict
  4. from decimal import Decimal, InvalidOperation
  5. from pathlib import Path
  6. from clients import calculate_customer, find_xml_files
  7. def extract_session(xml_path: Path) -> tuple[str, Decimal] | None:
  8. try:
  9. root = ET.parse(xml_path).getroot()
  10. except ET.ParseError:
  11. return None
  12. session = root.find("Session")
  13. if session is None:
  14. return None
  15. client_description = session.find("SessionDescription[@Name='ClientName']")
  16. client_name = "" if client_description is None else client_description.get("Description", "")
  17. duration = session.get("Duration", "").strip()
  18. if not client_name.strip() or not duration:
  19. return None
  20. try:
  21. return calculate_customer(client_name), Decimal(duration)
  22. except InvalidOperation:
  23. return None
  24. def write_summary(rows: list[dict[str, str]], output: Path) -> None:
  25. output.parent.mkdir(parents=True, exist_ok=True)
  26. with output.open("w", newline="", encoding="latin-1", errors="replace") as csv_file:
  27. writer = csv.DictWriter(csv_file, fieldnames=["Kunde", "AnzahlSitzungen", "Dauer"], delimiter=";")
  28. writer.writeheader()
  29. writer.writerows(rows)
  30. def format_duration(duration: Decimal) -> str:
  31. value = format(duration, "f")
  32. if "." in value:
  33. value = value.rstrip("0").rstrip(".")
  34. return value or "0"
  35. def run(directory: Path, output: Path) -> tuple[int, int]:
  36. if not directory.is_dir():
  37. raise ValueError(f"Das Verzeichnis existiert nicht: {directory}")
  38. totals: defaultdict[str, list[Decimal | int]] = defaultdict(lambda: [0, Decimal("0")])
  39. checked_count = 0
  40. for xml_file in find_xml_files(directory):
  41. checked_count += 1
  42. session = extract_session(xml_file)
  43. if session is None:
  44. continue
  45. customer, duration = session
  46. totals[customer][0] += 1
  47. totals[customer][1] += duration
  48. rows = [
  49. {
  50. "Kunde": customer,
  51. "AnzahlSitzungen": str(values[0]),
  52. "Dauer": format_duration(values[1]),
  53. }
  54. for customer, values in sorted(totals.items(), key=lambda item: item[0].casefold())
  55. ]
  56. write_summary(rows, output)
  57. return checked_count, len(rows)