Steuerkram/tests/31_UstvaFloorKz81_89Test.php

118 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 31: Kz 81 und Kz 89 werden auf volle Euro abgerundet (floor).
*
* Buchungen mit Cent-Beträgen dürfen in der UStVA nur als ganzer Euro-Betrag
* erscheinen; die USt wird auf dem abgerundeten Wert berechnet.
*/
class UstvaFloorKz81_89Test extends TestCase
{
protected string $testName = 'Test 31: UStVA Kz 81/89 – floor auf volle Euro';
public function run(): void
{
$year = (int)date('Y');
$month = (int)date('n');
$datum = date('Y-m-d');
$erloesId = $this->findAccountByNr('8400'); // Erlöse 19 % USt → ustva_kz=81
$ausgabeId = $this->findKonto('Betriebsausgabe');
$zahlungId = $this->findKonto('Zahlungskonto');
if (!$erloesId || !$ausgabeId || !$zahlungId) {
$this->assert(false, 'Benötigte Konten nicht gefunden');
return;
}
$calc = new \Steuerkram\Services\UstvaCalculator();
$kzPre = $calc->calculate($year, $month);
// Kz-81-Buchung mit Cent-Betrag: 100,77 € netto
$belegId = \Steuerkram\Models\Beleg::create([
'beleg_nr' => 'TEST-FLOOR81-' . uniqid(),
'filename' => 'test-floor81.pdf',
'storage_path' => '',
'mime_type' => 'application/pdf',
'file_hash' => hash('sha256', 'test-floor81-' . uniqid()),
'beleg_datum' => $datum,
'belegtyp' => 'Ausgangsrechnung',
]);
\Steuerkram\Models\Booking::create([
'beleg_id' => $belegId,
'buchungs_datum' => $datum,
'buchungstyp' => 'Einnahme',
'steuerart' => null,
'ust_satz' => 19.0,
'kategorie_konto_id' => $erloesId,
'zahlungskonto_id' => $zahlungId,
'betrag_netto' => 100.77,
'buchungstext' => 'Test Floor Kz 81',
]);
// Kz-89-Buchung mit Cent-Betrag: 200,55 € netto (ig. Erwerb 19 %)
$belegId2 = \Steuerkram\Models\Beleg::create([
'beleg_nr' => 'TEST-FLOOR89-' . uniqid(),
'filename' => 'test-floor89.pdf',
'storage_path' => '',
'mime_type' => 'application/pdf',
'file_hash' => hash('sha256', 'test-floor89-' . uniqid()),
'beleg_datum' => $datum,
'belegtyp' => 'Eingangsrechnung',
]);
\Steuerkram\Models\Booking::create([
'beleg_id' => $belegId2,
'buchungs_datum' => $datum,
'buchungstyp' => 'Ausgabe',
'steuerart' => 'ig_erwerb_19',
'ust_satz' => 0.0,
'kategorie_konto_id' => $ausgabeId,
'zahlungskonto_id' => $zahlungId,
'betrag_netto' => 200.55,
'buchungstext' => 'Test Floor Kz 89',
]);
$kz = $calc->calculate($year, $month);
// Kz 81: Delta muss exakt 100,00 sein (floor von 100,77)
$delta81 = round((float)$kz['81']['betrag'] - (float)$kzPre['81']['betrag'], 2);
$this->assertEquals(100.00, $delta81, 'Kz 81: floor(100,77) = 100,00');
// USt Kz 81: 100 * 0,19 = 19,00 (nicht 100,77 * 0,19 = 19,15)
$deltaUst81 = round((float)$kz['ust81']['steuer'] - (float)$kzPre['ust81']['steuer'], 2);
$this->assertEquals(19.00, $deltaUst81, 'USt Kz 81: 100 × 0,19 = 19,00');
// Kz 89: Delta muss exakt 200,00 sein (floor von 200,55)
$delta89 = round((float)$kz['89']['betrag'] - (float)$kzPre['89']['betrag'], 2);
$this->assertEquals(200.00, $delta89, 'Kz 89: floor(200,55) = 200,00');
// USt Kz 89: 200 * 0,19 = 38,00 (nicht 200,55 * 0,19 = 38,10)
$deltaUst89 = round((float)$kz['ust89']['steuer'] - (float)$kzPre['ust89']['steuer'], 2);
$this->assertEquals(38.00, $deltaUst89, 'USt Kz 89: 200 × 0,19 = 38,00');
// ganze_euro-Flag muss gesetzt sein
$this->assert($kz['81']['ganze_euro'] === true, 'Kz 81 hat ganze_euro=true');
$this->assert($kz['89']['ganze_euro'] === true, 'Kz 89 hat ganze_euro=true');
$this->assert($kz['ust81']['ganze_euro'] === false, 'ust81 hat ganze_euro=false');
}
private function findKonto(string $kontenart): ?int
{
$row = \Steuerkram\Database::fetchOne(
"SELECT id FROM accounts WHERE kontenart = ? AND aktiv = 1 LIMIT 1",
[$kontenart]
);
return $row ? (int)$row['id'] : null;
}
private function findAccountByNr(string $nr): ?int
{
$row = \Steuerkram\Database::fetchOne(
"SELECT id FROM accounts WHERE kontonummer = ? AND aktiv = 1 LIMIT 1",
[$nr]
);
return $row ? (int)$row['id'] : null;
}
}