From 35c5d2c84af23116117de4af9c6fa0a068dba671 Mon Sep 17 00:00:00 2001 From: Scarriffle Date: Wed, 30 Sep 2026 20:59:48 +0200 Subject: [PATCH] fix: Ein Saldo-Abgleich, der nicht mehr gilt, sagt das jetzt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Der Abgleich wird einmal serverseitig gerechnet, beim Erzeugen der Vorschau. Wer danach eine Zeile von Hand umstellt, erreicht ihn nicht – das gruene "stimmt" blieb stehen, obwohl es sich auf eine andere Leserichtung bezog. Mit der neuen Sammelaktion "Richtung umdrehen" waere das leicht passiert: ein Klick, und die Bestaetigung darueber stimmt nicht mehr. Nachgerechnet wird nicht – das waere eine zweite Wahrheit neben der ersten. Stattdessen sagt der Hinweis, dass seine Aussage veraltet ist. Beim Einlesen kommt die Art aus dem Vorzeichen; jede Abweichung ist also nachweislich eine Handaenderung. Co-Authored-By: Claude Opus 5 --- web/src/locales/de.json | 1 + web/src/locales/en.json | 1 + web/src/pages/Import.jsx | 21 ++++++++++++++++++--- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/web/src/locales/de.json b/web/src/locales/de.json index e5586be..cba634f 100644 --- a/web/src/locales/de.json +++ b/web/src/locales/de.json @@ -479,6 +479,7 @@ "skipCurrency": "andere Währung", "colBalance": "Kontostand (laufend)", "reconOk": "Saldo-Abgleich stimmt: alle {{n}} Schritte passen zur Kontostand-Spalte der Datei.", + "reconStale": "Der Saldo-Abgleich gilt für die ursprünglich gelesene Richtung. Seitdem wurden Zeilen von Hand umgestellt – er sagt über den jetzigen Stand nichts mehr.", "reconDiff": "Der Kontostand geht nicht auf. Die Datei endet bei {{file}}, aus den Zeilen errechnet sich aber {{app}} – es fehlen bzw. sind {{diff}} zu viel.", "reconFirst": "Ab dem {{date}} laufen beide auseinander, bei „{{payee}}“: Die Kontostand-Spalte der Datei springt um {{expected}}, die Zeile selbst weist {{actual}} aus.", "reconOpening": "Vor der ersten Zeile stand die Datei bei {{value}}. Trage das beim Konto als Anfangssaldo ein, mit einem Stichtag am Tag davor.", diff --git a/web/src/locales/en.json b/web/src/locales/en.json index 68d4df0..c25fd5b 100644 --- a/web/src/locales/en.json +++ b/web/src/locales/en.json @@ -479,6 +479,7 @@ "skipCurrency": "other currency", "colBalance": "Balance (running)", "reconOk": "Balance check passes: all {{n}} steps match the file's balance column.", + "reconStale": "The balance check applies to the direction originally read. Rows have been changed by hand since — it no longer says anything about the current state.", "reconDiff": "The balance doesn't add up. The file ends at {{file}}, but the rows add up to {{app}} – {{diff}} missing or too much.", "reconFirst": "They start to diverge on {{date}} at “{{payee}}”: the file's balance column moves by {{expected}}, while the row itself states {{actual}}.", "reconOpening": "Before the first row the file stood at {{value}}. Enter that as the account's opening balance, dated the day before.", diff --git a/web/src/pages/Import.jsx b/web/src/pages/Import.jsx index fc610da..de131a2 100644 --- a/web/src/pages/Import.jsx +++ b/web/src/pages/Import.jsx @@ -390,6 +390,18 @@ export default function Import() { const includeCount = rows ? rows.filter((r) => r.include).length : 0; + // Der Saldo-Abgleich wird EINMAL serverseitig gerechnet, beim Erzeugen der + // Vorschau. Eine von Hand geaenderte Richtung erreicht ihn nicht – das + // gruene „stimmt" bliebe stehen, obwohl es nicht mehr gilt. + // + // Nachrechnen waere die zweite Wahrheit neben der ersten. Stattdessen sagen + // wir, dass die Aussage veraltet ist: Beim Parsen kommt die Art aus dem + // Vorzeichen, jede Abweichung ist also eine Handaenderung. + const abgleichVeraltet = (rows || []).some( + (r) => r.include && r.valid && r.type !== "transfer" + && Math.sign(r.amount_cents || 0) !== richtung(r), + ); + // Summe je Richtung ueber die Zeilen, die wirklich gebucht werden. // // Eine gespiegelte Datei sieht man daran auf einen Blick: Ein Kartenauszug @@ -935,10 +947,13 @@ export default function Import() { )} {recon?.available && ( -
- +
+
- {recon.ok ? ( + {abgleichVeraltet ? ( + {t("import.reconStale")} + ) : recon.ok ? ( {t("import.reconOk", { n: recon.checked })} ) : ( <>