Files
stiftung-management-system/app/templates/stiftung/kalender/admin.html
Jan Remmer Siebels c289cc3c58 Fix payment system balance integration and add calendar functionality
- 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
2025-10-05 00:38:18 +02:00

346 lines
18 KiB
HTML

{% extends "base.html" %}
{% block title %}{{ title }}{% endblock %}
{% block content %}
<div class="container-fluid">
<!-- Header -->
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">
<i class="fas fa-cogs me-2"></i>{{ title }}
</h1>
<div class="d-flex gap-2">
<a href="{% url 'stiftung:kalender' %}" class="btn btn-secondary">
<i class="fas fa-arrow-left me-1"></i>Zurück zum Kalender
</a>
<a href="{% url 'stiftung:kalender_create' %}" class="btn btn-success">
<i class="fas fa-plus me-1"></i>Neuer Termin
</a>
</div>
</div>
<!-- Statistics Cards -->
<div class="row mb-4">
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-primary shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-primary text-uppercase mb-1">
Benutzerdefinierte Termine
</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">{{ stats.custom_count }}</div>
</div>
<div class="col-auto">
<i class="fas fa-calendar fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-success shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">
Zahlungsereignisse
</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">{{ stats.payment_events }}</div>
</div>
<div class="col-auto">
<i class="fas fa-euro-sign fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-info shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-info text-uppercase mb-1">
Pachtverträge
</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">{{ stats.lease_events }}</div>
</div>
<div class="col-auto">
<i class="fas fa-handshake fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-warning shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-warning text-uppercase mb-1">
Geburtstage
</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">{{ stats.birthday_events }}</div>
</div>
<div class="col-auto">
<i class="fas fa-birthday-cake fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Filter Controls -->
<div class="row">
<div class="col-12">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">
<i class="fas fa-filter me-2"></i>Ereignisquellen & Filter
</h6>
</div>
<div class="card-body">
<form method="get" class="row g-3">
<!-- Event Source Toggles -->
<div class="col-12">
<label class="form-label fw-bold">Ereignisquellen anzeigen:</label>
<div class="row">
<div class="col-md-3">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="show_custom"
name="show_custom" value="true"
{% if show_custom %}checked{% endif %}
onchange="this.form.submit()">
<label class="form-check-label" for="show_custom">
<i class="fas fa-calendar text-primary me-1"></i>Benutzerdefinierte Termine
</label>
</div>
</div>
<div class="col-md-3">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="show_payments"
name="show_payments" value="true"
{% if show_payments %}checked{% endif %}
onchange="this.form.submit()">
<label class="form-check-label" for="show_payments">
<i class="fas fa-euro-sign text-success me-1"></i>Zahlungserinnerungen
</label>
</div>
</div>
<div class="col-md-3">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="show_leases"
name="show_leases" value="true"
{% if show_leases %}checked{% endif %}
onchange="this.form.submit()">
<label class="form-check-label" for="show_leases">
<i class="fas fa-handshake text-info me-1"></i>Pachtverträge
</label>
</div>
</div>
<div class="col-md-3">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="show_birthdays"
name="show_birthdays" value="true"
{% if show_birthdays %}checked{% endif %}
onchange="this.form.submit()">
<label class="form-check-label" for="show_birthdays">
<i class="fas fa-birthday-cake text-warning me-1"></i>Geburtstage
</label>
</div>
</div>
</div>
</div>
<!-- Additional Filters -->
<div class="col-md-4">
<label for="category" class="form-label">Kategorie:</label>
<select class="form-control" id="category" name="category" onchange="this.form.submit()">
<option value="">Alle Kategorien</option>
{% for value, display in categories %}
<option value="{{ value }}" {% if category_filter == value %}selected{% endif %}>
{{ display }}
</option>
{% endfor %}
</select>
</div>
<div class="col-md-4">
<label for="priority" class="form-label">Priorität:</label>
<select class="form-control" id="priority" name="priority" onchange="this.form.submit()">
<option value="">Alle Prioritäten</option>
{% for value, display in priorities %}
<option value="{{ value }}" {% if priority_filter == value %}selected{% endif %}>
{{ display }}
</option>
{% endfor %}
</select>
</div>
<div class="col-md-4">
<label class="form-label">&nbsp;</label>
<div>
<button type="submit" class="btn btn-primary">
<i class="fas fa-search me-1"></i>Filter anwenden
</button>
<a href="{% url 'stiftung:kalender_admin' %}" class="btn btn-outline-secondary">
<i class="fas fa-undo me-1"></i>Zurücksetzen
</a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Events Table -->
<div class="row">
<div class="col-12">
<div class="card shadow">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">
<i class="fas fa-list me-2"></i>Ereignisse ({{ stats.total_events }} Einträge)
</h6>
</div>
<div class="card-body">
{% if events %}
<div class="table-responsive">
<table class="table table-bordered" id="eventsTable">
<thead>
<tr>
<th>Datum</th>
<th>Titel</th>
<th>Kategorie</th>
<th>Priorität</th>
<th>Quelle</th>
<th>Status</th>
<th>Aktionen</th>
</tr>
</thead>
<tbody>
{% for event in events %}
<tr>
<td>
<strong>{{ event.date|date:"d.m.Y" }}</strong>
{% if event.time %}
<br><small class="text-muted">{{ event.time|time:"H:i" }}</small>
{% endif %}
</td>
<td>
<i class="{{ event.icon }} me-2"></i>{{ event.title }}
{% if event.description %}
<br><small class="text-muted">{{ event.description|truncatechars:50 }}</small>
{% endif %}
</td>
<td>
<span class="badge bg-secondary">{{ event.category_display }}</span>
</td>
<td>
<span class="badge bg-{% if event.priority == 'hoch' %}danger{% elif event.priority == 'mittel' %}warning{% else %}secondary{% endif %}">
{% if event.priority == 'hoch' %}
<i class="fas fa-exclamation-triangle me-1"></i>
{% elif event.priority == 'mittel' %}
<i class="fas fa-exclamation-circle me-1"></i>
{% else %}
<i class="fas fa-info-circle me-1"></i>
{% endif %}
{{ event.priority_display|default:"Normal" }}
</span>
</td>
<td>
{% if event.source == 'custom' %}
<span class="badge bg-primary">Benutzerdefiniert</span>
{% elif event.source == 'payment' %}
<span class="badge bg-success">Zahlung</span>
{% elif event.source == 'lease' %}
<span class="badge bg-info">Pacht</span>
{% elif event.source == 'birthday' %}
<span class="badge bg-warning">Geburtstag</span>
{% else %}
<span class="badge bg-secondary">System</span>
{% endif %}
</td>
<td>
{% if event.source == 'custom' %}
{% if event.completed %}
<span class="badge bg-success">
<i class="fas fa-check me-1"></i>Erledigt
</span>
{% else %}
<span class="badge bg-warning">
<i class="fas fa-clock me-1"></i>Ausstehend
</span>
{% endif %}
{% else %}
<span class="badge bg-light text-dark">
<i class="fas fa-robot me-1"></i>Automatisch
</span>
{% endif %}
</td>
<td>
{% if event.source == 'custom' and event.id %}
<div class="btn-group btn-group-sm">
<a href="{% url 'stiftung:kalender_detail' event.id %}"
class="btn btn-outline-primary btn-sm" title="Details">
<i class="fas fa-eye"></i>
</a>
<a href="{% url 'stiftung:kalender_edit' event.id %}"
class="btn btn-outline-secondary btn-sm" title="Bearbeiten">
<i class="fas fa-edit"></i>
</a>
<a href="{% url 'stiftung:kalender_delete' event.id %}"
class="btn btn-outline-danger btn-sm" title="Löschen">
<i class="fas fa-trash"></i>
</a>
</div>
{% else %}
<span class="text-muted small">
<i class="fas fa-lock me-1"></i>Systemereignis
</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="text-center py-5">
<i class="fas fa-calendar-times fa-3x text-muted mb-3"></i>
<h5 class="text-muted">Keine Ereignisse gefunden</h5>
<p class="text-muted">
Aktivieren Sie Ereignisquellen oder fügen Sie neue Termine hinzu.
</p>
<a href="{% url 'stiftung:kalender_create' %}" class="btn btn-primary">
<i class="fas fa-plus me-1"></i>Neuen Termin hinzufügen
</a>
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
<style>
.border-left-primary { border-left: 0.25rem solid #4e73df !important; }
.border-left-success { border-left: 0.25rem solid #1cc88a !important; }
.border-left-info { border-left: 0.25rem solid #36b9cc !important; }
.border-left-warning { border-left: 0.25rem solid #f6c23e !important; }
.form-switch .form-check-input {
width: 2rem;
height: 1rem;
}
#eventsTable th {
background-color: #f8f9fc;
border-top: none;
}
</style>
{% endblock %}