From ae33420478d3debcb53560d0613a8f2c2695aef3 Mon Sep 17 00:00:00 2001 From: fds2610-bot Date: Thu, 1 Oct 2026 10:19:10 +0200 Subject: [PATCH] Fix n.n.: Neue Buchungen erhalten automatisch eine laufende Nummer je Konto Co-Authored-By: Claude Sonnet 5.5 --- Changes.md | 5 ++++ src/Models/Buchung.php | 19 +++++++++++++ tests/53_BuchungsnummerTest.php | 49 +++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 tests/53_BuchungsnummerTest.php diff --git a/Changes.md b/Changes.md index a261f6b..fc3f871 100644 --- a/Changes.md +++ b/Changes.md @@ -1,5 +1,10 @@ # Änderungen +## Automatische Buchungsnummer (01.10.2026) + +- Neue Buchungen ohne Nummer erhalten beim Anlegen die nächste laufende Nummer ihres Kontos (höchste rein numerische Nummer + 1, `Buchung::naechsteNummer()`). Vorgegebene Nummern (QIF, CSV, Formular) bleiben, bestehende Buchungen werden nicht verändert; die interne ID bleibt verborgen. +- Test: `53_BuchungsnummerTest.php`. + ## „+ Neu“ öffnet das Formular als Dialog (01.10.2026) - Das Formular zur Neuanlage stand in elf Ansichten unter der Liste. Jetzt öffnet der Knopf „+ Neu“ es als modalen Dialog (`app.js`, `.neudialog`); nach dem Speichern erscheint die Liste wieder, mit dem neuen Eintrag. Betroffen: Klassen, Buchungsvorlagen, Regelmäßige Buchungen, Erinnerungen, Verträge, Adressen, Sparziele, Kredite, Abgleichregeln, Budgets, Berichtsgruppen. diff --git a/src/Models/Buchung.php b/src/Models/Buchung.php index a6c2882..f3cba8e 100644 --- a/src/Models/Buchung.php +++ b/src/Models/Buchung.php @@ -99,6 +99,9 @@ class Buchung Monatsabschluss::verlangeOffen($felder['datum']); return (int)Database::transaktion(static function () use ($felder, $splits, $adressen): int { + if ($felder['nummer'] === '') { + $felder['nummer'] = self::naechsteNummer($felder['konto_id']); + } Database::execute( 'INSERT INTO buchungen (benutzer_id, konto_id, datum, valuta, betrag, empfaenger, iban, bankname, buchungstext, @@ -121,6 +124,22 @@ class Buchung }); } + /** + * Laufende Nummer je Konto: die höchste rein numerische Nummer plus eins. + * Vorhandene Nummern (etwa Schecknummern aus dem QIF-Import) bleiben unberührt. + */ + private static function naechsteNummer(int $kontoId): string + { + $hoechste = Database::fetchValue( + "SELECT MAX(CAST(nummer AS UNSIGNED)) FROM buchungen + WHERE konto_id = ? AND nummer REGEXP '^[0-9]{1,9}$'", + [$kontoId], + 0 + ); + + return (string)((int)$hoechste + 1); + } + /** * @param array $daten * @param list> $splits diff --git a/tests/53_BuchungsnummerTest.php b/tests/53_BuchungsnummerTest.php new file mode 100644 index 0000000..c4e4719 --- /dev/null +++ b/tests/53_BuchungsnummerTest.php @@ -0,0 +1,49 @@ +mandantAnlegen(); + + $a = Konto::anlegen(['name' => 'Nummer A', 'kontoart' => 'bank', 'anfangssaldo' => 0, 'aktiv' => 1]); + $b = Konto::anlegen(['name' => 'Nummer B', 'kontoart' => 'bank', 'anfangssaldo' => 0, 'aktiv' => 1]); + + $erste = $this->buche($a); + $this->assertEquals('1', Buchung::find($erste)['nummer'], 'Die erste Buchung eines Kontos bekommt die 1'); + $zweite = $this->buche($a); + $this->assertEquals('2', Buchung::find($zweite)['nummer'], 'Die nächste zählt hoch'); + $this->assertEquals('1', Buchung::find($this->buche($b))['nummer'], 'Jedes Konto zählt für sich'); + + $fest = $this->buche($a, '603'); + $this->assertEquals('603', Buchung::find($fest)['nummer'], 'Eine vorgegebene Nummer bleibt'); + $this->assertEquals('604', Buchung::find($this->buche($a))['nummer'], 'Danach geht es hinter der höchsten weiter'); + + $this->buche($a, 'Scheck-A'); + $this->assertEquals('605', Buchung::find($this->buche($a))['nummer'], 'Nichtnumerische Nummern stören nicht'); + + Buchung::speichern($erste, [ + 'konto_id' => $a, 'datum' => '2026-05-01', 'betrag' => -1.0, 'nummer' => '', + ]); + $this->assertEquals('', Buchung::find($erste)['nummer'], 'Beim Ändern wird nichts nachvergeben'); + } + + private function buche(int $konto, string $nummer = ''): int + { + return Buchung::anlegen([ + 'konto_id' => $konto, 'datum' => '2026-05-01', 'betrag' => -1.0, + 'empfaenger' => 'Test', 'nummer' => $nummer, + ]); + } +}