import csv import xml.etree.ElementTree as ET from collections import defaultdict from dataclasses import dataclass from decimal import Decimal, InvalidOperation from pathlib import Path from clients import calculate_customer, find_xml_files @dataclass(frozen=True) class SummaryResult: xml_count: int customer_count: int def extract_session(xml_path: Path) -> tuple[str, Decimal] | None: try: root = ET.parse(xml_path).getroot() except ET.ParseError: return None session = root.find("Session") if session is None: return None client_description = session.find("SessionDescription[@Name='ClientName']") client_name = "" if client_description is None else client_description.get("Description", "") duration = session.get("Duration", "").strip() if not client_name.strip() or not duration: return None try: return calculate_customer(client_name), Decimal(duration) except InvalidOperation: return None def write_summary(rows: list[dict[str, str]], output: Path) -> None: output.parent.mkdir(parents=True, exist_ok=True) with output.open("w", newline="", encoding="latin-1", errors="replace") as csv_file: writer = csv.DictWriter(csv_file, fieldnames=["Kunde", "AnzahlSitzungen", "Dauer"], delimiter=";") writer.writeheader() writer.writerows(rows) def format_duration(duration: Decimal) -> str: value = format(duration, "f") if "." in value: value = value.rstrip("0").rstrip(".") return value or "0" def run(directory: Path, output: Path) -> SummaryResult: if not directory.is_dir(): raise ValueError(f"Das Verzeichnis existiert nicht: {directory}") totals: defaultdict[str, list[Decimal | int]] = defaultdict(lambda: [0, Decimal("0")]) checked_count = 0 for xml_file in find_xml_files(directory): checked_count += 1 session = extract_session(xml_file) if session is None: continue customer, duration = session totals[customer][0] += 1 totals[customer][1] += duration rows = [ { "Kunde": customer, "AnzahlSitzungen": str(values[0]), "Dauer": format_duration(values[1]), } for customer, values in sorted(totals.items(), key=lambda item: item[0].casefold()) ] write_summary(rows, output) return SummaryResult(xml_count=checked_count, customer_count=len(rows))