Steuerkram/tests/04_InvoiceBuchungTest.php

134 lines
5.5 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 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)
$debitorId = $this->findAccountId('1400'); // Debitorenkonto
$erloesId = $this->findAccountId('8000'); // Erlöse 19 %
if (!$debitorId) {
$this->assert(false, 'Debitorenkonto 1400 nicht gefunden – SKR03-Seed vorhanden?');
return;
}
if (!$erloesId) {
$this->assert(false, 'Erlöskonto 8000 nicht gefunden – SKR03-Seed vorhanden?');
return;
}
$this->assert(true, 'Benötigte Konten (1400, 8000) 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('Gesendet', $invoice['status'] ?? null, 'Rechnungsstatus ist Gesendet');
// Buchungen erzeugen (wie InvoiceController::createBelegAndBookings)
$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'],
'eingangs_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'],
'soll_konto_id' => $debitorId,
'haben_konto_id' => $erloesId,
'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['soll_nr'], 'Soll-Konto im Journal vorhanden');
$this->assertNotEmpty($row['haben_nr'], 'Haben-Konto im Journal vorhanden');
break;
}
}
}
}