Merge pull request 'Fix n.n.: Umbuchung wird auch von der Gegenkontoseite erkannt' (#81) from fds2610-bot/Finanzmanager:main into main
Reviewed-on: https://codeberg.org/fds2610/Finanzmanager/pulls/81
This commit is contained in:
commit
963a242fc5
2 changed files with 67 additions and 4 deletions
|
|
@ -200,6 +200,12 @@ class Bankumsatz
|
|||
* Konto, gleicher Betrag, Datum nah beieinander, noch mit keinem anderen
|
||||
* Umsatz verbunden.
|
||||
*
|
||||
* Eine Umbuchung ist dabei auch dann „dasselbe Konto“, wenn sie auf ihrem
|
||||
* Ursprungskonto steht und dieses Konto nur ihr Gegenkonto ist – sonst fände
|
||||
* der Kontoauszug der Empfängerseite seine eigene Umbuchung nie, weil die
|
||||
* Buchung formal einem anderen Konto gehört. Auf der Gegenkonto-Seite zählt
|
||||
* der Betrag mit umgekehrtem Vorzeichen, wie im Kontoblatt auch.
|
||||
*
|
||||
* Die Toleranz in Tagen steht in den Einstellungen (`banking_abgleich_tage`):
|
||||
* Zwischen dem Tag, an dem man eine Zahlung erfasst, und dem Tag, an dem die
|
||||
* Bank sie bucht, liegen erfahrungsgemäß ein paar Tage.
|
||||
|
|
@ -214,13 +220,16 @@ class Bankumsatz
|
|||
return null;
|
||||
}
|
||||
|
||||
$tage = max(0, Einstellung::getInt('banking_abgleich_tage', 5));
|
||||
$tage = max(0, Einstellung::getInt('banking_abgleich_tage', 5));
|
||||
$betrag = round((float)$umsatz['betrag'], 2);
|
||||
|
||||
$zeile = Database::fetchOne(
|
||||
'SELECT b.* FROM buchungen b
|
||||
WHERE b.benutzer_id = ?
|
||||
AND b.konto_id = ?
|
||||
AND ABS(b.betrag - ?) < 0.005
|
||||
AND (
|
||||
(b.konto_id = ? AND ABS(b.betrag - ?) < 0.005)
|
||||
OR (b.gegenkonto_id = ? AND b.gesplittet = 0 AND ABS(b.betrag + ?) < 0.005)
|
||||
)
|
||||
AND ABS(DATEDIFF(b.datum, ?)) <= ?
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM bank_umsaetze u
|
||||
|
|
@ -230,7 +239,9 @@ class Bankumsatz
|
|||
[
|
||||
Mandant::id(),
|
||||
$kontoId,
|
||||
round((float)$umsatz['betrag'], 2),
|
||||
$betrag,
|
||||
$kontoId,
|
||||
$betrag,
|
||||
(string)$umsatz['buchungstag'],
|
||||
$tage,
|
||||
(int)($umsatz['id'] ?? 0),
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ class BankingTest extends TestCase
|
|||
$this->splitsHaltenDasVerhaeltnis();
|
||||
$this->ungueltigesMusterWirdAbgewiesen();
|
||||
$this->abgleichFindetVorhandeneBuchung();
|
||||
$this->umbuchungWirdAuchVonDerGegenkontoseiteErkannt();
|
||||
$this->uebernehmenErzeugtEineBuchung();
|
||||
$this->regelmitSplitsErzeugtEineSplitbuchung();
|
||||
$this->buchungOhneKategorieWirdGefunden();
|
||||
|
|
@ -680,6 +681,57 @@ class BankingTest extends TestCase
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Eine Umbuchung gehört ihrem Ursprungskonto – hier dem Giro. Der
|
||||
* Kontoauszug des Gegenkontos (Sparbuch) muss sie trotzdem finden, sonst
|
||||
* bucht der automatische Abgleich sie dort ein zweites Mal.
|
||||
*/
|
||||
private function umbuchungWirdAuchVonDerGegenkontoseiteErkannt(): void
|
||||
{
|
||||
Einstellung::set('banking_abgleich_tage', '5', 'banking');
|
||||
|
||||
$umbuchungId = Buchung::anlegen([
|
||||
'konto_id' => $this->giro, 'datum' => '2026-08-20', 'betrag' => -40.00,
|
||||
'empfaenger' => 'Umbuchung Sparbuch', 'gegenkonto_id' => $this->sparkonto,
|
||||
]);
|
||||
|
||||
// Die Bank bucht das Sparbuch erst einen Tag später – auf der
|
||||
// Gegenkonto-Seite zählt der Betrag mit umgekehrtem Vorzeichen.
|
||||
$umsatzId = Bankumsatz::anlegen([
|
||||
'zugang_id' => $this->zugang,
|
||||
'konto_id' => $this->sparkonto,
|
||||
'extern_id' => 'test-gegenkonto-1',
|
||||
'buchungstag' => '2026-08-21',
|
||||
'wertstellung' => '2026-08-21',
|
||||
'betrag' => 40.00,
|
||||
'empfaenger' => 'Giro',
|
||||
'buchungsart' => 'GUTSCHRIFT',
|
||||
]);
|
||||
$umsatz = Bankumsatz::find((int)$umsatzId);
|
||||
|
||||
$treffer = Bankumsatz::passendeBuchung($umsatz);
|
||||
$this->assertNotEmpty($treffer, 'Die Umbuchung wird auch von der Gegenkontoseite gefunden');
|
||||
$this->assertEquals($umbuchungId, (int)$treffer['id'], 'Und zwar genau sie');
|
||||
|
||||
$vorschlag = Bankumsatz::vorschlag($umsatz);
|
||||
$this->assertEquals('verbinden', $vorschlag['art'], 'Der Vorschlag lautet: verbinden');
|
||||
|
||||
Bankumsatz::verbinden((int)$umsatzId, $umbuchungId);
|
||||
$this->assertEquals(
|
||||
1,
|
||||
(int)Buchung::find($umbuchungId)['abgeglichen'],
|
||||
'Die Umbuchung gilt jetzt als abgeglichen'
|
||||
);
|
||||
|
||||
// Ein anderer Betrag auf der Gegenkontoseite passt nicht.
|
||||
$this->assertNull(
|
||||
Bankumsatz::passendeBuchung([
|
||||
'konto_id' => $this->sparkonto, 'buchungstag' => '2026-08-21', 'betrag' => 12.34, 'id' => 0,
|
||||
]),
|
||||
'Ein anderer Betrag ist keine Umbuchung von drüben'
|
||||
);
|
||||
}
|
||||
|
||||
private function uebernehmenErzeugtEineBuchung(): void
|
||||
{
|
||||
$offen = Bankumsatz::liste(['status' => 'offen']);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue