Steuerkram/tests/100_VorsteuerEuerZeileTest.php

157 lines
6.9 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
declare(strict_types=1);
/**
* Test 100: Gezahlte Vorsteuer als Betriebsausgabe in der EÜR.
*
* Die EÜR wird nach der Bruttomethode gerechnet: vereinnahmte USt ist
* Betriebseinnahme (Zeile 17), an das Finanzamt gezahlte USt ist
* Betriebsausgabe (Zeile 58) – und die gezahlte Vorsteuer gehört als
* Betriebsausgabe in Zeile 57 (ELSTER-Kennzahl 185, Migration 095).
*
* Maßgeblich für die Summenbildung ist dabei `kontenart`; `euer_zeile` wertet
* der EuerCalculator nur beim Wert '74' aus. Der Test prüft trotzdem beides,
* weil die Zeilennummer die Position der amtlichen Anlage EÜR dokumentiert.
*/
class VorsteuerEuerZeileTest extends TestCase
{
protected string $testName = 'Test 100: Vorsteuer in EÜR-Zeile 57 (Kz 185)';
public function run(): void
{
// ── 1. Kontenstamm: Vorsteuerkonten sind Betriebsausgabe, Zeile 57 ──
foreach (['1571', '1574', '1576'] as $nr) {
$kto = \Steuerkram\Database::fetchOne(
'SELECT kontenart, euer_zeile FROM accounts WHERE kontonummer = ?',
[$nr]
);
$this->assertNotEmpty($kto, "Vorsteuerkonto $nr existiert");
$this->assertEquals('Betriebsausgabe', $kto['kontenart'] ?? null, "Konto $nr ist Betriebsausgabe");
$this->assertEquals('57', $kto['euer_zeile'] ?? null, "Konto $nr hat euer_zeile=57");
}
// ── 2. Auswahlliste im Kontenformular führt Zeile 57 mit Kennzahl 185 ──
$form = (string)file_get_contents(__DIR__ . '/../src/Views/accounts/form.php');
$this->assert(
str_contains($form, "'57' => '57 (Kz 185)"),
'Kontenformular bietet EÜR-Zeile 57 mit ELSTER-Kennzahl 185 an'
);
$this->assert(
str_contains($form, "(string)\$val ? ' selected' : ''"),
'Gespeicherte EÜR-Zeile wird im Formular vorausgewählt (String-Vergleich)'
);
// ── 3. Vorsteuer einer Ausgabe landet in der EÜR-Ausgabenspalte ──────
$datum = date('Y-m-d');
$jahr = (int)date('Y');
$bankId = $this->findAccountId('1200');
$kostenId = $this->findAccountId('4600');
if (!$bankId || !$kostenId) {
$this->assert(false, 'Benötigte Konten (1200, 4600) nicht gefunden');
return;
}
$vorher = (new \Steuerkram\Services\EuerCalculator())->calculate($jahr);
$beleg = \Steuerkram\Models\Beleg::create([
'beleg_nr' => 'TEST-VST185-' . uniqid(),
'filename' => 'test.pdf',
'storage_path' => '',
'mime_type' => 'application/pdf',
'file_hash' => hash('sha256', 'vst185' . uniqid()),
'beleg_datum' => $datum,
'belegtyp' => 'Eingangsrechnung',
]);
\Steuerkram\Models\Booking::create([
'beleg_id' => $beleg,
'buchungs_datum' => $datum,
'buchungstyp' => 'Ausgabe',
'kategorie_konto_id' => $kostenId,
'zahlungskonto_id' => $bankId,
'betrag_netto' => 1000.00,
'ust_satz' => 19.0,
'buchungstext' => 'Test Ausgabe mit Vorsteuer',
]);
$nachher = (new \Steuerkram\Services\EuerCalculator())->calculate($jahr);
$ausKonten = array_column($nachher['ausgaben'], 'kontonummer');
$this->assert(
in_array('1576', $ausKonten, true),
'Konto 1576 erscheint als Betriebsausgabe in der EÜR'
);
// Netto 1000 + Vorsteuer 190 = 1190 mehr Betriebsausgaben
$delta = round((float)$nachher['total_ausgaben'] - (float)$vorher['total_ausgaben'], 2);
$this->assertEquals(1190.00, $delta, 'Betriebsausgaben steigen um Netto + Vorsteuer');
// Vorsteuer darf nicht im Abschnitt "nicht abzugsfähig" landen
$naKonten = array_column($nachher['nicht_abzugsfaehig'], 'kontonummer');
$this->assert(
!in_array('1576', $naKonten, true),
'Konto 1576 erscheint nicht unter den nicht abzugsfähigen Ausgaben'
);
// ── 4. Reverse-Charge bleibt ergebnisneutral ────────────────────────
// Die Kindzeilen auf 1574 (Vorsteuer) und 1774 (Erwerbsteuer) tragen
// denselben Betrag: als Betriebsausgabe bzw. Betriebseinnahme heben sie
// sich auf. Bliebe 1574 ein Zahlungskonto, wäre der Gewinn zu hoch.
$ige = \Steuerkram\Database::fetchOne(
"SELECT kontenart, euer_zeile FROM accounts WHERE kontonummer = '1774'"
);
$this->assertEquals('Betriebseinnahme', $ige['kontenart'] ?? null, 'Konto 1774 ist Betriebseinnahme');
$vorIge = (new \Steuerkram\Services\EuerCalculator())->calculate($jahr);
$belegIge = \Steuerkram\Models\Beleg::create([
'beleg_nr' => 'TEST-IGE185-' . uniqid(),
'filename' => 'test.pdf',
'storage_path' => '',
'mime_type' => 'application/pdf',
'file_hash' => hash('sha256', 'ige185' . uniqid()),
'beleg_datum' => $datum,
'belegtyp' => 'Eingangsrechnung',
]);
\Steuerkram\Models\Booking::create([
'beleg_id' => $belegIge,
'buchungs_datum' => $datum,
'buchungstyp' => 'Ausgabe',
'kategorie_konto_id' => $kostenId,
'zahlungskonto_id' => $bankId,
'betrag_netto' => 500.00,
'ust_satz' => 0.0,
'steuerart' => 'ig_erwerb_19',
'buchungstext' => 'Test ig. Erwerb',
]);
$nachIge = (new \Steuerkram\Services\EuerCalculator())->calculate($jahr);
// Nur die Netto-Ausgabe von 500 € darf den Gewinn mindern, die 95 €
// Erwerbsteuer stehen auf beiden Seiten.
$this->assertEquals(
round((float)$vorIge['gewinn'] - 500.00, 2),
round((float)$nachIge['gewinn'], 2),
'Erwerbsteuer und Vorsteuer aus ig. Erwerb heben sich im Gewinn auf'
);
$this->assertEquals(
round((float)$vorIge['total_einnahmen'] + 95.00, 2),
round((float)$nachIge['total_einnahmen'], 2),
'Erwerbsteuer (1774) erhöht die Betriebseinnahmen um 95 €'
);
$this->assertEquals(
round((float)$vorIge['total_ausgaben'] + 595.00, 2),
round((float)$nachIge['total_ausgaben'], 2),
'Netto + Vorsteuer ig. Erwerb (1574) erhöhen die Betriebsausgaben um 595 €'
);
// ── 5. Dashboard-Kacheln (summary) rechnen identisch ────────────────
$summary = (new \Steuerkram\Services\EuerCalculator())->summary($jahr);
$this->assertEquals(
(float)$nachIge['total_ausgaben'],
(float)$summary['ausgaben'],
'summary() und calculate() liefern dieselben Betriebsausgaben'
);
}
}