135 lines
5.6 KiB
PHP
135 lines
5.6 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
/**
|
||
* Test 4: Ausgangsrechnung finalisieren und buchen → Buchungsjournal prüfen.
|
||
*
|
||
* Erstellt eine Rechnung, finalisiert sie (Entwurf → Gesendet) und erstellt
|
||
* die zugehörigen Buchungen. Dann wird geprüft, ob die Buchungszeilen
|
||
* im Buchungsjournal erscheinen.
|
||
*/
|
||
class InvoiceBuchungTest extends TestCase
|
||
{
|
||
protected string $testName = 'Test 4: Rechnung buchen → Buchungsjournal';
|
||
|
||
public function run(): void
|
||
{
|
||
// Benötigte Konten prüfen (SKR03)
|
||
$zahlungsId = $this->findAccountId('1200'); // Bank (Zahlungskonto)
|
||
$kategorieId = $this->findAccountId('8400'); // Erlöse 19 % USt (Betriebseinnahme)
|
||
|
||
if (!$zahlungsId) {
|
||
$this->assert(false, 'Bankkonto 1200 nicht gefunden – SKR03-Seed vorhanden?');
|
||
return;
|
||
}
|
||
if (!$kategorieId) {
|
||
$this->assert(false, 'Erlöskonto 8400 nicht gefunden – SKR03-Seed vorhanden?');
|
||
return;
|
||
}
|
||
|
||
$this->assert(true, 'Benötigte Konten (1200, 8400) vorhanden');
|
||
|
||
// Testkunden anlegen
|
||
$customerId = \Steuerkram\Models\Customer::create([
|
||
'nachname' => 'Buchungstest',
|
||
'firma' => 'Buchungs GmbH',
|
||
'strasse' => 'Hauptstraße 1',
|
||
'plz' => '10115',
|
||
'ort' => 'Berlin',
|
||
'payment_days' => 30,
|
||
]);
|
||
|
||
// Rechnung anlegen und finalisieren
|
||
$datum = date('Y-m-d');
|
||
$invoiceId = \Steuerkram\Models\Invoice::create([
|
||
'customer_id' => $customerId,
|
||
'betreff' => 'Testrechnung für Buchungstest',
|
||
'rechnungs_datum' => $datum,
|
||
'leistungszeitraum_von' => date('Y-m-01'),
|
||
'leistungszeitraum_bis' => date('Y-m-t'),
|
||
'lines' => [
|
||
[
|
||
'bezeichnung' => 'Beratungsleistung',
|
||
'menge' => 5,
|
||
'einheit' => 'Std.',
|
||
'einzelpreis' => 200.00,
|
||
'ust_satz' => 19.0,
|
||
],
|
||
],
|
||
]);
|
||
|
||
$nr = \Steuerkram\Models\Invoice::finalize($invoiceId);
|
||
$this->assertNotEmpty($nr, 'Rechnung wurde finalisiert (Rechnungsnummer erhalten)');
|
||
|
||
$invoice = \Steuerkram\Models\Invoice::find($invoiceId);
|
||
$this->assertEquals('Finalisiert', $invoice['status'] ?? null, 'Rechnungsstatus ist Finalisiert');
|
||
|
||
// Buchungen erzeugen (EÜR: Einnahme)
|
||
$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' => $invoice['rechnungs_datum'],
|
||
'rechnungs_nr' => $nr,
|
||
'betrag_brutto' => $invoice['betrag_brutto'],
|
||
'belegtyp' => 'Ausgangsrechnung',
|
||
]);
|
||
|
||
$lines = \Steuerkram\Models\Invoice::lines($invoiceId);
|
||
$gruppenNetto = [];
|
||
foreach ($lines as $line) {
|
||
$satz = (float)$line['ust_satz'];
|
||
$netto = round((float)$line['menge'] * (float)$line['einzelpreis'], 2);
|
||
$gruppenNetto[$satz] = ($gruppenNetto[$satz] ?? 0.0) + $netto;
|
||
}
|
||
|
||
$buchungIds = [];
|
||
foreach ($gruppenNetto as $satz => $netto) {
|
||
$buchungIds[] = \Steuerkram\Models\Booking::create([
|
||
'beleg_id' => $belegId,
|
||
'buchungs_datum' => $invoice['rechnungs_datum'],
|
||
'buchungstyp' => 'Einnahme',
|
||
'kategorie_konto_id' => $kategorieId,
|
||
'zahlungskonto_id' => $zahlungsId,
|
||
'betrag_netto' => round($netto, 2),
|
||
'ust_satz' => $satz,
|
||
'buchungstext' => 'Ausgangsrechnung ' . $nr,
|
||
]);
|
||
}
|
||
|
||
$this->assertGreaterThan(0, count($buchungIds), 'Mindestens eine Buchung wurde erzeugt');
|
||
|
||
// Im Journal auffindbar
|
||
$year = (int)date('Y');
|
||
$month = (int)date('n');
|
||
$journal = \Steuerkram\Models\Booking::journal(['year' => $year, 'month' => $month], 1, 999);
|
||
|
||
$foundCount = 0;
|
||
foreach ($journal['rows'] as $row) {
|
||
if (in_array((int)$row['id'], $buchungIds, true)) {
|
||
$foundCount++;
|
||
}
|
||
}
|
||
$this->assertEquals(count($buchungIds), $foundCount, 'Alle Buchungszeilen im Buchungsjournal');
|
||
|
||
// Buchungsinhalt prüfen (erste Buchung)
|
||
$firstId = $buchungIds[0];
|
||
foreach ($journal['rows'] as $row) {
|
||
if ((int)$row['id'] === $firstId) {
|
||
$this->assertEquals(1000.00, (float)$row['betrag_netto'], 'Nettobetrag 1000 € korrekt');
|
||
$this->assertEquals(19.0, (float)$row['ust_satz'], 'USt-Satz 19 % korrekt');
|
||
$this->assertEquals(190.00, (float)$row['betrag_ust'], 'USt-Betrag 190 € korrekt');
|
||
$this->assertEquals(1190.00, (float)$row['betrag_brutto'], 'Bruttobetrag 1190 € korrekt');
|
||
$this->assertNotEmpty($row['beleg_nr'], 'Belegnummer im Journal vorhanden');
|
||
$this->assertNotEmpty($row['kategorie_nr'], 'Kategorie-Konto im Journal vorhanden');
|
||
$this->assertNotEmpty($row['zahlungs_nr'], 'Zahlungskonto im Journal vorhanden');
|
||
$this->assertEquals('Einnahme', $row['buchungstyp'], 'Buchungstyp ist Einnahme');
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|