Fix: FinTS-Kontostand über dedizierte GetBalance-Abfrage statt Statement-Saldo
This commit is contained in:
parent
2b93d38513
commit
ff4e0aac31
3 changed files with 30 additions and 7 deletions
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
- **`migrations/087_bank_sources_last_balance.sql`:** Neue Spalte `last_balance` in `bank_sources`.
|
||||
- **`src/Models/BankSource.php`:** `updateLastFetched()` nimmt optional den beim Abruf ermittelten Kontostand entgegen und persistiert ihn; ohne neuen Wert bleibt der zuletzt bekannte Stand erhalten (kein Verlust bei Fehlern während des Abrufs).
|
||||
- **`src/Services/FinTsFetchService.php`:** Summiert nach dem Abruf pro Konto den Schlusssaldo (`getEndBalance()`, Fallback `getStartBalance()`) des letzten Statements und übergibt ihn an `updateLastFetched()`.
|
||||
- **`src/Services/PayPalNvpFetchService.php`:** Der bereits vorhandene `GetBalance`-Aufruf in `testCredentials()` liefert den aktuellen Kontostand (`AMT`), der nun mitgespeichert wird.
|
||||
- **`src/Services/FinTsFetchService.php`:** Fragt pro Konto zusätzlich per dedizierter `GetBalance`-Aktion (HKSAL) den aktuellen gebuchten Saldo ab und summiert diesen. Fällt nur auf den Schlusssaldo des letzten Statements zurück, wenn die Saldenabfrage fehlschlägt – der ursprüngliche Ansatz (Saldo nur aus dem Statement ableiten) lieferte keinen Wert, wenn die Bank mangels neuer Buchungen kein MT940/CAMT-Statement zurückgab (häufigster Fall bei täglichen Abrufen ohne neue Umsätze).
|
||||
- **`src/Services/PayPalNvpFetchService.php`:** Der bereits vorhandene `GetBalance`-Aufruf in `testCredentials()` liefert den aktuellen Kontostand (`AMT`), der nun mitgespeichert und im Abruf-Log ausgegeben wird.
|
||||
- **`src/Views/bank/fints.php`:** Kachel zeigt bei vorhandenem Kontostand rechts neben dem Abrufdatum den Betrag an (gleiche Höhe wie das Datum), mit dem Label „Kontostand" rechtsbündig darüber. Kachelgröße unverändert.
|
||||
- **`tests/57_BankSourceLastBalanceTest.php`:** Neuer Test prüft, dass `last_balance` beim Abruf gesetzt wird und bei einem Abruf ohne ermittelten Kontostand erhalten bleibt.
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ namespace Steuerkram\Services;
|
|||
use Steuerkram\Database;
|
||||
use Steuerkram\Models\BankSource;
|
||||
|
||||
use Fhp\Action\GetBalance;
|
||||
use Fhp\Action\GetSEPAAccounts;
|
||||
use Fhp\Action\GetStatementOfAccount;
|
||||
use Fhp\BaseAction;
|
||||
|
|
@ -225,14 +226,33 @@ class FinTsFetchService
|
|||
continue;
|
||||
}
|
||||
|
||||
$accountBalance = null;
|
||||
try {
|
||||
$balAction = GetBalance::create($account);
|
||||
$fints->execute($balAction);
|
||||
if ($balAction->needsTan()) {
|
||||
if (!$this->handleStrongAuthentication($balAction, $iban . ' (Saldo)')) {
|
||||
throw new \RuntimeException('TAN für Saldenabfrage nicht bestätigt.');
|
||||
}
|
||||
}
|
||||
foreach ($balAction->getBalances() as $hisal) {
|
||||
$accountBalance = ($accountBalance ?? 0.0) + $hisal->getGebuchterSaldo()->getAmount();
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$log(' → Saldenabfrage fehlgeschlagen: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
// Fallback: Saldo aus dem letzten Statement ableiten, falls die dedizierte
|
||||
// Saldenabfrage (HKSAL) fehlschlägt oder von der Bank nicht unterstützt wird.
|
||||
$statements = $soa->getStatements();
|
||||
if (!empty($statements)) {
|
||||
if ($accountBalance === null && !empty($statements)) {
|
||||
$lastStatement = end($statements);
|
||||
$accountBalance = $lastStatement->getEndBalance() ?? $lastStatement->getStartBalance();
|
||||
if ($accountBalance !== null) {
|
||||
$balance = ($balance ?? 0.0) + $accountBalance;
|
||||
$log(' → Kontostand: ' . number_format($accountBalance, 2, ',', '.') . ' €');
|
||||
}
|
||||
}
|
||||
|
||||
if ($accountBalance !== null) {
|
||||
$balance = ($balance ?? 0.0) + $accountBalance;
|
||||
$log(' → Kontostand: ' . number_format($accountBalance, 2, ',', '.') . ' €');
|
||||
}
|
||||
|
||||
$accountNew = 0;
|
||||
|
|
|
|||
|
|
@ -314,6 +314,9 @@ class PayPalNvpFetchService
|
|||
}
|
||||
if (isset($result['AMT']) && is_numeric($result['AMT'])) {
|
||||
$this->lastBalance = (float)$result['AMT'];
|
||||
($this->log)('Kontostand: ' . number_format($this->lastBalance, 2, ',', '.') . ' ' . ($result['CURRENCYCODE'] ?? 'EUR'));
|
||||
} else {
|
||||
($this->log)('Kontostand: nicht in GetBalance-Antwort enthalten (Felder: ' . implode(', ', array_keys($result)) . ')');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue