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>
82 lines
2.9 KiB
PHP
82 lines
2.9 KiB
PHP
<?php
|
||
|
||
use Finanzmanager\View;
|
||
|
||
/**
|
||
* Die TAN-Maske. Sie steht zwischen zwei Requests: Der Dialog mit der Bank ist
|
||
* offen und liegt so lange in der Sitzung, bis die Freigabe da ist oder der
|
||
* Abruf abgebrochen wird.
|
||
*
|
||
* @var array<string,mixed> $tan
|
||
* @var string $meldung
|
||
* @var list<string> $protokoll
|
||
* @var string $csrfToken
|
||
*/
|
||
|
||
$entkoppelt = ($tan['entkoppelt'] ?? false) === true;
|
||
|
||
include __DIR__ . '/../layout/kopf.php';
|
||
?>
|
||
|
||
<div class="kachel einzeln">
|
||
<header>
|
||
<h2><?= $entkoppelt ? 'Freigabe im Banking-Gerät' : 'TAN eingeben' ?></h2>
|
||
<p class="kachelhinweis"><?= View::h($tan['bezeichnung'] ?? 'Abruf') ?></p>
|
||
</header>
|
||
|
||
<p class="hinweis"><?= View::h($meldung) ?></p>
|
||
|
||
<?php if (($tan['hinweis'] ?? '') !== ''): ?>
|
||
<p class="tanhinweis"><?= View::h($tan['hinweis']) ?></p>
|
||
<?php endif; ?>
|
||
|
||
<?php if (($tan['medium'] ?? '') !== ''): ?>
|
||
<p class="feldhinweis">TAN-Medium: <?= View::h($tan['medium']) ?></p>
|
||
<?php endif; ?>
|
||
|
||
<?php if (!empty($tan['bild_daten'])): ?>
|
||
<?php /* photoTAN: Das Bild kommt als Datenadresse, nicht als Datei –
|
||
es gehört zu genau diesem Dialog und ist danach wertlos. */ ?>
|
||
<img class="tanbild" alt="TAN-Grafik der Bank"
|
||
src="data:<?= View::h($tan['bild_typ'] ?? 'image/png') ?>;base64,<?= View::h($tan['bild_daten']) ?>">
|
||
<?php endif; ?>
|
||
|
||
<form method="post" action="/banking/tan" class="formular">
|
||
<input type="hidden" name="csrf_token" value="<?= View::h($csrfToken) ?>">
|
||
|
||
<?php if ($entkoppelt): ?>
|
||
<p class="feldhinweis">
|
||
Die Bank hat die Freigabe an dein Banking-Gerät geschickt. Dort bestätigen und
|
||
anschließend hier prüfen lassen – der Abruf läuft dann weiter.
|
||
</p>
|
||
<input type="hidden" name="tan" value="">
|
||
<div class="knopfleiste">
|
||
<button type="submit" class="knopf primaer">Freigabe prüfen</button>
|
||
</div>
|
||
<?php else: ?>
|
||
<label for="tan">TAN</label>
|
||
<input type="text" id="tan" name="tan" inputmode="numeric" autocomplete="one-time-code"
|
||
autofocus required>
|
||
<div class="knopfleiste">
|
||
<button type="submit" class="knopf primaer">TAN senden</button>
|
||
</div>
|
||
<?php endif; ?>
|
||
</form>
|
||
|
||
<form method="post" action="/banking/tan/abbrechen" class="formular">
|
||
<input type="hidden" name="csrf_token" value="<?= View::h($csrfToken) ?>">
|
||
<div class="knopfleiste">
|
||
<button type="submit" class="knopf">Abruf abbrechen</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<?php if ($protokoll !== []): ?>
|
||
<div class="kachel einzeln">
|
||
<header><h2>Bisheriger Verlauf</h2></header>
|
||
<pre class="protokolltext"><?php foreach ($protokoll as $zeile): ?><?= View::h($zeile) ?>
|
||
<?php endforeach; ?></pre>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php include __DIR__ . '/../layout/fuss.php'; ?>
|