Finanzmanager/src/Views/banking/umsaetze.php
fds2610-bot d2635183ec Fix #98: Liste "Umsätze abgleichen" durchgehend linksbündig, Empfänger ohne Fettung
.umsatztext hatte in der Flex-Zeile .umsatzkopf keinen flex-grow, wodurch
justify-content: space-between die Restfläche auf beide Zwischenräume
verteilte – der Text schwebte dadurch zentriert zwischen Ankreuzfeld und
Betrag statt linksbündig am Ankreuzfeld zu stehen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-30 14:08:24 +02:00

216 lines
12 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
use Finanzmanager\Models\Bankumsatz;
use Finanzmanager\View;
/**
* Die Vorschlagsliste des Abgleichs. Zu jedem offenen Umsatz steht daneben, was
* die Anwendung vorschlägt: mit einer vorhandenen Buchung verbinden, nach Regel
* übernehmen oder von Hand zuordnen.
*
* @var string $status
* @var list<array<string,mixed>> $umsaetze
* @var list<array<string,mixed>> $kategorien
* @var list<array<string,mixed>> $klassen
* @var list<array<string,mixed>> $konten
* @var int $offen
* @var string $csrfToken
*/
// Für die Splitzeilen einer Regel: Die Vorschläge tragen nur Kennungen, hier
// soll der Pfad der Kategorie stehen.
$kategoriepfad = [];
foreach ($kategorien as $eintrag) {
$kategoriepfad[(int)$eintrag['id']] = (string)$eintrag['pfad'];
}
include __DIR__ . '/../layout/kopf.php';
?>
<div class="tableiste">
<a href="/banking" class="tab">Bankverbindungen</a>
<?php foreach (Bankumsatz::STATUS as $schluessel => $beschriftung): ?>
<a href="/banking/umsaetze?status=<?= View::h($schluessel) ?>"
class="tab <?= $status === $schluessel ? 'aktiv' : '' ?>">
<?= View::h(ucfirst($beschriftung)) ?><?= $schluessel === 'offen' && $offen > 0 ? ' (' . $offen . ')' : '' ?>
</a>
<?php endforeach; ?>
<a href="/banking/regeln" class="tab rechtsbuendig">Regeln</a>
</div>
<?php if ($umsaetze !== []): ?>
<div class="seitenaktionen">
<?php if ($status === 'offen'): ?>
<form method="post" action="/banking/umsaetze/alle" class="inline"
data-bestaetigen="Alle eindeutigen Vorschläge übernehmen? Umsätze ohne Regel bleiben offen.">
<input type="hidden" name="csrf_token" value="<?= View::h($csrfToken) ?>">
<button type="submit" class="knopf primaer">Alle eindeutigen übernehmen</button>
</form>
<a href="/banking/regeln" class="knopf">Regeln pflegen</a>
<?php endif; ?>
<?php /* Wie im Kontoblatt: Das Formular steht in der Aktionsleiste, seine
Ankreuzfelder stehen in den Umsatzkarten – verbunden über das
form-Attribut. Ein Formular um die ganze Liste verschachtelte
sich mit den Formularen der einzelnen Umsätze. */ ?>
<form method="post" action="/banking/umsaetze/loeschen?status=<?= View::h($status) ?>"
id="umsatzauswahl" class="inline"
data-bestaetigen="Die ausgewählten Umsätze wirklich löschen?"
data-frage-eine="Den ausgewählten Umsatz wirklich löschen? Eine daraus erzeugte Buchung bleibt im Kontoblatt stehen."
data-frage-mehrere="{anzahl} ausgewählte Umsätze wirklich löschen? Daraus erzeugte Buchungen bleiben im Kontoblatt stehen.">
<input type="hidden" name="csrf_token" value="<?= View::h($csrfToken) ?>">
<button type="submit" class="knopf gefahr">Auswahl löschen</button>
</form>
</div>
<?php endif; ?>
<?php if ($umsaetze === []): ?>
<p class="platzhalter">
<?= $status === 'offen'
? 'Nichts abzugleichen – alle abgerufenen Umsätze sind erledigt.'
: 'Keine Umsätze mit diesem Status.' ?>
</p>
<?php else: ?>
<?php /* Die Titelleiste der Liste. Eine Tabelle mit Kopfzeile gibt es hier
nicht, das Ankreuzfeld „alle wählen“ braucht aber seinen Platz. */ ?>
<div class="listenkopf">
<label class="ankreuzfeld">
<input type="checkbox" class="alle-waehlen" data-waehlt="umsatzauswahl"
aria-label="Alle angezeigten Umsätze auswählen">
Alle auswählen
</label>
<span class="nebentext">
<?= count($umsaetze) ?> <?= count($umsaetze) === 1 ? 'Umsatz' : 'Umsätze' ?>
</span>
</div>
<?php foreach ($umsaetze as $umsatz): ?>
<?php
$id = (int)$umsatz['id'];
$vorschlag = $umsatz['vorschlag'] ?? null;
$zuordnung = $vorschlag['zuordnung'] ?? null;
$buchung = $vorschlag['buchung'] ?? null;
?>
<section class="umsatz">
<div class="umsatzkopf">
<input type="checkbox" name="umsaetze[]" value="<?= $id ?>" form="umsatzauswahl"
class="umsatzwahl"
aria-label="Umsatz vom <?= View::h(View::datum($umsatz['buchungstag'])) ?> über <?= View::h(View::betrag($umsatz['betrag'])) ?> auswählen">
<div class="umsatztext">
<span><?= View::h($umsatz['empfaenger'] ?: 'Ohne Empfänger') ?></span>
<span class="nebentext"><?= View::h(View::datum($umsatz['buchungstag'])) ?>
· <?= View::h($umsatz['kontoname'] ?? 'Konto nicht zugeordnet') ?>
· <?= View::h($umsatz['zugangsname']) ?></span>
<p class="verwendungszweck"><?= View::h($umsatz['verwendungszweck'] ?? '') ?></p>
</div>
<div class="umsatzbetrag <?= View::betragKlasse($umsatz['betrag']) ?>">
<?= View::betrag($umsatz['betrag']) ?>
</div>
</div>
<?php if ($status !== 'offen'): ?>
<div class="umsatzaktion">
<span class="nebentext">
<?= View::h(Bankumsatz::STATUS[$umsatz['status']]) ?><?php
if ($umsatz['buchung_id'] !== null): ?>,
<a href="/buchungen/<?= (int)$umsatz['buchung_id'] ?>">zur Buchung</a>
<?php endif; ?>
</span>
<form method="post" action="/banking/umsaetze/<?= $id ?>/zuruecksetzen" class="inline">
<input type="hidden" name="csrf_token" value="<?= View::h($csrfToken) ?>">
<button type="submit" class="knopf klein">Wieder offen</button>
</form>
</div>
<?php else: ?>
<?php if ($buchung !== null): ?>
<?php /* Der stärkste Vorschlag: Die Buchung steht schon im
Kontoblatt, der Umsatz bestätigt sie nur. */ ?>
<form method="post" action="/banking/umsaetze/<?= $id ?>/uebernehmen" class="umsatzaktion">
<input type="hidden" name="csrf_token" value="<?= View::h($csrfToken) ?>">
<input type="hidden" name="buchung_id" value="<?= (int)$buchung['id'] ?>">
<span class="vorschlagsmarke">Vorschlag: verbinden<?= (int)$buchung['konto_id'] !== (int)$umsatz['konto_id'] ? ' (Gegenseite einer Umbuchung)' : '' ?></span>
<span class="nebentext">
mit der Buchung vom <?= View::h(View::datum($buchung['datum'])) ?>
über <?= View::betrag($buchung['betrag']) ?>
<?= $buchung['empfaenger'] !== '' ? '(' . View::h($buchung['empfaenger']) . ')' : '' ?>
</span>
<button type="submit" class="knopf klein primaer">Verbinden</button>
</form>
<?php endif; ?>
<form method="post" action="/banking/umsaetze/<?= $id ?>/uebernehmen" class="umsatzaktion">
<input type="hidden" name="csrf_token" value="<?= View::h($csrfToken) ?>">
<?php if ($vorschlag['regel'] !== null): ?>
<span class="vorschlagsmarke">Regel: <?= View::h($vorschlag['regel']['name']) ?></span>
<?php endif; ?>
<?php if ((int)$umsatz['konto_id'] === 0): ?>
<select name="konto_id" required>
<option value="">– Konto wählen –</option>
<?php foreach ($konten as $konto): ?>
<option value="<?= (int)$konto['id'] ?>"><?= View::h($konto['name']) ?></option>
<?php endforeach; ?>
</select>
<?php endif; ?>
<?php $regelsplits = $zuordnung['splits'] ?? []; ?>
<?php if ($regelsplits !== []): ?>
<?php /* Die Regel teilt den Umsatz auf. Die Zeilen stehen hier
nur zum Nachlesen und wandern unverändert mit – geändert
wird eine Aufteilung im Kontoblatt, wo die ganze Buchung
samt Summenprüfung vor einem liegt. */ ?>
<ul class="vorschlagssplits">
<?php foreach ($regelsplits as $nr => $zeile): ?>
<li>
<span><?= View::h($kategoriepfad[(int)($zeile['kategorie_id'] ?? 0)] ?? 'ohne Kategorie') ?></span>
<span class="betrag <?= View::betragKlasse($zeile['betrag']) ?>">
<?= View::betrag($zeile['betrag']) ?>
</span>
<input type="hidden" name="split[<?= (int)$nr ?>][kategorie_id]"
value="<?= (int)($zeile['kategorie_id'] ?? 0) ?>">
<input type="hidden" name="split[<?= (int)$nr ?>][klasse_id]"
value="<?= (int)($zeile['klasse_id'] ?? 0) ?: '' ?>">
<input type="hidden" name="split[<?= (int)$nr ?>][notiz]"
value="<?= View::h((string)($zeile['notiz'] ?? '')) ?>">
<input type="hidden" name="split[<?= (int)$nr ?>][betrag]"
value="<?= View::h(number_format((float)$zeile['betrag'], 2, '.', '')) ?>">
</li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<select name="kategorie_id">
<option value="">– ohne Kategorie –</option>
<?php foreach ($kategorien as $kategorie): ?>
<option value="<?= (int)$kategorie['id'] ?>"
<?= (int)($zuordnung['kategorie_id'] ?? 0) === (int)$kategorie['id'] ? 'selected' : '' ?>>
<?= View::h($kategorie['pfad']) ?>
</option>
<?php endforeach; ?>
</select>
<select name="klasse_id">
<option value="">– ohne Klasse –</option>
<?php foreach ($klassen as $klasse): ?>
<option value="<?= (int)$klasse['id'] ?>"
<?= (int)($zuordnung['klasse_id'] ?? 0) === (int)$klasse['id'] ? 'selected' : '' ?>>
<?= View::h($klasse['name']) ?>
</option>
<?php endforeach; ?>
</select>
<?php endif; ?>
<button type="submit" class="knopf klein <?= $buchung === null ? 'primaer' : '' ?>">
<?= $regelsplits === [] ? 'Als neue Buchung' : 'Als Splitbuchung' ?>
</button>
</form>
<form method="post" action="/banking/umsaetze/<?= $id ?>/verwerfen" class="umsatzaktion">
<input type="hidden" name="csrf_token" value="<?= View::h($csrfToken) ?>">
<button type="submit" class="knopf klein">Verwerfen</button>
</form>
<?php endif; ?>
</section>
<?php endforeach; ?>
<?php endif; ?>
<?php include __DIR__ . '/../layout/fuss.php'; ?>