Steuerkram/src/Services/EuerCalculator.php
fds2610-bot 49d145e251 Feature: Anlage-Links auf Bearbeitungsmaske, Backfill anlage_nr, README
- Anlage-Spalte in allen Buchungstabellen verlinkt jetzt auf /assets/{id}/edit
- bk.asset_id in UstvaCalculator und EuerCalculator-Queries ergänzt
- Fallback-Anzeige: Bezeichnung wenn anlage_nr leer ist
- Migration 032: anlage_nr für bestehende Anlagegüter nachgenerieren
- README: Feature Anlagevermögen dokumentiert
2026-04-12 18:51:54 +02:00

98 lines
3.9 KiB
PHP

<?php
declare(strict_types=1);
namespace Steuerkram\Services;
use Steuerkram\Database;
/**
* Berechnet die Einnahmen-Überschuss-Rechnung (EÜR) für ein Geschäftsjahr.
*
* Maßgeblich ist ausschließlich accounts.kontenart des Kategorie-Kontos:
* Betriebseinnahme → Einnahmen-Spalte
* Betriebsausgabe → Ausgaben-Spalte
* Privat / Zahlungskonto / Verbindlichkeit → nicht in EÜR
*
* Vorzeichen von betrag_netto werden beibehalten:
* positiver Wert → addiert zur jeweiligen Spalte
* negativer Wert → mindert die jeweilige Spalte (z.B. Gutschriften)
*/
class EuerCalculator
{
public function calculate(int $year): array
{
$rows = Database::fetchAll(
'SELECT
a.id,
a.kontonummer,
a.bezeichnung,
a.kontenart,
a.euer_zeile,
SUM(bk.betrag_netto) AS summe_netto,
COUNT(bk.id) AS buchungsanzahl
FROM bookings bk
JOIN accounts a ON bk.kategorie_konto_id = a.id
JOIN fiscal_years fy ON bk.fiscal_year_id = fy.id
WHERE fy.year = ?
AND a.kontenart IN (\'Betriebseinnahme\', \'Betriebsausgabe\')
GROUP BY a.id, a.kontonummer, a.bezeichnung, a.kontenart, a.euer_zeile
HAVING buchungsanzahl > 0
ORDER BY a.kontonummer',
[$year]
);
$einnahmen = [];
$ausgaben = [];
$nichtAbzugsfaehig = [];
foreach ($rows as $row) {
$netto = round((float)$row['summe_netto'], 2);
if ($row['kontenart'] === 'Betriebseinnahme') {
$einnahmen[] = array_merge($row, ['netto' => $netto]);
} elseif ($row['euer_zeile'] === '51') {
$nichtAbzugsfaehig[] = array_merge($row, ['netto' => $netto]);
} else {
$ausgaben[] = array_merge($row, ['netto' => $netto]);
}
}
$totalEinnahmen = array_sum(array_column($einnahmen, 'netto'));
$totalAusgaben = array_sum(array_column($ausgaben, 'netto'));
$totalNichtAbzugsfaehig = array_sum(array_column($nichtAbzugsfaehig, 'netto'));
$gewinn = round($totalEinnahmen - $totalAusgaben, 2);
return [
'year' => $year,
'einnahmen' => $einnahmen,
'ausgaben' => $ausgaben,
'nicht_abzugsfaehig' => $nichtAbzugsfaehig,
'total_einnahmen' => round($totalEinnahmen, 2),
'total_ausgaben' => round($totalAusgaben, 2),
'total_nicht_abzugsfaehig' => round($totalNichtAbzugsfaehig, 2),
'gewinn' => $gewinn,
];
}
public function fetchBookingsForKonto(int $year, int $kontoId): array
{
return Database::fetchAll(
'SELECT bk.id, bk.buchungs_datum, bk.buchungstyp, bk.ust_satz,
bk.betrag_netto, bk.betrag_ust, bk.betrag_brutto, bk.buchungstext,
bk.is_reversal, bk.beleg_id, bk.asset_id, bl.beleg_nr,
k.kontonummer AS kategorie_nr, k.bezeichnung AS kategorie_name,
z.kontonummer AS zahlungs_nr, z.bezeichnung AS zahlungs_name,
a.anlage_nr, a.bezeichnung AS anlage_bezeichnung
FROM bookings bk
JOIN fiscal_years fy ON bk.fiscal_year_id = fy.id
LEFT JOIN belege bl ON bk.beleg_id = bl.id
JOIN accounts k ON bk.kategorie_konto_id = k.id
JOIN accounts z ON bk.zahlungskonto_id = z.id
LEFT JOIN assets a ON bk.asset_id = a.id
WHERE fy.year = ? AND bk.kategorie_konto_id = ?
ORDER BY bk.buchungs_datum, bk.id',
[$year, $kontoId]
);
}
}