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:
@@ -657,11 +657,7 @@
|
||||
<div class="sidebar-heading">Dokumente</div>
|
||||
<a class="sidebar-link" href="{% url 'stiftung:dms_list' %}">
|
||||
<i class="fas fa-folder-open"></i>
|
||||
<span>DMS</span>
|
||||
</a>
|
||||
<a class="sidebar-link" href="{% url 'stiftung:dokument_management' %}">
|
||||
<i class="fas fa-archive"></i>
|
||||
<span>Paperless (Legacy)</span>
|
||||
<span>Dokumente</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -260,7 +260,7 @@
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<a href="{% url 'stiftung:dokument_management' %}" class="btn btn-outline-secondary w-100">
|
||||
<a href="{% url 'stiftung:dms_list' %}" class="btn btn-outline-secondary w-100">
|
||||
<i class="fas fa-folder-open d-block mb-2 fa-2x"></i>
|
||||
<span>Dokumentenverwaltung</span>
|
||||
</a>
|
||||
|
||||
@@ -622,8 +622,8 @@
|
||||
{# ════════ TAB: Dokumente ════════ #}
|
||||
<div class="tab-pane fade" id="pane-dokumente" role="tabpanel">
|
||||
<div class="d-flex justify-content-end mb-3">
|
||||
<a href="{% url 'stiftung:dokument_management' %}" class="btn btn-success btn-sm">
|
||||
<i class="fas fa-plus me-1"></i>Dokument verknuepfen
|
||||
<a href="{% url 'stiftung:dms_upload' %}?destinataer={{ destinataer.pk }}" class="btn btn-success btn-sm">
|
||||
<i class="fas fa-upload me-1"></i>Dokument hochladen
|
||||
</a>
|
||||
</div>
|
||||
{% if verknuepfte_dokumente %}
|
||||
@@ -635,14 +635,17 @@
|
||||
<tbody>
|
||||
{% for d in verknuepfte_dokumente %}
|
||||
<tr>
|
||||
<td><strong>{{ d.titel }}</strong><br><small class="text-muted">ID: {{ d.paperless_document_id }}</small></td>
|
||||
<td>
|
||||
<strong>{{ d.titel }}</strong>
|
||||
{% if d.dateiname_original %}<br><small class="text-muted">{{ d.dateiname_original }} ({{ d.get_human_size }})</small>{% endif %}
|
||||
</td>
|
||||
<td><span class="badge bg-secondary">{{ d.get_kontext_display }}</span></td>
|
||||
<td>{{ d.beschreibung|default:"-"|truncatewords:10 }}</td>
|
||||
<td>
|
||||
<div class="btn-group btn-group-sm">
|
||||
<a href="{{ d.get_paperless_url }}" target="_blank" class="btn btn-outline-primary" title="In Paperless oeffnen"><i class="fas fa-external-link-alt"></i></a>
|
||||
<a href="{% url 'stiftung:dokument_update' d.pk %}" class="btn btn-outline-warning" title="Bearbeiten"><i class="fas fa-edit"></i></a>
|
||||
<a href="{% url 'stiftung:dokument_delete' d.pk %}" class="btn btn-outline-danger" title="Loeschen"><i class="fas fa-unlink"></i></a>
|
||||
<a href="{% url 'stiftung:dms_download' d.pk %}" class="btn btn-outline-primary" title="Herunterladen"><i class="fas fa-download"></i></a>
|
||||
<a href="{% url 'stiftung:dms_edit' d.pk %}" class="btn btn-outline-warning" title="Bearbeiten"><i class="fas fa-edit"></i></a>
|
||||
<a href="{% url 'stiftung:dms_delete' d.pk %}" class="btn btn-outline-danger" title="Loeschen"><i class="fas fa-trash"></i></a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -653,7 +656,7 @@
|
||||
{% else %}
|
||||
<div class="text-center py-4 text-muted">
|
||||
<i class="fas fa-file-alt fa-2x mb-2"></i>
|
||||
<p>Keine Dokumente verknuepft.</p>
|
||||
<p>Keine Dokumente vorhanden.</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
<form method="post" enctype="multipart/form-data" id="upload-form">
|
||||
{% csrf_token %}
|
||||
{% if initial.foerderung_id %}<input type="hidden" name="foerderung_id" value="{{ initial.foerderung_id }}">{% endif %}
|
||||
{% if initial.verpachtung_id %}<input type="hidden" name="verpachtung_id" value="{{ initial.verpachtung_id }}">{% endif %}
|
||||
|
||||
<!-- Drag & Drop Zone -->
|
||||
<div class="card shadow mb-4">
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block title %}Dokument löschen - Stiftungsverwaltung{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-6 mx-auto">
|
||||
<div class="card shadow">
|
||||
<div class="card-header bg-danger text-white">
|
||||
<h4 class="mb-0">
|
||||
<i class="fas fa-exclamation-triangle me-2"></i>Dokument löschen
|
||||
</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="alert alert-warning">
|
||||
<h5 class="alert-heading">
|
||||
<i class="fas fa-exclamation-triangle me-2"></i>Warnung!
|
||||
</h5>
|
||||
<p class="mb-0">
|
||||
Sind Sie sicher, dass Sie das Dokument <strong>{{ dokument.titel }}</strong> löschen möchten?
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title">Dokumentdetails:</h6>
|
||||
<p class="card-text">
|
||||
<strong>Titel:</strong> {{ dokument.titel }}<br>
|
||||
<strong>Kontext:</strong> {{ dokument.get_kontext_display }}<br>
|
||||
<strong>Paperless ID:</strong> {{ dokument.paperless_document_id }}<br>
|
||||
{% if dokument.beschreibung %}
|
||||
<strong>Beschreibung:</strong> {{ dokument.beschreibung }}
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-info">
|
||||
<h6 class="alert-heading">
|
||||
<i class="fas fa-info-circle me-2"></i>Wichtiger Hinweis
|
||||
</h6>
|
||||
<p class="mb-0">
|
||||
Diese Aktion kann nicht rückgängig gemacht werden. Alle zugehörigen Verknüpfungen werden ebenfalls gelöscht.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<div class="d-flex justify-content-between">
|
||||
<a href="{% url 'stiftung:dokument_detail' dokument.pk %}" class="btn btn-secondary">
|
||||
<i class="fas fa-arrow-left me-2"></i>Abbrechen
|
||||
</a>
|
||||
<button type="submit" class="btn btn-danger">
|
||||
<i class="fas fa-trash me-2"></i>Endgültig löschen
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -1,168 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block title %}{{ title }} - Stiftungsverwaltung{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<!-- Header -->
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1 class="h3">
|
||||
<i class="fas fa-file-alt text-primary me-2"></i>{{ title }}
|
||||
</h1>
|
||||
<div class="btn-group" role="group">
|
||||
<a href="{% url 'stiftung:dokument_update' dokument.pk %}" class="btn btn-warning">
|
||||
<i class="fas fa-edit me-2"></i>Bearbeiten
|
||||
</a>
|
||||
<a href="{% url 'stiftung:dokument_delete' dokument.pk %}" class="btn btn-danger">
|
||||
<i class="fas fa-trash me-2"></i>Löschen
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<!-- Main Information -->
|
||||
<div class="col-lg-8">
|
||||
<!-- Dokument Details -->
|
||||
<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-info-circle me-2"></i>Dokumentdetails
|
||||
</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h6 class="text-primary">Titel</h6>
|
||||
<p class="mb-3">{{ dokument.titel }}</p>
|
||||
|
||||
<h6 class="text-primary">Kontext</h6>
|
||||
<p class="mb-3">
|
||||
<span class="badge bg-secondary">{{ dokument.get_kontext_display }}</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h6 class="text-primary">Paperless ID</h6>
|
||||
<p class="mb-3">
|
||||
<code>{{ dokument.paperless_document_id }}</code>
|
||||
</p>
|
||||
|
||||
<h6 class="text-primary">Erstellt</h6>
|
||||
<p class="mb-3">{{ dokument.id }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if dokument.beschreibung %}
|
||||
<hr class="my-3">
|
||||
<h6 class="text-primary">Beschreibung</h6>
|
||||
<p class="mb-0">{{ dokument.beschreibung }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Verknüpfungen -->
|
||||
<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-link me-2"></i>Verknüpfungen
|
||||
</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if dokument.foerderung_set.exists or dokument.verpachtung_set.exists %}
|
||||
{% if dokument.foerderung_set.exists %}
|
||||
<h6 class="text-primary">Förderungen</h6>
|
||||
<div class="list-group list-group-flush mb-3">
|
||||
{% for foerderung in dokument.foerderung_set.all %}
|
||||
<div class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<strong>{{ foerderung.person.get_full_name }}</strong> - {{ foerderung.jahr }}
|
||||
<br>
|
||||
<small class="text-muted">€{{ foerderung.betrag|floatformat:2 }}</small>
|
||||
</div>
|
||||
<a href="{% url 'stiftung:foerderung_detail' foerderung.pk %}" class="btn btn-sm btn-outline-primary">
|
||||
<i class="fas fa-eye"></i>
|
||||
</a>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if dokument.verpachtung_set.exists %}
|
||||
<h6 class="text-primary">Verpachtungen</h6>
|
||||
<div class="list-group list-group-flush">
|
||||
{% for verpachtung in dokument.verpachtung_set.all %}
|
||||
<div class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<strong>{{ verpachtung.vertragsnummer }}</strong> - {{ verpachtung.land.gemeinde }}
|
||||
<br>
|
||||
<small class="text-muted">{{ verpachtung.paechter.get_full_name }}</small>
|
||||
</div>
|
||||
<a href="{% url 'stiftung:verpachtung_detail' verpachtung.pk %}" class="btn btn-sm btn-outline-primary">
|
||||
<i class="fas fa-eye"></i>
|
||||
</a>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<div class="text-center py-4">
|
||||
<i class="fas fa-link fa-3x text-muted mb-3"></i>
|
||||
<h5 class="text-muted">Keine Verknüpfungen</h5>
|
||||
<p class="text-muted">Dieses Dokument ist noch nicht mit Förderungen oder Verpachtungen verknüpft.</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<div class="col-lg-4">
|
||||
<!-- Quick Stats -->
|
||||
<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-chart-pie me-2"></i>Übersicht
|
||||
</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row text-center">
|
||||
<div class="col-6">
|
||||
<div class="border-end">
|
||||
<h4 class="text-primary">{{ dokument.foerderung_set.count }}</h4>
|
||||
<small class="text-muted">Förderungen</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<h4 class="text-success">{{ dokument.verpachtung_set.count }}</h4>
|
||||
<small class="text-muted">Verpachtungen</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Actions -->
|
||||
<div class="card shadow">
|
||||
<div class="card-header py-3">
|
||||
<h6 class="m-0 font-weight-bold text-primary">
|
||||
<i class="fas fa-bolt me-2"></i>Schnellzugriff
|
||||
</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="d-grid gap-2">
|
||||
<a href="{% url 'stiftung:dokument_update' dokument.pk %}" class="btn btn-warning">
|
||||
<i class="fas fa-edit me-2"></i>Dokument bearbeiten
|
||||
</a>
|
||||
<a href="{% url 'stiftung:dokument_list' %}" class="btn btn-outline-secondary">
|
||||
<i class="fas fa-arrow-left me-2"></i>Zurück zur Liste
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -1,139 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block title %}{{ title }} - Stiftung Management{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-lg-8 mx-auto">
|
||||
<div class="card shadow">
|
||||
<div class="card-header">
|
||||
<h4 class="mb-0">
|
||||
<i class="fas fa-file-alt text-primary me-2"></i>{{ title }}
|
||||
</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
<!-- Verknüpfungsanzeigen -->
|
||||
{% if form.land_verpachtung_id.value %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fas fa-info-circle me-2"></i>
|
||||
<strong>Verknüpfung:</strong> Dieses Dokument wird mit einer Verpachtung verknüpft.
|
||||
</div>
|
||||
{% elif form.verpachtung_id.value %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fas fa-info-circle me-2"></i>
|
||||
<strong>Verknüpfung:</strong> Dieses Dokument wird mit einer Verpachtung (Legacy) verknüpft.
|
||||
</div>
|
||||
{% elif form.land_id.value %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fas fa-info-circle me-2"></i>
|
||||
<strong>Verknüpfung:</strong> Dieses Dokument wird mit einer Länderei verknüpft.
|
||||
</div>
|
||||
{% elif form.paechter_id.value %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fas fa-info-circle me-2"></i>
|
||||
<strong>Verknüpfung:</strong> Dieses Dokument wird mit einem Pächter verknüpft.
|
||||
</div>
|
||||
{% elif form.destinataer_id.value %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fas fa-info-circle me-2"></i>
|
||||
<strong>Verknüpfung:</strong> Dieses Dokument wird mit einem Destinatär verknüpft.
|
||||
</div>
|
||||
{% elif form.foerderung_id.value %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fas fa-info-circle me-2"></i>
|
||||
<strong>Verknüpfung:</strong> Dieses Dokument wird mit einer Förderung verknüpft.
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="{{ form.paperless_document_id.id_for_label }}" class="form-label">
|
||||
{{ form.paperless_document_id.label }} *
|
||||
</label>
|
||||
{{ form.paperless_document_id }}
|
||||
{% if form.paperless_document_id.errors %}
|
||||
<div class="invalid-feedback d-block">
|
||||
{{ form.paperless_document_id.errors.0 }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<small class="form-text text-muted">
|
||||
Die Dokument-ID aus Paperless (z.B. aus der URL: /documents/12345/)
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="{{ form.kontext.id_for_label }}" class="form-label">
|
||||
{{ form.kontext.label }} *
|
||||
</label>
|
||||
{{ form.kontext }}
|
||||
{% if form.kontext.errors %}
|
||||
<div class="invalid-feedback d-block">
|
||||
{{ form.kontext.errors.0 }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.titel.id_for_label }}" class="form-label">
|
||||
{{ form.titel.label }} *
|
||||
</label>
|
||||
{{ form.titel }}
|
||||
{% if form.titel.errors %}
|
||||
<div class="invalid-feedback d-block">
|
||||
{{ form.titel.errors.0 }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.beschreibung.id_for_label }}" class="form-label">
|
||||
{{ form.beschreibung.label }}
|
||||
</label>
|
||||
{{ form.beschreibung }}
|
||||
{% if form.beschreibung.errors %}
|
||||
<div class="invalid-feedback d-block">
|
||||
{{ form.beschreibung.errors.0 }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Versteckte Verknüpfungsfelder -->
|
||||
{{ form.land_verpachtung_id }}
|
||||
{{ form.verpachtung_id }}
|
||||
{{ form.land_id }}
|
||||
{{ form.paechter_id }}
|
||||
{{ form.destinataer_id }}
|
||||
{{ form.foerderung_id }}
|
||||
|
||||
<div class="d-flex justify-content-between">
|
||||
<a href="{% url 'stiftung:dokument_list' %}" class="btn btn-outline-secondary">
|
||||
<i class="fas fa-arrow-left me-1"></i>Zurück zur Liste
|
||||
</a>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fas fa-save me-1"></i>
|
||||
{% if dokument %}Aktualisieren{% else %}Verknüpfen{% endif %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_css %}
|
||||
<style>
|
||||
.form-control, .form-select {
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
.form-control:focus, .form-select:focus {
|
||||
border-color: #86b7fe;
|
||||
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
@@ -1,146 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block title %}Alle Dokumente - Stiftungsverwaltung{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1 class="h3 mb-0">
|
||||
<i class="fas fa-file-alt text-primary me-2"></i>
|
||||
Alle Dokumente
|
||||
</h1>
|
||||
<div>
|
||||
<a href="{% url 'stiftung:dokument_management' %}" class="btn btn-info me-2">
|
||||
<i class="fas fa-external-link-alt me-1"></i>Dokumentenverwaltung
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Verknüpfte Dokumente -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card shadow">
|
||||
<div class="card-header py-3">
|
||||
<h6 class="m-0 font-weight-bold text-success">
|
||||
<i class="fas fa-link me-2"></i>Verknüpfte Dokumente ({{ dokumente|length }})
|
||||
</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if dokumente %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Dokument</th>
|
||||
<th>Kontext</th>
|
||||
<th>Verknüpft mit</th>
|
||||
<th>Aktionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for dokument in dokumente %}
|
||||
<tr>
|
||||
<td>
|
||||
<strong>{{ dokument.titel }}</strong>
|
||||
<br>
|
||||
<small class="text-muted">ID: {{ dokument.paperless_document_id }}</small>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge bg-secondary">{{ dokument.get_kontext_display }}</span>
|
||||
</td>
|
||||
<td>
|
||||
{% if dokument.verpachtung_id %}
|
||||
<span class="badge bg-info">Verpachtung</span>
|
||||
{% elif dokument.land_id %}
|
||||
<span class="badge bg-success">Länderei</span>
|
||||
{% elif dokument.paechter_id %}
|
||||
<span class="badge bg-primary">Pächter</span>
|
||||
{% elif dokument.destinataer_id %}
|
||||
<span class="badge bg-warning">Destinatär</span>
|
||||
{% elif dokument.foerderung_id %}
|
||||
<span class="badge bg-secondary">Förderung</span>
|
||||
{% else %}
|
||||
<span class="text-muted">Keine Verknüpfung</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group" role="group">
|
||||
<a href="{{ dokument.get_paperless_url }}" target="_blank" class="btn btn-sm btn-outline-primary" title="In Paperless öffnen">
|
||||
<i class="fas fa-external-link-alt"></i>
|
||||
</a>
|
||||
<a href="{% url 'stiftung:dokument_detail' dokument.pk %}" class="btn btn-sm btn-outline-info" title="Details">
|
||||
<i class="fas fa-eye"></i>
|
||||
</a>
|
||||
<a href="{% url 'stiftung:dokument_update' dokument.pk %}" class="btn btn-sm btn-outline-warning" title="Bearbeiten">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="text-center py-4">
|
||||
<i class="fas fa-link fa-3x text-muted mb-3"></i>
|
||||
<h5 class="text-muted">Keine Dokumente verknüpft</h5>
|
||||
<p class="text-muted">Verknüpfen Sie Dokumente aus Paperless mit Ihren Entitäten.</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Verfügbare Paperless-Dokumente -->
|
||||
{% if available_dokumente %}
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card shadow">
|
||||
<div class="card-header py-3">
|
||||
<h6 class="m-0 font-weight-bold text-info">
|
||||
<i class="fas fa-plus-circle me-2"></i>Verfügbare Paperless-Dokumente ({{ available_dokumente|length }})
|
||||
</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
{% for doc in available_dokumente %}
|
||||
<div class="col-md-6 col-lg-4 mb-3">
|
||||
<div class="card h-100 border-info">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title">{{ doc.title }}</h6>
|
||||
<div class="mb-2">
|
||||
{% for tag in doc.tags %}
|
||||
{% if tag == 'Stiftung_Destinatäre' or tag == 'Stiftung_Land_und_Pächter' or tag == 'Stiftung_Administration' %}
|
||||
<span class="badge bg-primary me-1">{{ tag }}</span>
|
||||
{% else %}
|
||||
<span class="badge bg-light text-dark me-1">{{ tag }}</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<a href="{{ doc.document_url }}" target="_blank" class="btn btn-sm btn-outline-info">
|
||||
<i class="fas fa-external-link-alt me-1"></i>In Paperless öffnen
|
||||
</a>
|
||||
<a href="{% url 'stiftung:dokument_management' %}" class="btn btn-sm btn-success">
|
||||
<i class="fas fa-link me-1"></i>Verknüpfen
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
@@ -1,557 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block title %}Dokumentenverwaltung - Stiftung{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1><i class="fas fa-folder-open me-2"></i>Dokumentenverwaltung</h1>
|
||||
<div>
|
||||
<a href="{% url 'stiftung:dokument_list' %}" class="btn btn-outline-primary">
|
||||
<i class="fas fa-list me-1"></i>Alle Dokumente anzeigen
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="statusMessages"></div>
|
||||
|
||||
<!-- Filter -->
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
<i class="fas fa-filter me-2"></i>Filter
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">Kategorie</label>
|
||||
<select id="filterCategory" class="form-select">
|
||||
<option value="all">Alle</option>
|
||||
<option value="destinaere">Destinatäre</option>
|
||||
<option value="land">Ländereien</option>
|
||||
<option value="admin">Administration</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Suche im Titel</label>
|
||||
<input id="filterQuery" class="form-control" placeholder="Titel enthält..." />
|
||||
</div>
|
||||
<div class="col-md-3 d-flex align-items-end">
|
||||
<button id="refreshDocuments" class="btn btn-primary w-100">
|
||||
<i class="fas fa-sync me-1"></i>Aktualisieren
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Dokumente-Liste -->
|
||||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<div><i class="fas fa-file-alt me-2"></i>Dokumente</div>
|
||||
<small class="text-muted" id="counts"></small>
|
||||
</div>
|
||||
<div class="card-body" id="documentsContainer">
|
||||
<div class="text-center py-5 text-muted" id="loadingState">
|
||||
<div class="spinner-border" role="status"></div>
|
||||
<p class="mt-2">Lade Dokumente...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Re-Link Modal -->
|
||||
<div class="modal fade" id="relinkModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Dokument neu verknüpfen</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3"><strong id="relinkDocTitle"></strong></div>
|
||||
<div id="currentLinks" class="mb-3"></div>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">Kategorie</label>
|
||||
<select id="relinkCategory" class="form-select">
|
||||
<option value="destinataer">Destinatäre</option>
|
||||
<option value="land">Ländereien</option>
|
||||
<option value="paechter">Pächter</option>
|
||||
<option value="verpachtung">Verpachtungen</option>
|
||||
<option value="foerderung">Förderungen</option>
|
||||
<option value="abrechnung">Abrechnungen</option>
|
||||
<option value="rentmeister">Rentmeister</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<label class="form-label">Suche</label>
|
||||
<div class="input-group">
|
||||
<input id="relinkQuery" class="form-control" placeholder="Name, Ort, E-Mail, Telefon, Adresse..." />
|
||||
<button id="relinkSearch" class="btn btn-outline-secondary"><i class="fas fa-search"></i></button>
|
||||
</div>
|
||||
<small class="form-text text-muted">Durchsucht Name, Adresse, E-Mail, Telefon und weitere Felder</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-3" id="relinkResults" style="max-height: 400px; overflow-y: auto; border: 1px solid #dee2e6; border-radius: 0.375rem; padding: 0.5rem;"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Schließen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_css %}
|
||||
<style>
|
||||
.search-result-item:hover {
|
||||
background-color: #f8f9fa !important;
|
||||
border-color: #0d6efd !important;
|
||||
}
|
||||
#relinkResults::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
#relinkResults::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
border-radius: 4px;
|
||||
}
|
||||
#relinkResults::-webkit-scrollbar-thumb {
|
||||
background: #c1c1c1;
|
||||
border-radius: 4px;
|
||||
}
|
||||
#relinkResults::-webkit-scrollbar-thumb:hover {
|
||||
background: #a8a8a8;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block javascript %}
|
||||
<script>
|
||||
let allDocuments = [];
|
||||
let linksByPaperlessId = new Map();
|
||||
let currentRelink = { linkId: null, paperlessId: null };
|
||||
|
||||
function showMessage(message, type) {
|
||||
const statusDiv = document.getElementById('statusMessages');
|
||||
const alert = document.createElement('div');
|
||||
alert.className = `alert alert-${type} alert-dismissible fade show`;
|
||||
alert.innerHTML = `${message}<button type="button" class="btn-close" data-bs-dismiss="alert"></button>`;
|
||||
statusDiv.appendChild(alert);
|
||||
setTimeout(() => alert.remove(), 5000);
|
||||
}
|
||||
|
||||
function fetchData() {
|
||||
console.log('Fetching updated document data...'); // Debug log
|
||||
const loadingState = document.getElementById('loadingState');
|
||||
if (loadingState) {
|
||||
loadingState.style.display = 'block';
|
||||
}
|
||||
|
||||
console.log('Making API calls to:', [
|
||||
'/api/paperless/documents/?poll=1',
|
||||
'/api/link-document/list/'
|
||||
]);
|
||||
|
||||
Promise.all([
|
||||
fetch('/api/paperless/documents/?poll=1').then(r => {
|
||||
console.log('Paperless API response status:', r.status, r.ok);
|
||||
if (!r.ok) {
|
||||
throw new Error(`Paperless API failed: ${r.status} ${r.statusText}`);
|
||||
}
|
||||
return r.json();
|
||||
}),
|
||||
fetch('/api/link-document/list/').then(r => {
|
||||
console.log('Link API response status:', r.status, r.ok);
|
||||
if (!r.ok) {
|
||||
throw new Error(`Link API failed: ${r.status} ${r.statusText}`);
|
||||
}
|
||||
return r.json();
|
||||
})
|
||||
]).then(([docs, linksResp]) => {
|
||||
console.log('Data fetched successfully:', { docs: docs.documents?.length, links: linksResp.links?.length }); // Debug log
|
||||
console.log('Full docs response:', docs); // Debug the full response
|
||||
console.log('Full links response:', linksResp); // Debug the full response
|
||||
allDocuments = docs.documents || [];
|
||||
linksByPaperlessId = new Map();
|
||||
// Handle new grouped links format
|
||||
(linksResp.links || []).forEach(docLinks => {
|
||||
console.log(`Setting linksByPaperlessId for document ${docLinks.paperless_id}:`, docLinks);
|
||||
linksByPaperlessId.set(docLinks.paperless_id, docLinks);
|
||||
});
|
||||
console.log('Final linksByPaperlessId Map:', linksByPaperlessId);
|
||||
renderDocuments();
|
||||
const countsElement = document.getElementById('counts');
|
||||
if (countsElement) {
|
||||
countsElement.textContent = `Gesamt: ${docs.total_all} | Destinatäre: ${docs.total_destinaere} | Land: ${docs.total_land} | Admin: ${docs.total_admin}`;
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error('Error fetching data:', err);
|
||||
console.error('Error details:', {
|
||||
message: err.message,
|
||||
stack: err.stack,
|
||||
name: err.name
|
||||
});
|
||||
showMessage('Fehler beim Laden der Daten: ' + err.message, 'danger');
|
||||
|
||||
// Show error in the container
|
||||
const container = document.getElementById('documentsContainer');
|
||||
if (container) {
|
||||
container.innerHTML = `
|
||||
<div class="alert alert-danger">
|
||||
<h6><i class="fas fa-exclamation-triangle me-2"></i>Fehler beim Laden der Dokumente</h6>
|
||||
<p class="mb-0">${err.message}</p>
|
||||
<button class="btn btn-primary mt-2" onclick="fetchData()">
|
||||
<i class="fas fa-sync me-1"></i>Erneut versuchen
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}).finally(() => {
|
||||
const loadingState = document.getElementById('loadingState');
|
||||
if (loadingState) {
|
||||
loadingState.style.display = 'none';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function renderDocuments() {
|
||||
const container = document.getElementById('documentsContainer');
|
||||
const category = document.getElementById('filterCategory').value;
|
||||
const query = document.getElementById('filterQuery').value.toLowerCase();
|
||||
let filtered = allDocuments.slice();
|
||||
if (category !== 'all') {
|
||||
filtered = filtered.filter(d => d.tag_category === category);
|
||||
}
|
||||
if (query) {
|
||||
filtered = filtered.filter(d => (d.title || '').toLowerCase().includes(query));
|
||||
}
|
||||
if (!filtered.length) {
|
||||
container.innerHTML = '<p class="text-muted">Keine Dokumente gefunden.</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
let html = '<div class="table-responsive"><table class="table table-striped align-middle"><thead><tr><th>Titel</th><th>Kategorie</th><th>Verknüpft mit</th><th>Aktionen</th></tr></thead><tbody>';
|
||||
filtered.forEach(doc => {
|
||||
const linkData = linksByPaperlessId.get(doc.id);
|
||||
let linkedTo = '<span class="text-muted">nicht verknüpft</span>';
|
||||
let hasLinks = false;
|
||||
|
||||
if (linkData && linkData.links && linkData.links.length > 0) {
|
||||
console.log(`Document ${doc.id} (${doc.title}) has ${linkData.links.length} links:`, linkData.links);
|
||||
hasLinks = true;
|
||||
const linkItems = linkData.links.map(link => {
|
||||
const obj = link.linked_object;
|
||||
if (!obj) {
|
||||
console.warn('Link missing linked_object:', link);
|
||||
return `<div class="mb-1"><span class="badge bg-warning me-1">Fehler</span> Fehlerhafter Link</div>`;
|
||||
}
|
||||
// Generate the appropriate detail URL based on link type
|
||||
let detailUrl = '#';
|
||||
if (link.link_type === 'destinataer') {
|
||||
detailUrl = `/destinataere/${obj.id}/`;
|
||||
} else if (link.link_type === 'land') {
|
||||
detailUrl = `/laendereien/${obj.id}/`;
|
||||
} else if (link.link_type === 'paechter') {
|
||||
detailUrl = `/paechter/${obj.id}/`;
|
||||
} else if (link.link_type === 'verpachtung') {
|
||||
detailUrl = `/laendereien/verpachtungen/${obj.id}/`;
|
||||
} else if (link.link_type === 'foerderung') {
|
||||
detailUrl = `/foerderungen/${obj.id}/`;
|
||||
} else if (link.link_type === 'abrechnung') {
|
||||
detailUrl = `/laendereien/abrechnungen/${obj.id}/`;
|
||||
} else if (link.link_type === 'rentmeister') {
|
||||
detailUrl = `/geschaeftsfuehrung/rentmeister/${obj.id}/`;
|
||||
}
|
||||
|
||||
return `<div class="mb-1 d-flex align-items-center justify-content-between">
|
||||
<div class="flex-grow-1">
|
||||
<span class="badge bg-info me-1">${obj?.type || 'Unbekannt'}</span>
|
||||
<a href="${detailUrl}" class="text-decoration-none small text-primary" title="Zu ${obj?.type || 'Entität'} navigieren">
|
||||
${obj?.name || 'Unbekannt'}
|
||||
<i class="fas fa-external-link-alt ms-1" style="font-size: 0.7em;"></i>
|
||||
</a>
|
||||
</div>
|
||||
<button class="btn btn-sm btn-outline-danger ms-2" onclick="onDeleteLink('${link.id}')" title="Diese Verknüpfung löschen">
|
||||
<i class="fas fa-times" style="font-size: 0.7em;"></i>
|
||||
</button>
|
||||
</div>`;
|
||||
}).join('');
|
||||
linkedTo = `<div class="small">${linkItems}</div>`;
|
||||
console.log(`Final linkedTo HTML for doc ${doc.id}:`, linkedTo);
|
||||
}
|
||||
|
||||
const openUrl = `/api/paperless/documents/${doc.id}/`;
|
||||
html += `
|
||||
<tr>
|
||||
<td><strong>${doc.title || 'Ohne Titel'}</strong><br><small class="text-muted">Paperless-ID: ${doc.id}</small></td>
|
||||
<td><span class="badge bg-secondary">${doc.tag_category}</span></td>
|
||||
<td>${linkedTo}</td>
|
||||
<td>
|
||||
<a class="btn btn-sm btn-outline-primary" href="${openUrl}" target="_blank" title="In Paperless öffnen"><i class="fas fa-external-link-alt"></i></a>
|
||||
${hasLinks ? `<button class="btn btn-sm btn-outline-danger" onclick="onDeleteAllLinks(${doc.id})" title="Alle Verknüpfungen löschen"><i class="fas fa-trash"></i></button>` : ''}
|
||||
<button class="btn btn-sm btn-outline-success" onclick="onRelink('', ${doc.id}, '${(doc.title||'').replace(/'/g, "'")}')" title="Neu verknüpfen"><i class="fas fa-link"></i></button>
|
||||
</td>
|
||||
</tr>`;
|
||||
});
|
||||
html += '</tbody></table></div>';
|
||||
container.innerHTML = html;
|
||||
}
|
||||
|
||||
function onRelink(linkId, paperlessId, title) {
|
||||
currentRelink = { linkId, paperlessId };
|
||||
document.getElementById('relinkDocTitle').textContent = title;
|
||||
|
||||
// Show current links in modal
|
||||
const linkData = linksByPaperlessId.get(paperlessId);
|
||||
const currentLinksDiv = document.getElementById('currentLinks');
|
||||
if (linkData && linkData.links && linkData.links.length > 0) {
|
||||
let currentLinksHtml = '<div class="alert alert-info"><strong>Aktuell verknüpft mit:</strong><ul class="mb-0 mt-2">';
|
||||
linkData.links.forEach(link => {
|
||||
const obj = link.linked_object;
|
||||
currentLinksHtml += `<li><span class="badge bg-secondary me-1">${obj?.type || 'Unbekannt'}</span> ${obj?.name || 'Unbekannt'}</li>`;
|
||||
});
|
||||
currentLinksHtml += '</ul></div>';
|
||||
currentLinksDiv.innerHTML = currentLinksHtml;
|
||||
} else {
|
||||
currentLinksDiv.innerHTML = '<div class="alert alert-warning">Dieses Dokument ist noch nicht verknüpft.</div>';
|
||||
}
|
||||
|
||||
document.getElementById('relinkResults').innerHTML = '';
|
||||
const modal = new bootstrap.Modal(document.getElementById('relinkModal'));
|
||||
modal.show();
|
||||
}
|
||||
|
||||
document.getElementById('relinkSearch').addEventListener('click', function() {
|
||||
const category = document.getElementById('relinkCategory').value;
|
||||
const q = document.getElementById('relinkQuery').value || 'all';
|
||||
const target = document.getElementById('relinkResults');
|
||||
target.innerHTML = '<div class="d-flex align-items-center"><div class="spinner-border spinner-border-sm me-2" role="status"></div>Suche...</div>';
|
||||
fetch(`/api/link-document/search/?q=${encodeURIComponent(q)}&category=${category}`)
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
let items = data[category] || [];
|
||||
if (!items.length) {
|
||||
target.innerHTML = '<div class="text-center py-3 text-muted"><i class="fas fa-search me-2"></i>Keine Treffer gefunden.</div>';
|
||||
return;
|
||||
}
|
||||
let html = `<div class="mb-2"><small class="text-muted">${items.length} Treffer gefunden</small></div>`;
|
||||
|
||||
// Get current links for this document to mark already linked entities
|
||||
const linkData = linksByPaperlessId.get(currentRelink.paperlessId);
|
||||
const currentlyLinkedIds = new Set();
|
||||
if (linkData && linkData.links) {
|
||||
linkData.links.forEach(link => {
|
||||
if (link.linked_object && link.linked_object.id) {
|
||||
currentlyLinkedIds.add(link.linked_object.id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
items.forEach(it => {
|
||||
const isLinked = currentlyLinkedIds.has(it.id);
|
||||
const linkClass = isLinked ? 'border-success bg-light' : 'border';
|
||||
const buttonClass = isLinked ? 'btn-success' : 'btn-outline-primary';
|
||||
const buttonIcon = isLinked ? 'fas fa-check-circle' : 'fas fa-plus';
|
||||
const buttonText = isLinked ? 'Bereits verknüpft' : 'Verknüpfen';
|
||||
|
||||
html += `<div class="d-flex justify-content-between align-items-start ${linkClass} rounded p-3 mb-2 search-result-item" style="transition: all 0.2s;">
|
||||
<div class="flex-grow-1">
|
||||
<div class="fw-bold mb-1">${it.name}</div>
|
||||
<div class="text-muted small mb-1">${it.details || ''}</div>
|
||||
${isLinked ? '<span class="badge bg-success mt-1"><i class="fas fa-check-circle me-1"></i>Aktuell verknüpft</span>' : ''}
|
||||
</div>
|
||||
<button class="btn btn-sm ${buttonClass} ms-3" onclick="confirmRelink('${it.id}', '${category}')" title="${buttonText}" ${isLinked ? 'disabled' : ''}>
|
||||
<i class="${buttonIcon} me-1"></i>${isLinked ? 'Verknüpft' : 'Auswählen'}
|
||||
</button>
|
||||
</div>`;
|
||||
});
|
||||
target.innerHTML = html;
|
||||
})
|
||||
.catch(() => { target.innerHTML = '<div class="text-center py-3 text-danger"><i class="fas fa-exclamation-triangle me-2"></i>Fehler bei der Suche</div>'; });
|
||||
});
|
||||
|
||||
function onDeleteAllLinks(paperlessId) {
|
||||
const linkData = linksByPaperlessId.get(paperlessId);
|
||||
if (!linkData || !linkData.links || linkData.links.length === 0) {
|
||||
showMessage('Keine Verknüpfungen zum Löschen gefunden', 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!confirm(`Möchten Sie wirklich alle ${linkData.links.length} Verknüpfung(en) für dieses Dokument löschen?`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Deleting all ${linkData.links.length} links for document ${paperlessId}:`, linkData.links);
|
||||
|
||||
// Delete all links for this document with proper CSRF token
|
||||
const deletePromises = linkData.links.map(link => {
|
||||
console.log(`Deleting link ${link.id}`);
|
||||
return fetch(`/api/link-document/delete/${link.id}/`, {
|
||||
method: 'DELETE',
|
||||
headers: { 'X-CSRFToken': getCookie('csrftoken') }
|
||||
});
|
||||
});
|
||||
|
||||
Promise.all(deletePromises).then(responses => {
|
||||
console.log('All delete responses:', responses.map(r => ({ status: r.status, ok: r.ok })));
|
||||
const allSuccessful = responses.every(r => r.ok);
|
||||
const failedCount = responses.filter(r => !r.ok).length;
|
||||
|
||||
if (allSuccessful) {
|
||||
showMessage('Alle Verknüpfungen erfolgreich gelöscht', 'success');
|
||||
setTimeout(() => {
|
||||
fetchData();
|
||||
}, 300);
|
||||
} else {
|
||||
console.error(`${failedCount} of ${responses.length} delete requests failed`);
|
||||
showMessage(`Fehler beim Löschen von ${failedCount} Verknüpfung(en)`, 'danger');
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error('Error during bulk delete:', err);
|
||||
showMessage('Fehler beim Löschen der Verknüpfungen', 'danger');
|
||||
});
|
||||
}
|
||||
|
||||
// Add Enter key support for search
|
||||
document.getElementById('relinkQuery').addEventListener('keypress', function(e) {
|
||||
if (e.key === 'Enter') {
|
||||
document.getElementById('relinkSearch').click();
|
||||
}
|
||||
});
|
||||
|
||||
function confirmRelink(targetId, category) {
|
||||
console.log('confirmRelink called:', { targetId, category, currentRelink });
|
||||
|
||||
const isUpdate = !!currentRelink.linkId;
|
||||
const url = isUpdate ? '/api/link-document/update/' : '/api/link-document/create/';
|
||||
const payload = isUpdate ? {
|
||||
link_id: currentRelink.linkId,
|
||||
link_type: category,
|
||||
link_id_target: targetId
|
||||
} : {
|
||||
paperless_id: currentRelink.paperlessId,
|
||||
paperless_title: document.getElementById('relinkDocTitle').textContent,
|
||||
paperless_url: `/api/paperless/documents/${currentRelink.paperlessId}/`,
|
||||
link_type: category,
|
||||
link_id: targetId
|
||||
};
|
||||
|
||||
console.log('Sending request:', { url, payload });
|
||||
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') },
|
||||
body: JSON.stringify(payload)
|
||||
}).then(async r => {
|
||||
console.log('Response status:', r.status, r.ok);
|
||||
|
||||
let resp = {};
|
||||
try {
|
||||
resp = await r.json();
|
||||
console.log('Response data:', resp);
|
||||
} catch (e) {
|
||||
console.log('No JSON response, treating as success if status OK');
|
||||
if (r.ok) {
|
||||
resp = { success: true };
|
||||
} else {
|
||||
throw new Error('Network response was not ok');
|
||||
}
|
||||
}
|
||||
|
||||
if (r.ok && (resp.success || resp.message)) {
|
||||
console.log('Success! Showing message and refreshing...');
|
||||
showMessage(resp.message || 'Verknüpfung gespeichert', 'success');
|
||||
|
||||
// Close modal first, then refresh data
|
||||
const modal = bootstrap.Modal.getInstance(document.getElementById('relinkModal'));
|
||||
if (modal) {
|
||||
console.log('Closing modal...');
|
||||
modal.hide();
|
||||
}
|
||||
|
||||
// Clear search results to prevent confusion
|
||||
document.getElementById('relinkResults').innerHTML = '';
|
||||
document.getElementById('relinkQuery').value = '';
|
||||
|
||||
// Try immediate refresh first
|
||||
console.log('Calling fetchData() immediately...');
|
||||
fetchData();
|
||||
|
||||
// Also schedule a backup refresh to be sure
|
||||
console.log('Scheduling backup refresh in 500ms...');
|
||||
setTimeout(() => {
|
||||
console.log('Backup fetchData() call...');
|
||||
fetchData();
|
||||
}, 500);
|
||||
} else {
|
||||
console.log('Error response:', resp);
|
||||
showMessage(resp.error || 'Fehler beim Speichern', 'danger');
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error('Relink error:', err);
|
||||
showMessage('Fehler beim Speichern', 'danger');
|
||||
});
|
||||
}
|
||||
|
||||
function onDeleteLink(linkId) {
|
||||
if (!confirm('Diese Verknüpfung wirklich löschen?')) return;
|
||||
|
||||
console.log('Deleting individual link:', linkId);
|
||||
|
||||
fetch(`/api/link-document/delete/${linkId}/`, {
|
||||
method: 'DELETE',
|
||||
headers: { 'X-CSRFToken': getCookie('csrftoken') }
|
||||
})
|
||||
.then(async r => {
|
||||
console.log('Delete response status:', r.status, r.ok);
|
||||
let data = {};
|
||||
try {
|
||||
data = await r.json();
|
||||
console.log('Delete response data:', data);
|
||||
} catch (_) {
|
||||
console.log('No JSON response, treating as success if status OK');
|
||||
}
|
||||
|
||||
if (r.ok && (data.success === undefined || data.success === true)) {
|
||||
showMessage('Verknüpfung gelöscht', 'success');
|
||||
setTimeout(() => {
|
||||
fetchData();
|
||||
}, 300);
|
||||
} else {
|
||||
showMessage((data && data.error) || 'Fehler beim Löschen', 'danger');
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Delete error:', err);
|
||||
showMessage('Fehler beim Löschen', 'danger');
|
||||
});
|
||||
}
|
||||
|
||||
function getCookie(name) {
|
||||
let cookieValue = null;
|
||||
if (document.cookie && document.cookie !== '') {
|
||||
const cookies = document.cookie.split(';');
|
||||
for (let i = 0; i < cookies.length; i++) {
|
||||
const cookie = cookies[i].trim();
|
||||
if (cookie.substring(0, name.length + 1) === (name + '=')) {
|
||||
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cookieValue;
|
||||
}
|
||||
|
||||
document.getElementById('refreshDocuments').addEventListener('click', fetchData);
|
||||
document.getElementById('filterCategory').addEventListener('change', renderDocuments);
|
||||
document.getElementById('filterQuery').addEventListener('input', () => { renderDocuments(); });
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
console.log('Dokumentenverwaltung page loaded, calling fetchData()...');
|
||||
fetchData();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load humanize %}
|
||||
|
||||
{% block title %}E-Mail-Eingang Detail - van Hees-Theyssen-Vogel'sche Stiftung{% endblock %}
|
||||
{% block title %}E-Mail-Eingang Detail - Stiftungsverwaltung{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
@@ -11,22 +11,31 @@
|
||||
<i class="fas fa-envelope me-2"></i>E-Mail-Eingang
|
||||
</h1>
|
||||
<a href="{% url 'stiftung:email_eingang_list' %}" class="btn btn-outline-secondary btn-sm">
|
||||
<i class="fas fa-arrow-left me-1"></i>Zurück zur Übersicht
|
||||
<i class="fas fa-arrow-left me-1"></i>Zurueck zur Uebersicht
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<!-- Linke Spalte: E-Mail-Details -->
|
||||
{# Linke Spalte: E-Mail-Details #}
|
||||
<div class="col-lg-8">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<span><i class="fas fa-envelope-open me-2"></i>E-Mail-Details</span>
|
||||
<span>
|
||||
{# Kategorie-Badge #}
|
||||
{% if eingang.kategorie == "rechnung" %}<span class="badge bg-warning text-dark me-1"><i class="fas fa-file-invoice me-1"></i>Rechnung</span>
|
||||
{% elif eingang.kategorie == "destinataer" %}<span class="badge bg-info me-1"><i class="fas fa-user me-1"></i>Destinataer</span>
|
||||
{% elif eingang.kategorie == "land_pacht" %}<span class="badge bg-success me-1"><i class="fas fa-map me-1"></i>Land/Pacht</span>
|
||||
{% elif eingang.kategorie == "stiftungsgeschichte" %}<span class="badge bg-dark me-1"><i class="fas fa-landmark me-1"></i>Geschichte</span>
|
||||
{% endif %}
|
||||
{# Status-Badge #}
|
||||
{% if eingang.status == "neu" %}<span class="badge bg-warning text-dark">Neu</span>
|
||||
{% elif eingang.status == "zugewiesen" %}<span class="badge bg-primary">Zugewiesen</span>
|
||||
{% elif eingang.status == "verarbeitet" %}<span class="badge bg-success">Verarbeitet</span>
|
||||
{% elif eingang.status == "rechnung_erfasst" %}<span class="badge bg-info">Rechnung erfasst</span>
|
||||
{% elif eingang.status == "zahlung_gebucht" %}<span class="badge bg-success">Zahlung gebucht</span>
|
||||
{% elif eingang.status == "unbekannt" %}<span class="badge bg-danger">Unbekannter Absender</span>
|
||||
{% elif eingang.status == "fehler" %}<span class="badge bg-secondary">Fehler</span>
|
||||
{% endif %}
|
||||
@@ -47,17 +56,27 @@
|
||||
<dt class="col-sm-3">Betreff</dt>
|
||||
<dd class="col-sm-9">{{ eingang.betreff|default:"(kein Betreff)" }}</dd>
|
||||
|
||||
<dt class="col-sm-3">Destinatär</dt>
|
||||
<dt class="col-sm-3">Destinataer</dt>
|
||||
<dd class="col-sm-9">
|
||||
{% if eingang.destinataer %}
|
||||
<a href="{% url 'stiftung:destinataer_detail' eingang.destinataer.pk %}">
|
||||
{{ eingang.destinataer }}
|
||||
</a>
|
||||
{% else %}
|
||||
<span class="text-danger"><i class="fas fa-exclamation-circle me-1"></i>Nicht zugeordnet</span>
|
||||
<span class="text-muted">Nicht zugeordnet</span>
|
||||
{% endif %}
|
||||
</dd>
|
||||
|
||||
{% if eingang.verwaltungskosten %}
|
||||
<dt class="col-sm-3">Rechnung</dt>
|
||||
<dd class="col-sm-9">
|
||||
<a href="{% url 'stiftung:verwaltungskosten_edit' eingang.verwaltungskosten.pk %}">
|
||||
{{ eingang.verwaltungskosten.bezeichnung }} ({{ eingang.verwaltungskosten.betrag }} EUR)
|
||||
</a>
|
||||
<span class="badge bg-{{ eingang.verwaltungskosten.get_status_color }}">{{ eingang.verwaltungskosten.get_status_display }}</span>
|
||||
</dd>
|
||||
{% endif %}
|
||||
|
||||
{% if eingang.quartalsnachweis %}
|
||||
<dt class="col-sm-3">Quartalsnachweis</dt>
|
||||
<dd class="col-sm-9">
|
||||
@@ -82,32 +101,34 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Anhänge / Paperless-Dokumente -->
|
||||
{% if dokument_links %}
|
||||
{# Anhaenge / DMS-Dokumente #}
|
||||
{% if dms_dokumente %}
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
<i class="fas fa-paperclip me-2"></i>Anhänge in Paperless-NGX
|
||||
<i class="fas fa-paperclip me-2"></i>Anhaenge ({{ dms_dokumente|length }})
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<table class="table mb-0">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Titel</th>
|
||||
<th>Kontext</th>
|
||||
<th>Paperless-ID</th>
|
||||
<th>Dateiname</th>
|
||||
<th>Typ</th>
|
||||
<th>Groesse</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for link in dokument_links %}
|
||||
{% for dok in dms_dokumente %}
|
||||
<tr>
|
||||
<td>{{ link.titel }}</td>
|
||||
<td>{{ link.get_kontext_display }}</td>
|
||||
<td><code>{{ link.paperless_document_id }}</code></td>
|
||||
<td>{{ dok.dateiname_original|default:dok.titel }}</td>
|
||||
<td><span class="text-muted small">{{ dok.dateityp|default:"–" }}</span></td>
|
||||
<td><span class="text-muted small">{{ dok.get_human_size }}</span></td>
|
||||
<td>
|
||||
<a href="{{ link.get_paperless_url }}" target="_blank" class="btn btn-sm btn-outline-info">
|
||||
<i class="fas fa-external-link-alt me-1"></i>Öffnen
|
||||
{% if dok.datei %}
|
||||
<a href="{% url 'stiftung:dms_download' dok.pk %}" class="btn btn-sm btn-outline-primary">
|
||||
<i class="fas fa-download me-1"></i>Herunterladen
|
||||
</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
@@ -115,43 +136,109 @@
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% elif eingang.paperless_dokument_ids %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fas fa-info-circle me-1"></i>
|
||||
{{ eingang.paperless_dokument_ids|length }} Anhang/-hänge in Paperless hochgeladen
|
||||
(IDs: {{ eingang.paperless_dokument_ids|join:", " }}), aber noch kein DokumentLink erstellt.
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="card mb-4">
|
||||
<div class="card-body text-muted text-center py-3">
|
||||
<i class="fas fa-paperclip me-1"></i>Keine Anhänge in dieser E-Mail.
|
||||
<i class="fas fa-paperclip me-1"></i>Keine Anhaenge in dieser E-Mail.
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Rechte Spalte: Aktionen -->
|
||||
{# Rechte Spalte: Aktionen #}
|
||||
<div class="col-lg-4">
|
||||
|
||||
<!-- Manuelle Destinatär-Zuordnung -->
|
||||
{% if not eingang.destinataer or eingang.status == "unbekannt" %}
|
||||
{# Kategorie aendern #}
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
<i class="fas fa-tag me-2"></i>Kategorie
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="action" value="set_kategorie">
|
||||
<div class="mb-2">
|
||||
<select class="form-select form-select-sm" name="kategorie">
|
||||
<option value="allgemein" {% if eingang.kategorie == "allgemein" %}selected{% endif %}>Allgemein</option>
|
||||
<option value="destinataer" {% if eingang.kategorie == "destinataer" %}selected{% endif %}>Destinataer</option>
|
||||
<option value="rechnung" {% if eingang.kategorie == "rechnung" %}selected{% endif %}>Rechnung</option>
|
||||
<option value="land_pacht" {% if eingang.kategorie == "land_pacht" %}selected{% endif %}>Grundstueck / Pacht</option>
|
||||
<option value="stiftungsgeschichte" {% if eingang.kategorie == "stiftungsgeschichte" %}selected{% endif %}>Stiftungsgeschichte</option>
|
||||
</select>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-outline-primary btn-sm w-100">
|
||||
<i class="fas fa-save me-1"></i>Kategorie setzen
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Rechnung erfassen (nur wenn noch keine zugeordnet) #}
|
||||
{% if not eingang.verwaltungskosten and eingang.status != "zahlung_gebucht" %}
|
||||
<div class="card mb-4 border-warning">
|
||||
<div class="card-header bg-warning text-dark">
|
||||
<i class="fas fa-user-plus me-2"></i>Destinatär manuell zuordnen
|
||||
<i class="fas fa-file-invoice-dollar me-2"></i>Als Rechnung erfassen
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="small text-muted">
|
||||
Die E-Mail-Adresse <strong>{{ eingang.absender_email }}</strong>
|
||||
konnte keinem Destinatär automatisch zugeordnet werden.
|
||||
Bitte wählen Sie den passenden Destinatär aus.
|
||||
Erstellt einen Verwaltungskosten-Eintrag und verknuepft die Anhaenge als Rechnungsdokumente.
|
||||
</p>
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="action" value="erfasse_rechnung">
|
||||
<div class="mb-2">
|
||||
<label class="form-label small">Bezeichnung</label>
|
||||
<input type="text" class="form-control form-control-sm" name="bezeichnung"
|
||||
value="{{ eingang.betreff }}" required>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label small">Betrag (EUR)</label>
|
||||
<input type="number" step="0.01" class="form-control form-control-sm" name="betrag"
|
||||
placeholder="0.00" required>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label small">Lieferant / Firma</label>
|
||||
<input type="text" class="form-control form-control-sm" name="lieferant"
|
||||
value="{{ eingang.absender_name|default:eingang.absender_email }}">
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label small">Rechnungsnummer</label>
|
||||
<input type="text" class="form-control form-control-sm" name="rechnungsnummer"
|
||||
placeholder="z.B. RE-2026001">
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label small">Kategorie</label>
|
||||
<select class="form-select form-select-sm" name="vk_kategorie">
|
||||
{% for key, label in vk_kategorie_choices %}
|
||||
<option value="{{ key }}" {% if key == "rechnung_intern" %}selected{% endif %}>{{ label }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-warning w-100">
|
||||
<i class="fas fa-file-invoice me-1"></i>Rechnung erfassen
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# Manuelle Destinataer-Zuordnung #}
|
||||
{% if not eingang.destinataer or eingang.status == "unbekannt" %}
|
||||
<div class="card mb-4 border-info">
|
||||
<div class="card-header bg-info text-white">
|
||||
<i class="fas fa-user-plus me-2"></i>Destinataer zuordnen
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="small text-muted">
|
||||
Absender <strong>{{ eingang.absender_email }}</strong>
|
||||
konnte nicht automatisch zugeordnet werden.
|
||||
</p>
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="action" value="assign_destinataer">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Destinatär</label>
|
||||
<select class="form-select" name="destinataer_id" required>
|
||||
<option value="">– Bitte wählen –</option>
|
||||
<select class="form-select form-select-sm" name="destinataer_id" required>
|
||||
<option value="">– Bitte waehlen –</option>
|
||||
{% for d in alle_destinataere %}
|
||||
<option value="{{ d.pk }}">{{ d.nachname }}, {{ d.vorname }}
|
||||
{% if d.email %} ({{ d.email }}){% endif %}
|
||||
@@ -159,16 +246,16 @@
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-warning w-100">
|
||||
<i class="fas fa-link me-1"></i>Zuordnen & Speichern
|
||||
<button type="submit" class="btn btn-info w-100">
|
||||
<i class="fas fa-link me-1"></i>Zuordnen
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Als verarbeitet markieren -->
|
||||
{% if eingang.status != "verarbeitet" %}
|
||||
{# Als verarbeitet markieren #}
|
||||
{% if eingang.status != "verarbeitet" and eingang.status != "zahlung_gebucht" %}
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
<i class="fas fa-check-circle me-2"></i>Als verarbeitet markieren
|
||||
@@ -178,9 +265,8 @@
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="action" value="mark_verarbeitet">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Interne Notiz (optional)</label>
|
||||
<textarea class="form-control" name="notizen" rows="3"
|
||||
placeholder="Z. B. 'Studiennachweis für WS 2025/26 eingegangen und geprüft.'">{{ eingang.notizen }}</textarea>
|
||||
<textarea class="form-control form-control-sm" name="notizen" rows="3"
|
||||
placeholder="Optionale Notiz...">{{ eingang.notizen }}</textarea>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-success w-100">
|
||||
<i class="fas fa-check me-1"></i>Verarbeitet
|
||||
@@ -190,7 +276,7 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Notizen bearbeiten -->
|
||||
{# Notizen #}
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
<i class="fas fa-sticky-note me-2"></i>Interne Notizen
|
||||
@@ -200,41 +286,42 @@
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="action" value="save_notizen">
|
||||
<div class="mb-3">
|
||||
<textarea class="form-control" name="notizen" rows="5"
|
||||
placeholder="Interne Notizen zur E-Mail...">{{ eingang.notizen }}</textarea>
|
||||
<textarea class="form-control form-control-sm" name="notizen" rows="4"
|
||||
placeholder="Interne Notizen...">{{ eingang.notizen }}</textarea>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-outline-secondary w-100">
|
||||
<button type="submit" class="btn btn-outline-secondary btn-sm w-100">
|
||||
<i class="fas fa-save me-1"></i>Notizen speichern
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Metadaten -->
|
||||
{# Metadaten #}
|
||||
<div class="card mb-4">
|
||||
<div class="card-header"><i class="fas fa-info-circle me-2"></i>Metadaten</div>
|
||||
<div class="card-body">
|
||||
<dl class="row mb-0 small">
|
||||
<dt class="col-6">Erfasst am</dt>
|
||||
<dd class="col-6">{{ eingang.created_at|date:"d.m.Y H:i" }}</dd>
|
||||
<dt class="col-6">Kategorie</dt>
|
||||
<dd class="col-6">{{ eingang.get_kategorie_display }}</dd>
|
||||
<dt class="col-6">Datensatz-ID</dt>
|
||||
<dd class="col-6 text-muted"><code>{{ eingang.pk|stringformat:"s"|slice:":8" }}…</code></dd>
|
||||
<dd class="col-6 text-muted"><code>{{ eingang.pk|stringformat:"s"|slice:":8" }}...</code></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Löschen -->
|
||||
{# Loeschen #}
|
||||
<div class="card border-danger">
|
||||
<div class="card-header text-danger">
|
||||
<i class="fas fa-trash-alt me-2"></i>E-Mail löschen
|
||||
<i class="fas fa-trash-alt me-2"></i>E-Mail loeschen
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="small text-muted mb-2">Diese E-Mail unwiderruflich aus dem System entfernen.</p>
|
||||
<form method="post" action="{% url 'stiftung:email_eingang_delete' eingang.pk %}"
|
||||
onsubmit="return confirm('E-Mail wirklich löschen?');">
|
||||
onsubmit="return confirm('E-Mail wirklich loeschen?');">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-outline-danger w-100">
|
||||
<i class="fas fa-trash-alt me-1"></i>Löschen
|
||||
<button type="submit" class="btn btn-outline-danger btn-sm w-100">
|
||||
<i class="fas fa-trash-alt me-1"></i>Loeschen
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -72,18 +72,21 @@
|
||||
<div class="col-12">
|
||||
<h6 class="text-primary">Verwendungsnachweis</h6>
|
||||
<p class="mb-3">
|
||||
<a href="{% url 'stiftung:dokument_detail' foerderung.verwendungsnachweis.pk %}">
|
||||
{{ foerderung.verwendungsnachweis.titel }}
|
||||
</a>
|
||||
{{ foerderung.verwendungsnachweis.titel }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Verknüpfte Dokumente -->
|
||||
<!-- Dokumente (DMS) -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h6 class="text-primary">Verknüpfte Dokumente</h6>
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<h6 class="text-primary mb-0">Dokumente</h6>
|
||||
<a href="{% url 'stiftung:dms_upload' %}?foerderung={{ foerderung.pk }}" class="btn btn-sm btn-success">
|
||||
<i class="fas fa-upload me-1"></i>Dokument hochladen
|
||||
</a>
|
||||
</div>
|
||||
{% if verknuepfte_dokumente %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-hover">
|
||||
@@ -100,8 +103,7 @@
|
||||
<tr>
|
||||
<td>
|
||||
<strong>{{ dokument.titel }}</strong>
|
||||
<br>
|
||||
<small class="text-muted">ID: {{ dokument.paperless_document_id }}</small>
|
||||
{% if dokument.dateiname_original %}<br><small class="text-muted">{{ dokument.dateiname_original }} ({{ dokument.get_human_size }})</small>{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge bg-secondary">{{ dokument.get_kontext_display }}</span>
|
||||
@@ -115,12 +117,15 @@
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group" role="group">
|
||||
<a href="{{ dokument.get_paperless_url }}" target="_blank" class="btn btn-sm btn-outline-primary" title="In Paperless öffnen">
|
||||
<i class="fas fa-external-link-alt"></i>
|
||||
<a href="{% url 'stiftung:dms_download' dokument.pk %}" class="btn btn-sm btn-outline-primary" title="Herunterladen">
|
||||
<i class="fas fa-download"></i>
|
||||
</a>
|
||||
<a href="{% url 'stiftung:dokument_update' dokument.pk %}" class="btn btn-sm btn-outline-warning" title="Bearbeiten">
|
||||
<a href="{% url 'stiftung:dms_edit' dokument.pk %}" class="btn btn-sm btn-outline-warning" title="Bearbeiten">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
<a href="{% url 'stiftung:dms_delete' dokument.pk %}" class="btn btn-sm btn-outline-danger" title="Löschen">
|
||||
<i class="fas fa-trash"></i>
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -128,17 +133,12 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
<a href="{% url 'stiftung:dokument_management' %}" class="btn btn-sm btn-success">
|
||||
<i class="fas fa-plus me-1"></i>Weiteres Dokument verknüpfen
|
||||
</a>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="text-center py-3">
|
||||
<i class="fas fa-file-alt fa-2x text-muted mb-2"></i>
|
||||
<p class="text-muted mb-2">Keine Dokumente verknüpft</p>
|
||||
<a href="{% url 'stiftung:dokument_management' %}" class="btn btn-success btn-sm">
|
||||
<i class="fas fa-plus me-1"></i>Erstes Dokument verknüpfen
|
||||
<p class="text-muted mb-2">Keine Dokumente vorhanden</p>
|
||||
<a href="{% url 'stiftung:dms_upload' %}?foerderung={{ foerderung.pk }}" class="btn btn-success btn-sm">
|
||||
<i class="fas fa-upload me-1"></i>Erstes Dokument hochladen
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-text">
|
||||
Optionale Verknüpfung zu einem Dokument aus dem Paperless-System
|
||||
Optionale Verknüpfung zu einem Verwendungsnachweis (Legacy)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -177,6 +177,35 @@
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if geschichte_dokumente %}
|
||||
<div class="card mt-3">
|
||||
<div class="card-header bg-dark text-white">
|
||||
<h6 class="mb-0"><i class="fas fa-landmark me-2"></i>Verfuegbare Geschichtsdokumente</h6>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<div class="list-group list-group-flush">
|
||||
{% for dok in geschichte_dokumente %}
|
||||
<div class="list-group-item">
|
||||
<div class="d-flex justify-content-between align-items-start">
|
||||
<div>
|
||||
<div class="small fw-bold">{{ dok.titel|truncatechars:40 }}</div>
|
||||
<small class="text-muted">{{ dok.dateiname_original }} ({{ dok.get_human_size }})</small>
|
||||
<br><small class="text-muted">{{ dok.erstellt_am|date:"d.m.Y" }}</small>
|
||||
</div>
|
||||
<a href="{% url 'stiftung:dms_download' dok.pk %}" class="btn btn-sm btn-outline-primary" title="Herunterladen">
|
||||
<i class="fas fa-download"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer small text-muted">
|
||||
Dokumente aus dem DMS mit Kontext "Stiftungsgeschichte". Eingegangen per E-Mail oder manuell hochgeladen.
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -303,11 +303,8 @@
|
||||
{% endif %}
|
||||
|
||||
<div class="d-grid gap-2">
|
||||
<a href="{% url 'stiftung:dokument_management' %}" class="btn btn-outline-primary btn-sm">
|
||||
<i class="fas fa-link me-2"></i>Dokumente verknüpfen
|
||||
</a>
|
||||
<a href="mailto:paperless@vhtv-stiftung.de?subject=Dokumente für {{ land }}" class="btn btn-outline-info btn-sm">
|
||||
<i class="fas fa-envelope me-2"></i>E-Mail an Paperless
|
||||
<a href="{% url 'stiftung:dms_list' %}" class="btn btn-outline-primary btn-sm">
|
||||
<i class="fas fa-folder-open me-2"></i>Zum DMS
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -234,14 +234,11 @@
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="text-muted mb-3">
|
||||
Dokumente werden über Paperless verwaltet und verknüpft.
|
||||
Dokumente werden im DMS verwaltet.
|
||||
</p>
|
||||
<div class="d-grid gap-2">
|
||||
<a href="{% url 'stiftung:dokument_management' %}" class="btn btn-outline-primary btn-sm">
|
||||
<i class="fas fa-link me-2"></i>Dokumente verknüpfen
|
||||
</a>
|
||||
<a href="mailto:paperless@vhtv-stiftung.de" class="btn btn-outline-info btn-sm">
|
||||
<i class="fas fa-envelope me-2"></i>E-Mail an Paperless
|
||||
<a href="{% url 'stiftung:dms_list' %}" class="btn btn-outline-primary btn-sm">
|
||||
<i class="fas fa-folder-open me-2"></i>Zum DMS
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -479,14 +479,14 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Verknüpfte Dokumente -->
|
||||
<!-- Dokumente (DMS) -->
|
||||
<div class="card shadow mb-4">
|
||||
<div class="card-header py-3 d-flex justify-content-between align-items-center">
|
||||
<h6 class="m-0 font-weight-bold text-success">
|
||||
<i class="fas fa-file-alt me-2"></i>Verknüpfte Dokumente
|
||||
<i class="fas fa-file-alt me-2"></i>Dokumente
|
||||
</h6>
|
||||
<a href="{% url 'stiftung:dokument_management' %}" class="btn btn-sm btn-success">
|
||||
<i class="fas fa-plus me-2"></i>Dokument verknüpfen
|
||||
<a href="{% url 'stiftung:dms_upload' %}?land={{ land.pk }}" class="btn btn-sm btn-success">
|
||||
<i class="fas fa-upload me-2"></i>Dokument hochladen
|
||||
</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@@ -506,8 +506,7 @@
|
||||
<tr>
|
||||
<td>
|
||||
<strong>{{ dokument.titel }}</strong>
|
||||
<br>
|
||||
<small class="text-muted">ID: {{ dokument.paperless_document_id }}</small>
|
||||
{% if dokument.dateiname_original %}<br><small class="text-muted">{{ dokument.dateiname_original }} ({{ dokument.get_human_size }})</small>{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge bg-secondary">{{ dokument.get_kontext_display }}</span>
|
||||
@@ -521,17 +520,14 @@
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group" role="group">
|
||||
<a href="{{ dokument.get_paperless_url }}" target="_blank" class="btn btn-sm btn-outline-primary" title="In Paperless öffnen">
|
||||
<i class="fas fa-external-link-alt"></i>
|
||||
<a href="{% url 'stiftung:dms_download' dokument.pk %}" class="btn btn-sm btn-outline-primary" title="Herunterladen">
|
||||
<i class="fas fa-download"></i>
|
||||
</a>
|
||||
<a href="{{ dokument.get_paperless_thumbnail_url }}" target="_blank" class="btn btn-sm btn-outline-info" title="Thumbnail anzeigen">
|
||||
<i class="fas fa-image"></i>
|
||||
</a>
|
||||
<a href="{% url 'stiftung:dokument_update' dokument.pk %}" class="btn btn-sm btn-outline-warning" title="Bearbeiten">
|
||||
<a href="{% url 'stiftung:dms_edit' dokument.pk %}" class="btn btn-sm btn-outline-warning" title="Bearbeiten">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
<a href="{% url 'stiftung:dokument_delete' dokument.pk %}" class="btn btn-sm btn-outline-danger" title="Verknüpfung löschen">
|
||||
<i class="fas fa-unlink"></i>
|
||||
<a href="{% url 'stiftung:dms_delete' dokument.pk %}" class="btn btn-sm btn-outline-danger" title="Löschen">
|
||||
<i class="fas fa-trash"></i>
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
@@ -543,10 +539,10 @@
|
||||
{% else %}
|
||||
<div class="text-center py-4">
|
||||
<i class="fas fa-file-alt fa-3x text-muted mb-3"></i>
|
||||
<h5 class="text-muted">Keine Dokumente verknüpft</h5>
|
||||
<p class="text-muted">Verknüpfen Sie Dokumente aus Paperless mit dieser Länderei.</p>
|
||||
<a href="{% url 'stiftung:dokument_management' %}" class="btn btn-success">
|
||||
<i class="fas fa-plus me-2"></i>Erstes Dokument verknüpfen
|
||||
<h5 class="text-muted">Keine Dokumente vorhanden</h5>
|
||||
<p class="text-muted">Laden Sie Dokumente direkt hoch und verknüpfen Sie sie mit dieser Länderei.</p>
|
||||
<a href="{% url 'stiftung:dms_upload' %}?land={{ land.pk }}" class="btn btn-success">
|
||||
<i class="fas fa-upload me-2"></i>Erstes Dokument hochladen
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@@ -188,12 +188,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Verknüpfte Dokumente -->
|
||||
<!-- Dokumente (DMS) -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h5 class="mb-0"><i class="fas fa-folder-open me-2"></i>Verknüpfte Dokumente</h5>
|
||||
<a href="/dokumente/verwaltung/" class="btn btn-sm btn-outline-primary">
|
||||
<i class="fas fa-link me-1"></i>Dokument verknüpfen
|
||||
<h5 class="mb-0"><i class="fas fa-folder-open me-2"></i>Dokumente</h5>
|
||||
<a href="{% url 'stiftung:dms_upload' %}?verpachtung={{ landverpachtung.pk }}" class="btn btn-sm btn-outline-primary">
|
||||
<i class="fas fa-upload me-1"></i>Dokument hochladen
|
||||
</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@@ -212,14 +212,21 @@
|
||||
<tr>
|
||||
<td>
|
||||
<strong>{{ doc.titel|default:"Ohne Titel" }}</strong>
|
||||
<br>
|
||||
<small class="text-muted">Paperless-ID: {{ doc.paperless_document_id }}</small>
|
||||
{% if doc.dateiname_original %}<br><small class="text-muted">{{ doc.dateiname_original }} ({{ doc.get_human_size }})</small>{% endif %}
|
||||
</td>
|
||||
<td>{{ doc.get_kontext_display }}</td>
|
||||
<td>
|
||||
<a href="{{ doc.get_paperless_url }}" target="_blank" class="btn btn-sm btn-outline-primary" title="In Paperless öffnen">
|
||||
<i class="fas fa-external-link-alt"></i>
|
||||
</a>
|
||||
<div class="btn-group" role="group">
|
||||
<a href="{% url 'stiftung:dms_download' doc.pk %}" class="btn btn-sm btn-outline-primary" title="Herunterladen">
|
||||
<i class="fas fa-download"></i>
|
||||
</a>
|
||||
<a href="{% url 'stiftung:dms_edit' doc.pk %}" class="btn btn-sm btn-outline-warning" title="Bearbeiten">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
<a href="{% url 'stiftung:dms_delete' doc.pk %}" class="btn btn-sm btn-outline-danger" title="Löschen">
|
||||
<i class="fas fa-trash"></i>
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
@@ -227,7 +234,7 @@
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<p class="text-muted">Keine Dokumente verknüpft.</p>
|
||||
<p class="text-muted">Keine Dokumente vorhanden.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -279,14 +279,14 @@
|
||||
|
||||
<!-- Legacy Verpachtungen entfernt für saubere UI -->
|
||||
|
||||
<!-- Verknüpfte Dokumente -->
|
||||
<!-- Dokumente (DMS) -->
|
||||
<div class="card shadow mb-4">
|
||||
<div class="card-header bg-success text-white d-flex justify-content-between align-items-center">
|
||||
<h5 class="card-title mb-0">
|
||||
<i class="fas fa-file-alt me-2"></i>Verknüpfte Dokumente
|
||||
<i class="fas fa-file-alt me-2"></i>Dokumente
|
||||
</h5>
|
||||
<a href="{% url 'stiftung:dokument_management' %}" class="btn btn-light btn-sm">
|
||||
<i class="fas fa-plus me-1"></i>Dokument verknüpfen
|
||||
<a href="{% url 'stiftung:dms_upload' %}?paechter={{ paechter.pk }}" class="btn btn-light btn-sm">
|
||||
<i class="fas fa-upload me-1"></i>Dokument hochladen
|
||||
</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@@ -306,8 +306,7 @@
|
||||
<tr>
|
||||
<td>
|
||||
<strong>{{ dokument.titel }}</strong>
|
||||
<br>
|
||||
<small class="text-muted">ID: {{ dokument.paperless_document_id }}</small>
|
||||
{% if dokument.dateiname_original %}<br><small class="text-muted">{{ dokument.dateiname_original }} ({{ dokument.get_human_size }})</small>{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge bg-secondary">{{ dokument.get_kontext_display }}</span>
|
||||
@@ -321,17 +320,14 @@
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group" role="group">
|
||||
<a href="{{ dokument.get_paperless_url }}" target="_blank" class="btn btn-sm btn-outline-primary" title="In Paperless öffnen">
|
||||
<i class="fas fa-external-link-alt"></i>
|
||||
<a href="{% url 'stiftung:dms_download' dokument.pk %}" class="btn btn-sm btn-outline-primary" title="Herunterladen">
|
||||
<i class="fas fa-download"></i>
|
||||
</a>
|
||||
<a href="{{ dokument.get_paperless_thumbnail_url }}" target="_blank" class="btn btn-sm btn-outline-info" title="Thumbnail anzeigen">
|
||||
<i class="fas fa-image"></i>
|
||||
</a>
|
||||
<a href="{% url 'stiftung:dokument_update' dokument.pk %}" class="btn btn-sm btn-outline-warning" title="Bearbeiten">
|
||||
<a href="{% url 'stiftung:dms_edit' dokument.pk %}" class="btn btn-sm btn-outline-warning" title="Bearbeiten">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
<a href="{% url 'stiftung:dokument_delete' dokument.pk %}" class="btn btn-sm btn-outline-danger" title="Verknüpfung löschen">
|
||||
<i class="fas fa-unlink"></i>
|
||||
<a href="{% url 'stiftung:dms_delete' dokument.pk %}" class="btn btn-sm btn-outline-danger" title="Löschen">
|
||||
<i class="fas fa-trash"></i>
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
@@ -343,10 +339,10 @@
|
||||
{% else %}
|
||||
<div class="text-center py-4">
|
||||
<i class="fas fa-file-alt fa-3x text-muted mb-3"></i>
|
||||
<h5 class="text-muted">Keine Dokumente verknüpft</h5>
|
||||
<p class="text-muted">Verknüpfen Sie Dokumente aus Paperless mit diesem Pächter.</p>
|
||||
<a href="{% url 'stiftung:dokument_management' %}" class="btn btn-success">
|
||||
<i class="fas fa-plus me-2"></i>Erstes Dokument verknüpfen
|
||||
<h5 class="text-muted">Keine Dokumente vorhanden</h5>
|
||||
<p class="text-muted">Laden Sie Dokumente direkt hoch und verknüpfen Sie sie mit diesem Pächter.</p>
|
||||
<a href="{% url 'stiftung:dms_upload' %}?paechter={{ paechter.pk }}" class="btn btn-success">
|
||||
<i class="fas fa-upload me-2"></i>Erstes Dokument hochladen
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@@ -296,8 +296,8 @@
|
||||
<span class="badge bg-primary ms-2">{{ verknuepfte_dokumente.count }}</span>
|
||||
{% endif %}
|
||||
</h6>
|
||||
<a href="/dokumente/verwaltung/" class="btn btn-outline-primary btn-sm">
|
||||
<i class="fas fa-link me-1"></i>Dokumentenverwaltung
|
||||
<a href="{% url 'stiftung:dms_list' %}" class="btn btn-outline-primary btn-sm">
|
||||
<i class="fas fa-folder-open me-1"></i>Dokumentenverwaltung
|
||||
</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@@ -318,10 +318,7 @@
|
||||
</small>
|
||||
</div>
|
||||
<div class="d-flex gap-2">
|
||||
<a href="/api/paperless/documents/{{ dokument.paperless_document_id }}/"
|
||||
class="btn btn-outline-primary btn-sm" target="_blank" title="In Paperless öffnen">
|
||||
<i class="fas fa-external-link-alt"></i>
|
||||
</a>
|
||||
<span class="badge bg-secondary">Legacy</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
@@ -332,7 +329,7 @@
|
||||
<small class="text-muted">
|
||||
<i class="fas fa-info-circle me-1"></i>
|
||||
Es werden nur die neuesten 10 Dokumente angezeigt.
|
||||
<a href="/dokumente/verwaltung/" class="text-decoration-none">Alle Dokumente anzeigen</a>
|
||||
<a href="{% url 'stiftung:dms_list' %}" class="text-decoration-none">Alle Dokumente anzeigen</a>
|
||||
</small>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -342,7 +339,7 @@
|
||||
<h5 class="text-muted">Keine Dokumente verknüpft</h5>
|
||||
<p class="text-muted">
|
||||
Verknüpfen Sie Dokumente über die
|
||||
<a href="/dokumente/verwaltung/" class="text-decoration-none">Dokumentenverwaltung</a>.
|
||||
<a href="{% url 'stiftung:dms_list' %}" class="text-decoration-none">Dokumentenverwaltung</a>.
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@@ -292,66 +292,60 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Verknüpfte Dokumente -->
|
||||
{% if verknuepfte_dokumente %}
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card shadow mb-4">
|
||||
<div class="card-header bg-success text-white">
|
||||
<h5 class="card-title mb-0">
|
||||
<i class="fas fa-file-alt me-2"></i>Verknüpfte Dokumente ({{ verknuepfte_dokumente.count }})
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
{% for dokument in verknuepfte_dokumente %}
|
||||
<div class="col-md-6 mb-3">
|
||||
<div class="card border-left-success">
|
||||
<div class="card-body py-2">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h6 class="mb-1">{{ dokument.titel }}</h6>
|
||||
<small class="text-muted">{{ dokument.kontext }}</small>
|
||||
</div>
|
||||
<div>
|
||||
<a href="{{ dokument.paperless_url }}" target="_blank"
|
||||
class="btn btn-sm btn-outline-success">
|
||||
<i class="fas fa-external-link-alt"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Dokument Management Section -->
|
||||
<!-- Dokumente (DMS) -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card shadow">
|
||||
<div class="card-header py-3 d-flex justify-content-between align-items-center">
|
||||
<h6 class="m-0 font-weight-bold text-primary">
|
||||
<i class="fas fa-paperclip me-2"></i>Dokumente verwalten
|
||||
<i class="fas fa-file-alt me-2"></i>Dokumente{% if verknuepfte_dokumente %} ({{ verknuepfte_dokumente.count }}){% endif %}
|
||||
</h6>
|
||||
<a href="{% url 'stiftung:dokument_create' %}?land_verpachtung_id={{ verpachtung.pk }}"
|
||||
<a href="{% url 'stiftung:dms_upload' %}?verpachtung={{ verpachtung.pk }}"
|
||||
class="btn btn-sm btn-success">
|
||||
<i class="fas fa-plus me-1"></i>Dokument verknüpfen
|
||||
<i class="fas fa-upload me-1"></i>Dokument hochladen
|
||||
</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if verknuepfte_dokumente %}
|
||||
<p class="text-muted mb-3">{{ verknuepfte_dokumente.count }} Dokument{{ verknuepfte_dokumente.count|pluralize:"e" }} verknüpft</p>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-sm align-middle">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Titel</th>
|
||||
<th>Kontext</th>
|
||||
<th>Aktionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for dokument in verknuepfte_dokumente %}
|
||||
<tr>
|
||||
<td>
|
||||
<strong>{{ dokument.titel }}</strong>
|
||||
{% if dokument.dateiname_original %}<br><small class="text-muted">{{ dokument.dateiname_original }} ({{ dokument.get_human_size }})</small>{% endif %}
|
||||
</td>
|
||||
<td><span class="badge bg-secondary">{{ dokument.get_kontext_display }}</span></td>
|
||||
<td>
|
||||
<div class="btn-group" role="group">
|
||||
<a href="{% url 'stiftung:dms_download' dokument.pk %}" class="btn btn-sm btn-outline-primary" title="Herunterladen">
|
||||
<i class="fas fa-download"></i>
|
||||
</a>
|
||||
<a href="{% url 'stiftung:dms_edit' dokument.pk %}" class="btn btn-sm btn-outline-warning" title="Bearbeiten">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
<a href="{% url 'stiftung:dms_delete' dokument.pk %}" class="btn btn-sm btn-outline-danger" title="Löschen">
|
||||
<i class="fas fa-trash"></i>
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<p class="text-muted mb-0">
|
||||
<i class="fas fa-info-circle me-2"></i>
|
||||
Noch keine Dokumente mit dieser Verpachtung verknüpft.
|
||||
Klicken Sie auf "Dokument verknüpfen", um Dokumente aus dem Paperless-System zu verknüpfen.
|
||||
Noch keine Dokumente vorhanden.
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
@@ -341,7 +341,7 @@
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="text-muted small">Dokumente können nach dem Speichern der Verpachtung verknüpft werden.</p>
|
||||
<a href="{% url 'stiftung:dokument_create' %}?land_verpachtung_id={{ form.instance.pk }}"
|
||||
<a href="{% url 'stiftung:dms_upload' %}?land_verpachtung_id={{ form.instance.pk }}"
|
||||
class="btn btn-outline-primary btn-sm">
|
||||
<i class="fas fa-plus me-1"></i>Neues Dokument
|
||||
</a>
|
||||
|
||||
Reference in New Issue
Block a user