> */ public static function alle(): array { return Database::fetchAll( 'SELECT * FROM kontengruppen WHERE benutzer_id = ? ORDER BY sortierung, name', [Mandant::id()] ); } /** * Wie alle(), zusätzlich mit der Zahl der zugeordneten Konten – die Liste * zeigt sie in einer eigenen Spalte. * * @return list> */ public static function alleMitKontenzahl(): array { return Database::fetchAll( 'SELECT g.*, COUNT(k.id) AS anzahl_konten FROM kontengruppen g LEFT JOIN konten k ON k.kontengruppe_id = g.id WHERE g.benutzer_id = ? GROUP BY g.id ORDER BY g.sortierung, g.name', [Mandant::id()] ); } /** Konten, die unter „Nicht gruppiert“ stehen. */ public static function anzahlOhneGruppe(): int { return (int)Database::fetchValue( 'SELECT COUNT(*) FROM konten WHERE benutzer_id = ? AND kontengruppe_id IS NULL', [Mandant::id()] ); } public static function find(int $id): ?array { $zeile = Database::fetchOne( 'SELECT * FROM kontengruppen WHERE id = ? AND benutzer_id = ?', [$id, Mandant::id()] ); return $zeile === false ? null : $zeile; } public static function findeNachName(string $name): ?array { $zeile = Database::fetchOne( 'SELECT * FROM kontengruppen WHERE name = ? AND benutzer_id = ?', [trim($name), Mandant::id()] ); return $zeile === false ? null : $zeile; } public static function anlegen(string $name, string $beschreibung = '', int $sortierung = 0): int { $name = trim($name); if ($name === '') { throw new \InvalidArgumentException('Die Kontengruppe braucht einen Namen.'); } if (self::findeNachName($name) !== null) { throw new \RuntimeException('Die Kontengruppe „' . $name . '“ gibt es bereits.'); } Database::execute( 'INSERT INTO kontengruppen (benutzer_id, name, beschreibung, sortierung) VALUES (?, ?, ?, ?)', [Mandant::id(), $name, $beschreibung, $sortierung] ); return Database::lastInsertId(); } public static function findenOderAnlegen(string $name): int { $vorhanden = self::findeNachName($name); return $vorhanden !== null ? (int)$vorhanden['id'] : self::anlegen($name); } public static function speichern(int $id, string $name, string $beschreibung, int $sortierung): void { $name = trim($name); if ($name === '') { throw new \InvalidArgumentException('Die Kontengruppe braucht einen Namen.'); } $andere = self::findeNachName($name); if ($andere !== null && (int)$andere['id'] !== $id) { throw new \RuntimeException('Die Kontengruppe „' . $name . '“ gibt es bereits.'); } Database::execute( 'UPDATE kontengruppen SET name = ?, beschreibung = ?, sortierung = ? WHERE id = ? AND benutzer_id = ?', [$name, $beschreibung, $sortierung, $id, Mandant::id()] ); } /** * Legt fest, welche Konten zur Gruppe gehören. Konten, die vorher in der * Gruppe standen und jetzt fehlen, rutschen zurück zu „Nicht gruppiert“ – * Konten anderer Gruppen bleiben unberührt. * * @param list $kontoIds */ public static function kontenZuordnen(int $id, array $kontoIds): void { Database::execute( 'UPDATE konten SET kontengruppe_id = NULL WHERE kontengruppe_id = ? AND benutzer_id = ?', [$id, Mandant::id()] ); $kontoIds = array_values(array_unique(array_map('intval', $kontoIds))); if ($kontoIds === []) { return; } $platzhalter = implode(', ', array_fill(0, count($kontoIds), '?')); Database::execute( 'UPDATE konten SET kontengruppe_id = ? WHERE benutzer_id = ? AND id IN (' . $platzhalter . ')', array_merge([$id, Mandant::id()], $kontoIds) ); } /** Die zugeordneten Konten rutschen per ON DELETE SET NULL zu „Nicht gruppiert“. */ public static function loeschen(int $id): void { Database::execute( 'DELETE FROM kontengruppen WHERE id = ? AND benutzer_id = ?', [$id, Mandant::id()] ); } }