feat(aufgaben): Verknüpfungen, implizite Fälligkeit, Issue-Facade (WP-0015)

- Aufgabe.erstellt_am für implizite 7-Tage-Fälligkeit
- frist_effektiv property; ist_ueberfaellig nutzt sie
- AufgabenVerknuepfung (GenericForeignKey) mit HTMX-Panel
- ExternalIssue (OneToOne) mit IssueAdapter-ABC und HTMX-Panel
- link_registry.py und issue_facade.py als zentrale Registries
- 8 neue Tests, 76 gesamt grün

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-14 04:18:28 +02:00
parent a0c0ddf2eb
commit 816c281f6a
19 changed files with 713 additions and 19 deletions

View File

@@ -17,7 +17,17 @@
{% render_field aufgabe "typ" "Typ" %}
{% render_field aufgabe "prioritaet" "Priorität" %}
{% render_field aufgabe "status" "Status" %}
{% render_field aufgabe "frist" "Frist" %}
<div class="flex justify-between text-sm py-0.5">
<dt class="text-slate-500">Frist</dt>
<dd class="text-slate-800">
{% if aufgabe.frist %}
{{ aufgabe.frist }}
{% else %}
<span class="text-slate-400">keine</span>
<span class="text-xs text-amber-600 ml-1">(implizit fällig: {{ aufgabe.frist_effektiv|date:"d.m.Y" }})</span>
{% endif %}
</dd>
</div>
{% render_field aufgabe "verantwortlicher" "Verantwortlich" %}
{% if aufgabe.beschreibung %}
<div>
@@ -61,6 +71,28 @@
class="text-sm text-blue-600 hover:underline">{{ aufgabe.los.lostitel }}</a>
</div>
{% endif %}
<!-- Verknüpfungen -->
<div class="card">
<div class="flex items-center justify-between mb-2">
<p class="text-xs font-medium text-slate-500 uppercase tracking-wide">Verknüpfungen</p>
<button class="btn-ghost text-xs"
hx-get="{% url 'ausschreibungen:aufgaben:verknuepfung_neu' ausschreibung.pk aufgabe.pk %}"
hx-target="#verknuepfung-form-container"
hx-swap="innerHTML">+ Verknüpfen</button>
</div>
<div id="verknuepfung-form-container"></div>
<ul id="verknuepfungen-list" class="space-y-1 mt-1">
{% for v in aufgabe.verknuepfungen.all %}
{% include "aufgaben/partials/verknuepfung_row.html" %}
{% endfor %}
</ul>
</div>
<!-- Externes Issue -->
<div class="card" id="external-issue-panel">
{% include "aufgaben/partials/external_issue_panel.html" %}
</div>
</div>
</div>