diff --git a/changelog.txt b/changelog.txt index ebdd89c..f9e0785 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,4 +1,4 @@ -- Neu: Eigentümersuche im Tab „Eigentümer“. Den Serienbriefexport (CSV) von Hand als Layer laden, als Eigentümerdatei wählen, Name und/oder Vorname eingeben: Die Trefferliste zeigt Name, Anschrift, E-Mail und die Kennzeichen „verstorben“/„Rechtsperson“. Gleiche Personen mit gleicher Anschrift werden zusammengefasst, Groß-/Kleinschreibung und Umlautschreibweise spielen keine Rolle (#56) +- Neu: Eigentümersuche im Tab „Eigentümer“. Den Serienbriefexport (CSV) von Hand als Layer laden, als Eigentümerdatei wählen, Name und/oder Vorname eingeben: Die Trefferliste zeigt Name, Anschrift, E-Mail, den Wert von PER_RECHTSPERSON (0, 1, 5 oder 9, noch nicht entschlüsselt) und das Kennzeichen „verstorben“. Gleiche Personen mit gleicher Anschrift werden zusammengefasst, Groß-/Kleinschreibung und Umlautschreibweise spielen keine Rolle (#56) - Intern: Die Auswahltabelle aus „Verfahrensgebiete aus Landkreis laden“ (Suchfeld, „Alle auswählen“, Mehrfachauswahl) ist als gemeinsame Funktion herausgelöst und wird von der Eigentümer-Trefferliste mitgenutzt; der Landkreis-Dialog verhält sich unverändert (#56) - Neu: Tab „Eigentümer“ mit Flurstückssuche. Gemarkung (Name oder Nummer) und Flurstücksnummer (z. B. 562 oder 12/3) eingeben, die Treffer werden im Layer „Flurstücke“ ausgewählt und angezoomt. Ohne Nenner werden alle Flurstücke mit diesem Zähler gefunden. Fehlt der Layer „Flurstücke“, weist ein Dialog darauf hin, zuerst Verfahrensgebiet und Flurstücke aus ALKIS zu laden (#56) - Bugfix: Nach dem Laden des Verfahrensgebiets (ALKIS oder Shape) sprang die Karte an die falsche Stelle, wenn ein anderes Projekt-KBS als EPSG:25833 eingestellt war. Der Zoom rechnet die Ausdehnung jetzt in das KBS der Kartenansicht um (`zoom_auf_layer` aus sn_basis, setzt sn_basis mit Basis #99 voraus) (Basis #99) diff --git a/functions/eigentuemer_suche.py b/functions/eigentuemer_suche.py index 3bdbd99..7e4a7db 100644 --- a/functions/eigentuemer_suche.py +++ b/functions/eigentuemer_suche.py @@ -62,7 +62,7 @@ class Eigentuemer: ortsteil: str = "" emails: Tuple[str, ...] = () verstorben: bool = False - rechtsperson: bool = False + rechtsperson: Tuple[str, ...] = () per_ids: Tuple[str, ...] = () konten: Tuple[str, ...] = () feature_ids: Tuple[int, ...] = () @@ -85,8 +85,12 @@ class Eigentuemer: @property def hinweise(self) -> str: """Kennzeichen für die Trefferliste (nicht für das Anzeigefenster).""" - return ", ".join(t for t, gesetzt in (("verstorben", self.verstorben), - ("Rechtsperson", self.rechtsperson)) if gesetzt) + return "verstorben" if self.verstorben else "" + + @property + def rechtsperson_text(self) -> str: + """Rohwert(e) von ``PER_RECHTSPERSON`` (bekannt: 0, 1, 5, 9), noch nicht entschlüsselt.""" + return ", ".join(self.rechtsperson) def _text(wert) -> str: @@ -192,17 +196,17 @@ def suche_eigentuemer(layer, nachname: str, vorname: str) -> List[Eigentuemer]: gruppe = gruppen.setdefault(_gruppenschluessel(werte), { "werte": werte, "emails": [], "per_ids": [], "konten": [], "feature_ids": [], - "verstorben": False, "rechtsperson": False, + "verstorben": False, "rechtsperson": [], }) for k in ("anrede", "titel"): if not gruppe["werte"][k] and werte[k]: gruppe["werte"][k] = werte[k] - for liste, wert in (("emails", werte["email"]), ("per_ids", werte["per_id"]), ("konten", werte["konto"])): + for liste, wert in (("emails", werte["email"]), ("per_ids", werte["per_id"]), + ("konten", werte["konto"]), ("rechtsperson", werte["rechtsperson"])): if wert and wert not in gruppe[liste]: gruppe[liste].append(wert) gruppe["feature_ids"].append(feature.id()) gruppe["verstorben"] = gruppe["verstorben"] or _ist_gesetzt(werte["verstorben"]) - gruppe["rechtsperson"] = gruppe["rechtsperson"] or _ist_gesetzt(werte["rechtsperson"]) treffer = [] for gruppe in gruppen.values(): @@ -211,7 +215,7 @@ def suche_eigentuemer(layer, nachname: str, vorname: str) -> List[Eigentuemer]: anrede=w["anrede"], titel=w["titel"], vorname=w["vorname"], nachname=w["nachname"], strasse=w["strasse"], plz=w["plz"], wohnort=w["wohnort"], ortsteil=w["ortsteil"], emails=tuple(gruppe["emails"]), - verstorben=gruppe["verstorben"], rechtsperson=gruppe["rechtsperson"], + verstorben=gruppe["verstorben"], rechtsperson=tuple(gruppe["rechtsperson"]), per_ids=tuple(gruppe["per_ids"]), konten=tuple(gruppe["konten"]), feature_ids=tuple(gruppe["feature_ids"]), )) diff --git a/tests/test_eigentuemer_suche.py b/tests/test_eigentuemer_suche.py index b311324..e148b85 100644 --- a/tests/test_eigentuemer_suche.py +++ b/tests/test_eigentuemer_suche.py @@ -139,18 +139,29 @@ class TestSuche(unittest.TestCase): treffer = es.suche_eigentuemer(layer, "Beispiel", "Anna") self.assertEqual([e.wohnort for e in treffer], ["Altdorf", "Zettlitz"]) - def test_kennzeichen_verstorben_und_rechtsperson(self): - """Prüft, dass „verstorben“ und „Rechtsperson“ aus üblichen Ja-Werten erkannt werden und Nein-Werte, Leeres und NULL nicht zählen.""" - ja = ["J", "ja", "1", "true", "X"] - nein = ["", "0", "N", "nein", "false", None, _Null()] - zeilen = [_zeile(f"Ja{i}", "Test", PER_VERSTORBEN=w, PER_RECHTSPERSON=w) for i, w in enumerate(ja)] - zeilen += [_zeile(f"Nein{i}", "Test", PER_VERSTORBEN=w, PER_RECHTSPERSON=w) for i, w in enumerate(nein)] + def test_kennzeichen_verstorben(self): + """Prüft, dass „verstorben“ beim Exportwert 1 (auch als Zahl gelesen) gesetzt ist und bei 0, Leerem und NULL nicht.""" + ja = ["1", 1] + nein = ["0", 0, "", None, _Null()] + zeilen = [_zeile(f"Ja{i}", "Test", PER_VERSTORBEN=w) for i, w in enumerate(ja)] + zeilen += [_zeile(f"Nein{i}", "Test", PER_VERSTORBEN=w) for i, w in enumerate(nein)] for e in es.suche_eigentuemer(_Layer(zeilen), "", "Test"): erwartet = e.nachname.startswith("Ja") with self.subTest(name=e.nachname): self.assertEqual(e.verstorben, erwartet) - self.assertEqual(e.rechtsperson, erwartet) - self.assertEqual(e.hinweise, "verstorben, Rechtsperson" if erwartet else "") + self.assertEqual(e.hinweise, "verstorben" if erwartet else "") + + def test_rechtsperson_als_rohwert(self): + """Prüft, dass PER_RECHTSPERSON unverändert angezeigt wird (0, 1, 5, 9; noch nicht entschlüsselt) und abweichende Werte einer Person gesammelt werden.""" + layer = _Layer([ + _zeile("Beispiel", "Anna", PER_RECHTSPERSON="0"), + _zeile("Gemeinde Musterstadt", "", strasse="Markt 1", PER_RECHTSPERSON=5), + _zeile("Muster", "Bernd", PER_RECHTSPERSON="1"), + _zeile("Muster", "Bernd", PER_RECHTSPERSON="9"), + _zeile("Ohnewert", "Clara", PER_RECHTSPERSON=_Null()), + ]) + werte = {e.nachname: e.rechtsperson_text for e in es.suche_eigentuemer(layer, "e", "")} + self.assertEqual(werte, {"Beispiel": "0", "Gemeinde Musterstadt": "5", "Muster": "1, 9", "Ohnewert": ""}) def test_plz_mit_fuehrender_null(self): """Prüft, dass eine von QGIS als Zahl gelesene PLZ wieder fünfstellig mit führender Null erscheint und Zeilen dadurch zusammenfinden.""" diff --git a/tests/test_eigentuemer_tab.py b/tests/test_eigentuemer_tab.py index b9523b6..e68280e 100644 --- a/tests/test_eigentuemer_tab.py +++ b/tests/test_eigentuemer_tab.py @@ -103,7 +103,8 @@ def _eig_tab(nachname="Beispiel", vorname="", layer_id="csv1"): _ANNA = Eigentuemer(vorname="Anna", nachname="Beispiel", strasse="Hauptstraße 1", plz="01234", - wohnort="Musterstadt", emails=("anna@example.org",), verstorben=True) + wohnort="Musterstadt", emails=("anna@example.org",), verstorben=True, + rechtsperson=("0",)) @patch.object(et, "info") @@ -152,10 +153,10 @@ class TestEigentuemerSuchen(unittest.TestCase): class TestTrefferliste(unittest.TestCase): def test_trefferzeile_mit_hinweis(self): - """Prüft, dass die Trefferliste Name, Anschrift, E-Mail und die Kennzeichen „verstorben“/„Rechtsperson“ zeigt.""" + """Prüft, dass die Trefferliste Name, Anschrift, E-Mail, den Rohwert von PER_RECHTSPERSON und das Kennzeichen „verstorben“ zeigt.""" self.assertEqual( trefferzeile(_ANNA), - ("Beispiel, Anna", "Hauptstraße 1, 01234 Musterstadt", "anna@example.org", "verstorben"), + ("Beispiel, Anna", "Hauptstraße 1, 01234 Musterstadt", "anna@example.org", "0", "verstorben"), ) def test_ausgewaehlte_eigentuemer(self): diff --git a/ui/eigentuemer_treffer.py b/ui/eigentuemer_treffer.py index c75ce18..d2e501a 100644 --- a/ui/eigentuemer_treffer.py +++ b/ui/eigentuemer_treffer.py @@ -1,8 +1,8 @@ """sn_verfahrensgebiet/ui/eigentuemer_treffer.py – Trefferliste der Eigentümersuche (#56). Nicht modales Fenster für den Bearbeiter. Es zeigt die zusammengefassten -Treffer mit den Kennzeichen „verstorben“ und „Rechtsperson“ und erlaubt die -Mehrfachauswahl. Die Tabelle kommt aus +Treffer mit dem Wert von ``PER_RECHTSPERSON`` (noch nicht entschlüsselt) und dem +Kennzeichen „verstorben“ und erlaubt die Mehrfachauswahl. Die Tabelle kommt aus :func:`~sn_verfahrensgebiet.functions.verfahrensgebiet_dialoge.baue_auswahltabelle`, dieselbe wie bei „Verfahrensgebiete aus Landkreis laden“. """ @@ -17,15 +17,16 @@ from sn_verfahrensgebiet.functions.verfahrensgebiet_dialoge import ( ausgewaehlte_indizes, ) -SPALTENKOEPFE = ["Name", "Anschrift", "E-Mail", "Hinweis"] +SPALTENKOEPFE = ["Name", "Anschrift", "E-Mail", "Rechtsperson", "Hinweis"] -def trefferzeile(eigentuemer: Eigentuemer) -> Tuple[str, str, str, str]: +def trefferzeile(eigentuemer: Eigentuemer) -> Tuple[str, str, str, str, str]: """Spaltentexte eines Treffers in der Reihenfolge von :data:`SPALTENKOEPFE`.""" return ( eigentuemer.name, eigentuemer.anschrift, ", ".join(eigentuemer.emails), + eigentuemer.rechtsperson_text, eigentuemer.hinweise, )