Feature: Drag&Drop-Upload in Bank-Zuordnung; Beleg-Upload ohne sofortige Verknüpfung; Button 'Verknüpfung aufheben' im Belegs-Badge
This commit is contained in:
parent
702b0e4664
commit
b1be01ff86
3 changed files with 100 additions and 28 deletions
|
|
@ -209,9 +209,12 @@ class BankController
|
|||
{
|
||||
$id = (int)($params['id'] ?? 0);
|
||||
$belegId = (int)($_POST['beleg_id'] ?? 0);
|
||||
$redirectTo = $_POST['redirect_to'] ?? '';
|
||||
|
||||
BankTransaction::unlinkBeleg($id, $belegId);
|
||||
View::redirect("/bank/$id", 'Beleg-Verknüpfung entfernt.');
|
||||
|
||||
$safe = (preg_match('#^/[a-zA-Z0-9/_-]#', $redirectTo)) ? $redirectTo : "/bank/$id";
|
||||
View::redirect($safe, 'Beleg-Verknüpfung entfernt.');
|
||||
}
|
||||
|
||||
public function uploadBeleg(array $params): void
|
||||
|
|
@ -263,9 +266,7 @@ class BankController
|
|||
'belegtyp' => (float)$transaction['wert'] >= 0 ? 'Ausgangsrechnung' : 'Eingangsrechnung',
|
||||
]);
|
||||
|
||||
$betrag = BankTransaction::getRemainingBetrag($id) ?: abs((float)$transaction['wert']);
|
||||
BankTransaction::linkBeleg($id, $belegId, $betrag);
|
||||
View::redirect('/bank', 'Beleg hochgeladen und Buchung verknüpft.');
|
||||
View::redirect("/bank/$id", 'Beleg hochgeladen – bitte jetzt verknüpfen.');
|
||||
}
|
||||
|
||||
private function renderView(string $name, array $data = []): string
|
||||
|
|
|
|||
|
|
@ -126,22 +126,81 @@ $restFormatted = number_format($remaining, 2, ',', '.');
|
|||
<?php if ($remaining > 0.01): ?>
|
||||
<!-- Beleg hochladen -->
|
||||
<div class="card mb-2">
|
||||
<div class="card-header"><div class="card-title">Neuen Beleg hochladen & verknüpfen</div></div>
|
||||
<div class="card-body">
|
||||
<form method="post" action="/bank/<?= (int)$transaction['id'] ?>/beleg" enctype="multipart/form-data">
|
||||
<div style="display:flex;gap:.75rem;align-items:flex-end;flex-wrap:wrap">
|
||||
<div class="form-group" style="margin:0;flex:1;min-width:200px">
|
||||
<input type="file" name="beleg_file" required
|
||||
<div class="card-header"><div class="card-title">Neuen Beleg hochladen</div></div>
|
||||
<div class="card-body" style="padding-bottom:1rem">
|
||||
<form method="post" action="/bank/<?= (int)$transaction['id'] ?>/beleg"
|
||||
enctype="multipart/form-data" id="beleg-upload-form">
|
||||
<div id="beleg-dnd-zone" style="
|
||||
border:2px dashed var(--color-border);
|
||||
border-radius:var(--radius);
|
||||
background:var(--color-surface);
|
||||
padding:1.5rem 2rem;
|
||||
text-align:center;
|
||||
cursor:pointer;
|
||||
transition:border-color .15s,background .15s;
|
||||
position:relative;
|
||||
">
|
||||
<input type="file" name="beleg_file" id="beleg-dnd-input" required
|
||||
accept=".pdf,.png,.jpg,.jpeg,.tif,.tiff,.xml"
|
||||
style="display:block">
|
||||
<div class="form-hint">PDF, PNG, JPEG, TIFF, XML</div>
|
||||
style="position:absolute;inset:0;opacity:0;cursor:pointer;width:100%;height:100%">
|
||||
<div style="pointer-events:none">
|
||||
<div style="font-size:1.5rem;line-height:1;margin-bottom:.4rem">📄</div>
|
||||
<div style="font-weight:600">Beleg hierher ziehen oder klicken</div>
|
||||
<div class="text-muted text-sm" style="margin-top:.25rem">PDF · PNG · JPEG · TIFF · XML</div>
|
||||
<div id="beleg-dnd-status" style="margin-top:.5rem;min-height:1.25rem"></div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Hochladen & verknüpfen</button>
|
||||
</div>
|
||||
<div style="margin-top:.75rem;display:flex;justify-content:flex-end">
|
||||
<button type="submit" class="btn btn-primary" id="beleg-upload-btn" disabled>
|
||||
Hochladen
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
const zone = document.getElementById('beleg-dnd-zone');
|
||||
const input = document.getElementById('beleg-dnd-input');
|
||||
const status = document.getElementById('beleg-dnd-status');
|
||||
const btn = document.getElementById('beleg-upload-btn');
|
||||
|
||||
function setActive(on) {
|
||||
zone.style.borderColor = on ? 'var(--color-primary)' : 'var(--color-border)';
|
||||
zone.style.background = on ? '#eff6ff' : 'var(--color-surface)';
|
||||
}
|
||||
|
||||
function onFile(file) {
|
||||
if (!file) return;
|
||||
const ext = file.name.split('.').pop().toLowerCase();
|
||||
if (!['pdf','png','jpg','jpeg','tif','tiff','xml'].includes(ext)) {
|
||||
status.innerHTML = '<span style="color:var(--color-danger)">Nicht unterstütztes Format.</span>';
|
||||
btn.disabled = true;
|
||||
return;
|
||||
}
|
||||
status.innerHTML = '<span style="color:var(--color-success)">✓ ' + file.name
|
||||
+ ' (' + (file.size / 1024).toFixed(1) + ' KB)</span>';
|
||||
btn.disabled = false;
|
||||
}
|
||||
|
||||
zone.addEventListener('dragover', e => { e.preventDefault(); setActive(true); });
|
||||
zone.addEventListener('dragleave', e => { if (!zone.contains(e.relatedTarget)) setActive(false); });
|
||||
zone.addEventListener('drop', e => {
|
||||
e.preventDefault();
|
||||
setActive(false);
|
||||
const file = e.dataTransfer.files[0];
|
||||
if (file) {
|
||||
const dt = new DataTransfer();
|
||||
dt.items.add(file);
|
||||
input.files = dt.files;
|
||||
onFile(file);
|
||||
}
|
||||
});
|
||||
input.addEventListener('change', () => onFile(input.files[0]));
|
||||
})();
|
||||
</script>
|
||||
|
||||
<!-- Offene Belege + Vorschau nebeneinander -->
|
||||
<div style="display:flex;gap:1rem;align-items:flex-start">
|
||||
|
||||
|
|
|
|||
|
|
@ -298,11 +298,11 @@ $suppliers = $suppliers ?? [];
|
|||
<!-- Gespeicherte Bankbuchungs-Verknüpfung -->
|
||||
<?php if ($linkedBankTx ?? null): ?>
|
||||
<?php $lbt = $linkedBankTx; $lbwert = (float)$lbt['wert']; ?>
|
||||
<a href="/bank/<?= (int)$lbt['id'] ?>" class="card mb-2"
|
||||
style="display:block;text-decoration:none;color:inherit;border-left:4px solid var(--color-success)">
|
||||
<div class="card mb-2" style="border-left:4px solid var(--color-success)">
|
||||
<div class="card-body" style="padding:.6rem 1.25rem">
|
||||
<div style="display:flex;align-items:center;gap:.75rem;flex-wrap:wrap">
|
||||
<span class="badge badge-green" style="font-size:.8rem">Bankbuchung</span>
|
||||
<a href="/bank/<?= (int)$lbt['id'] ?>" style="display:contents;text-decoration:none;color:inherit">
|
||||
<span class="td-mono text-sm"><?= View::formatDate($lbt['wertstellung']) ?></span>
|
||||
<?php if ($lbt['vorgang']): ?>
|
||||
<span class="text-sm text-muted"><?= $h($lbt['vorgang']) ?></span>
|
||||
|
|
@ -311,10 +311,22 @@ $suppliers = $suppliers ?? [];
|
|||
title="<?= $h($lbt['buchungstext']) ?>"><?= $h($lbt['buchungstext']) ?></span>
|
||||
<strong style="white-space:nowrap;color:<?= $lbwert >= 0 ? 'var(--color-success)' : 'var(--color-danger)' ?>">
|
||||
<?= $lbwert >= 0 ? '+' : '' ?><?= number_format($lbwert, 2, ',', '.') ?> €
|
||||
<?php if (!empty($lbt['alloc_betrag']) && (float)$lbt['alloc_betrag'] !== abs($lbwert)): ?>
|
||||
<span class="text-muted" style="font-weight:normal;font-size:.85em">
|
||||
(zugeordnet: <?= number_format((float)$lbt['alloc_betrag'], 2, ',', '.') ?> €)
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<form method="post" action="/bank/<?= (int)$lbt['id'] ?>/unlink"
|
||||
data-confirm="Verknüpfung mit dieser Bankbuchung wirklich aufheben?">
|
||||
<input type="hidden" name="beleg_id" value="<?= (int)$beleg['id'] ?>">
|
||||
<input type="hidden" name="redirect_to" value="/belege/<?= (int)$beleg['id'] ?>">
|
||||
<button type="submit" class="btn btn-secondary btn-sm">Verknüpfung aufheben</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- BankBuchung-Badge (ersetzt KI-Badge wenn aus Bank-Kontext) -->
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue