Der grösste Funktionsblock von CluHu (~60 Versionen, v0.14.40–v0.16.52). Wandelt beliebige Vereins-Excels in Member- + Person-Datensätze um.
- Nur Erst-Import: gesperrt sobald Mitglieder existieren (Neuanlauf via „ALLE LÖSCHEN"-Reset). Kein Update-/Delta-Import.
- Single-Person-Mode: nur der Hauptkontakt wird als Person angelegt; weitere Personen extrahiert später der Mehrpersonen-Canvas.
- Vorschau = Vertrag: Vorschau und Import nutzen exakt dieselben Reader/Splitter/Cluster-Funktionen — was du siehst, wird importiert.
- „Nie stillschweigend": geparkte Spalten werden namentlich gelistet, verwaiste Regeln bleiben sichtbar, Fehler werden pro Zeile rapportiert.
- Formate:
.xlsx (openpyxl, inkl. Merged-Cells und Header-Zellfarben), .xls (calamine), .csv (chardet-Encoding + Sniffer-Delimiter)
- Header-Detection per Score-Heuristik (Füllgrad, String-Anteil, kurze eindeutige Texte; Single-Cell-Zeilen = Titel, nie Header). Gruppen-Header („Adresse" über Strasse/PLZ/Ort) via Merged-Ranges bzw. Sparse-Zeilen-Heuristik; Header werden geflattet („Adresse / Strasse")
- ~20 Detectoren (Plugin-Architektur
apps/importer/detectors/) erkennen Spaltentypen mit Confidence: E-Mail, Telefon, PLZ-CH, Datum, IBAN, Mitgliedernummer, Vor-/Nachname, Strasse, Ort, Land, Status, Austritt, Jahrgang, Boolean, Dropdown, Mehrpersonen-Zelle, kombinierte Adresse
- Schweizer-Namen-DB (
swiss_names.py, ~4000 Vor-/Nachnamen): einzige Möglichkeit, „Müller Hans" (CH-Reihenfolge) von „Hans Müller" zu unterscheiden
- Two-Pass-Detection: Pass 2 nur über Werte, nur Detectoren mit harten Patterns, reduzierte Confidence +
tentative-Flag. Formel garantiert: Header-Match schlägt immer Werte-only-Match
- Excel-Serial-Daten: 44927 → 01.01.2023, mit Range-Guard 15000–60000 (≈1941–2064) und nur bei Datums-Header — damit PLZ und Jahrgänge nicht als Datum gelten
- Cluster-Engine mit Hinweis-Pyramide: Gruppen-Header (0.95) → Header-Farbe (0.9) → Suffix „_1"/„M" (0.85) → Feldtyp-Wiederholungssequenz (0.7) → Nachbarschaft (0.4). Score + deutsche Begründung als Tooltip persistiert
- Dropdown je Spalte (Auto-Erkennung vorausgefüllt,
__ignore__ möglich; User-Änderung = Confidence 1.0)
- Splitter erzeugen virtuelle Sub-Spalten mit Live-Vorschau:
multi_name_cell („Hans & Maria Müller" — Reihenfolge per Spalten-Mehrheits-Heuristik) und combined_address („Dorfstrasse 73, 8699 Bremgarten" — 4 Modi)
- Hauptkontakt-Checkboxen inline bei ≥2 Spalten desselben Identitäts-Typs. E-Mail/Telefon mehrfach wählbar (privat + geschäftlich); Hinweis-Popup (nicht Blockieren!) bei zwei Handy-Spalten
- Adress-Blöcke: bei ≥2 Blöcken wählt der User EINEN als Postadresse (Block als Ganzes); ein einzelner Block wird unsichtbar automatisch übernommen
- Fehlende Mitgliedernummern-Spalte → stillschweigend Auto-Nummerierung
- Entitäts-Gruppierung (v0.16.18): Header wie „Vorname Spieler" werden in Feld-Typ + Entitäts-Label zerlegt; die beste Identität wird Hauptkontakt
- Zwei Tabellen: Mitglieder (native Spalten + Rollen-Verweise „P3 | Hans Müller") und Personen (temporäre IDs P1..Pn). Adresse wird bewusst unter Mitglieder gezeigt („Adresse ist ein Mitglieder-Ding"), landet aber technisch am Hauptkontakt
- Render-Cap 300 Zeilen — Totals immer über alle Zeilen
- XLSX-Export der Vorschau (2 Sheets, ohne Cap)
- E-Mail-Konflikt-Dialog: identische E-Mails im File → Auto-Merge-Anzeige; abweichende Felder → interaktiver Dialog mit Optionen Merge / Getrennt (mit E-Mail je Vorkommen) / mit bestehender DB-Person verknüpfen
- „Abbrechen" bietet „Speichern & schliessen" — der Import bleibt offen und ist via Banner „Offener Import → Fortsetzen" wieder aufrufbar (Save & Resume)
- Doppel-Submit-Schutz: Frontend-Overlay +
select_for_update-Status-Claiming (preview → importing)
- Eine Transaktion mit Savepoint pro Zeile: ein Zeilenfehler verwirft nur diese Zeile. >50 Fehler → Komplett-Rollback (Batch bleibt korrigierbar in preview)
- Auto-Merge über Zeilen: identische Identität + identische E-Mail wie eine frühere Zeile → Person wird wiederverwendet, zusätzliche Mitgliedschaft verknüpft. Reine Namensgleichheit merged NICHT (dafür gibt es den Dubletten-Finder)
- Keine „Geister-Personen": Adresse + Festnetz allein (ohne Name/E-Mail) erzeugen keine Person
- Cross-Column-Familienname-Forward-Fill: Kind-Spalten ohne Nachnamen erben ihn
- Weitere E-Mail-/Telefon-Spalten werden an strukturierte Custom-Felder gebunden (deterministischer Key — über Importe hinweg dasselbe Feld)
- Re-Import verwendet bestehende Feld-Definitionen wieder (keine „_2"-Duplikate)
- Am Ende:
sync_import_mappings legt die Verdrahtungsregeln an (PersonFieldMapping)
Jeder Import schreibt /app/import_logs/[yymmdd]_[version]_[slug]/ mit Original-Datei, importierten CSVs, spaltenzuordnung.md (Auto-Erkennung vs. User-Override — Lern-Feedback für die Detectoren) und summary.md. Läuft auch bei Fehlschlägen und wirft nie Exceptions. Zweck laut Code: „damit wir aus dem Verhalten der Test-User lernen können."
- Erste Tabelle / erstes Sheet only
- Auto-Merge-Verhalten: namensgleiche Personen, die sich nur in einer Nicht-Hauptkontakt-Spalte unterscheiden, werden zusammengeführt — soll die Spalte zählen, muss sie in Schritt 1 als Hauptkontakt-Feld markiert sein
- Beim Konflikt-Merge sind nur Identitäts- und Telefonfelder wählbar; bei übrigen abweichenden Feldern gewinnt stillschweigend die erstgenannte Person
- Spalten mit 1 unique Wert + vielen Leeren werden nicht als Boolean erkannt → manuell auf Ja/Nein stellen