Steuerkram/tests/07_UstvaAuslandTest.php

192 lines
7.7 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 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.
*/
class UstvaAuslandTest extends TestCase
{
protected string $testName = 'Test 7: UStVA Auslandsumsätze und ig. Erwerb';
public function run(): void
{
$year = (int)date('Y');
$month = (int)date('n');
$datum = date('Y-m-d');
// Konten aus SKR03
$erloesId = $this->findKonto('Betriebseinnahme');
$ausgabeId = $this->findKonto('Betriebsausgabe');
$zahlungId = $this->findKonto('Zahlungskonto');
if (!$erloesId || !$ausgabeId || !$zahlungId) {
$this->assert(false, 'Benötigte Konten nicht gefunden – SKR03-Seed vorhanden?');
return;
}
$this->assert(true, 'Konten vorhanden');
// Zweites Zahlungskonto für Ausgabe-Buchungen
$bankId = \Steuerkram\Database::fetchOne(
"SELECT id FROM accounts WHERE kontenart = 'Zahlungskonto' AND aktiv = 1 AND id != ? LIMIT 1",
[$zahlungId]
);
$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(),
'filename' => 'test-igl.pdf',
'storage_path' => '',
'mime_type' => 'application/pdf',
'file_hash' => hash('sha256', 'test-igl'),
'beleg_datum' => $datum,
'belegtyp' => 'Ausgangsrechnung',
]);
\Steuerkram\Models\Booking::create([
'beleg_id' => $belegIgL,
'buchungs_datum' => $datum,
'buchungstyp' => 'Einnahme',
'steuerart' => 'ig_lieferung',
'kategorie_konto_id' => $erloesId,
'zahlungskonto_id' => $zahlungId,
'betrag_netto' => 1000.00,
'ust_satz' => 0.0,
'buchungstext' => 'Test ig. Lieferung EU',
]);
// ── 2. Steuerfreie Ausfuhr → Kz 43 ───────────────────────────────
$belegExp = \Steuerkram\Models\Beleg::create([
'beleg_nr' => 'TEST-EXP-' . uniqid(),
'filename' => 'test-exp.pdf',
'storage_path' => '',
'mime_type' => 'application/pdf',
'file_hash' => hash('sha256', 'test-exp'),
'beleg_datum' => $datum,
'belegtyp' => 'Ausgangsrechnung',
]);
\Steuerkram\Models\Booking::create([
'beleg_id' => $belegExp,
'buchungs_datum' => $datum,
'buchungstyp' => 'Einnahme',
'steuerart' => 'export',
'kategorie_konto_id' => $erloesId,
'zahlungskonto_id' => $zahlungId,
'betrag_netto' => 2000.00,
'ust_satz' => 0.0,
'buchungstext' => 'Test Ausfuhr Drittland',
]);
// ── 3. Ig. Erwerb 19 % → Kz 89 (Bemessungsgrundlage), Kz 61 (Vorsteuer) ──
$belegIgE19 = \Steuerkram\Models\Beleg::create([
'beleg_nr' => 'TEST-IGE19-' . uniqid(),
'filename' => 'test-ige19.pdf',
'storage_path' => '',
'mime_type' => 'application/pdf',
'file_hash' => hash('sha256', 'test-ige19'),
'beleg_datum' => $datum,
'belegtyp' => 'Eingangsrechnung',
]);
\Steuerkram\Models\Booking::create([
'beleg_id' => $belegIgE19,
'buchungs_datum' => $datum,
'buchungstyp' => 'Ausgabe',
'steuerart' => 'ig_erwerb_19',
'kategorie_konto_id' => $ausgabeId,
'zahlungskonto_id' => $bankId,
'betrag_netto' => 500.00,
'ust_satz' => 0.0,
'buchungstext' => 'Test ig. Erwerb 19%',
]);
// ── 4. Ig. Erwerb 7 % → Kz 93 (Bemessungsgrundlage), Kz 61 (Vorsteuer) ───
$belegIgE7 = \Steuerkram\Models\Beleg::create([
'beleg_nr' => 'TEST-IGE7-' . uniqid(),
'filename' => 'test-ige7.pdf',
'storage_path' => '',
'mime_type' => 'application/pdf',
'file_hash' => hash('sha256', 'test-ige7'),
'beleg_datum' => $datum,
'belegtyp' => 'Eingangsrechnung',
]);
\Steuerkram\Models\Booking::create([
'beleg_id' => $belegIgE7,
'buchungs_datum' => $datum,
'buchungstyp' => 'Ausgabe',
'steuerart' => 'ig_erwerb_7',
'kategorie_konto_id' => $ausgabeId,
'zahlungskonto_id' => $bankId,
'betrag_netto' => 300.00,
'ust_satz' => 0.0,
'buchungstext' => 'Test ig. Erwerb 7%',
]);
// ── UStVA berechnen und Kennzahlen prüfen ─────────────────────────
$calc = new \Steuerkram\Services\UstvaCalculator();
$kz = $calc->calculate($year, $month);
// Kz 41: ig. Lieferung 1000 €
$this->assert(
(float)$kz['41']['betrag'] >= 1000.00,
'Kz 41 (ig. Lieferung): Betrag ≥ 1.000 €'
);
// Kz 43: Ausfuhr 2000 €
$this->assert(
(float)$kz['43']['betrag'] >= 2000.00,
'Kz 43 (Ausfuhr): Betrag ≥ 2.000 €'
);
// Kz 89: ig. Erwerb 19% Bemessungsgrundlage 500 €
$this->assert(
(float)$kz['89']['betrag'] >= 500.00,
'Kz 89 (ig. Erwerb 19% Bmgl.): Betrag ≥ 500 €'
);
// 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);
$this->assertEquals(
$erwartetKz61,
(float)$kz['61']['steuer'],
'Kz 61 (Vorsteuer ig. Erwerb § 3d): Steuer = 116,00 €'
);
// Kz 83 (Zahllast): ig. Erwerb/Lieferung/Ausfuhr sind USt-neutral (betrag_ust=0)
// → Zahllast darf sich gegenüber Baseline nicht verändert haben
$this->assertEquals(
round($kz83Pre, 2),
(float)$kz['83']['steuer'],
'Kz 83 (Zahllast) unverändert – alle EU-Buchungen sind USt-neutral'
);
// ig. Erwerb darf NICHT in Kz 48 landen (steuerfreie Umsätze ohne VSt-Abzug)
$this->assertEquals(
0.0,
(float)$kz['48']['betrag'],
'Kz 48 (steuerfreie Inlandsumsätze) = 0 (kein steuerfreier Inlandsumsatz gebucht)'
);
}
private function findKonto(string $kontenart): ?int
{
$row = \Steuerkram\Database::fetchOne(
"SELECT id FROM accounts WHERE kontenart = ? AND aktiv = 1 LIMIT 1",
[$kontenart]
);
return $row ? (int)$row['id'] : null;
}
}