diff --git a/CHANGELOG.md b/CHANGELOG.md index f8b280d..aae8dea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ Das Format folgt [Keep a Changelog](https://keepachangelog.com/de/1.1.0/). - Regeln: Die Splittabellen zeigen die Spalte „Anteil“ ohne Prozentzeichen und darunter die laufend berechnete Summe der Anteile +- Buchungsmaske und Splitdialog im Kontoblatt: Die Summenzeile der Splitbuchungen zeigt den + noch offenen Restbetrag zum Buchungswert statt der Summe der Zeilen; „Speichern“ bleibt + gesperrt, solange Splitzeilen befüllt sind und der Restbetrag nicht Null ist (#96) ### Fixed diff --git a/Changes.md b/Changes.md index 1528a81..b570754 100644 --- a/Changes.md +++ b/Changes.md @@ -1,5 +1,19 @@ # Änderungen +## Splitbuchungen: Summenzeile zeigt den Restbetrag, Speichern nur bei Null (29.09.2026) + +- Die Summenzeile der Splitbuchungen (Buchungsmaske und Splitdialog im Kontoblatt) zeigte + bisher die Summe der erfassten Zeilen, mit „(Rest X)“ als Zusatz. Jetzt steht dort direkt + der noch offene Restbetrag zum Buchungswert (`Buchungswert - Summe der Zeilen`) – die + gemeinsame Rechenfunktion `FmBetrag.splitsumme()` in `betrag.js` liefert ihn beiden Masken. +- „Speichern“ (bzw. „Splitbuchung speichern“) bleibt gesperrt, solange mindestens eine + Splitzeile einen Betrag trägt und der Restbetrag nicht Null ist. Ohne Splitzeilen – egal ob + unbelegt oder mit direkter Kategorie/Gegenkonto zugeordnet – bleibt der Knopf wie bisher an; + das Model prüft die Summe der Splitzeilen ohnehin schon serverseitig. +- Der bisherige E2E-Test, der eine unstimmige Splitsumme über eine serverseitige Fehlermeldung + prüfte, prüft jetzt die neue Sperre im Browser; die serverseitige Prüfung selbst deckt + weiterhin Test 09 (PHP) ab. + ## Regel direkt aus einer Buchung anlegen (29.09.2026) - Neuer Toggle „Regel anlegen“ in der Buchungsmaske, standardmäßig aus; das bisherige diff --git a/public/static/betrag.js b/public/static/betrag.js index d6e08e7..dfb7ca3 100644 --- a/public/static/betrag.js +++ b/public/static/betrag.js @@ -31,7 +31,9 @@ } /* Die Summe der Splitzeilen unter `felder` gegen `ziel` – das Ergebnis geht - * so in die Anzeige, wie beide Masken es brauchen. */ + * so in die Anzeige, wie beide Masken es brauchen. Angezeigt wird der noch + * offene Restbetrag (ziel - summe), nicht die Summe der Zeilen selbst: Nur + * so sieht man auf einen Blick, was noch fehlt. */ function splitsumme(felder, ziel) { let summe = 0; let belegt = false; @@ -50,7 +52,7 @@ belegt: belegt, summe: summe, rest: rest, - text: belegt ? formatiere(summe) + (rest === 0 ? '' : ' (Rest ' + formatiere(rest) + ')') : '0,00' + text: formatiere(rest) }; } diff --git a/public/static/buchungsmaske.js b/public/static/buchungsmaske.js index ae14dbd..99510cb 100644 --- a/public/static/buchungsmaske.js +++ b/public/static/buchungsmaske.js @@ -1,6 +1,10 @@ /* Buchungsmaske: Restbetrag der Splitzeilen mitrechnen und direkte Zuordnung * und Splitbuchung gegeneinander sperren. * + * Solange Splitzeilen befüllt sind, aber noch ein Restbetrag zum + * Buchungswert offen ist, bleibt „Speichern“ gesperrt – das Model wiese die + * Buchung sonst ohnehin ab, hier spart es die Rundreise zum Server. + * * Nur Komfort – die Maske kommt fertig vom Server. Ohne JavaScript bleibt alles * bedienbar: Die Splitsumme prüft ohnehin das Model. * @@ -26,6 +30,7 @@ const summenfeld = document.getElementById('splitsumme'); const betragsfeld = document.getElementById('betrag'); + const speichernknopf = maske.querySelector('button[type="submit"]'); function rechneSumme() { if (!summenfeld) { @@ -46,6 +51,13 @@ summenfeld.textContent = stand.text; summenfeld.classList.toggle('negativ', stand.belegt && stand.rest !== 0); + + // Gesperrt nur, solange tatsächlich Splitzeilen mit Beträgen stehen und + // deren Summe den Buchungswert verfehlt. Eine direkte Zuordnung (oder + // gar keine Eingabe) deckt den ganzen Betrag stets ab. + if (speichernknopf) { + speichernknopf.disabled = stand.belegt && stand.rest !== 0; + } } const direktfelder = ['zuordnung', 'klasse_id'] diff --git a/public/static/kontoblatt.js b/public/static/kontoblatt.js index fe3e5cf..3a79f72 100644 --- a/public/static/kontoblatt.js +++ b/public/static/kontoblatt.js @@ -335,6 +335,7 @@ const zeilenkasten = document.getElementById('splitdialogzeilen'); const summenfeld = document.getElementById('splitdialogsumme'); const loeschknopf = document.getElementById('splitloeschen'); + const speichernknopf = dialog.querySelector('button[type="submit"].primaer'); const vorlage = zeilenkasten.innerHTML; let buchungsbetrag = 0; @@ -342,10 +343,16 @@ return Array.from(zeilenkasten.querySelectorAll('.splitbetrag')); } + // Gesperrt nur, solange Beträge stehen, deren Summe den Buchungswert + // verfehlt. Bleiben alle Zeilen leer, hebt „Splitbuchung speichern“ die + // Aufteilung auf – das bleibt erlaubt. function rechneSumme() { const stand = window.FmBetrag.splitsumme(felder(), buchungsbetrag); summenfeld.textContent = stand.text; summenfeld.classList.toggle('negativ', stand.belegt && stand.rest !== 0); + if (speichernknopf) { + speichernknopf.disabled = stand.belegt && stand.rest !== 0; + } } /* Eine weitere Zeile: die letzte kopieren, leeren und neu durchnummerieren. diff --git a/src/Views/buchungen/formular.php b/src/Views/buchungen/formular.php index 31995f2..53681a0 100644 --- a/src/Views/buchungen/formular.php +++ b/src/Views/buchungen/formular.php @@ -205,7 +205,7 @@ include __DIR__ . '/../layout/kopf.php';