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; // ── 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, 'eingangs_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 44 ─────────────────────────────── $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, 'eingangs_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/91/67 ───────────────────────────── $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, 'eingangs_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/94/67 ────────────────────────────── $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, 'eingangs_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 44: Ausfuhr 2000 € $this->assert( (float)$kz['44']['betrag'] >= 2000.00, 'Kz 44 (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 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 94: USt auf ig. Erwerb 7% = 300 * 0.07 = 21 € $this->assertEquals( round(300.00 * 0.07, 2), (float)$kz['94']['steuer'], 'Kz 94 (USt ig. Erwerb 7%): Steuer = 21,00 €' ); // Kz 67: Vorsteuer aus ig. Erwerb = Kz 91 + Kz 94 = 116 € $erwartetKz67 = round((float)$kz['91']['steuer'] + (float)$kz['94']['steuer'], 2); $this->assertEquals( $erwartetKz67, (float)$kz['67']['steuer'], 'Kz 67 (Vorsteuer ig. Erwerb) = Kz 91 + Kz 94' ); // 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['35']['betrag'], 'Kz 35 (steuerfreie Inlandsumsätze) = 0 (kein normaler 0%-Umsatz 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; } }