Phase 4: SEPA-Validierung (schwifty), Globale Suche (Cmd+K) & Jahresbericht-Modul
- SEPA-Export: IBAN/BIC-Validierung via schwifty, Schuldner-Konto aus StiftungsKonto - Globale Suche: Cmd+K Modal über Destinatäre, Pächter, Ländereien, Förderungen, Dokumente - Jahresbericht: Vollständige Jahresbilanz mit Einnahmen/Ausgaben/Netto, Unterstützungen, Landabrechnungen, Verwaltungskosten nach Kategorie, PDF-Export Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -777,5 +777,223 @@
|
||||
</script>
|
||||
|
||||
{% block javascript %}{% endblock %}
|
||||
|
||||
<!-- Phase 4: Globale Suche (Cmd+K) -->
|
||||
<div id="global-search-overlay" style="display:none; position:fixed; inset:0; z-index:9999; background:rgba(0,0,0,0.5);" onclick="closeGlobalSearch()">
|
||||
</div>
|
||||
<div id="global-search-modal" style="display:none; position:fixed; top:15%; left:50%; transform:translateX(-50%); z-index:10000; width:min(600px, 90vw); background:#fff; border-radius:0.75rem; box-shadow:0 20px 60px rgba(0,0,0,0.3); overflow:hidden;">
|
||||
<div style="padding:0.75rem 1rem; border-bottom:1px solid #e9ecef; display:flex; align-items:center; gap:0.5rem;">
|
||||
<i class="fas fa-search" style="color:#6c757d;"></i>
|
||||
<input id="global-search-input" type="text" placeholder="Suche über alle Bereiche..." autocomplete="off"
|
||||
style="flex:1; border:none; outline:none; font-size:1rem; background:transparent; color:#212529;">
|
||||
<kbd style="font-size:0.75rem; padding:2px 6px; background:#f8f9fa; border:1px solid #dee2e6; border-radius:4px; color:#6c757d;">Esc</kbd>
|
||||
</div>
|
||||
<div id="global-search-results" style="max-height:420px; overflow-y:auto; padding:0.5rem 0;">
|
||||
<div class="px-3 py-4 text-center text-muted" id="global-search-hint">
|
||||
<i class="fas fa-search fa-2x mb-2 d-block" style="opacity:0.3;"></i>
|
||||
Mindestens 2 Zeichen eingeben …
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Suche-Trigger in Topbar -->
|
||||
<style>
|
||||
#global-search-btn {
|
||||
background: none;
|
||||
border: 1px solid #dee2e6;
|
||||
border-radius: 6px;
|
||||
padding: 4px 10px;
|
||||
color: #6c757d;
|
||||
font-size: 0.85rem;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
white-space: nowrap;
|
||||
transition: border-color 0.15s, color 0.15s;
|
||||
}
|
||||
#global-search-btn:hover {
|
||||
border-color: var(--racing-green);
|
||||
color: var(--racing-green);
|
||||
}
|
||||
.search-result-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
padding: 0.6rem 1rem;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
color: #212529;
|
||||
transition: background 0.1s;
|
||||
}
|
||||
.search-result-item:hover, .search-result-item.highlighted {
|
||||
background: #f0f7f4;
|
||||
color: var(--racing-green-dark);
|
||||
}
|
||||
.search-result-icon {
|
||||
width: 32px; height: 32px;
|
||||
border-radius: 50%;
|
||||
background: var(--racing-green);
|
||||
color: white;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
flex-shrink: 0;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
.search-result-typ {
|
||||
font-size: 0.7rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
color: #6c757d;
|
||||
}
|
||||
.search-group-label {
|
||||
padding: 0.25rem 1rem;
|
||||
font-size: 0.7rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
color: #adb5bd;
|
||||
font-weight: 600;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
.search-group-label:first-child { border-top: none; margin-top: 0; }
|
||||
</style>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
const overlay = document.getElementById('global-search-overlay');
|
||||
const modal = document.getElementById('global-search-modal');
|
||||
const input = document.getElementById('global-search-input');
|
||||
const resultsEl = document.getElementById('global-search-results');
|
||||
const hintEl = document.getElementById('global-search-hint');
|
||||
let debounceTimer = null;
|
||||
let currentHighlight = -1;
|
||||
let resultLinks = [];
|
||||
|
||||
function openGlobalSearch() {
|
||||
overlay.style.display = 'block';
|
||||
modal.style.display = 'block';
|
||||
input.focus();
|
||||
input.select();
|
||||
}
|
||||
|
||||
window.closeGlobalSearch = function() {
|
||||
overlay.style.display = 'none';
|
||||
modal.style.display = 'none';
|
||||
};
|
||||
|
||||
// Cmd+K / Ctrl+K öffnet Suche
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
|
||||
e.preventDefault();
|
||||
if (modal.style.display === 'block') {
|
||||
closeGlobalSearch();
|
||||
} else {
|
||||
openGlobalSearch();
|
||||
}
|
||||
}
|
||||
if (e.key === 'Escape' && modal.style.display === 'block') {
|
||||
closeGlobalSearch();
|
||||
}
|
||||
// Keyboard navigation
|
||||
if (modal.style.display === 'block' && (e.key === 'ArrowDown' || e.key === 'ArrowUp')) {
|
||||
e.preventDefault();
|
||||
resultLinks = Array.from(resultsEl.querySelectorAll('.search-result-item'));
|
||||
if (!resultLinks.length) return;
|
||||
resultLinks.forEach(l => l.classList.remove('highlighted'));
|
||||
if (e.key === 'ArrowDown') currentHighlight = Math.min(currentHighlight + 1, resultLinks.length - 1);
|
||||
else currentHighlight = Math.max(currentHighlight - 1, 0);
|
||||
if (currentHighlight >= 0) {
|
||||
resultLinks[currentHighlight].classList.add('highlighted');
|
||||
resultLinks[currentHighlight].scrollIntoView({ block: 'nearest' });
|
||||
}
|
||||
}
|
||||
if (modal.style.display === 'block' && e.key === 'Enter') {
|
||||
resultLinks = Array.from(resultsEl.querySelectorAll('.search-result-item'));
|
||||
if (currentHighlight >= 0 && resultLinks[currentHighlight]) {
|
||||
window.location.href = resultLinks[currentHighlight].href;
|
||||
} else if (resultLinks.length === 1) {
|
||||
window.location.href = resultLinks[0].href;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Prevent modal click from closing
|
||||
modal.addEventListener('click', function(e) { e.stopPropagation(); });
|
||||
|
||||
input.addEventListener('input', function() {
|
||||
clearTimeout(debounceTimer);
|
||||
currentHighlight = -1;
|
||||
const q = input.value.trim();
|
||||
if (q.length < 2) {
|
||||
hintEl.style.display = '';
|
||||
resultsEl.innerHTML = '';
|
||||
resultsEl.appendChild(hintEl);
|
||||
return;
|
||||
}
|
||||
debounceTimer = setTimeout(function() { doSearch(q); }, 200);
|
||||
});
|
||||
|
||||
function doSearch(q) {
|
||||
fetch("{% url 'stiftung:globale_suche_api' %}?q=" + encodeURIComponent(q), {
|
||||
headers: { 'X-Requested-With': 'XMLHttpRequest' }
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(data => renderResults(data.results, q))
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
function renderResults(results, q) {
|
||||
resultsEl.innerHTML = '';
|
||||
if (!results || !results.length) {
|
||||
const empty = document.createElement('div');
|
||||
empty.className = 'px-3 py-4 text-center text-muted';
|
||||
empty.innerHTML = '<i class="fas fa-search-minus fa-2x mb-2 d-block" style="opacity:0.3;"></i>Keine Ergebnisse für „' + escapeHtml(q) + '"';
|
||||
resultsEl.appendChild(empty);
|
||||
return;
|
||||
}
|
||||
// Group by type
|
||||
const grouped = {};
|
||||
results.forEach(r => {
|
||||
if (!grouped[r.typ]) grouped[r.typ] = [];
|
||||
grouped[r.typ].push(r);
|
||||
});
|
||||
Object.entries(grouped).forEach(([typ, items]) => {
|
||||
const label = document.createElement('div');
|
||||
label.className = 'search-group-label';
|
||||
label.textContent = typ;
|
||||
resultsEl.appendChild(label);
|
||||
items.forEach(item => {
|
||||
const a = document.createElement('a');
|
||||
a.className = 'search-result-item';
|
||||
a.href = item.url;
|
||||
a.innerHTML = `
|
||||
<div class="search-result-icon"><i class="${item.icon}"></i></div>
|
||||
<div style="min-width:0;">
|
||||
<div style="font-weight:500; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">${escapeHtml(item.titel)}</div>
|
||||
${item.untertitel ? '<div class="search-result-typ">' + escapeHtml(item.untertitel) + '</div>' : ''}
|
||||
</div>`;
|
||||
a.addEventListener('click', closeGlobalSearch);
|
||||
resultsEl.appendChild(a);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function escapeHtml(s) {
|
||||
return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"');
|
||||
}
|
||||
|
||||
// Inject search button into topbar
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const topbarActions = document.querySelector('.topbar-actions');
|
||||
if (topbarActions) {
|
||||
const btn = document.createElement('button');
|
||||
btn.id = 'global-search-btn';
|
||||
btn.onclick = openGlobalSearch;
|
||||
btn.innerHTML = '<i class="fas fa-search"></i> Suche <kbd style="font-size:0.7rem; padding:1px 4px; background:#f8f9fa; border:1px solid #dee2e6; border-radius:3px; margin-left:4px;">⌘K</kbd>';
|
||||
topbarActions.insertBefore(btn, topbarActions.firstChild);
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -4,12 +4,13 @@
|
||||
<meta charset="utf-8">
|
||||
<title>Stiftung – Jahresbericht {{ jahr }}</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
line-height: 1.6;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
}
|
||||
.header {
|
||||
text-align: center;
|
||||
@@ -17,129 +18,200 @@
|
||||
padding-bottom: 20px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
.header h1 {
|
||||
color: #2c3e50;
|
||||
margin: 0;
|
||||
font-size: 2.5em;
|
||||
}
|
||||
.header .subtitle {
|
||||
color: #7f8c8d;
|
||||
font-size: 1.2em;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.section {
|
||||
margin-bottom: 30px;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
.header h1 { color: #2c3e50; margin: 0; font-size: 2.2em; }
|
||||
.header .subtitle { color: #7f8c8d; font-size: 1.1em; margin-top: 8px; }
|
||||
.section { margin-bottom: 30px; page-break-inside: avoid; }
|
||||
.section h2 {
|
||||
color: #34495e;
|
||||
border-bottom: 2px solid #3498db;
|
||||
padding-bottom: 10px;
|
||||
margin-bottom: 20px;
|
||||
color: #1a4a2e;
|
||||
border-bottom: 2px solid #2c7a4b;
|
||||
padding-bottom: 8px;
|
||||
margin-bottom: 16px;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
.section h3 { color: #34495e; font-size: 1em; margin-top: 16px; margin-bottom: 8px; }
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 20px;
|
||||
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
||||
gap: 16px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.stat-card {
|
||||
background: #f8f9fa;
|
||||
border: 1px solid #dee2e6;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
padding: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
.stat-card .value {
|
||||
font-size: 2em;
|
||||
font-weight: bold;
|
||||
color: #2c3e50;
|
||||
}
|
||||
.stat-card .label {
|
||||
color: #7f8c8d;
|
||||
margin-top: 5px;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
.stat-card .value { font-size: 1.6em; font-weight: bold; color: #1a4a2e; }
|
||||
.stat-card .label { color: #7f8c8d; margin-top: 4px; font-size: 0.85em; }
|
||||
.bilanz-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 16px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid #dee2e6;
|
||||
padding: 12px;
|
||||
text-align: left;
|
||||
.bilanz-card {
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
th {
|
||||
background-color: #f8f9fa;
|
||||
font-weight: 600;
|
||||
color: #2c3e50;
|
||||
}
|
||||
tr:nth-child(even) {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
.amount {
|
||||
text-align: right;
|
||||
font-family: 'Courier New', monospace;
|
||||
}
|
||||
.status-badge {
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
.bilanz-card.einnahmen { background: #d4edda; border: 1px solid #c3e6cb; }
|
||||
.bilanz-card.ausgaben { background: #f8d7da; border: 1px solid #f5c6cb; }
|
||||
.bilanz-card.netto-positiv { background: #d1ecf1; border: 1px solid #bee5eb; }
|
||||
.bilanz-card.netto-negativ { background: #fff3cd; border: 1px solid #ffeeba; }
|
||||
.bilanz-card .value { font-size: 1.5em; font-weight: bold; }
|
||||
.bilanz-card .label { font-size: 0.85em; margin-top: 4px; color: #555; }
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin-bottom: 16px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
th, td { border: 1px solid #dee2e6; padding: 8px 10px; text-align: left; }
|
||||
th { background-color: #f0f7f4; font-weight: 600; color: #1a4a2e; }
|
||||
tr:nth-child(even) { background-color: #f8f9fa; }
|
||||
.amount { text-align: right; font-family: 'Courier New', monospace; }
|
||||
.status-badge {
|
||||
padding: 3px 7px;
|
||||
border-radius: 4px;
|
||||
font-size: 0.8em;
|
||||
font-weight: 500;
|
||||
}
|
||||
.status-beantragt { background-color: #fff3cd; color: #856404; }
|
||||
.status-genehmigt { background-color: #d1ecf1; color: #0c5460; }
|
||||
.status-ausgezahlt { background-color: #d4edda; color: #155724; }
|
||||
.status-abgelehnt { background-color: #f8d7da; color: #721c24; }
|
||||
.status-storniert { background-color: #e2e3e5; color: #383d41; }
|
||||
.status-ausgezahlt, .status-abgeschlossen { background-color: #d4edda; color: #155724; }
|
||||
.status-abgelehnt, .status-storniert { background-color: #f8d7da; color: #721c24; }
|
||||
.status-geplant, .status-faellig { background-color: #e2e3e5; color: #383d41; }
|
||||
.footer {
|
||||
margin-top: 40px;
|
||||
padding-top: 20px;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid #dee2e6;
|
||||
text-align: center;
|
||||
color: #7f8c8d;
|
||||
font-size: 0.9em;
|
||||
font-size: 0.85em;
|
||||
}
|
||||
@media print {
|
||||
body { margin: 0; padding: 15px; }
|
||||
body { margin: 0; padding: 10px; }
|
||||
.section { page-break-inside: avoid; }
|
||||
.no-print { display: none; }
|
||||
}
|
||||
.print-btn {
|
||||
display: inline-block;
|
||||
padding: 8px 20px;
|
||||
background: #1a4a2e;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 0.9em;
|
||||
text-decoration: none;
|
||||
margin-right: 8px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
<h1>Stiftung – Jahresbericht {{ jahr }}</h1>
|
||||
<div class="subtitle">Jahresübersicht über Förderungen und Verpachtungen</div>
|
||||
<div class="subtitle">Erstellt am {{ "now"|date:"d.m.Y" }}</div>
|
||||
<!-- Aktionsleiste (nur Bildschirm, nicht Druck) -->
|
||||
<div class="no-print" style="margin-bottom: 20px; display: flex; align-items: center; gap: 12px;">
|
||||
<a href="{% url 'stiftung:bericht_list' %}" style="color: #1a4a2e;">← Berichte</a>
|
||||
<span style="color: #dee2e6;">|</span>
|
||||
<a href="{% url 'stiftung:jahresbericht_pdf' jahr=jahr %}" class="print-btn">
|
||||
PDF herunterladen
|
||||
</a>
|
||||
<button onclick="window.print()" class="print-btn" style="background: #34495e;">
|
||||
Drucken
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Executive Summary -->
|
||||
<!-- Kopfzeile -->
|
||||
<div class="header">
|
||||
<h1>Jahresbericht {{ jahr }}</h1>
|
||||
<div class="subtitle">van Hees-Theyssen-Vogel'sche Familienstiftung</div>
|
||||
<div class="subtitle">Erstellt am {% now "d.m.Y" %}</div>
|
||||
</div>
|
||||
|
||||
<!-- 1. Gesamtübersicht / Bilanz -->
|
||||
<div class="section">
|
||||
<h2>Zusammenfassung</h2>
|
||||
<h2>1. Jahresbilanz {{ jahr }}</h2>
|
||||
<div class="bilanz-grid">
|
||||
<div class="bilanz-card einnahmen">
|
||||
<div class="value">€{{ total_einnahmen|floatformat:2 }}</div>
|
||||
<div class="label">Einnahmen (Pacht)</div>
|
||||
</div>
|
||||
<div class="bilanz-card ausgaben">
|
||||
<div class="value">€{{ total_ausgaben|floatformat:2 }}</div>
|
||||
<div class="label">Ausgaben gesamt</div>
|
||||
</div>
|
||||
<div class="bilanz-card {% if netto >= 0 %}netto-positiv{% else %}netto-negativ{% endif %}">
|
||||
<div class="value">{% if netto >= 0 %}+{% endif %}€{{ netto|floatformat:2 }}</div>
|
||||
<div class="label">Nettosaldo</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card">
|
||||
<div class="value">€{{ total_foerderungen|floatformat:2 }}</div>
|
||||
<div class="label">Gesamtförderungen</div>
|
||||
<div class="value">€{{ total_ausgaben_foerderung|floatformat:2 }}</div>
|
||||
<div class="label">Förderausgaben</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="value">€{{ total_pachtzins|floatformat:2 }}</div>
|
||||
<div class="label">Gesamtpachtzins</div>
|
||||
<div class="value">€{{ total_verwaltungskosten|floatformat:2 }}</div>
|
||||
<div class="label">Verwaltungskosten</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="value">{{ foerderungen.count }}</div>
|
||||
<div class="label">Förderungen</div>
|
||||
<div class="value">€{{ pacht_vereinnahmt|floatformat:2 }}</div>
|
||||
<div class="label">Pacht vereinnahmt</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="value">{{ verpachtungen.count }}</div>
|
||||
<div class="label">Aktive Verpachtungen</div>
|
||||
<div class="value">€{{ grundsteuer_gesamt|floatformat:2 }}</div>
|
||||
<div class="label">Grundsteuer</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Förderungen Section -->
|
||||
<!-- 2. Unterstützungen (Zahlungs-Pipeline) -->
|
||||
{% if unterstuetzungen %}
|
||||
<div class="section">
|
||||
<h2>2. Unterstützungszahlungen {{ jahr }}</h2>
|
||||
<p style="color: #666; margin-bottom: 12px;">
|
||||
{{ unterstuetzungen.count }} Unterstützung(en) geplant/ausgezahlt ·
|
||||
{{ unterstuetzungen_ausgezahlt.count }} überwiesen (€{{ total_unterstuetzungen|floatformat:2 }})
|
||||
</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Destinatär</th>
|
||||
<th>Betrag</th>
|
||||
<th>Fällig am</th>
|
||||
<th>Status</th>
|
||||
<th>Verwendungszweck</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for u in unterstuetzungen %}
|
||||
<tr>
|
||||
<td>{{ u.destinataer.get_full_name }}</td>
|
||||
<td class="amount">€{{ u.betrag|floatformat:2 }}</td>
|
||||
<td>{{ u.faellig_am|date:"d.m.Y" }}</td>
|
||||
<td>
|
||||
<span class="status-badge status-{{ u.status }}">{{ u.get_status_display }}</span>
|
||||
</td>
|
||||
<td>{{ u.beschreibung|default:"-" }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr style="font-weight: bold; background: #f0f7f4;">
|
||||
<td>Summe ausgezahlt</td>
|
||||
<td class="amount">€{{ total_unterstuetzungen|floatformat:2 }}</td>
|
||||
<td colspan="3"></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- 3. Förderungen (legacy Foerderung-Modell) -->
|
||||
{% if foerderungen %}
|
||||
<div class="section">
|
||||
<h2>Förderungen im Jahr {{ jahr }}</h2>
|
||||
<h2>3. Förderungen {{ jahr }}</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -151,77 +223,144 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for foerderung in foerderungen %}
|
||||
{% for f in foerderungen %}
|
||||
<tr>
|
||||
<td>{{ foerderung.person.get_full_name }}</td>
|
||||
<td>{{ foerderung.get_kategorie_display }}</td>
|
||||
<td class="amount">€{{ foerderung.betrag|floatformat:2 }}</td>
|
||||
<td>
|
||||
<span class="status-badge status-{{ foerderung.status }}">
|
||||
{{ foerderung.get_status_display }}
|
||||
</span>
|
||||
{% if f.destinataer %}{{ f.destinataer.get_full_name }}
|
||||
{% elif f.person %}{{ f.person.get_full_name }}
|
||||
{% else %}–{% endif %}
|
||||
</td>
|
||||
<td>{{ foerderung.antragsdatum|date:"d.m.Y" }}</td>
|
||||
<td>{{ f.get_kategorie_display }}</td>
|
||||
<td class="amount">€{{ f.betrag|floatformat:2 }}</td>
|
||||
<td>
|
||||
<span class="status-badge status-{{ f.status }}">{{ f.get_status_display }}</span>
|
||||
</td>
|
||||
<td>{{ f.antragsdatum|date:"d.m.Y" }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr style="font-weight: bold; background: #f0f7f4;">
|
||||
<td colspan="2">Summe</td>
|
||||
<td class="amount">€{{ total_foerderungen_legacy|floatformat:2 }}</td>
|
||||
<td colspan="2"></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Verpachtungen Section -->
|
||||
{% if verpachtungen %}
|
||||
<!-- 4. Grundstücksverwaltung -->
|
||||
<div class="section">
|
||||
<h2>Aktive Verpachtungen im Jahr {{ jahr }}</h2>
|
||||
<h2>4. Grundstücksverwaltung</h2>
|
||||
|
||||
{% if verpachtungen %}
|
||||
<h3>Aktive Verpachtungen</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Länderei</th>
|
||||
<th>Pächter</th>
|
||||
<th>Vertragsnummer</th>
|
||||
<th>Verpachtete Fläche</th>
|
||||
<th>Jährlicher Pachtzins</th>
|
||||
<th>Jahrespachtzins</th>
|
||||
<th>Pachtende</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for verpachtung in verpachtungen %}
|
||||
{% for v in verpachtungen %}
|
||||
<tr>
|
||||
<td>{{ verpachtung.land }}</td>
|
||||
<td>{{ verpachtung.paechter.get_full_name }}</td>
|
||||
<td>{{ verpachtung.vertragsnummer }}</td>
|
||||
<td>{{ verpachtung.verpachtete_flaeche|floatformat:2 }} qm</td>
|
||||
<td class="amount">€{{ verpachtung.pachtzins_jaehrlich|floatformat:2 }}</td>
|
||||
<td>{{ verpachtung.pachtende|date:"d.m.Y" }}</td>
|
||||
<td>{{ v.land }}</td>
|
||||
<td>{{ v.paechter.get_full_name }}</td>
|
||||
<td class="amount">{{ v.verpachtete_flaeche|floatformat:0 }} qm</td>
|
||||
<td class="amount">€{{ v.pachtzins_pauschal|floatformat:2 }}</td>
|
||||
<td>{% if v.pachtende %}{{ v.pachtende|date:"d.m.Y" }}{% else %}unbefristet{% endif %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr style="font-weight: bold; background: #f0f7f4;">
|
||||
<td colspan="3">Gesamtpachtzins (kalkuliert)</td>
|
||||
<td class="amount">€{{ total_pachtzins|floatformat:2 }}</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
{% if landabrechnungen %}
|
||||
<h3>Landabrechnungen {{ jahr }}</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Länderei</th>
|
||||
<th>Pacht vereinnahmt</th>
|
||||
<th>Umlagen</th>
|
||||
<th>Grundsteuer</th>
|
||||
<th>Sonstige Einnahmen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for a in landabrechnungen %}
|
||||
<tr>
|
||||
<td>{{ a.land }}</td>
|
||||
<td class="amount">€{{ a.pacht_vereinnahmt|floatformat:2 }}</td>
|
||||
<td class="amount">€{{ a.umlagen_vereinnahmt|floatformat:2 }}</td>
|
||||
<td class="amount">€{{ a.grundsteuer_betrag|floatformat:2 }}</td>
|
||||
<td class="amount">€{{ a.sonstige_einnahmen|floatformat:2 }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr style="font-weight: bold; background: #f0f7f4;">
|
||||
<td>Summe</td>
|
||||
<td class="amount">€{{ pacht_vereinnahmt|floatformat:2 }}</td>
|
||||
<td></td>
|
||||
<td class="amount">€{{ grundsteuer_gesamt|floatformat:2 }}</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
{% if not verpachtungen and not landabrechnungen %}
|
||||
<p style="color: #999;">Keine Verpachtungs- oder Abrechnungsdaten für {{ jahr }} vorhanden.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- 5. Verwaltungskosten -->
|
||||
{% if verwaltungskosten_nach_kategorie %}
|
||||
<div class="section">
|
||||
<h2>5. Verwaltungskosten {{ jahr }}</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Kategorie</th>
|
||||
<th>Anzahl</th>
|
||||
<th>Betrag</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for k in verwaltungskosten_nach_kategorie %}
|
||||
<tr>
|
||||
<td>{{ k.kategorie|capfirst }}</td>
|
||||
<td>{{ k.anzahl }}</td>
|
||||
<td class="amount">€{{ k.summe|floatformat:2 }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr style="font-weight: bold; background: #f0f7f4;">
|
||||
<td colspan="2">Gesamt</td>
|
||||
<td class="amount">€{{ total_verwaltungskosten|floatformat:2 }}</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Financial Summary -->
|
||||
<div class="section">
|
||||
<h2>Finanzielle Übersicht</h2>
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card">
|
||||
<div class="value">€{{ total_foerderungen|floatformat:2 }}</div>
|
||||
<div class="label">Ausgaben (Förderungen)</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="value">€{{ total_pachtzins|floatformat:2 }}</div>
|
||||
<div class="label">Einnahmen (Pachtzins)</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="value">€{{ total_pachtzins|add:total_foerderungen|floatformat:2 }}</div>
|
||||
<div class="label">Netto-Position</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<p>Dieser Bericht wurde automatisch generiert von der Stiftungsverwaltung.</p>
|
||||
<p>Bei Fragen wenden Sie sich bitte an die Verwaltung.</p>
|
||||
<p>Jahresbericht {{ jahr }} — automatisch generiert von der Stiftungsverwaltung</p>
|
||||
<p>van Hees-Theyssen-Vogel'sche Familienstiftung · Vertraulich</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user