diff --git a/changelog.txt b/changelog.txt
index f02bd08..5005014 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,4 @@
+- Neu: Grenzpunkte aus ALKIS werden nach dem Laden im ALKIS-Stil dargestellt (styles/alkis_grenzpunkte.qml), statt ungestylt zu bleiben (#53)
- Intern: Tests von TestFlurstueckAlkis an die seit längerem geänderte Ladelogik angeglichen (Mocks zeigten noch auf die alte Ein-Query-/Zwei-Knopf-Variante), bbox-Dokumentation in flurstueck_alkis.py korrigiert (bbox wird nicht mehr ausgewertet) – keine Verhaltensänderung (Test-Audit #16)
- Intern: Der Button "aus gewählten Gemarkungen laden" nutzt jetzt dieselbe Ladelogik wie "Flurstücke laden" (flurstueck_alkis) statt einer eigenen, parallelen Implementierung – konsolidiert drei bisher getrennte Code-Pfade zum Flurstücke-Laden auf einen (#47)
- Bugfix: Flurstücke aus ALKIS an bestehenden Layer anhängen überspringt jetzt bereits vorhandene Flurstücke (Abgleich über flurstueckskennzeichen), statt sie doppelt zu laden – betrifft sowohl den Dialog in "Flurstücke laden" als auch den Button "aus gewählten Gemarkungen laden" (#28)
diff --git a/functions/grenzpunkt_alkis.py b/functions/grenzpunkt_alkis.py
index e7c5f6e..0297a6f 100644
--- a/functions/grenzpunkt_alkis.py
+++ b/functions/grenzpunkt_alkis.py
@@ -34,6 +34,7 @@ from sn_basis.functions import QgsVectorLayer, QgsProject
from sn_basis.functions import QMessageBox
from sn_basis.functions.message_wrapper import info, warning
from sn_basis.functions.dialog_wrapper import create_progress_dialog
+from sn_basis.functions.ly_style_wrapper import apply_style
ALKIS_SF_URL = "https://geodienste.sachsen.de/aaa/public_alkis/sf/wfs"
PUNKTORT_TA_TYPENAME = "adv:AX_PunktortTA"
@@ -1652,6 +1653,7 @@ def grenzpunkte_gemarkungsweise(
return None
project.addMapLayer(joined_layer)
+ apply_style(joined_layer, "alkis_grenzpunkte.qml")
prog.set_value(prog_gesamt)
prog.close()
diff --git a/styles/alkis_grenzpunkte.qml b/styles/alkis_grenzpunkte.qml
new file mode 100644
index 0000000..e0bf9d7
--- /dev/null
+++ b/styles/alkis_grenzpunkte.qml
@@ -0,0 +1,913 @@
+
+
+
+ 1
+ 1
+ 1
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 0
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+
+
+ 0
+ generatedlayout
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ COALESCE( "gml_id", '<NULL>' )
+
+ 0
+
diff --git a/tests/test_grenzpunkt_alkis.py b/tests/test_grenzpunkt_alkis.py
index 7411d51..fc441ac 100644
--- a/tests/test_grenzpunkt_alkis.py
+++ b/tests/test_grenzpunkt_alkis.py
@@ -43,6 +43,7 @@ if "qgis" not in sys.modules:
from sn_verfahrensgebiet.functions.grenzpunkt_alkis import (
grenzpunkt_alkis,
+ grenzpunkte_gemarkungsweise,
_extrahiere_gml_ids,
)
@@ -297,5 +298,134 @@ class TestGrenzpunktAlkis(unittest.TestCase):
self.assertIs(gp, gp_layer)
+# ---------------------------------------------------------------------------
+# Tests: grenzpunkte_gemarkungsweise – Stilanbringung (#53)
+# ---------------------------------------------------------------------------
+
+_G_PATCH_EXTENTS = "sn_verfahrensgebiet.functions.grenzpunkt_alkis._lade_gemarkung_extents"
+_G_PATCH_HITS = "sn_verfahrensgebiet.functions.grenzpunkt_alkis._wfs_hits_count"
+_G_PATCH_GET_GML = "sn_verfahrensgebiet.functions.grenzpunkt_alkis._wfs_get_gml"
+_G_PATCH_PARSE_GML = "sn_verfahrensgebiet.functions.grenzpunkt_alkis._parse_alkis_gml_memory_layer"
+_G_PATCH_ERKENNE_FELD = "sn_verfahrensgebiet.functions.grenzpunkt_alkis._erkenne_gehoert_zu_feld"
+_G_PATCH_EXTRAHIERE_ID = "sn_verfahrensgebiet.functions.grenzpunkt_alkis._extrahiere_feature_gml_id"
+_G_PATCH_LADE_GP_DICT = "sn_verfahrensgebiet.functions.grenzpunkt_alkis._lade_grenzpunkte_als_dict"
+_G_PATCH_ERSTELLE_JOINED = "sn_verfahrensgebiet.functions.grenzpunkt_alkis._erstelle_joined_layer"
+_G_PATCH_WFS_LAYER = "sn_verfahrensgebiet.functions.grenzpunkt_alkis.QgsVectorLayer"
+_G_PATCH_PROJECT = "sn_verfahrensgebiet.functions.grenzpunkt_alkis.QgsProject"
+_G_PATCH_PROGRESS = "sn_verfahrensgebiet.functions.grenzpunkt_alkis.create_progress_dialog"
+_G_PATCH_APPLY_STIL = "sn_verfahrensgebiet.functions.grenzpunkt_alkis.apply_style"
+# QgsField/QgsFeature werden innerhalb der Funktion per lokalem Import geholt
+# (from sn_basis.functions import QgsField/QgsFeature) - Patch-Ziel ist daher
+# die Quelle, nicht der Aufrufort.
+_G_PATCH_QGSFIELD = "sn_basis.functions.QgsField"
+_G_PATCH_QGSFEATURE = "sn_basis.functions.QgsFeature"
+
+
+class _DummyProgress:
+ def set_value(self, wert): pass
+ def set_label(self, text): pass
+ def set_total(self, wert): pass
+ def is_canceled(self): return False
+ def close(self): pass
+
+
+class _DummyBbox:
+ def xMinimum(self): return 414000.0
+ def yMinimum(self): return 5657000.0
+ def xMaximum(self): return 415000.0
+ def yMaximum(self): return 5658000.0
+
+
+class _DummyGmlFeld:
+ def __init__(self, name):
+ self._name = name
+
+ def name(self):
+ return self._name
+
+
+class _DummyGmlFeature:
+ def __init__(self, gehoert_zu_wert):
+ self._wert = gehoert_zu_wert
+
+ def geometry(self):
+ return object()
+
+ def __getitem__(self, key):
+ if key == "gehoertZu":
+ return self._wert
+ raise KeyError(key)
+
+
+class _DummyGmlLayer:
+ """Minimaler Ersatz für das Ergebnis von _parse_alkis_gml_memory_layer()."""
+
+ def __init__(self, feature):
+ self._feature = feature
+
+ def fields(self):
+ return [_DummyGmlFeld("gehoertZu")]
+
+ def getFeatures(self):
+ return [self._feature]
+
+
+class TestGrenzpunkteGemarkungsweiseStil(unittest.TestCase):
+
+ @patch(_G_PATCH_APPLY_STIL)
+ @patch(_G_PATCH_QGSFEATURE)
+ @patch(_G_PATCH_QGSFIELD)
+ @patch(_G_PATCH_PROGRESS)
+ @patch(_G_PATCH_PROJECT)
+ @patch(_G_PATCH_WFS_LAYER)
+ @patch(_G_PATCH_ERSTELLE_JOINED)
+ @patch(_G_PATCH_LADE_GP_DICT)
+ @patch(_G_PATCH_EXTRAHIERE_ID)
+ @patch(_G_PATCH_ERKENNE_FELD)
+ @patch(_G_PATCH_PARSE_GML)
+ @patch(_G_PATCH_GET_GML)
+ @patch(_G_PATCH_HITS)
+ @patch(_G_PATCH_EXTENTS)
+ def test_stil_wird_nach_dem_laden_auf_den_ergebnis_layer_angewendet(
+ self,
+ mock_extents,
+ mock_hits,
+ mock_get_gml,
+ mock_parse_gml,
+ mock_erkenne_feld,
+ mock_extrahiere_id,
+ mock_lade_gp_dict,
+ mock_erstelle_joined,
+ mock_wfs_layer_cls,
+ mock_project_cls,
+ mock_progress,
+ mock_qgsfield,
+ mock_qgsfeature,
+ mock_apply_style,
+ ):
+ """Prüft, dass grenzpunkte_gemarkungsweise() nach dem Laden apply_style() mit dem neuen ALKIS-Grenzpunkt-Stil auf den fertigen Join-Layer anwendet (#53)."""
+ mock_extents.return_value = {"1234": _DummyBbox()}
+ mock_hits.return_value = 1
+ mock_get_gml.return_value = b""
+ mock_parse_gml.return_value = _DummyGmlLayer(_DummyGmlFeature("urn:adv:oid:GP1"))
+ mock_erkenne_feld.return_value = "gehoertZu"
+ mock_extrahiere_id.return_value = "PTA1"
+ mock_lade_gp_dict.return_value = ({"GP1": object()}, ["gp_feld"])
+
+ joined_layer = MagicMock()
+ mock_erstelle_joined.return_value = joined_layer
+ mock_wfs_layer_cls.return_value = MagicMock()
+
+ project = MagicMock()
+ mock_project_cls.instance.return_value = project
+ mock_progress.return_value = _DummyProgress()
+
+ ergebnis = grenzpunkte_gemarkungsweise(None, ["1234"])
+
+ self.assertIs(ergebnis, joined_layer)
+ project.addMapLayer.assert_called_once_with(joined_layer)
+ mock_apply_style.assert_called_once_with(joined_layer, "alkis_grenzpunkte.qml")
+
+
if __name__ == "__main__":
unittest.main()