- 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
98 lines
3.9 KiB
PHP
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]
|
|
);
|
|
}
|
|
}
|