mandantAnlegen(); $this->stammdaten(); $this->auswahlNimmtDieGeldbuchungenMit(); $this->bestandGibtDieLoeschungWiederHer(); $this->unbekannteNummernBleibenFolgenlos(); } private function stammdaten(): void { $this->depot = Konto::anlegen([ 'name' => 'Sammeldepot', 'kontoart' => 'depot', 'anfangssaldo' => 0, 'aktiv' => 1, ]); $this->verrechnung = Konto::anlegen([ 'name' => 'Sammelverrechnungskonto', 'kontoart' => 'bank', 'anfangssaldo' => 10000, 'aktiv' => 1, ]); $this->papier = Wertpapier::findenOderAnlegen([ 'name' => 'Sammelaktie AG', 'isin' => 'DE0007654321', 'art' => 'aktie', ]); } /** * Zwei Käufe, ein Verkauf, eine Dividende – wie eine Auswahl in der Liste. * * @return list */ private function vierBuchungen(): array { return [ Depotbuchung::anlegen([ 'konto_id' => $this->depot, 'wertpapier_id' => $this->papier, 'datum' => '2026-01-15', 'vorgang' => 'kauf', 'stueck' => 10, 'kurs' => 100, 'betrag' => 1000, 'gebuehren' => 10, 'verrechnungskonto_id' => $this->verrechnung, ]), Depotbuchung::anlegen([ 'konto_id' => $this->depot, 'wertpapier_id' => $this->papier, 'datum' => '2026-02-15', 'vorgang' => 'kauf', 'stueck' => 10, 'kurs' => 120, 'betrag' => 1200, 'gebuehren' => 10, 'verrechnungskonto_id' => $this->verrechnung, ]), Depotbuchung::anlegen([ 'konto_id' => $this->depot, 'wertpapier_id' => $this->papier, 'datum' => '2026-03-15', 'vorgang' => 'verkauf', 'stueck' => 5, 'kurs' => 150, 'betrag' => 750, 'gebuehren' => 15, 'steuern' => 20, 'verrechnungskonto_id' => $this->verrechnung, ]), Depotbuchung::anlegen([ 'konto_id' => $this->depot, 'wertpapier_id' => $this->papier, 'datum' => '2026-04-01', 'vorgang' => 'dividende', 'betrag' => 50, 'steuern' => 13.19, 'verrechnungskonto_id' => $this->verrechnung, ]), ]; } /** So arbeitet der Controller die Auswahl ab: Nummer für Nummer. */ private function auswahlLoeschen(array $ids): int { $anzahl = 0; foreach ($ids as $id) { if (Depotbuchung::find((int)$id) === null) { continue; } Depotbuchung::loeschen((int)$id); $anzahl++; } return $anzahl; } private function auswahlNimmtDieGeldbuchungenMit(): void { $ids = $this->vierBuchungen(); $geldIds = []; foreach ($ids as $id) { $geldIds[] = (int)Depotbuchung::find($id)['buchung_id']; } $this->assertEquals(4, count(array_filter($geldIds)), 'Jede Depotbuchung hat ihre Geldbuchung'); // Die beiden Käufe auswählen – der Rest bleibt stehen. $this->assertEquals(2, $this->auswahlLoeschen([$ids[0], $ids[1]]), 'Zwei Buchungen gelöscht'); $this->assertNull(Depotbuchung::find($ids[0]), 'Der erste Kauf ist weg'); $this->assertNull(Depotbuchung::find($ids[1]), 'Der zweite Kauf auch'); $this->assertNotEmpty(Depotbuchung::find($ids[2]), 'Der Verkauf steht noch'); $this->assertNotEmpty(Depotbuchung::find($ids[3]), 'Die Dividende ebenso'); $this->assertNull(Buchung::find($geldIds[0]), 'Die Geldbuchung des ersten Kaufs ging mit'); $this->assertNull(Buchung::find($geldIds[1]), 'Die des zweiten Kaufs ebenso'); $this->assertNotEmpty(Buchung::find($geldIds[2]), 'Die des Verkaufs blieb unberührt'); // 10000 − 1010 − 1210 + 715 + 36,81; nach dem Löschen der Käufe fehlen // deren Belastungen wieder. $this->assertEquals( 10000.0 + 715.0 + 36.81, Konto::saldo($this->verrechnung, '2026-12-31'), 'Das Verrechnungskonto trägt nur noch Verkauf und Dividende' ); // Aufräumen für den nächsten Abschnitt. $this->auswahlLoeschen([$ids[2], $ids[3]]); } private function bestandGibtDieLoeschungWiederHer(): void { Wertpapier::kursSetzen($this->papier, '2026-06-30', 130.0, 'test'); $leer = Depot::bestand($this->depot, '2026-12-31'); $this->assertEquals(0, count($leer['positionen']), 'Vorher ist das Depot leer'); $ids = $this->vierBuchungen(); $voll = Depot::bestand($this->depot, '2026-12-31'); $this->assertEquals(15.0, $voll['positionen'][0]['stueck'], 'Fünfzehn Stück nach zwei Käufen und einem Verkauf'); $this->assertGreaterThan(0.0, $voll['realisiert'], 'Der Verkauf hat etwas realisiert'); $this->assertEquals(36.81, $voll['ertraege'], 'Die Dividende zählt als Ertrag'); // Verkauf und Dividende zurücknehmen: Der Bestand steht wieder auf den // beiden Käufen, realisierter Gewinn und Erträge fallen auf null. $this->assertEquals(2, $this->auswahlLoeschen([$ids[2], $ids[3]]), 'Zwei Buchungen gelöscht'); $nachher = Depot::bestand($this->depot, '2026-12-31'); $this->assertEquals(20.0, $nachher['positionen'][0]['stueck'], 'Die verkauften Stücke sind zurück'); $this->assertEquals(2220.0, $nachher['positionen'][0]['einstand'], 'Und der volle Einstand beider Käufe'); $this->assertEquals(2600.0, $nachher['wert'], 'Zwanzig Stück zu 130 €'); $this->assertEquals(0.0, $nachher['realisiert'], 'Ohne Verkauf ist nichts realisiert'); $this->assertEquals(0.0, $nachher['ertraege'], 'Ohne Dividende gibt es keinen Ertrag'); $veraeusserungen = Depot::veraeusserungen('2026-01-01', '2026-12-31', $this->depot); $this->assertEquals(0, count($veraeusserungen['geschaefte']), 'Kein Veräußerungsgeschäft mehr'); $this->assertEquals(0.0, $veraeusserungen['gewinn'], 'Und kein Gewinn in der Auswertung'); $this->auswahlLoeschen([$ids[0], $ids[1]]); } private function unbekannteNummernBleibenFolgenlos(): void { $id = $this->vierBuchungen()[0]; // Eine Nummer, die es nicht (mehr) gibt, wird übergangen – der Rest der // Auswahl verschwindet trotzdem. $this->assertEquals(1, $this->auswahlLoeschen([999999, $id]), 'Nur die vorhandene Buchung zählt'); $this->assertNull(Depotbuchung::find($id), 'Und sie ist gelöscht'); } }