# Qualitätssicherung HVB-ETL Tests für die Transformationslogik in [`include/02_etl_angebote_zuschlaege.py`](../include/02_etl_angebote_zuschlaege.py). Die Suite erzeugt deterministische Excel-Eingabedaten (≥4 Dateien je Quell-Ordner, inkl. Dubletten und Edge-Cases), führt das ETL-Skript real aus und prüft die erzeugten Output-CSVs gegen exakt berechnete Erwartungswerte. ## Ausführen ```bash # Einmalig: Umgebung (Python ≥ 3.10, das ETL nutzt `str | None`-Syntax) python3.12 -m venv .venv_test .venv_test/bin/pip install pandas openpyxl # Komplette QS (erzeugt Fixtures, läuft ETL, prüft Ergebnisse): .venv_test/bin/python tests/run_tests.py ``` Exit-Code `0` = alle Prüfungen bestanden (CI-tauglich). Bei Fehlern bleibt das temporäre Arbeitsverzeichnis zur Analyse erhalten; bei Erfolg wird es gelöscht. Nur die Eingabedaten erzeugen (ohne ETL/Prüfung): ```bash .venv_test/bin/python tests/generate_fixtures.py # -> tests/fixtures/input/ ``` ## Dateien | Datei | Zweck | |-------|-------| | `generate_fixtures.py` | Erzeugt die Excel-Testdaten (4 Dateien/Ordner). | | `run_tests.py` | Baut Workdir, führt ETL aus, 45 Prüfungen. | | `fixtures/` | Generierte Eingabedaten (nicht versioniert). | ## Testdatensatz (Soll-Bild) 9 Angebote (6 aus Export, 3 nur aus Archiv), 8 eindeutige Kunden, 3 Zuschläge. ### `taifun_export/` — 4 Dateien, „jüngster Export gewinnt" - **A-1001** liegt in 3 Dateien (Stände 500/2000/4000 via `_dateistand.csv`). Erwartung: jüngste Version (Stand 4000) gewinnt → Beschreibung „1000 m³", Kunde „Müller GmbH". 8 Rohzeilen → **6 eindeutige** Angebote. - **A-1004**: Kundenadresse leer, nur Standort „80331 München" → Standortadresse hat Vorrang (`adress_quelle = standort`). - **A-1006**: Land `CH`, PLZ „1010 Wien" (kein dt. Format) → kein Geo-Treffer. ### `pflege/` — 4 Dateien, UNION + gültiger Status - 8 Status-Events → **7 nach Dedup** (A-1003/Auftrag exakt doppelt). - **A-1001**: neuestes Datum 2024-03-05 mit Gleichstand „Verhandlung" (Rang 3) vs. „Angebot" (Rang 2) → **höherer Rang gewinnt: Verhandlung** (Ampel orange). - **A-1003**: Pflege „Auftrag" überschreibt Export-Abbruchtext → Auftrag (grün). - **A-9999**: Waisen-Status ohne Angebot → erscheint in `staging_status_historie`, **nicht** in `staging_angebote`. ### `archiv/` — 4 Dateien, Alt-Angebote ergänzen - **B-9001/9002/9003** nicht im Export → werden als `herkunft_stamm = archiv` ergänzt. **B-9001** über zwei Dateien dupliziert → nur einmal. - **A-1002** ist bereits im Export → Archiv-Version wird **verworfen** (Export-Kunde „Bauer AG" bleibt, nicht „Bauer AG ARCHIV"). ### Status-Ableitung (ohne Pflege) - **A-1004**: gültige Projektnummer `P-67890`, keine Pflege → `Auftrag` (`status_quelle = export_projekt`). - **A-1006**: Projekttext „kein Interesse" (kein Muster) → `Abgelehnt` (schwarz). - **A-1005**: weder Pflege noch Projekt → Default `Angebot` (gelb). - **Status-Konflikt**: A-1002 hat Projektnummer `P-12345`, Pflege sagt aber „Angebot" → `status_konflikt = True` (genau 1 Konflikt). ### Kunden-Dedup - „Müller GmbH | 70001" = A-1001 + A-1005 → **1 Kunde**, aktuellstes Angebot = A-1005 (jüngstes Datum). Gesamt **8 eindeutige Kunden**. ### `zuschlaege/` — 4 Dateien, zwei Blätter, Kopfzeile in Zeile 4 - Blätter `Zuschläge_Detailliert` + `Zuschläge_Kompakt` (jeweils `header=3`). - 6 Detailzeilen → **5 nach Dedup** je (Zuschlags-Nr, Flurstück); Z-100/F1 doppelt. **3 eindeutige Zuschläge**. - Gebotsmenge wird aus dem Kompakt-Blatt gemerged (Z-100 → 5000). - PLZ **04109** behält die führende Null. - `plz_mit_eigenem_angebot`: 10115 (eigenes Angebot) → True; 99999 → False. - Lead-Ampel durchgängig `lila`. ## Erwartete Kennzahlen (Übersicht) | Output-CSV | Zeilen | Kernaussage | |------------|-------:|-------------| | `staging_angebote` | 9 | 6 Export + 3 Archiv, Nummern eindeutig | | `staging_status_historie` | 7 | inkl. Waise A-9999, Dublette entfernt | | `staging_zuschlaege` | 5 | 3 eindeutige Zuschläge | | `v_angebote_karte` | 9 | 8/9 mit Koordinaten (A-1006 Ausland ohne) | | `v_angebote_karte_aktuell` | 8 | 1 Zeile je Kunde | | `v_kunden_pipeline` | 8 | Top-Kunde Müller GmbH (2 Angebote) | | `v_zuschlaege_karte` | 5 | 4/5 mit Koordinaten, Ampel lila | Status-Verteilung: `Angebot 5, Auftrag 2, Verhandlung 1, Abgelehnt 1`. > Hinweis: Die Geo-Prüfungen nutzen `etl_cache/geo_plz_koordinaten.csv`. Diese > Datei hat keine Spalte `kreis`, daher bleibt `landkreis` im Test leer — das > ist erwartet und wird vom ETL korrekt behandelt.