- Implement automated payment tracking with Django signals - Fix duplicate transaction creation with unique referenz system - Add calendar system with CRUD operations and event management - Reorganize navigation menu (rename sections, move admin functions) - Replace Geschichte editor with EasyMDE markdown editor - Add management commands for balance reconciliation - Create missing transactions for previously paid payments - Ensure account balances accurately reflect all payment activity Features added: - Calendar entries creation and administration via menu - Payment status tracking with automatic balance updates - Duplicate prevention for payment transactions - Markdown editor with live preview for Geschichte pages - Database reconciliation tools for payment/balance sync Bug fixes: - Resolved IntegrityError on payment status changes - Fixed missing account balance updates for paid payments - Prevented duplicate balance deductions on re-saves - Corrected menu structure and admin function placement
456 lines
23 KiB
HTML
456 lines
23 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}{{ title }} - Foundation Management System{% endblock %}
|
|
|
|
{% block content %}
|
|
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card shadow">
|
|
<div class="card-body text-center py-5">
|
|
<!-- Logo Placeholder -->
|
|
<div class="mb-4">
|
|
<div class="logo-placeholder mx-auto mb-3" style="width: 150px; height: 150px; border: 3px dashed #dee2e6; border-radius: 50%; display: flex; align-items: center; justify-content: center; background-color: #f8f9fa;">
|
|
<div class="text-center text-muted">
|
|
<i class="fas fa-image fa-2x mb-2"></i>
|
|
<div style="font-size: 0.8rem;">Logo hier<br>einfügen</div>
|
|
</div>
|
|
</div>
|
|
<!-- Alternative: Replace above div with actual logo when available -->
|
|
<!-- <img src="{% load static %}{% static 'images/stiftung-logo.png' %}" alt="Stiftung Logo" class="img-fluid mb-3" style="max-height: 150px;"> -->
|
|
</div>
|
|
|
|
<h1 class="display-4 mb-4">
|
|
<i class="fas fa-landmark text-primary me-3"></i>van Hees-Theyssen-Vogel'sche Stiftung
|
|
</h1>
|
|
<p class="lead text-muted mb-5">Stiftungsverwaltung - Modern Foundation Management System</p>
|
|
<div class="row justify-content-center mb-4">
|
|
<div class="col-md-8">
|
|
<div class="card border-0 bg-light">
|
|
<div class="card-body text-center py-3">
|
|
<p class="mb-1"><i class="fas fa-map-marker-alt text-primary me-2"></i>Raesfelder Str. 3, 46499 Hamminkeln</p>
|
|
<p class="mb-0"><i class="fas fa-phone text-primary me-2"></i>+49 (0) 2852 12345</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row g-4 mb-5">
|
|
<div class="col-md-4">
|
|
<div class="card h-100 border-0 shadow-sm">
|
|
<div class="card-body text-center p-4">
|
|
<i class="fas fa-users fa-3x text-primary mb-3"></i>
|
|
<h5 class="card-title">👥 Destinatäre</h5>
|
|
<p class="card-text">Verwalten Sie Stiftungsmitglieder, Familienzweige und Kontaktdaten zentral und übersichtlich.</p>
|
|
<a href="{% url 'stiftung:destinataer_list' %}" class="btn btn-outline-primary btn-sm mt-2">
|
|
<i class="fas fa-external-link-alt me-1"></i>Öffnen
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-4">
|
|
<div class="card h-100 border-0 shadow-sm">
|
|
<div class="card-body text-center p-4">
|
|
<i class="fas fa-hand-holding-usd fa-3x text-success mb-3"></i>
|
|
<h5 class="card-title">💰 Unterstützungsverwaltung</h5>
|
|
<p class="card-text">Erfassen und verfolgen Sie Unterstützungen, Beträge und Verwendungsnachweise systematisch.</p>
|
|
<a href="{% url 'stiftung:unterstuetzungen_all' %}" class="btn btn-outline-success btn-sm mt-2">
|
|
<i class="fas fa-external-link-alt me-1"></i>Öffnen
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-4">
|
|
<div class="card h-100 border-0 shadow-sm">
|
|
<div class="card-body text-center p-4">
|
|
<i class="fas fa-file-alt fa-3x text-info mb-3"></i>
|
|
<h5 class="card-title">📄 Dokumentenverwaltung</h5>
|
|
<p class="card-text">Stiftungsdokumente und Verträge</p>
|
|
<a href="{% url 'stiftung:dokument_management' %}" class="btn btn-outline-info btn-sm mt-2">
|
|
<i class="fas fa-external-link-alt me-1"></i>Öffnen
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Calendar and Events Section -->
|
|
<div class="row g-4 mb-5">
|
|
<div class="col-lg-8">
|
|
<div class="card h-100 border-0 shadow-sm">
|
|
<div class="card-header bg-primary text-white">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-calendar-alt me-2"></i>Anstehende Termine & Ereignisse
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
{% if overdue_events %}
|
|
<div class="alert alert-danger" role="alert">
|
|
<h6><i class="fas fa-exclamation-triangle me-2"></i>Überfällige Termine ({{ overdue_events|length }})</h6>
|
|
{% for event in overdue_events %}
|
|
<div class="d-flex justify-content-between align-items-center border-bottom py-2">
|
|
<div>
|
|
<i class="{{ event.icon }} me-2"></i>
|
|
<strong>{{ event.title }}</strong>
|
|
<small class="text-muted d-block">{{ event.description }}</small>
|
|
</div>
|
|
<span class="badge bg-danger">{{ event.date }}</span>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if upcoming_events %}
|
|
<h6 class="text-muted mb-3">Nächste {{ upcoming_events|length }} Termine</h6>
|
|
{% for event in upcoming_events %}
|
|
<div class="d-flex justify-content-between align-items-center border-bottom py-2">
|
|
<div class="flex-grow-1">
|
|
<i class="{{ event.icon }} me-2 text-{{ event.color }}"></i>
|
|
<strong>{{ event.title }}</strong>
|
|
{% if event.description %}
|
|
<small class="text-muted d-block">{{ event.description }}</small>
|
|
{% endif %}
|
|
</div>
|
|
<div class="text-end">
|
|
<span class="badge bg-{{ event.color }}">{{ event.date }}</span>
|
|
{% if event.time %}
|
|
<small class="d-block text-muted">{{ event.time }}</small>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% empty %}
|
|
<div class="text-center py-4 text-muted">
|
|
<i class="fas fa-calendar-check fa-3x mb-3"></i>
|
|
<p>Keine anstehenden Termine in den nächsten 14 Tagen.</p>
|
|
</div>
|
|
{% endfor %}
|
|
|
|
<div class="text-center mt-3">
|
|
<a href="{% url 'stiftung:kalender' %}" class="btn btn-outline-primary btn-sm">
|
|
<i class="fas fa-calendar me-1"></i>Vollständigen Kalender anzeigen
|
|
</a>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-lg-4">
|
|
<!-- Mini Calendar -->
|
|
<div class="card border-0 shadow-sm mb-3">
|
|
<div class="card-header bg-info text-white">
|
|
<h6 class="mb-0">
|
|
<i class="fas fa-calendar me-2"></i>{{ today|date:"F Y" }}
|
|
</h6>
|
|
</div>
|
|
<div class="card-body p-2">
|
|
<div class="mini-calendar">
|
|
<!-- Calendar will be generated by JavaScript -->
|
|
<div id="mini-calendar" data-events="{{ current_month_events|length }}">
|
|
<!-- Mini calendar grid will be inserted here -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Quick Actions -->
|
|
<div class="card border-0 shadow-sm">
|
|
<div class="card-header bg-success text-white">
|
|
<h6 class="mb-0">
|
|
<i class="fas fa-plus me-2"></i>Schnellzugriff
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="d-grid gap-2">
|
|
<a href="{% url 'stiftung:kalender_create' %}" class="btn btn-outline-primary btn-sm">
|
|
<i class="fas fa-calendar-plus me-1"></i>Termin hinzufügen
|
|
</a>
|
|
<a href="{% url 'stiftung:unterstuetzung_create' %}" class="btn btn-outline-success btn-sm">
|
|
<i class="fas fa-euro-sign me-1"></i>Zahlung planen
|
|
</a>
|
|
<a href="{% url 'stiftung:destinataer_create' %}" class="btn btn-outline-info btn-sm">
|
|
<i class="fas fa-user-plus me-1"></i>Destinatär anlegen
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row g-4 mb-5">
|
|
<div class="col-md-4">
|
|
<div class="card h-100 border-0 shadow-sm">
|
|
<div class="card-body text-center p-4">
|
|
<i class="fas fa-chart-bar fa-3x text-warning mb-3"></i>
|
|
<h5 class="card-title">📊 Berichte & Auswertungen</h5>
|
|
<p class="card-text">Generieren Sie detaillierte Berichte und Auswertungen für Ihre Stiftungsarbeit.</p>
|
|
<a href="{% url 'stiftung:bericht_list' %}" class="btn btn-outline-warning btn-sm mt-2">
|
|
<i class="fas fa-external-link-alt me-1"></i>Öffnen
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-4">
|
|
<div class="card h-100 border-0 shadow-sm">
|
|
<div class="card-body text-center p-4">
|
|
<i class="fas fa-map fa-3x text-danger mb-3"></i>
|
|
<h5 class="card-title">🗺️ Ländereiverwaltung</h5>
|
|
<p class="card-text">Verwalten Sie Grundstücke, Flächen und Verpachtungen professionell.</p>
|
|
<a href="{% url 'stiftung:land_list' %}" class="btn btn-outline-danger btn-sm mt-2">
|
|
<i class="fas fa-external-link-alt me-1"></i>Öffnen
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-4">
|
|
<div class="card h-100 border-0 shadow-sm">
|
|
<div class="card-body text-center p-4">
|
|
<i class="fas fa-handshake fa-3x text-secondary mb-3"></i>
|
|
<h5 class="card-title">🤝 Verpachtungsverwaltung</h5>
|
|
<p class="card-text">Organisieren Sie Pachtverträge und deren Verwaltung effizient.</p>
|
|
<a href="{% url 'stiftung:verpachtung_list' %}" class="btn btn-outline-secondary btn-sm mt-2">
|
|
<i class="fas fa-external-link-alt me-1"></i>Öffnen
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row g-4 mb-5">
|
|
<div class="col-md-6">
|
|
<div class="card h-100 border-0 shadow-sm">
|
|
<div class="card-body text-center p-4">
|
|
<i class="fas fa-link fa-3x text-purple mb-3"></i>
|
|
<h5 class="card-title">🔗 Dokumentenverknüpfung</h5>
|
|
<p class="card-text">Verknüpfen Sie Paperless-Dokumente direkt mit Destinatären, Ländereien und Verpachtungen.</p>
|
|
<a href="{% url 'stiftung:dokument_management' %}" class="btn btn-outline-purple btn-sm mt-2">
|
|
<i class="fas fa-external-link-alt me-1"></i>Öffnen
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<div class="card h-100 border-0 shadow-sm">
|
|
<div class="card-body text-center p-4">
|
|
<i class="fas fa-database fa-3x text-dark mb-3"></i>
|
|
<h5 class="card-title">🗃️ Dokumentenarchiv</h5>
|
|
<p class="card-text">Zentraler Zugriff auf alle verknüpften Dokumente und deren Metadaten.</p>
|
|
<a href="{% url 'stiftung:dokument_list' %}" class="btn btn-outline-dark btn-sm mt-2">
|
|
<i class="fas fa-external-link-alt me-1"></i>Öffnen
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="d-flex justify-content-center gap-3 flex-wrap">
|
|
<a href="{% url 'stiftung:destinataer_list' %}" class="btn btn-primary btn-lg">
|
|
<i class="fas fa-users me-2"></i>Destinatäre
|
|
</a>
|
|
<a href="{% url 'stiftung:land_list' %}" class="btn btn-success btn-lg">
|
|
<i class="fas fa-map me-2"></i>Ländereien
|
|
</a>
|
|
<a href="{% url 'stiftung:paechter_list' %}" class="btn btn-info btn-lg">
|
|
<i class="fas fa-user-tie me-2"></i>Pächter
|
|
</a>
|
|
<a href="{% url 'stiftung:land_list' %}" class="btn btn-secondary btn-lg">
|
|
<i class="fas fa-handshake me-2"></i>Verpachtungen
|
|
</a>
|
|
<a href="{% url 'stiftung:foerderung_list' %}" class="btn btn-warning btn-lg">
|
|
<i class="fas fa-gift me-2"></i>Förderungen
|
|
</a>
|
|
</div>
|
|
|
|
<div class="d-flex justify-content-center gap-3 flex-wrap mt-3">
|
|
<a href="{% url 'stiftung:dokument_management' %}" class="btn btn-info btn-lg">
|
|
<i class="fas fa-file-alt me-2"></i>Paperless Integration
|
|
</a>
|
|
<a href="{% url 'stiftung:dokument_management' %}" class="btn btn-purple btn-lg">
|
|
<i class="fas fa-link me-2"></i>Dokumente verknüpfen
|
|
</a>
|
|
<a href="{% url 'stiftung:dokument_list' %}" class="btn btn-dark btn-lg">
|
|
<i class="fas fa-database me-2"></i>Dokumentenarchiv
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="text-center mt-4">
|
|
<div class="alert alert-success d-inline-block">
|
|
<i class="fas fa-check-circle me-2"></i>
|
|
<span class="fw-bold">System läuft erfolgreich</span>
|
|
<br>
|
|
<small class="text-muted">Entwickelt mit Django & Docker</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% endblock %}
|
|
|
|
{% block extra_css %}
|
|
<style>
|
|
.mini-calendar {
|
|
font-size: 0.8rem;
|
|
}
|
|
|
|
.mini-calendar .calendar-day {
|
|
width: 32px;
|
|
height: 32px;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin: 1px;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.mini-calendar .calendar-day.today {
|
|
background-color: var(--bs-primary);
|
|
color: white;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.mini-calendar .calendar-day.has-events {
|
|
background-color: var(--bs-success);
|
|
color: white;
|
|
}
|
|
|
|
.mini-calendar .calendar-day:hover {
|
|
background-color: var(--bs-light);
|
|
}
|
|
|
|
.mini-calendar .calendar-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.mini-calendar .calendar-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(7, 1fr);
|
|
gap: 1px;
|
|
text-align: center;
|
|
}
|
|
|
|
.mini-calendar .calendar-weekday {
|
|
font-weight: bold;
|
|
color: var(--bs-secondary);
|
|
padding: 4px;
|
|
font-size: 0.7rem;
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block extra_js %}
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Generate mini calendar for current month
|
|
const today = new Date();
|
|
const currentMonth = today.getMonth();
|
|
const currentYear = today.getFullYear();
|
|
|
|
function generateMiniCalendar(year, month) {
|
|
const firstDay = new Date(year, month, 1);
|
|
const lastDay = new Date(year, month + 1, 0);
|
|
const startDate = new Date(firstDay);
|
|
startDate.setDate(startDate.getDate() - firstDay.getDay()); // Start from Sunday
|
|
|
|
const calendarEl = document.getElementById('mini-calendar');
|
|
|
|
let html = '<div class="calendar-grid">';
|
|
|
|
// Weekday headers
|
|
const weekdays = ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'];
|
|
weekdays.forEach(day => {
|
|
html += `<div class="calendar-weekday">${day}</div>`;
|
|
});
|
|
|
|
// Generate calendar days
|
|
const currentDate = new Date(startDate);
|
|
for (let i = 0; i < 42; i++) { // 6 weeks
|
|
const isCurrentMonth = currentDate.getMonth() === month;
|
|
const isToday = currentDate.toDateString() === today.toDateString();
|
|
|
|
let classes = ['calendar-day'];
|
|
if (isToday) classes.push('today');
|
|
if (!isCurrentMonth) classes.push('text-muted');
|
|
|
|
html += `<div class="${classes.join(' ')}">${currentDate.getDate()}</div>`;
|
|
currentDate.setDate(currentDate.getDate() + 1);
|
|
|
|
if (currentDate > lastDay && currentDate.getDay() === 0) {
|
|
break; // Stop at end of month on Sunday
|
|
}
|
|
}
|
|
|
|
html += '</div>';
|
|
calendarEl.innerHTML = html;
|
|
}
|
|
|
|
// Generate the current month calendar
|
|
generateMiniCalendar(currentYear, currentMonth);
|
|
});
|
|
</script>
|
|
|
|
<style>
|
|
/* Mini Calendar Styles */
|
|
.mini-calendar .calendar-day {
|
|
width: 32px;
|
|
height: 32px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 0.8rem;
|
|
border-radius: 3px;
|
|
cursor: pointer;
|
|
transition: background-color 0.2s;
|
|
}
|
|
|
|
.mini-calendar .calendar-day:hover {
|
|
background-color: var(--bs-primary-bg-subtle);
|
|
}
|
|
|
|
.mini-calendar .calendar-day.today {
|
|
background-color: var(--bs-primary);
|
|
color: white;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.mini-calendar .calendar-header {
|
|
font-weight: 600;
|
|
color: var(--bs-secondary);
|
|
font-size: 0.75rem;
|
|
}
|
|
|
|
/* Calendar event indicators */
|
|
.calendar-events-indicator {
|
|
position: absolute;
|
|
bottom: 2px;
|
|
right: 2px;
|
|
width: 6px;
|
|
height: 6px;
|
|
background-color: var(--bs-warning);
|
|
border-radius: 50%;
|
|
}
|
|
|
|
/* Overdue events styling */
|
|
.alert-danger .border-bottom:last-child {
|
|
border-bottom: none !important;
|
|
}
|
|
|
|
/* Calendar card hover effects */
|
|
.card.border-left-primary { border-left-color: var(--bs-primary) !important; }
|
|
.card.border-left-success { border-left-color: var(--bs-success) !important; }
|
|
.card.border-left-warning { border-left-color: var(--bs-warning) !important; }
|
|
.card.border-left-danger { border-left-color: var(--bs-danger) !important; }
|
|
.card.border-left-info { border-left-color: var(--bs-info) !important; }
|
|
</style>
|
|
{% endblock %}
|