- 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
337 lines
12 KiB
HTML
337 lines
12 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}{{ title }}{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container-fluid">
|
|
<!-- Calendar Header with View Controls -->
|
|
<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-list me-2"></i>{{ title }}
|
|
</h1>
|
|
<div class="d-flex gap-2">
|
|
<!-- View Type Buttons -->
|
|
<div class="btn-group" role="group">
|
|
<a href="?view=month&year={{ year }}&month={{ month }}"
|
|
class="btn btn-sm btn-outline-primary">
|
|
<i class="fas fa-calendar me-1"></i>Monat
|
|
</a>
|
|
<a href="?view=week"
|
|
class="btn btn-sm btn-outline-primary">
|
|
<i class="fas fa-calendar-week me-1"></i>Woche
|
|
</a>
|
|
<a href="?view=agenda"
|
|
class="btn btn-sm btn-primary">
|
|
<i class="fas fa-list me-1"></i>Agenda
|
|
</a>
|
|
<a href="?view=list"
|
|
class="btn btn-sm btn-outline-primary">
|
|
<i class="fas fa-list-ul me-1"></i>Liste
|
|
</a>
|
|
</div>
|
|
|
|
<a href="{% url 'stiftung:kalender_create' %}" class="btn btn-success">
|
|
<i class="fas fa-plus me-1"></i>Neuer Termin
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Agenda View -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card shadow">
|
|
<div class="card-header">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<h6 class="mb-0">
|
|
<i class="fas fa-clock me-2"></i>Agenda - Chronologische Übersicht
|
|
</h6>
|
|
<div class="btn-group btn-group-sm">
|
|
<!-- Date range filters -->
|
|
<div class="dropdown">
|
|
<button class="btn btn-outline-secondary dropdown-toggle" type="button"
|
|
id="dateRangeDropdown" data-bs-toggle="dropdown">
|
|
Zeitraum
|
|
</button>
|
|
<ul class="dropdown-menu">
|
|
<li><a class="dropdown-item" href="?view=agenda&range=today">Heute</a></li>
|
|
<li><a class="dropdown-item" href="?view=agenda&range=week">Diese Woche</a></li>
|
|
<li><a class="dropdown-item" href="?view=agenda&range=month">Dieser Monat</a></li>
|
|
<li><a class="dropdown-item" href="?view=agenda&range=3months">Nächste 3 Monate</a></li>
|
|
<li><a class="dropdown-item" href="?view=agenda">Alle</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="card-body p-0">
|
|
{% if events %}
|
|
<div class="agenda-timeline">
|
|
{% regroup events by date as events_by_date %}
|
|
{% for date_group in events_by_date %}
|
|
<div class="timeline-date-group">
|
|
<div class="date-divider">
|
|
<div class="date-line"></div>
|
|
<div class="date-badge {% if date_group.grouper == today %}today{% elif date_group.grouper < today %}past{% endif %}">
|
|
<div class="date-day">{{ date_group.grouper|date:"d" }}</div>
|
|
<div class="date-month-year">
|
|
{{ date_group.grouper|date:"M Y" }}
|
|
</div>
|
|
<div class="date-weekday">{{ date_group.grouper|date:"l" }}</div>
|
|
</div>
|
|
<div class="date-line"></div>
|
|
</div>
|
|
|
|
<div class="events-for-date">
|
|
{% for event in date_group.list %}
|
|
<div class="timeline-event event-{{ event.category }} {% if event.priority == 'hoch' %}high-priority{% elif event.priority == 'mittel' %}medium-priority{% endif %}">
|
|
<div class="event-time-indicator">
|
|
{% if event.time %}
|
|
<div class="event-time">{{ event.time|time:"H:i" }}</div>
|
|
{% else %}
|
|
<div class="event-time all-day">
|
|
<i class="fas fa-clock"></i>
|
|
<span>ganztags</span>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div class="event-content">
|
|
<div class="event-header">
|
|
<h6 class="event-title mb-1">
|
|
<i class="{{ event.icon }} me-2"></i>{{ event.title }}
|
|
{% if event.priority == 'hoch' %}
|
|
<span class="badge bg-danger ms-2">
|
|
<i class="fas fa-exclamation-triangle"></i>
|
|
</span>
|
|
{% endif %}
|
|
</h6>
|
|
<div class="event-meta">
|
|
<span class="badge bg-secondary me-2">{{ event.category_display }}</span>
|
|
{% if event.destinataer %}
|
|
<span class="badge bg-info">
|
|
<i class="fas fa-user me-1"></i>{{ event.destinataer }}
|
|
</span>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
{% if event.description %}
|
|
<div class="event-description">
|
|
{{ event.description }}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if event.location %}
|
|
<div class="event-location">
|
|
<i class="fas fa-map-marker-alt me-1"></i>{{ event.location }}
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="event-actions">
|
|
<a href="{% url 'stiftung:kalender_detail' event.id %}"
|
|
class="btn btn-sm btn-outline-primary">
|
|
<i class="fas fa-eye me-1"></i>Details
|
|
</a>
|
|
<a href="{% url 'stiftung:kalender_edit' event.id %}"
|
|
class="btn btn-sm btn-outline-secondary">
|
|
<i class="fas fa-edit me-1"></i>Bearbeiten
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</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 Termine gefunden</h5>
|
|
<p class="text-muted">Fügen Sie einen neuen Termin hinzu oder erweitern Sie den Zeitraum.</p>
|
|
<a href="{% url 'stiftung:kalender_create' %}" class="btn btn-primary">
|
|
<i class="fas fa-plus me-1"></i>Termin hinzufügen
|
|
</a>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.agenda-timeline {
|
|
padding: 20px;
|
|
}
|
|
|
|
.timeline-date-group {
|
|
margin-bottom: 40px;
|
|
}
|
|
|
|
.date-divider {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.date-line {
|
|
flex: 1;
|
|
height: 2px;
|
|
background: linear-gradient(to right, transparent, #dee2e6, transparent);
|
|
}
|
|
|
|
.date-badge {
|
|
background: white;
|
|
border: 2px solid #dee2e6;
|
|
border-radius: 15px;
|
|
padding: 15px 25px;
|
|
text-align: center;
|
|
margin: 0 20px;
|
|
min-width: 120px;
|
|
}
|
|
|
|
.date-badge.today {
|
|
background: #e3f2fd;
|
|
border-color: #2196f3;
|
|
color: #1976d2;
|
|
}
|
|
|
|
.date-badge.past {
|
|
background: #f5f5f5;
|
|
border-color: #bdbdbd;
|
|
color: #757575;
|
|
}
|
|
|
|
.date-day {
|
|
font-size: 2rem;
|
|
font-weight: bold;
|
|
line-height: 1;
|
|
}
|
|
|
|
.date-month-year {
|
|
font-size: 0.9rem;
|
|
font-weight: 600;
|
|
margin: 5px 0;
|
|
}
|
|
|
|
.date-weekday {
|
|
font-size: 0.8rem;
|
|
text-transform: uppercase;
|
|
opacity: 0.7;
|
|
}
|
|
|
|
.events-for-date {
|
|
padding-left: 40px;
|
|
}
|
|
|
|
.timeline-event {
|
|
display: flex;
|
|
margin-bottom: 20px;
|
|
border-left: 4px solid;
|
|
border-radius: 8px;
|
|
background: white;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.timeline-event:hover {
|
|
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
|
transform: translateX(5px);
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.timeline-event.high-priority {
|
|
box-shadow: 0 2px 8px rgba(244, 67, 54, 0.3);
|
|
}
|
|
|
|
.event-time-indicator {
|
|
background: #f8f9fa;
|
|
padding: 20px 15px;
|
|
min-width: 120px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-right: 1px solid #dee2e6;
|
|
}
|
|
|
|
.event-time {
|
|
font-size: 1.2rem;
|
|
font-weight: bold;
|
|
color: #495057;
|
|
}
|
|
|
|
.event-time.all-day {
|
|
font-size: 0.9rem;
|
|
text-align: center;
|
|
color: #6c757d;
|
|
}
|
|
|
|
.event-time.all-day i {
|
|
display: block;
|
|
margin-bottom: 5px;
|
|
}
|
|
|
|
.event-content {
|
|
flex: 1;
|
|
padding: 20px;
|
|
}
|
|
|
|
.event-title {
|
|
color: #343a40;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.event-meta {
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.event-description {
|
|
color: #6c757d;
|
|
margin-bottom: 12px;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.event-location {
|
|
color: #6c757d;
|
|
margin-bottom: 15px;
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.event-actions {
|
|
display: flex;
|
|
gap: 8px;
|
|
}
|
|
|
|
/* Event category colors */
|
|
.event-termin { border-left-color: #2196f3; }
|
|
.event-zahlung { border-left-color: #ff9800; }
|
|
.event-deadline { border-left-color: #f44336; }
|
|
.event-geburtstag { border-left-color: #4caf50; }
|
|
.event-vertrag { border-left-color: #9c27b0; }
|
|
.event-pruefung { border-left-color: #009688; }
|
|
|
|
@media (max-width: 768px) {
|
|
.timeline-event {
|
|
flex-direction: column;
|
|
}
|
|
|
|
.event-time-indicator {
|
|
min-width: auto;
|
|
padding: 15px;
|
|
border-right: none;
|
|
border-bottom: 1px solid #dee2e6;
|
|
}
|
|
|
|
.events-for-date {
|
|
padding-left: 20px;
|
|
}
|
|
|
|
.date-badge {
|
|
margin: 0 10px;
|
|
min-width: 100px;
|
|
padding: 10px 15px;
|
|
}
|
|
}
|
|
</style>
|
|
{% endblock %} |