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>
68 lines
1.7 KiB
PHP
68 lines
1.7 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
/**
|
||
* Täglicher Kursabruf für die Wertpapiere mit Bestand.
|
||
*
|
||
* Gedacht für einen Cron-Eintrag:
|
||
*
|
||
* docker compose exec -u www-data php php scripts/kursabruf.php
|
||
*
|
||
* Der Lauf bricht ab, wenn der automatische Abruf in den Einstellungen nicht
|
||
* eingeschaltet ist – so kostet ein vergessener Cron-Eintrag kein Kontingent.
|
||
* Der Knopf auf der Wertpapierseite arbeitet unabhängig davon.
|
||
*/
|
||
|
||
require dirname(__DIR__) . '/vendor/autoload.php';
|
||
|
||
use Finanzmanager\Config;
|
||
use Finanzmanager\Mandant;
|
||
use Finanzmanager\Models\Benutzer;
|
||
use Finanzmanager\Models\Einstellung;
|
||
use Finanzmanager\Services\Kursabruf;
|
||
|
||
Config::load();
|
||
|
||
$still = in_array('--still', $argv, true);
|
||
|
||
$sage = static function (string $zeile) use ($still): void {
|
||
if (!$still) {
|
||
echo $zeile . PHP_EOL;
|
||
}
|
||
};
|
||
|
||
if (!Einstellung::getBool('wertpapiere_kursabruf_aktiv')) {
|
||
$sage('Der automatische Kursabruf ist ausgeschaltet (Einstellungen → Wertpapiere).');
|
||
exit(0);
|
||
}
|
||
|
||
$fehlerGesamt = 0;
|
||
|
||
// Über alle Benutzer, nicht nur den ersten: Das Datenmodell ist
|
||
// mandantenfähig, und ein Cron-Lauf hat keine Sitzung, aus der ein Mandant
|
||
// hervorginge.
|
||
foreach (Benutzer::alle() as $benutzer) {
|
||
Mandant::setze((int)$benutzer['id']);
|
||
|
||
$ergebnis = Kursabruf::laufen();
|
||
|
||
$sage(sprintf(
|
||
'%s: %d abgerufen, %d übersprungen, %d fehlgeschlagen.',
|
||
$benutzer['benutzername'],
|
||
$ergebnis['abgerufen'],
|
||
$ergebnis['uebersprungen'],
|
||
$ergebnis['fehler']
|
||
));
|
||
|
||
foreach ($ergebnis['protokoll'] as $zeile) {
|
||
$sage(' ' . $zeile);
|
||
}
|
||
|
||
$fehlerGesamt += $ergebnis['fehler'];
|
||
}
|
||
|
||
Mandant::setze(null);
|
||
|
||
// Ein Rückgabewert ungleich null macht den Cron-Daemon aufmerksam.
|
||
exit($fehlerGesamt > 0 ? 1 : 0);
|