calculate((int)date('Y')); $einnahmenVorher = (float)$euerVorher['total_einnahmen']; $gewinnVorher = (float)$euerVorher['gewinn']; // ── Kontenarten prüfen ─────────────────────────────────────── $kontenarten = \Steuerkram\Database::fetchAll( "SELECT DISTINCT kontenart FROM accounts ORDER BY kontenart" ); $arten = array_column($kontenarten, 'kontenart'); $this->assert( in_array('Betriebseinnahme', $arten), 'Kontenart "Betriebseinnahme" existiert' ); $this->assert( in_array('Betriebsausgabe', $arten), 'Kontenart "Betriebsausgabe" existiert' ); $this->assert( in_array('Zahlungskonto', $arten), 'Kontenart "Zahlungskonto" existiert' ); $this->assert( !in_array('Aktiv', $arten) && !in_array('Passiv', $arten) && !in_array('Aufwand', $arten) && !in_array('Ertrag', $arten), 'Alte Kontenarten (Aktiv, Passiv, Aufwand, Ertrag) existieren nicht mehr' ); // Konten laden $erloesId = $this->findAccountId('8400'); // Erlöse 19 % USt (Betriebseinnahme) $ausgabeId = $this->findAccountId('4600'); // Werbekosten (Betriebsausgabe) $bankId = $this->findAccountId('1200'); // Bank (Zahlungskonto) if (!$erloesId || !$ausgabeId || !$bankId) { $this->assert(false, 'Benötigte Konten (8400, 4600, 1200) nicht gefunden'); return; } // ── Einnahme-Buchung ───────────────────────────────────────── $belegEinnahme = \Steuerkram\Models\Beleg::create([ 'beleg_nr' => 'TEST-EIN-' . uniqid(), 'filename' => 'test-einnahme.pdf', 'storage_path' => '', 'mime_type' => 'application/pdf', 'file_hash' => hash('sha256', 'einnahme-' . uniqid()), 'beleg_datum' => $datum, 'belegtyp' => 'Ausgangsrechnung', ]); $einnahmeId = \Steuerkram\Models\Booking::create([ 'beleg_id' => $belegEinnahme, 'buchungs_datum' => $datum, 'buchungstyp' => 'Einnahme', 'kategorie_konto_id' => $erloesId, 'zahlungskonto_id' => $bankId, 'betrag_netto' => 1000.00, 'ust_satz' => 19.0, 'buchungstext' => 'Test Einnahme', ]); $einnahme = \Steuerkram\Models\Booking::find($einnahmeId); $this->assertEquals('Einnahme', $einnahme['buchungstyp'], 'Einnahme-Buchung hat buchungstyp=Einnahme'); $this->assertEquals($erloesId, (int)$einnahme['kategorie_konto_id'], 'Kategorie-Konto ist Erlöskonto'); $this->assertEquals($bankId, (int)$einnahme['zahlungskonto_id'], 'Zahlungskonto ist Bankkonto'); $this->assertEquals(1000.00, (float)$einnahme['betrag_netto'], 'Nettobetrag korrekt'); $this->assertEquals(190.00, (float)$einnahme['betrag_ust'], 'USt-Betrag korrekt berechnet'); $this->assertEquals(1190.00, (float)$einnahme['betrag_brutto'], 'Bruttobetrag korrekt berechnet'); // ── Ausgabe-Buchung ────────────────────────────────────────── $belegAusgabe = \Steuerkram\Models\Beleg::create([ 'beleg_nr' => 'TEST-AUS-' . uniqid(), 'filename' => 'test-ausgabe.pdf', 'storage_path' => '', 'mime_type' => 'application/pdf', 'file_hash' => hash('sha256', 'ausgabe-' . uniqid()), 'beleg_datum' => $datum, 'belegtyp' => 'Eingangsrechnung', ]); $ausgabeBuchungId = \Steuerkram\Models\Booking::create([ 'beleg_id' => $belegAusgabe, 'buchungs_datum' => $datum, 'buchungstyp' => 'Ausgabe', 'kategorie_konto_id' => $ausgabeId, 'zahlungskonto_id' => $bankId, 'betrag_netto' => 300.00, 'ust_satz' => 19.0, 'buchungstext' => 'Test Ausgabe', ]); $ausgabe = \Steuerkram\Models\Booking::find($ausgabeBuchungId); $this->assertEquals('Ausgabe', $ausgabe['buchungstyp'], 'Ausgabe-Buchung hat buchungstyp=Ausgabe'); $this->assertEquals($ausgabeId, (int)$ausgabe['kategorie_konto_id'], 'Kategorie-Konto ist Ausgabenkonto'); // ── Storno prüfen ──────────────────────────────────────────── $stornoId = \Steuerkram\Models\Booking::reverse($ausgabeBuchungId, 'Testgrund'); $storno = \Steuerkram\Models\Booking::find($stornoId); $this->assertEquals('Ausgabe', $storno['buchungstyp'], 'Storno behält buchungstyp der Originalbuchung'); $this->assertEquals(1, (int)$storno['is_reversal'], 'Storno-Flag gesetzt'); $this->assertEquals($ausgabeId, (int)$storno['kategorie_konto_id'], 'Storno behält Kategorie-Konto'); $this->assertEquals($bankId, (int)$storno['zahlungskonto_id'], 'Storno behält Zahlungskonto'); // Original hat reversed_by $origNeu = \Steuerkram\Models\Booking::find($ausgabeBuchungId); $this->assertEquals($stornoId, (int)$origNeu['reversed_by'], 'Original verweist auf Storno-Buchung'); // ── EÜR-Berechnung ─────────────────────────────────────────── // Nach Einnahme (1000 €) + stornierter Ausgabe: Delta muss +1000 € betragen $euerNachher = (new \Steuerkram\Services\EuerCalculator())->calculate((int)date('Y')); $this->assert( (float)$euerNachher['total_einnahmen'] >= $einnahmenVorher + 1000.00, 'EÜR: Einnahmen enthalten die 1000 € Einnahme-Buchung' ); // Ausgabe wurde storniert → Netto-Effekt auf Gewinn: +1000 € $this->assert( (float)$euerNachher['gewinn'] >= $gewinnVorher + 1000.00, 'EÜR: Gewinn ist um ≥ 1000 € gestiegen (Einnahme + stornierte Ausgabe)' ); } }