140 lines
6.4 KiB
PHP
140 lines
6.4 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
/**
|
||
* Test 9: Ausgangsrechnung → Dashboard / EÜR / UStVA.
|
||
*
|
||
* Prüft den vollständigen Pfad: Ausgangsrechnung anlegen, finalisieren,
|
||
* Buchung erzeugen und sicherstellen, dass die Werte im Dashboard,
|
||
* in der EÜR und in der UStVA erscheinen.
|
||
*/
|
||
class InvoiceToReportsTest extends TestCase
|
||
{
|
||
protected string $testName = 'Test 9: Ausgangsrechnung → Dashboard/EÜR/UStVA';
|
||
|
||
public function run(): void
|
||
{
|
||
$year = (int)date('Y');
|
||
$month = (int)date('n');
|
||
$datum = date('Y-m-d');
|
||
|
||
// ── Konten prüfen ────────────────────────────────────────────────────
|
||
$zahlungsId = $this->findAccountId('1400'); // Forderungen
|
||
$erloes19Id = $this->findAccountId('8000'); // Erlöse 19 %
|
||
|
||
if (!$zahlungsId || !$erloes19Id) {
|
||
$this->assert(false, 'Benötigte Konten (1400, 8000) nicht gefunden – SKR03-Seed vorhanden?');
|
||
return;
|
||
}
|
||
$this->assert(true, 'Konten 1400 und 8000 vorhanden');
|
||
|
||
// ── Kunde und Rechnung anlegen ────────────────────────────────────────
|
||
$customerId = \Steuerkram\Models\Customer::create([
|
||
'nachname' => 'ReportTest',
|
||
'firma' => 'Report GmbH',
|
||
'strasse' => 'Musterstraße 1',
|
||
'plz' => '10115',
|
||
'ort' => 'Berlin',
|
||
'payment_days' => 14,
|
||
]);
|
||
|
||
$invoiceId = \Steuerkram\Models\Invoice::create([
|
||
'customer_id' => $customerId,
|
||
'betreff' => 'Testrechnung für Report-Integration',
|
||
'rechnungs_datum' => $datum,
|
||
'leistungszeitraum_von' => date('Y-m-01'),
|
||
'leistungszeitraum_bis' => date('Y-m-t'),
|
||
'lines' => [
|
||
[
|
||
'bezeichnung' => 'Beratungsleistung',
|
||
'menge' => 10,
|
||
'einheit' => 'h',
|
||
'einzelpreis' => 100.00,
|
||
'ust_satz' => 19.0,
|
||
],
|
||
],
|
||
]);
|
||
$this->assertGreaterThan(0, $invoiceId, 'Rechnung angelegt');
|
||
|
||
// ── Finalisieren (Modell-Methode, wie in InvoiceController::finalize) ──
|
||
$rechnungsNr = \Steuerkram\Models\Invoice::finalize($invoiceId);
|
||
$this->assertNotEmpty($rechnungsNr, 'Rechnungsnummer nach Finalisierung vorhanden');
|
||
|
||
$invoice = \Steuerkram\Models\Invoice::find($invoiceId);
|
||
$this->assertEquals('Gesendet', $invoice['status'] ?? null, 'Status nach Finalisierung: Gesendet');
|
||
|
||
// ── Beleg und Buchungen anlegen (wie InvoiceController::createBelegAndBookings) ──
|
||
$belegNr = \Steuerkram\Models\Beleg::generateBelegNr();
|
||
$belegId = \Steuerkram\Models\Beleg::create([
|
||
'beleg_nr' => $belegNr,
|
||
'filename' => $rechnungsNr . '.pdf',
|
||
'storage_path' => '',
|
||
'mime_type' => 'application/pdf',
|
||
'file_hash' => hash('sha256', $rechnungsNr),
|
||
'beleg_datum' => $invoice['rechnungs_datum'],
|
||
'eingangs_datum' => $invoice['rechnungs_datum'],
|
||
'rechnungs_nr' => $rechnungsNr,
|
||
'betrag_brutto' => $invoice['betrag_brutto'],
|
||
'belegtyp' => 'Ausgangsrechnung',
|
||
'notes' => 'Test Ausgangsrechnung',
|
||
]);
|
||
$this->assertGreaterThan(0, $belegId, 'Beleg angelegt');
|
||
|
||
$lines = \Steuerkram\Models\Invoice::lines($invoiceId);
|
||
$this->assertGreaterThan(0, count($lines), 'Rechnungspositionen vorhanden');
|
||
|
||
$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;
|
||
}
|
||
|
||
foreach ($gruppenNetto as $satz => $netto) {
|
||
$kategorieId = $erloes19Id; // vereinfacht für Test mit 19 %
|
||
\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 ' . $rechnungsNr,
|
||
]);
|
||
}
|
||
|
||
\Steuerkram\Database::execute(
|
||
'UPDATE invoices SET beleg_id=? WHERE id=?', [$belegId, $invoiceId]
|
||
);
|
||
$this->assert(true, 'Buchungen und Beleg-Verknüpfung erstellt');
|
||
|
||
// ── EÜR prüfen ───────────────────────────────────────────────────────
|
||
$euer = (new \Steuerkram\Services\EuerCalculator())->calculate($year);
|
||
$this->assert(
|
||
(float)$euer['total_einnahmen'] >= 1000.00,
|
||
'EÜR: Einnahmen ≥ 1000 € (Ausgangsrechnung eingeflossen)'
|
||
);
|
||
|
||
// ── UStVA prüfen ─────────────────────────────────────────────────────
|
||
$kz = (new \Steuerkram\Services\UstvaCalculator())->calculate($year, $month);
|
||
$this->assert(
|
||
(float)$kz['81']['betrag'] >= 1000.00,
|
||
'UStVA Kz 81 (Umsätze 19 %): Betrag ≥ 1000 € (Ausgangsrechnung eingeflossen)'
|
||
);
|
||
|
||
// ── Dashboard-Abfrage prüfen ─────────────────────────────────────────
|
||
$umsatz = \Steuerkram\Database::fetchOne(
|
||
'SELECT COALESCE(SUM(bk.betrag_netto),0) as total
|
||
FROM bookings bk
|
||
JOIN fiscal_years fy ON bk.fiscal_year_id = fy.id
|
||
WHERE bk.buchungstyp = \'Einnahme\' AND bk.is_reversal = 0 AND fy.year = ?',
|
||
[$year]
|
||
);
|
||
$this->assert(
|
||
(float)($umsatz['total'] ?? 0) >= 1000.00,
|
||
'Dashboard-Abfrage: Umsatz ≥ 1000 € (Ausgangsrechnung eingeflossen)'
|
||
);
|
||
}
|
||
}
|