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'); $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; $calc = new \Steuerkram\Services\UstvaCalculator(); $kzPre = $calc->calculate($year, $month); // ── 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 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, '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, '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%', ]); // ── UStVA berechnen und Delta prüfen ────────────────────────────── $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( round((float)$kz['89']['betrag'] - (float)$kzPre['89']['betrag'], 2) >= 500.00, 'Kz 89 (ig. Erwerb 19% Bmgl.): Delta ≥ 500 €' ); // Kz 91: USt ig. Erwerb kontobasiert (1774) +95 € $this->assertEquals( 95.00, round((float)$kz['91']['steuer'] - (float)$kzPre['91']['steuer'], 2), 'Kz 91 (USt ig. Erwerb 19%): Delta = 95,00 €' ); // Kz 67: VSt ig. Erwerb kontobasiert (1574) +95 € $this->assertEquals( 95.00, round((float)$kz['67']['steuer'] - (float)$kzPre['67']['steuer'], 2), 'Kz 67 (VSt ig. Erwerb): Delta = 95,00 €' ); // ReverseCharge ist zahllastneutral: Kz 69 unverändert $this->assertEquals( 0.00, round((float)$kz['69']['steuer'] - (float)$kzPre['69']['steuer'], 2), 'Kz 69 (Zahllast) durch ig. Erwerb nicht verändert' ); // ig. Erwerb darf nicht in Kz 35 landen $this->assertEquals( 0.0, (float)$kz['35']['betrag'], 'Kz 35 (steuerfreie Inlandsumsätze) = 0' ); } 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; } }