From c6f7f4c0c2e9c730c5884e7bb7845259310a1689 Mon Sep 17 00:00:00 2001 From: fds2610-bot Date: Sun, 26 Apr 2026 21:08:14 +0200 Subject: [PATCH] Revert "Fix: UStVA-Kennziffern auf offizielle ELSTER-Definitionen korrigiert" This reverts commit bbfb41232e0c4c4f797aaf5a0d6247d76df9ac7e. --- Changes.md | 11 -- docs/berechnungslogik.md | 41 ++++--- src/Controllers/UstvaController.php | 2 +- src/Services/ElsterXmlService.php | 16 +-- src/Services/UstvaCalculator.php | 163 +++++++++++++++------------- src/Views/tax/ustva_kz_bookings.php | 10 +- src/Views/tax/ustva_show.php | 19 ++-- tests/05_TaxSummenTest.php | 27 ++++- tests/07_UstvaAuslandTest.php | 64 ++++++----- tests/13_ElsterXmlKz39Test.php | 28 ++--- tests/18_StornoBuchungTest.php | 6 +- 11 files changed, 216 insertions(+), 171 deletions(-) diff --git a/Changes.md b/Changes.md index 3550cd2..e45ecef 100644 --- a/Changes.md +++ b/Changes.md @@ -18,17 +18,6 @@ --- -## 2026-04-26 – Fix UStVA: Kennziffern auf offizielle ELSTER-Definitionen korrigiert - -### Geändert -- `src/Services/UstvaCalculator.php`: Kz 66 ist jetzt die primäre Inlandsvorsteuer (§§ 14, 14a) – alle Ausgabe-Buchungen mit Vorsteuer fließen direkt in Kz 66 (buchungsbasiert, unabhängig vom USt-Satz). Kz 61 ist jetzt Vorsteuer aus ig. Erwerben (§ 3d) = Kz89×0,19 + Kz93×0,07. Kz 62 (Einfuhrumsatzsteuer) und Kz 67 (§ 13b) werden auf 0 gesetzt. Kz 83 ist jetzt das Ergebnis (Verbleibende Vorauszahlung / Überschuss) statt der USt auf 19 %-Umsätze. Kz 35/44 (veraltet seit Migration 017) und Kz 91/94 (wurden fälschlich als USt-Beträge auf ig. Erwerb genutzt) entfernt. Kz 43 (Ausfuhren) und Kz 48 (steuerfreie Umsätze ohne VSt-Abzug) hinzugefügt. -- `src/Services/ElsterXmlService.php`: Betragsfelder auf korrekte Kz aktualisiert (43/48 statt 35/44); Kz39-Export (Sondervorauszahlung) durch Kz83-Export (Vorauszahlung/Überschuss) ersetzt. -- `src/Views/tax/ustva_show.php`: Abschnitte und Beschriftungen auf korrekte ELSTER-Kennziffern angepasst. -- `src/Views/tax/ustva_kz_bookings.php`: Referenz auf Kz 69 → Kz 83 umgestellt. -- `src/Controllers/UstvaController.php`: Whitelist gültiger Kennziffern aktualisiert. -- `docs/berechnungslogik.md`: UStVA-Abschnitt vollständig neu beschrieben. - ---- ## 2026-04-26 – KI-Diagnose: Erreichbarkeitsprüfung und Fehlerlog für Ollama diff --git a/docs/berechnungslogik.md b/docs/berechnungslogik.md index d6b4bb5..9d4cd07 100644 --- a/docs/berechnungslogik.md +++ b/docs/berechnungslogik.md @@ -43,31 +43,44 @@ Die EÜR basiert auf dem Feld `accounts.kontenart` sowie `accounts.euer_zeile` d Die UStVA kombiniert drei Quellen: -**Quelle 1 – kontobasiert** (`accounts.ustva_kz`): Umsatz- und steuerfreie Konten. Buchungen mit EU-Steuerarten werden hier ausgeschlossen. +**Quelle 1 – kontobasiert** (`accounts.ustva_kz`): reguläre Umsätze. Buchungen mit EU-Steuerarten werden hier ausgeschlossen. Kz 61/62 sind aus dieser Quelle entfernt – `ustva_kz='61'/'62'` wird ignoriert. -**Quelle 2 – buchungsbasiert** (`buchungstyp='Ausgabe'`, `betrag_ust != 0`): Alle inländischen Eingangsrechnungen mit Vorsteuer → **Kz 66** (§§ 14, 14a UStG). Buchungen mit EU-Steuerarten sind ausgenommen. Der Wert `ustva_kz` auf Vorsteuer-Konten wird nicht ausgewertet. +**Quelle 2 – buchungsbasiert** (`bookings.ust_satz`): Vorsteuer Kz 61/62. Alle Ausgabe-Buchungen mit `betrag_ust != 0` fließen anhand ihres `ust_satz` direkt in Kz 61 (19 %) bzw. Kz 62 (7 %) ein, unabhängig davon welches Konto gebucht wurde. Buchungen mit EU-Steuerarten sind ausgenommen. **Quelle 3 – steuerartbasiert** (`bookings.steuerart`): EU-Sonderfälle (ig. Lieferung, Ausfuhr, ig. Erwerb). Diese Buchungen landen unabhängig vom Kategorie-Konto in den richtigen Kennzahlen. ### Kontozuordnung und Kennzahlen -| Kz | ELSTER-Bezeichnung | Quelle | Erläuterung | +| Kz | Bezeichnung | Quelle | Erläuterung | |---|---|---|---| | **81** | Steuerpfl. Umsätze 19 % | `SUM(betrag_netto)` WHERE `ustva_kz='81'` | 8400, 8570, 8720, 8801, 8820, 8922 | +| **83** | USt auf steuerpfl. Umsätze 19 % | `SUM(betrag_ust)` WHERE `ustva_kz='81'` | s.o. | | **86** | Steuerpfl. Umsätze 7 % | `SUM(betrag_netto)` WHERE `ustva_kz='86'` | 8300, 8710, 8921 | -| **41** | Steuerfreie ig. Lieferungen (§ 4 Nr. 1b) | kontobasiert (`ustva_kz='41'`) **+** `steuerart='ig_lieferung'` | 8125; oder Buchung mit steuerart | -| **43** | Steuerfreie Ausfuhren (§ 4 Nr. 1a) | kontobasiert (`ustva_kz='43'`) **+** `steuerart='export'` | 8120; oder Buchung mit steuerart | -| **48** | Steuerfreie Umsätze ohne Vorsteuerabzug | `SUM(betrag_netto)` WHERE `ustva_kz='48'` | 8100, 8105, 8110 | +| **84** | USt auf steuerpfl. Umsätze 7 % | `SUM(betrag_ust)` WHERE `ustva_kz='86'` | s.o. | +| **35** | Steuerfreie Umsätze | `SUM(betrag_netto)` WHERE `ustva_kz='35'` | 8100, 8105, 8110 | +| **41** | Steuerfreie ig. Lieferungen | kontobasiert (`ustva_kz='41'`) **+** `steuerart='ig_lieferung'` | 8125; oder Buchung mit steuerart | +| **44** | Steuerfreie Ausfuhren | kontobasiert (`ustva_kz='44'`) **+** `steuerart='export'` | 8120; oder Buchung mit steuerart | +| **61** | Vorsteuer 19 % | `SUM(betrag_ust)` WHERE `buchungstyp='Ausgabe' AND ROUND(ust_satz)=19` | buchungsbasiert – kein spezielles VSt19-Konto nötig | +| **62** | Vorsteuer 7 % | `SUM(betrag_ust)` WHERE `buchungstyp='Ausgabe' AND ROUND(ust_satz)=7` | buchungsbasiert – kein spezielles VSt7-Konto nötig | | **89** | Ig. Erwerb 19 % – Bemessungsgrundlage | `SUM(betrag_netto)` WHERE `steuerart='ig_erwerb_19'` | kein spezielles Konto nötig | +| **91** | USt auf ig. Erwerb 19 % | `Kz 89 × 0,19` | berechnet | | **93** | Ig. Erwerb 7 % – Bemessungsgrundlage | `SUM(betrag_netto)` WHERE `steuerart='ig_erwerb_7'` | kein spezielles Konto nötig | -| **66** | Vorsteuer aus Lieferungen/Leistungen (§§ 14, 14a) | `SUM(betrag_ust)` WHERE `buchungstyp='Ausgabe' AND betrag_ust != 0` | buchungsbasiert – alle inländischen VSt-Beträge unabhängig vom Satz | -| **61** | Vorsteuer aus ig. Erwerben (§ 3d) | `Kz 89 × 0,19 + Kz 93 × 0,07` | berechnet; ig. Erwerb ist USt-neutral (hebt sich in Kz 83 auf) | -| **62** | Vorsteuer aus Einfuhrumsatzsteuer | 0 | in diesem System nicht vorgesehen | -| **67** | Vorsteuer aus Leistungen nach § 13b | 0 | in diesem System nicht vorgesehen | -| **83** | Verbleibende Umsatzsteuer-Vorauszahlung / Überschuss | `ust19 + ust7 − Kz 66 − Kz 61` | Ergebnis; ust19/ust7 = intern aus `betrag_ust` von 81/86-Konten | +| **94** | USt auf ig. Erwerb 7 % | `Kz 93 × 0,07` | berechnet | -### Kennziffern-Bedeutung (ELSTER) +### Abgeleitete Kennzahlen -Kz 83 ist laut ELSTER-Hilfe das **Ergebnis der Voranmeldung** (Verbleibende Vorauszahlung oder Überschuss), nicht – wie in früheren Systemversionen – die USt auf 19 %-Umsätze. Die ELSTER-Kennziffern 83, 61, 62, 66, 67 wurden mit dieser Änderung (2026-04-26) auf die offiziellen ELSTER-Definitionen korrigiert. +| Kz | Bezeichnung | Berechnung | +|---|---|---| +| **67** | Vorsteuer aus ig. Erwerb | Kz 91 + Kz 94 | +| **66** | Vorsteuerbeträge gesamt | Kz 61 + Kz 62 + Kz 67 | +| **69** | Verbleibende USt-Vorauszahlung / Erstattung | (Kz 83 + Kz 84 + Kz 91 + Kz 94) − Kz 66 | -Kz 35 und Kz 44 wurden in Migration 017 auf Kz 48 (steuerfreie Umsätze ohne VSt-Abzug) bzw. Kz 43 (Ausfuhren) umgestellt und werden nicht mehr verwendet. +### Migration 022 – Vorsteuer-Kz-Aufteilung (historisch) + +Vor Migration 022 trugen alle Vorsteuer-Konten `ustva_kz='66'`. Migration 022 setzte `ustva_kz='61'/'62'` je nach `steuercode`. Diese kontobasierte Zuordnung war erforderlich, weil alle Ausgaben eines Kontos denselben USt-Satz hatten. + +### Buchungsbasierte Vorsteuer (ab 2026) + +Die kontobasierte Zuordnung über `ustva_kz='61'/'62'` wurde zugunsten einer buchungsbasierten Zuordnung aufgegeben: `UstvaCalculator` wertet jetzt direkt `bookings.ust_satz` aus (`buchungstyp='Ausgabe'`, `betrag_ust != 0`). Damit reicht ein einzelnes Aufwandskonto für 19 % und 7 % USt aus. Der Wert `ustva_kz='61'/'62'` auf Konten wird nicht mehr ausgewertet. + +Kz 66 wird weiterhin rechnerisch als `Kz 61 + Kz 62 + Kz 67` aggregiert. diff --git a/src/Controllers/UstvaController.php b/src/Controllers/UstvaController.php index 1cc29eb..059c174 100644 --- a/src/Controllers/UstvaController.php +++ b/src/Controllers/UstvaController.php @@ -104,7 +104,7 @@ class UstvaController $month = (int)$params['month']; $kz = $params['kz'] ?? ''; - $validKz = ['81','86','41','43','48','89','93','66','61','62','67','83']; + $validKz = ['81','83','86','84','35','41','44','89','91','93','94','61','62','67','66','69']; if (!in_array($kz, $validKz, true)) { View::redirect("/tax/ustva/{$year}/{$month}", 'Ungültige Kennzahl.', 'error'); return; diff --git a/src/Services/ElsterXmlService.php b/src/Services/ElsterXmlService.php index 54d2033..d61f249 100644 --- a/src/Services/ElsterXmlService.php +++ b/src/Services/ElsterXmlService.php @@ -114,12 +114,12 @@ class ElsterXmlService $ustva->appendChild($dom->createElement('Steuernummer', $steuernummer)); // Kz-Felder: Bemessungsgrundlagen ganzzahlig, Steuerbeträge mit 2 Dezimalstellen. - // Kz83 (Vorauszahlung/Überschuss) wird aus den Komponenten von ELSTER berechnet, - // muss aber dennoch mit übertragen werden. + // Kz83/Kz84 werden nicht übertragen (serverseitig aus Kz81/Kz86 abgeleitet). + // Kz69 (Zahllast) wird als Kz39 übertragen. $kzBetrag = fn(float $v): string => (string)(int)round($v); $kzSteuer = fn(float $v): string => number_format($v, 2, '.', ''); - $betragsfelder = ['81', '86', '41', '43', '48', '89', '93']; + $betragsfelder = ['81', '86', '35', '41', '44', '89', '93']; foreach ($betragsfelder as $nr) { $val = (float)($kz[$nr]['betrag'] ?? 0.0); if ($val != 0.0) { @@ -127,7 +127,7 @@ class ElsterXmlService } } - $steuerfelder = ['66', '61', '62', '67']; + $steuerfelder = ['61', '62', '67', '66']; foreach ($steuerfelder as $nr) { $val = (float)($kz[$nr]['steuer'] ?? 0.0); if ($val != 0.0) { @@ -135,10 +135,10 @@ class ElsterXmlService } } - // Kz83: Verbleibende Umsatzsteuer-Vorauszahlung (positiv) / Überschuss (negativ) - $kz83val = (float)($kz['83']['steuer'] ?? 0.0); - if ($kz83val != 0.0) { - $ustva->appendChild($dom->createElement('Kz83', $kzSteuer($kz83val))); + // Zahllast → Kz39 (nur bei positivem Wert; bei Erstattung weglassen, da kein Vorzeichen erlaubt) + $zahllast = (float)($kz['69']['steuer'] ?? 0.0); + if ($zahllast > 0.0) { + $ustva->appendChild($dom->createElement('Kz39', $kzSteuer($zahllast))); } return $dom->saveXML(); diff --git a/src/Services/UstvaCalculator.php b/src/Services/UstvaCalculator.php index ad9c253..6349af8 100644 --- a/src/Services/UstvaCalculator.php +++ b/src/Services/UstvaCalculator.php @@ -9,72 +9,76 @@ use Steuerkram\Database; /** * Berechnet alle ELSTER-Kennzahlen (Kz) für die Umsatzsteuervoranmeldung. * - * Drei Quellen fließen in die Berechnung ein: + * Zwei Quellen fließen in die Berechnung ein: * * 1. Kontobasiert (accounts.ustva_kz des Kategorie-Kontos): - * ustva_kz = '81' → Kz 81 (betrag_netto); intern: ust19 (betrag_ust) - * ustva_kz = '86' → Kz 86 (betrag_netto); intern: ust7 (betrag_ust) + * ustva_kz = '81' → Kz 81 (betrag_netto), Kz 83 (betrag_ust) + * ustva_kz = '86' → Kz 86 (betrag_netto), Kz 84 (betrag_ust) + * ustva_kz = '35' → Kz 35 (betrag_netto) * ustva_kz = '41' → Kz 41 (betrag_netto) [steuerfreie ig. Lieferungen via Konto] - * ustva_kz = '43' → Kz 43 (betrag_netto) [steuerfreie Ausfuhren § 4 Nr. 1a] - * ustva_kz = '48' → Kz 48 (betrag_netto) [steuerfreie Umsätze ohne Vorsteuerabzug] + * ustva_kz = '44' → Kz 44 (betrag_netto) [steuerfreie Ausfuhren via Konto] + * (Kz 61/62 werden NICHT mehr über ustva_kz geroutet) * - * 2. Buchungsbasiert (buchungstyp='Ausgabe', betrag_ust ≠ 0): - * Alle inländischen Eingangsrechnungen → Kz 66 (§§ 14, 14a UStG) + * 2. Buchungsbasiert (bookings.ust_satz, für Vorsteuer): + * buchungstyp = 'Ausgabe', ust_satz = 19 → Kz 61 (betrag_ust) + * buchungstyp = 'Ausgabe', ust_satz = 7 → Kz 62 (betrag_ust) + * Damit entfällt die Notwendigkeit separater VSt19/VSt7-Konten. * * 3. Steuerart-basiert (bookings.steuerart, unabhängig vom Konto): * steuerart = 'ig_lieferung' → Kz 41 (betrag_netto) - * steuerart = 'export' → Kz 43 (betrag_netto) - * steuerart = 'ig_erwerb_19' → Kz 89 (betrag_netto) - * steuerart = 'ig_erwerb_7' → Kz 93 (betrag_netto) + * steuerart = 'export' → Kz 44 (betrag_netto) + * steuerart = 'ig_erwerb_19' → Kz 89 (betrag_netto), Kz 91 (netto × 0,19) + * steuerart = 'ig_erwerb_7' → Kz 93 (betrag_netto), Kz 94 (netto × 0,07) * Buchungen mit diesen steuerart-Werten bleiben aus der kontobasierten Berechnung * ausgeschlossen, um Doppelzählung zu vermeiden. + * Buchungen mit EU-Steuerarten fließen ebenfalls NICHT in Kz 61/62. * * Abgeleitete Kennzahlen: - * Kz 61 = Kz89 × 0,19 + Kz93 × 0,07 (Vorsteuer aus ig. Erwerben, § 3d UStG) - * Kz 62 = 0 (Einfuhrumsatzsteuer – in diesem System n.v.) - * Kz 67 = 0 (§ 13b-Vorsteuer – in diesem System n.v.) - * Kz 83 = ust19 + ust7 − Kz66 − Kz61 − Kz62 − Kz67 - * = ust19 + ust7 − Kz66 (ig. Erwerb ist USt-neutral) + * Kz 67 = Kz 91 + Kz 94 (Vorsteuer aus ig. Erwerb) + * Kz 66 = Kz 61 + Kz 62 + Kz 67 (Vorsteuer gesamt) + * Kz 69 = (Kz 83 + Kz 84 + Kz 91 + Kz 94) − Kz 66 (Zahllast) */ class UstvaCalculator { /** Steuerart-Werte die AUSSCHLIESSLICH steuerart-basiert berechnet werden. */ private const EU_STEUERARTEN = ['ig_lieferung', 'export', 'ig_erwerb_19', 'ig_erwerb_7']; + /** Vorsteuer-Kennzahl je USt-Satz (buchungsbasiert). */ + private const VST_SATZ_KZ = [19 => '61', 7 => '62']; + /** - * Kontobasiertes Drill-down-Mapping. - * Kz 83 (Zahllast) enthält auch die Einnahmen-Konten 81/86. + * Welche accounts.ustva_kz-Werte liefern Buchungen für die Drill-down-Ansicht. + * Nur für den kontobasierten Teil; EU-Steuerarten kommen aus KZ_STEUERART_MAP. + * Kz 61/62 sind hier nicht mehr enthalten (buchungsbasiert via VST_SATZ_KZ). */ private const KZ_ACCOUNT_MAP = [ '81' => ['81'], + '83' => ['81'], '86' => ['86'], + '84' => ['86'], + '35' => ['35'], '41' => ['41'], - '43' => ['43'], - '48' => ['48'], - '83' => ['81', '86'], + '44' => ['44'], ]; /** - * Steuerart-basiertes Drill-down-Mapping. + * Welche steuerart-Werte liefern Buchungen für eine Kennzahl. */ private const KZ_STEUERART_MAP = [ '41' => ['ig_lieferung'], - '43' => ['export'], + '44' => ['export'], '89' => ['ig_erwerb_19'], + '91' => ['ig_erwerb_19'], '93' => ['ig_erwerb_7'], - '61' => ['ig_erwerb_19', 'ig_erwerb_7'], - '83' => ['ig_lieferung', 'export', 'ig_erwerb_19', 'ig_erwerb_7'], + '94' => ['ig_erwerb_7'], + '67' => ['ig_erwerb_19', 'ig_erwerb_7'], + '66' => ['ig_erwerb_19', 'ig_erwerb_7'], + '69' => ['ig_lieferung', 'export', 'ig_erwerb_19', 'ig_erwerb_7'], ]; - /** - * Kennzahlen, deren Drill-down alle inländischen Ausgaben mit Vorsteuer enthält. - * (buchungsbasiert: buchungstyp='Ausgabe', betrag_ust != 0, keine EU-Steuerarten) - */ - private const KZ_INCLUDES_VST = ['66', '83']; - public function calculate(int $year, int $month): array { - // ── 1. Kontobasierte Kennzahlen (EU-Steuerarten ausgeschlossen) ────────── + // ── 1. Kontobasierte Kennzahlen (EU-Steuerarten und Kz 61/62 ausgeschlossen) ── $euPlaceholders = implode(',', array_fill(0, count(self::EU_STEUERARTEN), '?')); $accountRows = Database::fetchAll( 'SELECT a.ustva_kz, @@ -85,6 +89,7 @@ class UstvaCalculator JOIN accounts a ON a.id = bk.kategorie_konto_id WHERE fy.year = ? AND MONTH(bk.buchungs_datum) = ? AND a.ustva_kz IS NOT NULL AND a.ustva_kz != \'\' + AND a.ustva_kz NOT IN (\'61\', \'62\') AND (bk.steuerart IS NULL OR bk.steuerart NOT IN (' . $euPlaceholders . ')) GROUP BY a.ustva_kz', array_merge([$year, $month], self::EU_STEUERARTEN) @@ -98,19 +103,26 @@ class UstvaCalculator ]; } - // ── 2. Buchungsbasierte Vorsteuer Kz 66 (alle inländischen Eingangsrechnungen) ── - $vstRow = Database::fetchOne( - 'SELECT SUM(bk.betrag_ust) AS summe_ust + // ── 2. Buchungsbasierte Vorsteuer Kz 61/62 (via ust_satz) ──────────── + $vstRows = Database::fetchAll( + 'SELECT bk.ust_satz, SUM(bk.betrag_ust) AS summe_ust FROM bookings bk JOIN fiscal_years fy ON bk.fiscal_year_id = fy.id WHERE fy.year = ? AND MONTH(bk.buchungs_datum) = ? AND bk.buchungstyp = \'Ausgabe\' AND bk.betrag_ust != 0 - AND (bk.steuerart IS NULL OR bk.steuerart NOT IN (' . $euPlaceholders . '))', + AND (bk.steuerart IS NULL OR bk.steuerart NOT IN (' . $euPlaceholders . ')) + GROUP BY bk.ust_satz', array_merge([$year, $month], self::EU_STEUERARTEN) ); - $byKz['66'] = ['netto' => 0.0, 'ust' => (float)($vstRow['summe_ust'] ?? 0.0)]; + foreach ($vstRows as $row) { + $satz = (int)round((float)$row['ust_satz']); + $kzNr = self::VST_SATZ_KZ[$satz] ?? null; + if ($kzNr !== null) { + $byKz[$kzNr] = ['netto' => 0.0, 'ust' => (float)$row['summe_ust']]; + } + } // ── 3. Steuerart-basierte Kennzahlen ───────────────────────────────── $stRows = Database::fetchAll( @@ -129,41 +141,42 @@ class UstvaCalculator } // ── 4. Kennzahlen zusammensetzen ───────────────────────────────────── - $n = fn(string $kz): float => (float)($byKz[$kz]['netto'] ?? 0.0); - $u = fn(string $kz): float => (float)($byKz[$kz]['ust'] ?? 0.0); - $st = fn(string $art): float => (float)($bySteuerart[$art] ?? 0.0); + $n = fn(string $kz): float => (float)($byKz[$kz]['netto'] ?? 0.0); + $u = fn(string $kz): float => (float)($byKz[$kz]['ust'] ?? 0.0); + $st = fn(string $art): float => (float)($bySteuerart[$art] ?? 0.0); - $kz81 = $n('81'); - $ust19 = $u('81'); // interne USt aus 19 %-Umsätzen (kein eigenständiges ELSTER-Kz) - $kz86 = $n('86'); - $ust7 = $u('86'); // interne USt aus 7 %-Umsätzen (kein eigenständiges ELSTER-Kz) - $kz41 = $n('41') + $st('ig_lieferung'); - $kz43 = $n('43') + $st('export'); - $kz48 = $n('48'); - $kz89 = $st('ig_erwerb_19'); - $kz93 = $st('ig_erwerb_7'); - $kz66 = $u('66'); // § 14, 14a - $kz61 = round($kz89 * 0.19, 2) + round($kz93 * 0.07, 2); // § 3d Satz 1 - $kz62 = 0.0; // Einfuhrumsatzsteuer n.v. - $kz67 = 0.0; // § 13b-Vorsteuer n.v. - // ig. Erwerb-USt gilt gleichzeitig als Output- und als Vorsteuer (kz61) → neutral - $igErwerbUst = round($kz89 * 0.19, 2) + round($kz93 * 0.07, 2); // = kz61 - $kz83 = ($ust19 + $ust7 + $igErwerbUst) - ($kz66 + $kz61 + $kz62 + $kz67); + $kz81 = $n('81'); $kz83 = $u('81'); + $kz86 = $n('86'); $kz84 = $u('86'); + $kz35 = $n('35'); + $kz41 = $n('41') + $st('ig_lieferung'); + $kz44 = $n('44') + $st('export'); + $kz89 = $st('ig_erwerb_19'); + $kz91 = round($kz89 * 0.19, 2); + $kz93 = $st('ig_erwerb_7'); + $kz94 = round($kz93 * 0.07, 2); + $kz61 = $u('61'); + $kz62 = $u('62'); + $kz67 = $kz91 + $kz94; + $kz66 = $kz61 + $kz62 + $kz67; + $kz69 = ($kz83 + $kz84 + $kz91 + $kz94) - $kz66; return [ - '81' => ['name' => 'Steuerpfl. Umsätze 19 %', 'betrag' => round($kz81, 2), 'steuer' => null], - '86' => ['name' => 'Steuerpfl. Umsätze 7 %', 'betrag' => round($kz86, 2), 'steuer' => null], - '43' => ['name' => 'Steuerfreie Ausfuhren (§ 4 Nr. 1a)', 'betrag' => round($kz43, 2), 'steuer' => null], - '48' => ['name' => 'Steuerfreie Umsätze ohne Vorsteuerabzug', 'betrag' => round($kz48, 2), 'steuer' => null], - '41' => ['name' => 'Steuerfreie ig. Lieferungen (§ 4 Nr. 1b)', 'betrag' => round($kz41, 2), 'steuer' => null], - '89' => ['name' => 'Ig. Erwerb 19 % – Bemessungsgrundlage', 'betrag' => round($kz89, 2), 'steuer' => null], - '93' => ['name' => 'Ig. Erwerb 7 % – Bemessungsgrundlage', 'betrag' => round($kz93, 2), 'steuer' => null], - '66' => ['name' => 'Vorsteuer aus Lieferungen/Leistungen (§§ 14, 14a)', 'betrag' => null, 'steuer' => round($kz66, 2)], - '61' => ['name' => 'Vorsteuer aus ig. Erwerben (§ 3d UStG)', 'betrag' => null, 'steuer' => round($kz61, 2)], - '62' => ['name' => 'Vorsteuer aus Einfuhrumsatzsteuer', 'betrag' => null, 'steuer' => round($kz62, 2)], - '67' => ['name' => 'Vorsteuer aus Leistungen nach § 13b UStG', 'betrag' => null, 'steuer' => round($kz67, 2)], - '83' => ['name' => 'Verbleibende Umsatzsteuer-Vorauszahlung / Überschuss', 'betrag' => null, 'steuer' => round($kz83, 2)], - '_ust' => ['name' => 'Umsatzsteuer gesamt (intern)', 'betrag' => null, 'steuer' => round($ust19 + $ust7, 2)], + '81' => ['name' => 'Steuerpfl. Umsätze 19 %', 'betrag' => round($kz81, 2), 'steuer' => null], + '83' => ['name' => 'USt auf steuerpfl. Umsätze 19 %', 'betrag' => null, 'steuer' => round($kz83, 2)], + '86' => ['name' => 'Steuerpfl. Umsätze 7 %', 'betrag' => round($kz86, 2), 'steuer' => null], + '84' => ['name' => 'USt auf steuerpfl. Umsätze 7 %', 'betrag' => null, 'steuer' => round($kz84, 2)], + '35' => ['name' => 'Steuerfreie Umsätze (ohne Vorsteuerabzug)', 'betrag' => round($kz35, 2), 'steuer' => null], + '41' => ['name' => 'Steuerfreie ig. Lieferungen (§ 4 Nr. 1b)', 'betrag' => round($kz41, 2), 'steuer' => null], + '44' => ['name' => 'Steuerfreie Ausfuhren (§ 4 Nr. 1a)', 'betrag' => round($kz44, 2), 'steuer' => null], + '89' => ['name' => 'Ig. Erwerb 19 % – Bemessungsgrundlage', 'betrag' => round($kz89, 2), 'steuer' => null], + '91' => ['name' => 'USt auf ig. Erwerb 19 %', 'betrag' => null, 'steuer' => round($kz91, 2)], + '93' => ['name' => 'Ig. Erwerb 7 % – Bemessungsgrundlage', 'betrag' => round($kz93, 2), 'steuer' => null], + '94' => ['name' => 'USt auf ig. Erwerb 7 %', 'betrag' => null, 'steuer' => round($kz94, 2)], + '61' => ['name' => 'Vorsteuer aus Eingangsrechnungen 19 %', 'betrag' => null, 'steuer' => round($kz61, 2)], + '62' => ['name' => 'Vorsteuer aus Eingangsrechnungen 7 %', 'betrag' => null, 'steuer' => round($kz62, 2)], + '67' => ['name' => 'Vorsteuer aus ig. Erwerb', 'betrag' => null, 'steuer' => round($kz67, 2)], + '66' => ['name' => 'Vorsteuerbeträge gesamt', 'betrag' => null, 'steuer' => round($kz66, 2)], + '69' => ['name' => 'Verbleibende USt-Vorauszahlung/Erstattung', 'betrag' => null, 'steuer' => round($kz69, 2)], ]; } @@ -173,11 +186,13 @@ class UstvaCalculator */ public function fetchBookingsForKz(int $year, int $month, string $kz): array { - $accountKzList = self::KZ_ACCOUNT_MAP[$kz] ?? []; - $steuerartList = self::KZ_STEUERART_MAP[$kz] ?? []; - $includesVst = in_array($kz, self::KZ_INCLUDES_VST, true); + $accountKzList = self::KZ_ACCOUNT_MAP[$kz] ?? []; + $steuerartList = self::KZ_STEUERART_MAP[$kz] ?? []; - if (empty($accountKzList) && empty($steuerartList) && !$includesVst) { + // Kz 61/62: buchungsbasiert via ust_satz + $vstSatz = array_search($kz, self::VST_SATZ_KZ, true); + + if (empty($accountKzList) && empty($steuerartList) && $vstSatz === false) { return []; } @@ -211,14 +226,16 @@ class UstvaCalculator ); } - if ($includesVst) { + if ($vstSatz !== false) { $euPh = implode(',', array_fill(0, count(self::EU_STEUERARTEN), '?')); $parts[] = $select . ' AND bk.buchungstyp = \'Ausgabe\'' . ' AND bk.betrag_ust != 0' + . ' AND ROUND(bk.ust_satz) = ?' . ' AND (bk.steuerart IS NULL OR bk.steuerart NOT IN (' . $euPh . '))'; $params = array_merge($params, [$year, $month], + [$vstSatz], self::EU_STEUERARTEN ); } diff --git a/src/Views/tax/ustva_kz_bookings.php b/src/Views/tax/ustva_kz_bookings.php index 717adb2..fa386d5 100644 --- a/src/Views/tax/ustva_kz_bookings.php +++ b/src/Views/tax/ustva_kz_bookings.php @@ -3,10 +3,10 @@ use Steuerkram\View; $h = fn($v) => View::h($v); $fmtKz = fn($v) => number_format((float)$v, 2, ',', '.') . ' €'; -// Für Kz 83: vorzeichenbehafteter USt-Beitrag zur Zahllast. +// Für Kz 69: vorzeichenbehafteter USt-Beitrag zur Zahllast. // Einnahmen mit USt = positiv, Ausgaben mit Vorsteuer = negativ, // ig_erwerb heben sich gegenseitig auf → 0. -$ustBeitragKz83 = function(array $b): float { +$ustBeitragKz69 = function(array $b): float { $steuerart = $b['steuerart'] ?? 'normal'; $ustSatz = (float)$b['ust_satz']; $betragUst = (float)$b['betrag_ust']; @@ -16,7 +16,7 @@ $ustBeitragKz83 = function(array $b): float { if ($b['buchungstyp'] === 'Ausgabe' && $steuerart === 'normal' && $betragUst != 0) { return -$betragUst; // Vorsteuer → Vorzeichen umkehren } - return 0.0; // steuerfreie Umsätze und ig_erwerb (Netto-Beitrag 0, da neutral) + return 0.0; // steuerfreie Umsätze und ig_erwerb (KZ91-KZ94 = KZ67, Netto-Beitrag 0) }; // Ausgaben werden als negative Beträge angezeigt (Geld fließt ab). @@ -49,7 +49,7 @@ $signedBetrag = fn(array $b, string $field): float => Kategorie Zahlungskonto Netto - + Brutto Anlage @@ -60,7 +60,7 @@ $signedBetrag = fn(array $b, string $field): float => $sumUst = 0.0; $sumBrutto = 0.0; foreach ($bookings as $b): - $ust = $kz === '83' ? $ustBeitragKz83($b) : $signedBetrag($b, 'betrag_ust'); + $ust = $kz === '69' ? $ustBeitragKz69($b) : $signedBetrag($b, 'betrag_ust'); $netto = $signedBetrag($b, 'betrag_netto'); $brutto = $signedBetrag($b, 'betrag_brutto'); $sumNetto += $netto; diff --git a/src/Views/tax/ustva_show.php b/src/Views/tax/ustva_show.php index 3ebaad9..5bcdc3f 100644 --- a/src/Views/tax/ustva_show.php +++ b/src/Views/tax/ustva_show.php @@ -30,10 +30,11 @@ $fmtKz = fn($v) => $v !== null ? number_format((float)$v, 2, ',', '.') . ' €' ['81', '86', '43', '48', '41'], - 'Innergemeinschaftlicher Erwerb' => ['89', '93'], - 'Abziehbare Vorsteuerbeträge' => ['66', '61', '62', '67'], - 'Verbleibende Zahllast' => ['83'], + 'Steuerpflichtige Umsätze' => ['81', '86', '35', '41', '44'], + 'Umsatzsteuer auf Umsätze' => ['83', '84'], + 'Innergemeinschaftlicher Erwerb' => ['89', '91', '93', '94'], + 'Vorsteuerbeträge' => ['61', '62', '67', '66'], + 'Verbleibende Zahllast' => ['69'], ]; foreach ($sections as $sectionTitle => $kzNrs): ?> @@ -45,7 +46,7 @@ $fmtKz = fn($v) => $v !== null ? number_format((float)$v, 2, ',', '.') . ' €' @@ -108,16 +109,16 @@ $fmtKz = fn($v) => $v !== null ? number_format((float)$v, 2, ',', '.') . ' €' USt gesamt - + Vorsteuer – - = 0 ? 'Vorauszahlung' : 'Erstattung' ?> - - + = 0 ? 'Vorauszahlung' : 'Erstattung' ?> + + diff --git a/tests/05_TaxSummenTest.php b/tests/05_TaxSummenTest.php index 4d90f6b..ef35c1c 100644 --- a/tests/05_TaxSummenTest.php +++ b/tests/05_TaxSummenTest.php @@ -111,15 +111,30 @@ class TaxSummenTest extends TestCase 'UStVA Kz 81 (Umsätze 19%): Betrag enthält Einnahme ≥ 500 €' ); - // Kz 66: reguläre Inlandsvorsteuer (§§ 14, 14a) – muss mindestens 38 € enthalten + // Kz 83: USt auf Umsätze 19% – abgeleitet (19% von Kz81-Betrag) $this->assert( - (float)$kz['66']['steuer'] >= 38.00, - 'UStVA Kz 66 (Vorsteuer §§ 14, 14a): Steuerbetrag enthält Ausgabe ≥ 38 €' + (float)$kz['83']['steuer'] >= 95.00, + 'UStVA Kz 83 (USt 19%): Steuerbetrag ≥ 95 €' ); - // Kz 83: Zahllast = _ust - Kz66 (USt gesamt minus Vorsteuer) - $erwKz83 = round((float)$kz['_ust']['steuer'] - (float)$kz['66']['steuer'], 2); - $this->assertEquals($erwKz83, (float)$kz['83']['steuer'], 'UStVA Kz 83 (Zahllast) korrekt berechnet'); + // Kz 61: Vorsteuer 19% – muss mindestens 38 € enthalten + $this->assert( + (float)$kz['61']['steuer'] >= 38.00, + 'UStVA Kz 61 (Vorsteuer 19%): Steuerbetrag enthält Ausgabe ≥ 38 €' + ); + + // Kz 66: Vorsteuer gesamt – muss ≥ Kz 61 sein + $this->assert( + (float)$kz['66']['steuer'] >= (float)$kz['61']['steuer'], + 'UStVA Kz 66 (Vorsteuer gesamt): ≥ Kz 61' + ); + + // Kz 69 Berechnung: USt gesamt - Vorsteuer gesamt + $erwKz69 = round( + ((float)$kz['83']['steuer'] + (float)$kz['84']['steuer']) - (float)$kz['66']['steuer'], + 2 + ); + $this->assertEquals($erwKz69, (float)$kz['69']['steuer'], 'UStVA Kz 69 (Zahllast) korrekt berechnet'); // ── EÜR prüfen ──────────────────────────────────────────────────── $euerCalc = new \Steuerkram\Services\EuerCalculator(); diff --git a/tests/07_UstvaAuslandTest.php b/tests/07_UstvaAuslandTest.php index 6eb872c..92e6ef3 100644 --- a/tests/07_UstvaAuslandTest.php +++ b/tests/07_UstvaAuslandTest.php @@ -6,7 +6,7 @@ declare(strict_types=1); * Test 7: UStVA-Kennzahlen für Auslandsumsätze und ig. Erwerb. * * Prüft, dass steuerart-Buchungen korrekt in die UStVA-Kennzahlen - * 41, 43, 89, 93 und 61 einfließen. + * 41, 44, 89, 91, 93, 94 und 67 einfließen. */ class UstvaAuslandTest extends TestCase { @@ -36,11 +36,6 @@ class UstvaAuslandTest extends TestCase ); $bankId = $bankId ? (int)$bankId['id'] : $zahlungId; - // Baseline Kz83 VOR den Test-Buchungen (reale Buchungen im laufenden Monat) - $calcPre = new \Steuerkram\Services\UstvaCalculator(); - $kzPre = $calcPre->calculate($year, $month); - $kz83Pre = (float)$kzPre['83']['steuer']; - // ── 1. Steuerfreie ig. Lieferung → Kz 41 ────────────────────────── $belegIgL = \Steuerkram\Models\Beleg::create([ 'beleg_nr' => 'TEST-IGL-' . uniqid(), @@ -63,7 +58,7 @@ class UstvaAuslandTest extends TestCase 'buchungstext' => 'Test ig. Lieferung EU', ]); - // ── 2. Steuerfreie Ausfuhr → Kz 43 ─────────────────────────────── + // ── 2. Steuerfreie Ausfuhr → Kz 44 ─────────────────────────────── $belegExp = \Steuerkram\Models\Beleg::create([ 'beleg_nr' => 'TEST-EXP-' . uniqid(), 'filename' => 'test-exp.pdf', @@ -85,7 +80,7 @@ class UstvaAuslandTest extends TestCase 'buchungstext' => 'Test Ausfuhr Drittland', ]); - // ── 3. Ig. Erwerb 19 % → Kz 89 (Bemessungsgrundlage), Kz 61 (Vorsteuer) ── + // ── 3. Ig. Erwerb 19 % → Kz 89/91/67 ───────────────────────────── $belegIgE19 = \Steuerkram\Models\Beleg::create([ 'beleg_nr' => 'TEST-IGE19-' . uniqid(), 'filename' => 'test-ige19.pdf', @@ -107,7 +102,7 @@ class UstvaAuslandTest extends TestCase 'buchungstext' => 'Test ig. Erwerb 19%', ]); - // ── 4. Ig. Erwerb 7 % → Kz 93 (Bemessungsgrundlage), Kz 61 (Vorsteuer) ─── + // ── 4. Ig. Erwerb 7 % → Kz 93/94/67 ────────────────────────────── $belegIgE7 = \Steuerkram\Models\Beleg::create([ 'beleg_nr' => 'TEST-IGE7-' . uniqid(), 'filename' => 'test-ige7.pdf', @@ -139,10 +134,10 @@ class UstvaAuslandTest extends TestCase 'Kz 41 (ig. Lieferung): Betrag ≥ 1.000 €' ); - // Kz 43: Ausfuhr 2000 € + // Kz 44: Ausfuhr 2000 € $this->assert( - (float)$kz['43']['betrag'] >= 2000.00, - 'Kz 43 (Ausfuhr): Betrag ≥ 2.000 €' + (float)$kz['44']['betrag'] >= 2000.00, + 'Kz 44 (Ausfuhr): Betrag ≥ 2.000 €' ); // Kz 89: ig. Erwerb 19% Bemessungsgrundlage 500 € @@ -151,33 +146,52 @@ class UstvaAuslandTest extends TestCase 'Kz 89 (ig. Erwerb 19% Bmgl.): Betrag ≥ 500 €' ); + // Kz 91: USt auf ig. Erwerb 19% = 500 * 0.19 = 95 € + $this->assertEquals( + round(500.00 * 0.19, 2), + (float)$kz['91']['steuer'], + 'Kz 91 (USt ig. Erwerb 19%): Steuer = 95,00 €' + ); + // Kz 93: ig. Erwerb 7% Bemessungsgrundlage 300 € $this->assert( (float)$kz['93']['betrag'] >= 300.00, 'Kz 93 (ig. Erwerb 7% Bmgl.): Betrag ≥ 300 €' ); - // Kz 61: Vorsteuer aus ig. Erwerben (§ 3d) = 500*0.19 + 300*0.07 = 95 + 21 = 116 € - $erwartetKz61 = round(500.00 * 0.19, 2) + round(300.00 * 0.07, 2); + // Kz 94: USt auf ig. Erwerb 7% = 300 * 0.07 = 21 € $this->assertEquals( - $erwartetKz61, - (float)$kz['61']['steuer'], - 'Kz 61 (Vorsteuer ig. Erwerb § 3d): Steuer = 116,00 €' + round(300.00 * 0.07, 2), + (float)$kz['94']['steuer'], + 'Kz 94 (USt ig. Erwerb 7%): Steuer = 21,00 €' ); - // Kz 83 (Zahllast): ig. Erwerb/Lieferung/Ausfuhr sind USt-neutral (betrag_ust=0) - // → Zahllast darf sich gegenüber Baseline nicht verändert haben + // Kz 67: Vorsteuer aus ig. Erwerb = Kz 91 + Kz 94 = 116 € + $erwartetKz67 = round((float)$kz['91']['steuer'] + (float)$kz['94']['steuer'], 2); $this->assertEquals( - round($kz83Pre, 2), - (float)$kz['83']['steuer'], - 'Kz 83 (Zahllast) unverändert – alle EU-Buchungen sind USt-neutral' + $erwartetKz67, + (float)$kz['67']['steuer'], + 'Kz 67 (Vorsteuer ig. Erwerb) = Kz 91 + Kz 94' ); - // ig. Erwerb darf NICHT in Kz 48 landen (steuerfreie Umsätze ohne VSt-Abzug) + // Kz 69 Plausibilitätsprüfung: ig. Erwerb neutralisiert sich durch Kz 67 + // USt auf Umsätze (83+84) + ig. Erwerb (91+94) - Vorsteuer (66) = 69 + $ust = (float)$kz['83']['steuer'] + (float)$kz['84']['steuer'] + + (float)$kz['91']['steuer'] + (float)$kz['94']['steuer']; + $erwartetKz69 = round($ust - (float)$kz['66']['steuer'], 2); + $this->assertEquals( + $erwartetKz69, + (float)$kz['69']['steuer'], + 'Kz 69 (Zahllast) korrekt berechnet' + ); + + // ig. Erwerb darf NICHT in Kz 35 oder Kz 61/62 landen + // (kz35 enthält nur normale 0%-Einnahmen, kz61 nur normale Vorsteuer) + // Wir buchten keine normalen 0%-Einnahmen, also muss Kz 35 = 0 sein $this->assertEquals( 0.0, - (float)$kz['48']['betrag'], - 'Kz 48 (steuerfreie Inlandsumsätze) = 0 (kein steuerfreier Inlandsumsatz gebucht)' + (float)$kz['35']['betrag'], + 'Kz 35 (steuerfreie Inlandsumsätze) = 0 (kein normaler 0%-Umsatz gebucht)' ); } diff --git a/tests/13_ElsterXmlKz39Test.php b/tests/13_ElsterXmlKz39Test.php index 76c61a3..1c4cfc5 100644 --- a/tests/13_ElsterXmlKz39Test.php +++ b/tests/13_ElsterXmlKz39Test.php @@ -6,33 +6,29 @@ use Steuerkram\Services\ElsterXmlService; class ElsterXmlKz39Test extends TestCase { - protected string $testName = 'Test 13: UStVA XML – Kz83 Vorauszahlung/Überschuss'; + protected string $testName = 'Test 13: UStVA XML – Kz39 Vorzeichen-Validierung'; public function run(): void { $service = new ElsterXmlService(); - // Fall 1: Zahllast positiv → Kz83 muss vorhanden und positiv sein - $kzZahllast = ['83' => ['steuer' => 150.00]]; + // Fall 1: Zahllast positiv → Kz39 muss vorhanden und positiv sein + $kzZahllast = ['69' => ['steuer' => 150.00]]; $xml = $service->generate(2026, 1, $kzZahllast); - $this->assert(str_contains($xml, ''), 'Kz83 bei Zahllast vorhanden'); - $this->assert(str_contains($xml, '150.00'), 'Kz83 enthält korrekten Betrag bei Zahllast'); + $this->assert(str_contains($xml, ''), 'Kz39 bei Zahllast vorhanden'); + $this->assert(str_contains($xml, '150.00'), 'Kz39 ohne Vorzeichen bei Zahllast'); - // Fall 2: Erstattung (negativ) → Kz83 muss vorhanden sein (Überschuss) - $kzErstattung = ['83' => ['steuer' => -50.00]]; + // Fall 2: Erstattung (negativ) → Kz39 darf nicht vorkommen + $kzErstattung = ['69' => ['steuer' => -50.00]]; $xml = $service->generate(2026, 1, $kzErstattung); - $this->assert(str_contains($xml, ''), 'Kz83 bei Erstattung vorhanden'); - $this->assert(str_contains($xml, '-50.00'), 'Kz83 enthält negativen Betrag bei Erstattung'); + $this->assert(!str_contains($xml, ''), 'Kz39 bei Erstattung nicht vorhanden'); - // Fall 3: Zahllast = 0 → Kz83 weglassen - $kzNull = ['83' => ['steuer' => 0.0]]; + // Fall 3: Zahllast = 0 → Kz39 weglassen + $kzNull = ['69' => ['steuer' => 0.0]]; $xml = $service->generate(2026, 1, $kzNull); - $this->assert(!str_contains($xml, ''), 'Kz83 bei Nullbetrag nicht vorhanden'); + $this->assert(!str_contains($xml, ''), 'Kz39 bei Nullbetrag nicht vorhanden'); - // Fall 4: Kz39 (Sondervorauszahlung) darf NICHT mehr als Zahllast exportiert werden - $this->assert(!str_contains($xml, ''), 'Kz39 (Sondervorauszahlung) wird nicht exportiert'); - - // Fall 5: XML ist valides XML + // Fall 4: XML ist valides XML $doc = new \DOMDocument(); $loaded = @$doc->loadXML($xml); $this->assert($loaded !== false, 'Generiertes XML ist wohlgeformt'); diff --git a/tests/18_StornoBuchungTest.php b/tests/18_StornoBuchungTest.php index 366546d..ec9294e 100644 --- a/tests/18_StornoBuchungTest.php +++ b/tests/18_StornoBuchungTest.php @@ -93,12 +93,12 @@ class StornoBuchungTest extends TestCase ); // ── UStVA: Vorsteuer-KZ hebt sich auf ───────────────────────── - // Kz 66 enthält alle inländischen Ausgaben mit Vorsteuer (buchungsbasiert). + // Kz 61 enthält Vorsteuer aus dem Ausgabe-Konto (ustva_kz='61'). // Original: +19, Storno: -19 → Summe = 0 (oder weniger als andere Tests einbringen). // Da weitere Tests parallel laufen können, prüfen wir nur, dass die Storno-Buchung // als eigenständige Zeile in fetchBookingsForKz erscheint. $ustvaCalc = new \Steuerkram\Services\UstvaCalculator(); - $bookings = $ustvaCalc->fetchBookingsForKz($year, $month, '66'); + $bookings = $ustvaCalc->fetchBookingsForKz($year, $month, '61'); $reversalFound = false; foreach ($bookings as $b) { @@ -109,6 +109,6 @@ class StornoBuchungTest extends TestCase break; } } - $this->assert($reversalFound, 'UStVA-Drilldown Kz 66: Stornobuchung erscheint in Detailansicht'); + $this->assert($reversalFound, 'UStVA-Drilldown Kz 61: Stornobuchung erscheint in Detailansicht'); } }