Steuerkram/tests/10_IstVersteuerungTest.php
fds2610-bot 55c02b54de Feature: USt-Buchungszeilen für Ausgangsrechnungen einführen
- Migration 046: ustva_kz='83'/'84' für Konten 1776/1771, Bestandsmigration für Einnahme-Buchungen
- Booking::create(): USt-Kindzeile auf 1771/1776 für Einnahmen mit 7/19 % (analog VSt)
- UstvaCalculator: Kz 83/84 kontobasiert via 1771/1776, KZ_ACCOUNT_MAP aktualisiert
- Invoice::cancel(): nur Hauptbuchungen direkt stornieren (parent_booking_id IS NULL)
- Tests 10, 27 angepasst; Test 29 neu
2026-05-10 15:11:00 +02:00

114 lines
4.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 10: IST-Versteuerung – Zahldatum unabhängig vom Rechnungsdatum.
*
* Prüft, dass:
* 1. Finalisieren einer Ausgangsrechnung keine Buchungen erzeugt.
* 2. Buchungen separat mit einem abweichenden Zahldatum erfasst werden können.
* 3. Die Buchung im Journal mit dem korrekten Zahldatum erscheint.
*/
class IstVersteuerungTest extends TestCase
{
protected string $testName = 'Test 10: IST-Versteuerung – Zahldatum';
public function run(): void
{
$rechnungsDatum = date('Y-m-d');
$zahlDatum = date('Y-m-d', strtotime('+7 days'));
// Konten prüfen
$zahlungsId = $this->findAccountId('1200'); // Bank
$kategorieId = $this->findAccountId('8000'); // Erlöse 19 %
if (!$zahlungsId || !$kategorieId) {
$zahlungsId = $zahlungsId ?? $this->findAccountId('1400');
$kategorieId = $kategorieId ?? $this->findAccountId('8400');
}
$this->assert($zahlungsId > 0, 'Zahlungskonto vorhanden');
$this->assert($kategorieId > 0, 'Einnahmekategorie vorhanden');
// Kunde anlegen
$customerId = \Steuerkram\Models\Customer::create([
'nachname' => 'IstTestKunde',
'firma' => 'IST GmbH',
'strasse' => 'Musterstr. 1',
'plz' => '10115',
'ort' => 'Berlin',
'payment_days' => 14,
]);
// Rechnung anlegen
$invoiceId = \Steuerkram\Models\Invoice::create([
'customer_id' => $customerId,
'betreff' => 'Test IST-Versteuerung',
'rechnungs_datum' => $rechnungsDatum,
'leistungszeitraum_von' => date('Y-m-01'),
'leistungszeitraum_bis' => date('Y-m-t'),
'lines' => [
[
'bezeichnung' => 'Beratung',
'menge' => 2,
'einheit' => 'Std.',
'einzelpreis' => 500.00,
'ust_satz' => 19.0,
],
],
]);
$this->assertGreaterThan(0, $invoiceId, 'Rechnung angelegt');
// Finalisieren
$nr = \Steuerkram\Models\Invoice::finalize($invoiceId);
$this->assertNotEmpty($nr, 'Rechnungsnummer vergeben');
$invoice = \Steuerkram\Models\Invoice::find($invoiceId);
$this->assertEquals('Finalisiert', $invoice['status'] ?? null, 'Status nach Finalisierung: Finalisiert');
// Beleg anlegen (wie in InvoiceController::createBeleg)
$belegNr = \Steuerkram\Models\Beleg::generateBelegNr();
$belegId = \Steuerkram\Models\Beleg::create([
'beleg_nr' => $belegNr,
'filename' => $nr . '.pdf',
'storage_path' => '',
'mime_type' => 'application/pdf',
'file_hash' => hash('sha256', $nr),
'beleg_datum' => $rechnungsDatum,
'rechnungs_nr' => $nr,
'betrag_brutto' => $invoice['betrag_brutto'],
'belegtyp' => 'Ausgangsrechnung',
]);
\Steuerkram\Database::execute('UPDATE invoices SET beleg_id=? WHERE id=?', [$belegId, $invoiceId]);
// Noch keine Buchungen vorhanden (finalize erzeugt keine mehr)
$buchungenNachFinalisierung = \Steuerkram\Models\Booking::forBeleg($belegId);
$this->assertEquals(0, count($buchungenNachFinalisierung), 'Nach Finalisierung: keine Buchungen vorhanden');
// Buchung separat mit Zahldatum erfassen
$buchungId = \Steuerkram\Models\Booking::create([
'beleg_id' => $belegId,
'buchungs_datum' => $zahlDatum,
'buchungstyp' => 'Einnahme',
'kategorie_konto_id' => $kategorieId,
'zahlungskonto_id' => $zahlungsId,
'betrag_netto' => 1000.00,
'ust_satz' => 19.0,
'buchungstext' => 'Ausgangsrechnung ' . $nr,
]);
$this->assertGreaterThan(0, $buchungId, 'Buchung mit Zahldatum erfasst');
// Buchung hat das Zahldatum – nicht das Rechnungsdatum
$buchungenNachZahlung = array_values(array_filter(
\Steuerkram\Models\Booking::forBeleg($belegId),
fn($b) => $b['parent_booking_id'] === null
));
$this->assertEquals(1, count($buchungenNachZahlung), 'Genau eine Hauptbuchung vorhanden');
$bk = $buchungenNachZahlung[0];
$this->assertEquals($zahlDatum, $bk['buchungs_datum'], 'Buchungsdatum ist das Zahldatum');
$this->assertNotEmpty($bk['buchungs_datum'] !== $rechnungsDatum || $zahlDatum === $rechnungsDatum,
'Zahldatum wurde korrekt gespeichert');
}
}