mandantAnlegen(); $this->stammdaten(); $this->letzteBuchungenNachEmpfaengerKontenuebergreifend(); $this->limitUndReihenfolge(); $this->ohneTrefferBleibtDieListeLeer(); $this->adressenseiteZeigtDieLetztenBuchungen(); $this->zahlungsempfaengerIstEinTypeahead(); } private function stammdaten(): void { $this->girokonto = Konto::anlegen([ 'name' => 'Adressen-Giro', 'kontoart' => 'bank', 'anfangssaldo' => 0, 'aktiv' => 1, ]); $this->sparkonto = Konto::anlegen([ 'name' => 'Adressen-Sparbuch', 'kontoart' => 'sparkonto', 'anfangssaldo' => 0, 'aktiv' => 1, ]); } private function letzteBuchungenNachEmpfaengerKontenuebergreifend(): void { Buchung::anlegen([ 'konto_id' => $this->girokonto, 'datum' => '2026-01-10', 'betrag' => -20.0, 'empfaenger' => 'Stadtwerke Musterstadt', 'buchungstext' => 'Strom Januar', ]); Buchung::anlegen([ 'konto_id' => $this->sparkonto, 'datum' => '2026-02-10', 'betrag' => -21.0, 'empfaenger' => 'Stadtwerke Musterstadt', 'buchungstext' => 'Strom Februar', ]); Buchung::anlegen([ 'konto_id' => $this->girokonto, 'datum' => '2026-01-15', 'betrag' => -5.0, 'empfaenger' => 'Anderer Empfänger', 'buchungstext' => 'Nichts damit zu tun', ]); $treffer = Buchung::letzteFuerEmpfaenger('Stadtwerke Musterstadt'); $this->assertEquals(2, count($treffer), 'Beide Konten liefern ihre Buchung zum Empfänger'); $this->assertEquals('Adressen-Sparbuch', $treffer[0]['kontoname'], 'Das Sparbuch führt (jüngstes Datum zuerst)'); $this->assertEquals('Adressen-Giro', $treffer[1]['kontoname'], 'Das Girokonto folgt'); } private function limitUndReihenfolge(): void { for ($i = 1; $i <= 7; $i++) { Buchung::anlegen([ 'konto_id' => $this->girokonto, 'datum' => sprintf('2026-03-%02d', $i), 'betrag' => -1.0 * $i, 'empfaenger' => 'Vielbucher GmbH', 'buchungstext' => 'Rechnung ' . $i, ]); } $treffer = Buchung::letzteFuerEmpfaenger('Vielbucher GmbH', 3); $this->assertEquals(3, count($treffer), 'Das Limit wird eingehalten'); $this->assertEquals('2026-03-07', $treffer[0]['datum'], 'Die jüngste Buchung steht vorn'); $this->assertEquals('2026-03-05', $treffer[2]['datum'], 'Danach bricht die Liste beim Limit ab'); } private function ohneTrefferBleibtDieListeLeer(): void { $this->assertEquals([], Buchung::letzteFuerEmpfaenger('Niemand hat je an diesen Namen gebucht'), 'Keine Treffer, keine Zeilen'); $this->assertEquals([], Buchung::letzteFuerEmpfaenger(''), 'Ein leerer Empfänger liefert keine Zeilen statt aller Buchungen'); } private function adressenseiteZeigtDieLetztenBuchungen(): void { Adresse::anlegen(['name' => 'Stadtwerke Musterstadt', 'iban' => 'DE02120300000000202051']); Adresse::anlegen(['name' => 'Ganz ohne Buchung']); $adressen = Adresse::alle(); foreach ($adressen as $nummer => $adresse) { $adressen[$nummer]['buchungen'] = Buchung::letzteFuerEmpfaenger((string)$adresse['name']); } $html = $this->adressenHtml($adressen); $this->assert(str_contains($html, 'Strom Februar'), 'Die letzte Buchung zur Adresse erscheint'); $this->assert(str_contains($html, 'Strom Januar'), 'Auch die ältere Buchung erscheint'); $this->assert(str_contains($html, 'Noch keine Buchung mit diesem Empfänger.'), 'Eine Adresse ohne Buchung sagt das auch so'); $this->assert(str_contains($html, '
'), 'Die Buchungen stehen hinter einem Klappelement'); } private function zahlungsempfaengerIstEinTypeahead(): void { $html = $this->zahlungsverkehrFormularHtml(); $this->assert( (bool)preg_match( '#