Damit ist der geplante Funktionsumfang beisammen. Phase 4 abgeschlossen - Konfigurierbare Cockpit-Kacheln; abgewählte werden nicht berechnet - Einnahmen/Ausgaben je Monat als Balkenpaare mit Saldolinie, aufgesetzt auf den Summenbericht statt auf eine eigene Abfrage - Meine Ausgaben als Ring auf der obersten Kategorieebene - Offene Vorgänge aus allen Modulen Phase 5 – Online-Banking - nemiah/php-fints als Fork auf Codeberg, psr/log direkt eingebaut: die Anwendung hängt an keinem fremden Update-Zyklus - PIN AES-256-GCM-verschlüsselt; Schlüssel aus APP_KEY oder aus data/schluessel/app_key, den der Entrypoint einmalig erzeugt - TAN-Dialog über mehrere Requests (FinTs::persist plus serialisierte Aktion in der Sitzung) – ein wartender Prozess wäre mit php-fpm der falsche Weg - Abgleich statt Direktbuchung: verbinden, übernehmen oder verwerfen - Regeln mit vier Vergleichsarten, Betragsgrenzen und Split-Schema Phase 6 – Wertpapiere - Depotbuchung und Geldbuchung als zwei Seiten eines Geschäfts; betrag ist der Bruttowert, Nebenkosten stehen daneben - Einstand nach gleitendem Durchschnitt, realisierte Gewinne, Erträge - Kursabruf über Leeway oder FMP, täglicher Lauf per Cron - QIF-Import für !Type:Invst Dabei behoben: Der Import buchte den Geldfluss jedes Wertpapiergeschäfts als Abgang – auch bei Verkäufen und Dividenden; und er erkannte das Verrechnungskonto nicht, wenn dem Konto im L-Feld eine Kategorie vorangeht (bei Verkäufen also immer). Phase 7 – Nebenmodule und Zahlungsverkehr - Buchungsvorlagen inklusive QIF-Import, Splits werden mitskaliert - Regelmäßige Buchungen mit Fälligkeitslauf, Finanzkalender, Erinnerungen - Adressen mit IBAN-Prüfung, Verträge mit Kündigungsfrist, Sparziele - Kredite mit gerechnetem Tilgungsplan - Überweisungen über FinTS; die Buchung entsteht erst nach Annahme durch die Bank. Die pain.001-Nachricht erzeugt SepaXml selbst Nebenbei: .dockerignore ergänzt (ohne sie brach der Build an data/mariadb ab), PlatzhalterController entfernt, zwei Inline-Handler beseitigt, die die Content-Security-Policy ohnehin blockierte. 888 PHP-Prüfungen und 45 E2E-Tests grün. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
79 lines
2.5 KiB
PHP
79 lines
2.5 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace Finanzmanager\Controllers;
|
||
|
||
use Finanzmanager\Models\Einstellung;
|
||
use Finanzmanager\Models\Konto;
|
||
use Finanzmanager\Services\Cockpit;
|
||
use Finanzmanager\Services\Vermoegensentwicklung;
|
||
use Finanzmanager\View;
|
||
|
||
class CockpitController extends BaseController
|
||
{
|
||
/**
|
||
* Der Schalter „nur aktive“ an der Vermögenskachel. Er merkt sich seinen
|
||
* Zustand über die Einstellungen und nicht in der Sitzung: Er soll auch beim
|
||
* nächsten Anmelden noch so stehen, wie der Nutzer ihn gelassen hat. Im
|
||
* Einstellungsdialog taucht er nicht auf – er gehört an die Kachel.
|
||
*/
|
||
public const SCHALTER_NUR_AKTIVE = 'cockpit_vermoegen_nur_aktive';
|
||
|
||
public function index(): void
|
||
{
|
||
$this->verlangeAnmeldung();
|
||
|
||
$nurAktive = Einstellung::getBool(self::SCHALTER_NUR_AKTIVE, true);
|
||
$sichtbar = Cockpit::sichtbar();
|
||
|
||
// Die Ebene steht in der Adresse, nicht in den Einstellungen: Wer in die
|
||
// „Übrigen Konten“ hineinsieht, will beim nächsten Aufruf wieder oben
|
||
// anfangen – und kann den Blick trotzdem als Lesezeichen ablegen.
|
||
$ebene = max(0, (int)$this->query('ebene'));
|
||
|
||
// Jede Kachel kostet Abfragen. Abgeschaltete werden deshalb gar nicht
|
||
// erst berechnet, statt nur ungezeichnet zu bleiben.
|
||
$daten = [
|
||
'titel' => 'Cockpit',
|
||
'sichtbar' => $sichtbar,
|
||
'nurAktive' => $nurAktive,
|
||
];
|
||
|
||
if (in_array('vermoegen', $sichtbar, true)) {
|
||
$daten['vermoegen'] = Vermoegensentwicklung::reihe(
|
||
$nurAktive,
|
||
Vermoegensentwicklung::MONATE,
|
||
null,
|
||
$ebene
|
||
);
|
||
}
|
||
if (in_array('einnahmen_ausgaben', $sichtbar, true)) {
|
||
$daten['monatsreihe'] = Cockpit::monatsreihe();
|
||
}
|
||
if (in_array('ausgaben', $sichtbar, true)) {
|
||
$daten['ausgaben'] = Cockpit::ausgaben();
|
||
}
|
||
if (in_array('kontostaende', $sichtbar, true)) {
|
||
$daten['uebersicht'] = Konto::uebersicht();
|
||
}
|
||
if (in_array('offene_vorgaenge', $sichtbar, true)) {
|
||
$daten['vorgaenge'] = Cockpit::offeneVorgaenge();
|
||
}
|
||
|
||
$this->render('cockpit/index.php', $daten);
|
||
}
|
||
|
||
public function kontenfilter(): void
|
||
{
|
||
$this->verlangeAnmeldung();
|
||
|
||
Einstellung::set(
|
||
self::SCHALTER_NUR_AKTIVE,
|
||
$this->post('nur_aktive') === '1' ? '1' : '0',
|
||
'darstellung'
|
||
);
|
||
|
||
View::redirect('/');
|
||
}
|
||
}
|