From 3f81addcfbeae7aabcdd823340397f66e394f02f Mon Sep 17 00:00:00 2001 From: Matthias Andreas Benkard Date: Fri, 24 Jul 2026 05:34:32 +0200 Subject: =?UTF-8?q?Add=20Saxony=20S=C3=A4chsBeamtVG=20acceptance=20case=20?= =?UTF-8?q?(first=20non-Bavarian=20Landesrecht)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Complete the first §-structured Landesrecht acceptance case for wave six: the Saxon Civil Servants' Pension Act (SächsBeamtVG) in its 1 Feb 2025 version plus the amending act of 13 April 2026 (SächsGVBl. S. 134). All five commands are recognised and applied without residue — the amount replacements in § 47 and the re-enactment of § 80(1) sentence 2. - LandesRechtTextParser: recognise arabic, keyword-first structural headings ("Abschnitt 1", "Unterabschnitt 2", "Teil 3") via GLIEDERUNG_ARABISCH, in addition to Bavaria's roman "I. Abschnitt" form. Bavaria behaviour unchanged. - TextBereiniger: strip the footer of revosax full-text output (REVOSAX_FUSS, "https://…revosax… Fassung vom … Seite N von M"). - Add the consolidated pre-amendment stem as canonical plaintext (sampledata/Sachsen/SaechsBeamtVG-alt.txt, derived from the archived revosax full text) and EndToEndTest.saechsBeamtVgAcceptance (5 applied, 0 manual). 220 tests green; federal and Bavarian pinned numbers unchanged. Co-Authored-By: Claude Opus 4.8 Change-Id: I8e878bc9506f24028cf643a873de000f3d066d64 --- src/test/java/eu/mulk/aendggner/EndToEndTest.java | 57 +++++++++++++++++++++++ 1 file changed, 57 insertions(+) (limited to 'src/test') diff --git a/src/test/java/eu/mulk/aendggner/EndToEndTest.java b/src/test/java/eu/mulk/aendggner/EndToEndTest.java index 0e90584..98a996f 100644 --- a/src/test/java/eu/mulk/aendggner/EndToEndTest.java +++ b/src/test/java/eu/mulk/aendggner/EndToEndTest.java @@ -310,4 +310,61 @@ class EndToEndTest { var anwendung = BefehlAnwender.anwenden(gesetz, parseErgebnis.befehle()); assertThat(anwendung.protokoll()).hasSameSizeAs(parseErgebnis.befehle()); } + + /** + * Sächsisches Landesrecht (Akzeptanzfall der sechsten Welle): das paragraphengegliederte + * SächsBeamtVG in der Fassung vom 1. Februar 2025 (Klartext, aus der archivierten revosax- + * Volltextfassung abgeleitet) + das Gesetz zur Änderung des SächsBeamtVG vom 13. April 2026 + * (SächsGVBl. S. 134). Anders als Bayern gliedert Sachsen in §; alle fünf Befehle werden erkannt + * und angewandt. + */ + @Test + void saechsBeamtVgAcceptance() throws Exception { + var alt = SAMPLEDATA.resolve("Sachsen/SaechsBeamtVG-alt.txt"); + var pdf = SAMPLEDATA.resolve("Sachsen/SaechsGVBl-2026-S134_AendG-SaechsBeamtVG_revosax.pdf"); + assumeTrue(Files.exists(alt) && Files.exists(pdf), "SächsBeamtVG-Beispieldaten fehlen"); + + // 1. Stammgesetz laden (§-gegliedert, amtliche Satznummern als Superskripte, arabische + // „Abschnitt N“-Gliederung). + var gesetz = new eu.mulk.aendggner.gesetz.land.LandesRechtLoader().load(alt); + assertThat(gesetz.jurabk()).isEqualTo("SächsBeamtVG"); + assertThat(gesetz.langue()).isEqualTo("Sächsisches Beamtenversorgungsgesetz"); + assertThat(gesetz.norm("§ 47").orElseThrow().absaetze()).hasSize(6); + assertThat(gesetz.norm("§ 47").orElseThrow().absaetze().get(0).text()).contains("80 000 Euro"); + assertThat(gesetz.norm("§ 80").orElseThrow().absaetze()).hasSize(4); + + // 2. Änderungsgesetz extrahieren (Superskript-Erhalt; revosax-Fußzeile entfernt). + var text = + TextBereiniger.bereinige( + new PatchTextExtraktor(eu.mulk.aendggner.aenderung.parse.SuperskriptModus.BEHALTEN) + .extrahiere(pdf)); + assertThat(text).doesNotContain("Fassung vom 30.04.2026"); + + // 3. Parsen: nur Artikel 1 ändert das SächsBeamtVG (Artikel 2 ist Inkrafttreten); fünf Befehle, + // keiner unbekannt. + var parseErgebnis = new AenderungsgesetzParser().parse(text, gesetz, null); + assertThat(parseErgebnis.artikel()).containsExactly("1"); + assertThat(parseErgebnis.befehle()).hasSize(5); + assertThat(parseErgebnis.befehle()).noneMatch(b -> b instanceof UnbekannterBefehl); + + // 4. Anwenden: alle fünf Befehle greifen, kein Residuum. + var anwendung = BefehlAnwender.anwenden(gesetz, parseErgebnis.befehle()); + assertThat(anwendung.protokoll()) + .hasSameSizeAs(parseErgebnis.befehle()) + .allMatch(a -> a.status() == BefehlAnwender.Status.ANGEWANDT); + + // 5. Stichproben auf der neuen Fassung. + var neu = anwendung.neu(); + var neuer47 = neu.norm("§ 47").orElseThrow(); + assertThat(neuer47.absaetze().get(0).text()).contains("150 000 Euro").doesNotContain("80 000"); + var abs2 = neuer47.absaetze().get(1).text(); + assertThat(abs2).contains("100 000 Euro").contains("40 000 Euro").contains("20 000 Euro"); + assertThat(neu.norm("§ 80").orElseThrow().absaetze().get(0).text()) + .contains("§ 47 Absatz 1 und 2"); + + // 6. Synopse rendern. + var synopse = SynopseBuilder.baue(gesetz, anwendung, parseErgebnis.warnungen(), false); + var html = HtmlRenderer.rendere(synopse, "E2E-Test SächsBeamtVG"); + assertThat(html).contains("§ 47"); + } } -- cgit v1.2.1