Finanzmanager/src/Controllers/VerwaltungController.php
fds2610-bot ba66ce7bdc Fix n.n.: Buchungsbericht – Bargeld-Abgleich, Gruppen-/Gesamtzeile, Filterbereich, Cockpit-Tooltip
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-01 11:18:04 +02:00

299 lines
10 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
declare(strict_types=1);
namespace Finanzmanager\Controllers;
use Finanzmanager\Models\Adresse;
use Finanzmanager\Models\Bankinstitut;
use Finanzmanager\Models\Buchung;
use Finanzmanager\Models\Einstellung;
use Finanzmanager\Models\Erinnerung;
use Finanzmanager\Models\Kategorie;
use Finanzmanager\Models\Klasse;
use Finanzmanager\Models\Konto;
use Finanzmanager\Models\Kontengruppe;
use Finanzmanager\Models\RegelmaessigeBuchung;
use Finanzmanager\Models\Vertrag;
use Finanzmanager\Services\BargeldAbgleich;
use Finanzmanager\Services\BargeldTool;
use Finanzmanager\Services\Crypto;
use Finanzmanager\View;
/**
* Einstiegsseite der Verwaltung sowie die beiden schlanken Stammdatenlisten
* Klassen und Kontengruppen – beide flach, beide mit Anlegen, Bearbeiten und
* Löschen auf einer Seite.
*/
class VerwaltungController extends BaseController
{
public function index(): void
{
$this->verlangeAnmeldung();
$this->render('verwaltung/index.php', [
'titel' => 'Verwaltung',
'zahlen' => [
'kategorien' => Kategorie::anzahl(),
'einnahmen' => Kategorie::anzahl('einnahme'),
'ausgaben' => Kategorie::anzahl('ausgabe'),
'klassen' => Klasse::anzahl(),
'konten' => Konto::anzahl(),
'kontengruppen' => count(Kontengruppe::alle()),
'bankinstitute' => Bankinstitut::anzahl(),
'reihen' => count(RegelmaessigeBuchung::alle(true)),
'erinnerungen' => Erinnerung::anzahlOffen(),
'vertraege' => count(Vertrag::alle(true)),
'fristen' => count(Vertrag::fristenLaufenAb(90)),
'bargeld' => count(Kategorie::bargeldAuswahl()),
'adressen' => Adresse::anzahl(),
],
'bargeldAktiv' => BargeldAbgleich::eingerichtet(),
]);
}
public function klassen(): void
{
$this->verlangeAnmeldung();
$this->render('verwaltung/klassen.php', [
'titel' => 'Klassen',
'klassen' => Klasse::alle(),
]);
}
public function klasseAnlegen(): void
{
$this->verlangeAnmeldung();
try {
Klasse::anlegen($this->post('name'), $this->post('beschreibung'));
} catch (\Throwable $e) {
View::redirect('/verwaltung/klassen', $e->getMessage(), 'fehler');
return;
}
View::redirect('/verwaltung/klassen', 'Klasse angelegt.');
}
/** @param array<string,string> $params */
public function klasseSpeichern(array $params): void
{
$this->verlangeAnmeldung();
try {
Klasse::speichern(
(int)$params['id'],
$this->post('name'),
$this->post('beschreibung'),
isset($_POST['aktiv'])
);
} catch (\Throwable $e) {
View::redirect('/verwaltung/klassen', $e->getMessage(), 'fehler');
return;
}
View::redirect('/verwaltung/klassen', 'Klasse gespeichert.');
}
/** @param array<string,string> $params */
public function klasseLoeschen(array $params): void
{
$this->verlangeAnmeldung();
Klasse::loeschen((int)$params['id']);
View::redirect('/verwaltung/klassen', 'Klasse gelöscht.');
}
public function kontengruppen(): void
{
$this->verlangeAnmeldung();
$this->render('verwaltung/kontengruppen.php', [
'titel' => 'Kontengruppen',
'gruppen' => Kontengruppe::alleMitKontenzahl(),
'ohneGruppe' => Kontengruppe::anzahlOhneGruppe(),
]);
}
public function kontengruppeNeu(): void
{
$this->verlangeAnmeldung();
$this->kontengruppeFormular(null);
}
/** @param array<string,string> $params */
public function kontengruppeBearbeiten(array $params): void
{
$this->verlangeAnmeldung();
$gruppe = Kontengruppe::find((int)$params['id']);
if ($gruppe === null) {
View::redirect('/verwaltung/kontengruppen', 'Kontengruppe nicht gefunden.', 'fehler');
return;
}
$this->kontengruppeFormular($gruppe);
}
/** @param array<string,mixed>|null $gruppe */
private function kontengruppeFormular(?array $gruppe): void
{
$this->render('verwaltung/kontengruppe-formular.php', [
'titel' => $gruppe === null ? 'Neue Kontengruppe' : 'Kontengruppe bearbeiten',
'gruppe' => $gruppe,
'konten' => Konto::alle(),
]);
}
public function kontengruppeAnlegen(): void
{
$this->verlangeAnmeldung();
try {
$id = Kontengruppe::anlegen(
$this->post('name'),
$this->post('beschreibung'),
(int)$this->post('sortierung', '0')
);
Kontengruppe::kontenZuordnen($id, $this->postIds('konten'));
} catch (\Throwable $e) {
View::redirect('/verwaltung/kontengruppen/neu', $e->getMessage(), 'fehler');
return;
}
View::redirect('/verwaltung/kontengruppen', 'Kontengruppe angelegt.');
}
/** @param array<string,string> $params */
public function kontengruppeSpeichern(array $params): void
{
$this->verlangeAnmeldung();
$id = (int)$params['id'];
try {
Kontengruppe::speichern(
$id,
$this->post('name'),
$this->post('beschreibung'),
(int)$this->post('sortierung', '0')
);
Kontengruppe::kontenZuordnen($id, $this->postIds('konten'));
} catch (\Throwable $e) {
View::redirect('/verwaltung/kontengruppen/' . $id, $e->getMessage(), 'fehler');
return;
}
View::redirect('/verwaltung/kontengruppen', 'Kontengruppe gespeichert.');
}
/** @param array<string,string> $params */
public function kontengruppeLoeschen(array $params): void
{
$this->verlangeAnmeldung();
Kontengruppe::loeschen((int)$params['id']);
View::redirect(
'/verwaltung/kontengruppen',
'Kontengruppe gelöscht. Die Konten stehen jetzt unter „' . Kontengruppe::OHNE_GRUPPE . '“.'
);
}
/**
* Die Konfiguration des Bargeld-Tools: Adresse, Zugangsdaten und die
* Auswahl der Kategorien, die damit abgeglichen werden.
*
* Diese Einstellungen stehen bewusst nicht im zentralen
* Einstellungsdialog: Ihr größerer Teil ist die Kategorienauswahl, und die
* gehört in die Verwaltung, wo die Kategorien selbst gepflegt werden.
*/
public function bargeld(): void
{
$this->verlangeAnmeldung();
$this->render('verwaltung/bargeld.php', [
'titel' => 'Bargeld-Tool',
'url' => (string)Einstellung::get('bargeld_url', ''),
// Nicht 'benutzer': So heißt im Layout der angemeldete Mensch.
'benutzerkennung' => (string)Einstellung::get('bargeld_benutzer', ''),
'hatPasswort' => (string)Einstellung::get('bargeld_passwort', '') !== '',
'tage' => BargeldAbgleich::fensterTage(),
'kategorien' => Kategorie::baumFlach(),
'auswahl' => Kategorie::bargeldAuswahl(),
'schluessel' => Crypto::einsatzbereit(),
]);
}
public function bargeldSpeichern(): void
{
$this->verlangeAnmeldung();
$url = trim($this->post('bargeld_url'));
if ($url !== '' && !preg_match('#^https?://#i', $url)) {
View::redirect('/verwaltung/bargeld', 'Die Adresse muss mit http:// oder https:// beginnen.', 'fehler');
return;
}
// Ein mitkopiertes „/api/v1“ am Ende fliegt raus – sonst hinge der
// Schnittstellenpfad ein zweites Mal dran.
Einstellung::set('bargeld_url', $url === '' ? '' : BargeldTool::basisadresse($url), 'bargeld');
Einstellung::set('bargeld_benutzer', trim($this->post('bargeld_benutzer')), 'bargeld');
// Wie bei der FinTS-PIN: Ein leeres Feld heißt „unverändert“, sonst
// ließe sich das Passwort nie speichern, ohne es erneut einzutippen.
$passwort = $this->post('bargeld_passwort');
if ($passwort !== '') {
Einstellung::set('bargeld_passwort', Crypto::verschluessle($passwort), 'bargeld');
}
if ($this->post('passwort_loeschen') !== '') {
Einstellung::set('bargeld_passwort', '', 'bargeld');
}
$tage = (int)$this->post('bargeld_tage', (string)BargeldAbgleich::TAGE_STANDARD);
Einstellung::set('bargeld_tage', (string)($tage > 0 ? min($tage, 365) : BargeldAbgleich::TAGE_STANDARD), 'bargeld');
$auswahl = $this->postIds('kategorien');
Kategorie::bargeldAuswahlSetzen($auswahl);
// Was nicht mehr abgeglichen wird, darf auch keinen Haken mehr tragen.
BargeldAbgleich::statusAufraeumen($auswahl);
View::redirect('/verwaltung/bargeld', 'Einstellungen zum Bargeld-Tool gespeichert.');
}
/** Der Verbindungstest – erreichbar? Zugangsdaten richtig? */
public function bargeldTest(): void
{
$this->verlangeAnmeldung();
$zugang = BargeldTool::ausEinstellungen();
if ($zugang === null) {
View::redirect('/verwaltung/bargeld', 'Es ist keine Adresse hinterlegt.', 'fehler');
return;
}
$ergebnis = $zugang->test();
View::redirect('/verwaltung/bargeld', $ergebnis['meldung'], $ergebnis['erfolg'] ? 'erfolg' : 'fehler');
}
/**
* Alle Buchungen, an denen die Bargeld-Tool-Prüfung zuletzt einen Fehler
* festgestellt hat – der Weg, den die Kachel „Offene Vorgänge“ des
* Cockpit anbietet, sobald es solche Buchungen gibt.
*/
public function bargeldFehler(): void
{
$this->verlangeAnmeldung();
$fehlt = ($_GET['status'] ?? '') === 'fehlt';
$this->render('verwaltung/bargeld_fehler.php', [
'titel' => $fehlt
? 'Bargeld-Tool: nicht gefundene Buchungen'
: 'Bargeld-Tool: fehlgeschlagene Prüfungen',
'fehlt' => $fehlt,
'buchungen' => Buchung::mitBargeldFehler($fehlt ? 'fehlt' : 'fehler'),
]);
}
}