.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>
216 lines
12 KiB
PHP
216 lines
12 KiB
PHP
<?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'; ?>
|