diff --git a/Changes.md b/Changes.md
index a5deecc..7046aae 100644
--- a/Changes.md
+++ b/Changes.md
@@ -1,5 +1,13 @@
# Änderungen
+## Regelmäßige Buchungen: automatisch abgleichen (12.10.2026)
+
+- Anlass (#123): Buchungen aus regelmäßigen Buchungen mussten nach dem Buchen einzeln abgeglichen werden.
+- Neuer Schalter „automatisch abgleichen“ unter „automatisch buchen“ im Dialog „Neue regelmäßige Buchung“, in der Vorgabe eingeschaltet. Gesetzt markiert er die entstandene Buchung als abgeglichen – beim Fälligkeitslauf ebenso wie beim Buchen von Hand.
+- Die Übersicht der regelmäßigen Buchungen hat eine neue Spalte „Abgleichen“ zwischen „Auto“ und „Aktiv“, per Klick umschaltbar.
+- Migration `029_regelmaessig_abgleichen.sql`; bestehende Reihen übernehmen die Vorgabe (eingeschaltet).
+- Tests: `tests/60_RegelmaessigAbgleichenTest.php`, `tests/e2e/specs/module.spec.js`.
+
## Buchungen: bewusst ohne Kategorie (12.10.2026)
- Anlass (#134): Abschreibungen oder rein rechnerische Solarerträge sollen ohne Kategorie gebucht werden können, ohne immer wieder als offen angemahnt zu werden. Mit Kategorie belastete eine Abschreibung die Auswertung zusätzlich zum gesunkenen Kontowert.
diff --git a/docs/nebenmodule.md b/docs/nebenmodule.md
index bc97ff1..0fbe855 100644
--- a/docs/nebenmodule.md
+++ b/docs/nebenmodule.md
@@ -35,6 +35,10 @@ Zwei Betriebsarten:
* **auf Bestätigung** – wird nur gemeldet und wartet auf Knopfdruck. Für alles, dessen
Betrag schwankt.
+Unabhängig davon legt **automatisch abgleichen** (Vorgabe: eingeschaltet) fest, ob die
+entstandene Buchung gleich als abgeglichen markiert wird. Die Übersicht zeigt den Schalter
+in der Spalte „Abgleichen“.
+
Der Lauf ist gutmütig gegenüber langen Pausen: Liegen mehrere Termine zurück, wird **jeder
einzeln** gebucht, nicht einer für alle – nur so stimmen die Monatssummen. Nach dem Buchen
rückt die Fälligkeit so weit vor, bis sie in der Zukunft liegt.
diff --git a/migrations/029_regelmaessig_abgleichen.sql b/migrations/029_regelmaessig_abgleichen.sql
new file mode 100644
index 0000000..f6c9f35
--- /dev/null
+++ b/migrations/029_regelmaessig_abgleichen.sql
@@ -0,0 +1,11 @@
+-- Regelmäßige Buchungen: automatisch abgleichen (#123).
+--
+-- Neben „automatisch buchen“ bekommt jede Reihe den Schalter „automatisch
+-- abgleichen“. Ist er gesetzt (Vorgabe), wird die aus der Reihe entstandene
+-- Buchung gleich als abgeglichen markiert. Bestehende Reihen übernehmen die
+-- Vorgabe.
+--
+-- Idempotent über IF NOT EXISTS.
+
+ALTER TABLE regelmaessige_buchungen
+ ADD COLUMN IF NOT EXISTS abgleichen TINYINT(1) NOT NULL DEFAULT 1 AFTER automatisch;
diff --git a/src/Controllers/TermineController.php b/src/Controllers/TermineController.php
index 5db5ef6..e4a19e5 100644
--- a/src/Controllers/TermineController.php
+++ b/src/Controllers/TermineController.php
@@ -202,6 +202,7 @@ class TermineController extends BaseController
'ende' => $this->post('ende'),
'naechste_faelligkeit' => $this->post('naechste_faelligkeit'),
'automatisch' => isset($_POST['automatisch']) ? 1 : 0,
+ 'abgleichen' => isset($_POST['abgleichen']) ? 1 : 0,
'vorlauf_tage' => $this->post('vorlauf_tage', '7'),
'aktiv' => isset($_POST['aktiv']) ? 1 : 0,
];
diff --git a/src/Models/RegelmaessigeBuchung.php b/src/Models/RegelmaessigeBuchung.php
index 8cddcb8..5186431 100644
--- a/src/Models/RegelmaessigeBuchung.php
+++ b/src/Models/RegelmaessigeBuchung.php
@@ -14,6 +14,9 @@ use Finanzmanager\Mandant;
* ansteht, bucht es und schreibt das Datum fort. So braucht es keine Tabelle
* vorausberechneter Termine, die bei jeder Änderung neu zu erzeugen wäre – der
* Finanzkalender rechnet die kommenden Termine bei Bedarf aus.
+ *
+ * Mit „automatisch abgleichen“ (Vorgabe) ist die entstandene Buchung gleich
+ * als abgeglichen markiert.
*/
class RegelmaessigeBuchung
{
@@ -95,13 +98,13 @@ class RegelmaessigeBuchung
'INSERT INTO regelmaessige_buchungen
(benutzer_id, name, konto_id, betrag, empfaenger, buchungstext, kategorie_id,
klasse_id, gegenkonto_id, splits, intervall, faktor, beginn, ende,
- naechste_faelligkeit, automatisch, vorlauf_tage, aktiv)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
+ naechste_faelligkeit, automatisch, abgleichen, vorlauf_tage, aktiv)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
[
Mandant::id(), $f['name'], $f['konto_id'], $f['betrag'], $f['empfaenger'],
$f['buchungstext'], $f['kategorie_id'], $f['klasse_id'], $f['gegenkonto_id'],
$f['splits'], $f['intervall'], $f['faktor'], $f['beginn'], $f['ende'],
- $f['beginn'], $f['automatisch'], $f['vorlauf_tage'], $f['aktiv'],
+ $f['beginn'], $f['automatisch'], $f['abgleichen'], $f['vorlauf_tage'], $f['aktiv'],
]
);
@@ -137,13 +140,13 @@ class RegelmaessigeBuchung
'UPDATE regelmaessige_buchungen SET name = ?, konto_id = ?, betrag = ?, empfaenger = ?,
buchungstext = ?, kategorie_id = ?, klasse_id = ?, gegenkonto_id = ?, splits = ?,
intervall = ?, faktor = ?, beginn = ?, ende = ?, naechste_faelligkeit = ?,
- automatisch = ?, vorlauf_tage = ?, aktiv = ?
+ automatisch = ?, abgleichen = ?, vorlauf_tage = ?, aktiv = ?
WHERE id = ? AND benutzer_id = ?',
[
$f['name'], $f['konto_id'], $f['betrag'], $f['empfaenger'], $f['buchungstext'],
$f['kategorie_id'], $f['klasse_id'], $f['gegenkonto_id'], $f['splits'],
$f['intervall'], $f['faktor'], $f['beginn'], $f['ende'], $naechste,
- $f['automatisch'], $f['vorlauf_tage'], $f['aktiv'], $id, Mandant::id(),
+ $f['automatisch'], $f['abgleichen'], $f['vorlauf_tage'], $f['aktiv'], $id, Mandant::id(),
]
);
}
@@ -194,6 +197,7 @@ class RegelmaessigeBuchung
'kategorie_id' => $splits === [] ? $reihe['kategorie_id'] : null,
'klasse_id' => $reihe['klasse_id'],
'gegenkonto_id' => $splits === [] ? $reihe['gegenkonto_id'] : null,
+ 'abgeglichen' => (int)$reihe['abgleichen'] === 1 ? 1 : 0,
],
$splits
);
@@ -383,6 +387,8 @@ class RegelmaessigeBuchung
'beginn' => $beginn,
'ende' => $ende,
'automatisch' => !empty($daten['automatisch']) ? 1 : 0,
+ // Vorgabe eingeschaltet: Fehlt der Schlüssel, wird abgeglichen.
+ 'abgleichen' => array_key_exists('abgleichen', $daten) && empty($daten['abgleichen']) ? 0 : 1,
'vorlauf_tage' => max(0, min(365, (int)($daten['vorlauf_tage'] ?? 7))),
'aktiv' => array_key_exists('aktiv', $daten) && empty($daten['aktiv']) ? 0 : 1,
];
diff --git a/src/Views/termine/index.php b/src/Views/termine/index.php
index 87c97d9..44b6175 100644
--- a/src/Views/termine/index.php
+++ b/src/Views/termine/index.php
@@ -106,7 +106,7 @@ include __DIR__ . '/../layout/kopf.php';
Name und Buchungstext Konto und Klasse Betrag Rhythmus
- Nächster Termin Ende Auto Aktiv Aktion
+ Nächster Termin Ende Auto Abgleichen Aktiv Aktion
+ Mit Haken ist die entstandene Buchung gleich als abgeglichen markiert. +
+ diff --git a/tests/60_RegelmaessigAbgleichenTest.php b/tests/60_RegelmaessigAbgleichenTest.php new file mode 100644 index 0000000..5992e42 --- /dev/null +++ b/tests/60_RegelmaessigAbgleichenTest.php @@ -0,0 +1,105 @@ +mandantAnlegen(); + + $this->giro = Konto::anlegen([ + 'name' => 'Abgleichgiro', 'kontoart' => 'bank', 'anfangssaldo' => 0, 'aktiv' => 1, + ]); + + $this->vorgabeIstEingeschaltet(); + $this->schalterLaesstSichSpeichern(); + $this->buchenGleichtAb(); + $this->ohneSchalterBleibtOffen(); + $this->faelligkeitslaufGleichtAb(); + } + + /** @param array