Generalize email system with invoice workflow and Stiftungsgeschichte category
- Rename DestinataerEmailEingang → EmailEingang with category support (destinataer, rechnung, land_pacht, stiftungsgeschichte, allgemein) - Add invoice capture workflow: create Verwaltungskosten from email, link DMS documents as invoice attachments, track payment status - Add Stiftungsgeschichte email category with auto-detection patterns (Ahnenforschung, Genealogie, Chronik, etc.) and DMS integration - Update poll_emails task with category detection and DMS context mapping - Show available history documents in Geschichte editor sidebar - Consolidate DMS views, remove legacy dokument templates - Update all detail/form templates for DMS document linking - Add deploy.sh script and streamline compose.yml Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load humanize %}
|
||||
|
||||
{% block title %}E-Mail-Eingang (Destinatäre) - van Hees-Theyssen-Vogel'sche Stiftung{% endblock %}
|
||||
{% block title %}E-Mail-Eingang - Stiftungsverwaltung{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<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-envelope-open-text me-2"></i>E-Mail-Eingang (Destinatäre)
|
||||
<i class="fas fa-envelope-open-text me-2"></i>E-Mail-Eingang
|
||||
</h1>
|
||||
<div class="d-flex gap-2">
|
||||
<form method="post" action="{% url 'stiftung:email_eingang_poll_trigger' %}" class="d-inline">
|
||||
@@ -17,79 +17,65 @@
|
||||
<i class="fas fa-sync-alt me-1"></i>Jetzt abrufen
|
||||
</button>
|
||||
</form>
|
||||
<a href="{% url 'stiftung:destinataer_list' %}" class="btn btn-outline-secondary btn-sm">
|
||||
<i class="fas fa-arrow-left me-1"></i>Destinatäre
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Statuskarten -->
|
||||
{# Statuskarten #}
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-3">
|
||||
<div class="col-md-3 col-6 mb-2">
|
||||
<div class="card border-left-primary 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">Gesamt</div>
|
||||
<div class="h5 mb-0 font-weight-bold text-gray-800">{{ counts.gesamt }}</div>
|
||||
</div>
|
||||
<div class="col-auto"><i class="fas fa-envelope fa-2x text-gray-300"></i></div>
|
||||
</div>
|
||||
<div class="text-xs font-weight-bold text-primary text-uppercase mb-1">Gesamt</div>
|
||||
<div class="h5 mb-0 font-weight-bold">{{ counts.gesamt }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="col-md-3 col-6 mb-2">
|
||||
<div class="card border-left-warning 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">Neu / Unbearbeitet</div>
|
||||
<div class="h5 mb-0 font-weight-bold text-gray-800">{{ counts.neu }}</div>
|
||||
</div>
|
||||
<div class="col-auto"><i class="fas fa-exclamation-circle fa-2x text-gray-300"></i></div>
|
||||
</div>
|
||||
<div class="text-xs font-weight-bold text-warning text-uppercase mb-1">Neu</div>
|
||||
<div class="h5 mb-0 font-weight-bold">{{ counts.neu }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="col-md-3 col-6 mb-2">
|
||||
<div class="card border-left-info h-100 py-2">
|
||||
<div class="card-body">
|
||||
<div class="text-xs font-weight-bold text-info text-uppercase mb-1">Rechnungen</div>
|
||||
<div class="h5 mb-0 font-weight-bold">{{ counts.rechnung }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 col-6 mb-2">
|
||||
<div class="card border-left-danger 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-danger text-uppercase mb-1">Unbekannter Absender</div>
|
||||
<div class="h5 mb-0 font-weight-bold text-gray-800">{{ counts.unbekannt }}</div>
|
||||
</div>
|
||||
<div class="col-auto"><i class="fas fa-user-times fa-2x text-gray-300"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card border-left-secondary 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-secondary text-uppercase mb-1">Fehler</div>
|
||||
<div class="h5 mb-0 font-weight-bold text-gray-800">{{ counts.fehler }}</div>
|
||||
</div>
|
||||
<div class="col-auto"><i class="fas fa-exclamation-triangle fa-2x text-gray-300"></i></div>
|
||||
</div>
|
||||
<div class="text-xs font-weight-bold text-danger text-uppercase mb-1">Unbekannt</div>
|
||||
<div class="h5 mb-0 font-weight-bold">{{ counts.unbekannt }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filter -->
|
||||
{# Filter #}
|
||||
<div class="card mb-4">
|
||||
<div class="card-header"><i class="fas fa-filter me-2"></i>Filter</div>
|
||||
<div class="card-body">
|
||||
<form method="get" class="row g-3">
|
||||
<div class="col-md-4">
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">Suche</label>
|
||||
<input type="text" class="form-control" name="q" value="{{ search }}"
|
||||
placeholder="Absender, Betreff, Destinatär...">
|
||||
placeholder="Absender, Betreff...">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">Kategorie</label>
|
||||
<select class="form-select" name="kategorie">
|
||||
<option value="">Alle</option>
|
||||
{% for value, label in kategorie_choices %}
|
||||
<option value="{{ value }}" {% if kategorie_filter == value %}selected{% endif %}>{{ label }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">Status</label>
|
||||
@@ -100,15 +86,15 @@
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2 d-flex align-items-end">
|
||||
<div class="col-md-1 d-flex align-items-end">
|
||||
<button type="submit" class="btn btn-primary w-100">
|
||||
<i class="fas fa-search me-1"></i>Filtern
|
||||
<i class="fas fa-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
{% if search or status_filter %}
|
||||
{% if search or status_filter or kategorie_filter %}
|
||||
<div class="col-md-2 d-flex align-items-end">
|
||||
<a href="{% url 'stiftung:email_eingang_list' %}" class="btn btn-outline-secondary w-100">
|
||||
<i class="fas fa-times me-1"></i>Zurücksetzen
|
||||
<i class="fas fa-times me-1"></i>Reset
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -116,11 +102,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tabelle -->
|
||||
{# Tabelle #}
|
||||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<span><i class="fas fa-inbox me-2"></i>Eingegangene E-Mails</span>
|
||||
<span class="text-muted small">{{ page_obj.paginator.count }} Einträge</span>
|
||||
<span class="text-muted small">{{ page_obj.paginator.count }} Eintraege</span>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
{% if page_obj %}
|
||||
@@ -130,9 +116,9 @@
|
||||
<tr>
|
||||
<th>Datum</th>
|
||||
<th>Absender</th>
|
||||
<th>Destinatär</th>
|
||||
<th>Betreff</th>
|
||||
<th>Anhänge</th>
|
||||
<th>Kategorie</th>
|
||||
<th>Zuordnung</th>
|
||||
<th>Status</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
@@ -149,19 +135,27 @@
|
||||
<small class="text-muted">{{ e.absender_email }}</small>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ e.betreff|truncatechars:50 }}</td>
|
||||
<td>
|
||||
{% if e.destinataer %}
|
||||
<a href="{% url 'stiftung:destinataer_detail' e.destinataer.pk %}">
|
||||
{{ e.destinataer }}
|
||||
</a>
|
||||
{% if e.kategorie == "rechnung" %}
|
||||
<span class="badge bg-warning text-dark"><i class="fas fa-file-invoice me-1"></i>Rechnung</span>
|
||||
{% elif e.kategorie == "destinataer" %}
|
||||
<span class="badge bg-info"><i class="fas fa-user me-1"></i>Destinataer</span>
|
||||
{% elif e.kategorie == "land_pacht" %}
|
||||
<span class="badge bg-success"><i class="fas fa-map me-1"></i>Land/Pacht</span>
|
||||
{% elif e.kategorie == "stiftungsgeschichte" %}
|
||||
<span class="badge bg-dark"><i class="fas fa-landmark me-1"></i>Geschichte</span>
|
||||
{% else %}
|
||||
<span class="text-danger"><i class="fas fa-question-circle me-1"></i>Unbekannt</span>
|
||||
<span class="badge bg-secondary">Allgemein</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ e.betreff|truncatechars:60 }}</td>
|
||||
<td class="text-center">
|
||||
{% if e.paperless_dokument_ids %}
|
||||
<span class="badge bg-info">{{ e.paperless_dokument_ids|length }}</span>
|
||||
<td>
|
||||
{% if e.destinataer %}
|
||||
<a href="{% url 'stiftung:destinataer_detail' e.destinataer.pk %}" class="text-decoration-none">
|
||||
{{ e.destinataer }}
|
||||
</a>
|
||||
{% elif e.verwaltungskosten %}
|
||||
<span class="text-info"><i class="fas fa-file-invoice-dollar me-1"></i>{{ e.verwaltungskosten.bezeichnung|truncatechars:30 }}</span>
|
||||
{% else %}
|
||||
<span class="text-muted">–</span>
|
||||
{% endif %}
|
||||
@@ -173,6 +167,10 @@
|
||||
<span class="badge bg-primary">Zugewiesen</span>
|
||||
{% elif e.status == "verarbeitet" %}
|
||||
<span class="badge bg-success">Verarbeitet</span>
|
||||
{% elif e.status == "rechnung_erfasst" %}
|
||||
<span class="badge bg-info">Rechnung erfasst</span>
|
||||
{% elif e.status == "zahlung_gebucht" %}
|
||||
<span class="badge bg-success">Bezahlt</span>
|
||||
{% elif e.status == "unbekannt" %}
|
||||
<span class="badge bg-danger">Unbekannt</span>
|
||||
{% elif e.status == "fehler" %}
|
||||
@@ -180,18 +178,9 @@
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group btn-group-sm">
|
||||
<a href="{% url 'stiftung:email_eingang_detail' e.pk %}" class="btn btn-outline-primary" title="Details">
|
||||
<i class="fas fa-eye"></i>
|
||||
</a>
|
||||
<form method="post" action="{% url 'stiftung:email_eingang_delete' e.pk %}" class="d-inline"
|
||||
onsubmit="return confirm('E-Mail wirklich löschen?');">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-outline-danger" title="Löschen">
|
||||
<i class="fas fa-trash-alt"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<a href="{% url 'stiftung:email_eingang_detail' e.pk %}" class="btn btn-sm btn-outline-primary" title="Details">
|
||||
<i class="fas fa-eye"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
@@ -199,14 +188,14 @@
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
{# Pagination #}
|
||||
{% if page_obj.has_other_pages %}
|
||||
<div class="d-flex justify-content-center py-3">
|
||||
<nav>
|
||||
<ul class="pagination mb-0">
|
||||
{% if page_obj.has_previous %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.previous_page_number }}&q={{ search }}&status={{ status_filter }}">
|
||||
<a class="page-link" href="?page={{ page_obj.previous_page_number }}&q={{ search }}&status={{ status_filter }}&kategorie={{ kategorie_filter }}">
|
||||
«
|
||||
</a>
|
||||
</li>
|
||||
@@ -216,7 +205,7 @@
|
||||
</li>
|
||||
{% if page_obj.has_next %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.next_page_number }}&q={{ search }}&status={{ status_filter }}">
|
||||
<a class="page-link" href="?page={{ page_obj.next_page_number }}&q={{ search }}&status={{ status_filter }}&kategorie={{ kategorie_filter }}">
|
||||
»
|
||||
</a>
|
||||
</li>
|
||||
@@ -230,7 +219,7 @@
|
||||
<div class="text-center py-5 text-muted">
|
||||
<i class="fas fa-inbox fa-3x mb-3"></i>
|
||||
<p>Keine E-Mails gefunden.</p>
|
||||
<small>Der automatische Abruf erfolgt alle 15 Minuten. Über den Button "Jetzt abrufen" kann der Vorgang manuell ausgelöst werden.</small>
|
||||
<small>Der automatische Abruf erfolgt alle 15 Minuten.</small>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user