diff --git a/dokumente/admin.py b/dokumente/admin.py
index f2002ad..82331ae 100644
--- a/dokumente/admin.py
+++ b/dokumente/admin.py
@@ -207,10 +207,43 @@ class ThemaAdmin(admin.ModelAdmin):
search_fields = ['name']
ordering = ['name']
+@admin.register(Vorgabe)
+class VorgabeAdmin(NestedModelAdmin):
+ form = VorgabeForm
+ list_display = ['vorgabe_nummer', 'titel', 'dokument', 'thema', 'gueltigkeit_von', 'gueltigkeit_bis']
+ list_filter = ['dokument', 'thema', 'gueltigkeit_von', 'gueltigkeit_bis']
+ search_fields = ['nummer', 'titel', 'dokument__nummer', 'dokument__name']
+ autocomplete_fields = ['stichworte', 'referenzen', 'relevanz']
+ ordering = ['dokument', 'order']
+
+ inlines = [
+ VorgabeKurztextInline,
+ VorgabeLangtextInline,
+ ChecklistenfragenInline
+ ]
+
+ fieldsets = (
+ ('Grunddaten', {
+ 'fields': (('order', 'nummer'), ('dokument', 'thema'), 'titel'),
+ 'classes': ('wide',),
+ }),
+ ('Gültigkeit', {
+ 'fields': (('gueltigkeit_von', 'gueltigkeit_bis'),),
+ 'classes': ('wide',),
+ }),
+ ('Verknüpfungen', {
+ 'fields': (('referenzen', 'stichworte', 'relevanz'),),
+ 'classes': ('wide',),
+ }),
+ )
+
+ def vorgabe_nummer(self, obj):
+ return obj.Vorgabennummer()
+ vorgabe_nummer.short_description = 'Vorgabennummer'
+
admin.site.register(Checklistenfrage)
admin.site.register(Dokumententyp)
#admin.site.register(Person)
#admin.site.register(Referenz, DraggableM§PTTAdmin)
-admin.site.register(Vorgabe)
#admin.site.register(Changelog)
diff --git a/dokumente/templates/standards/incomplete_vorgaben.html b/dokumente/templates/standards/incomplete_vorgaben.html
index d0d8251..e6c9f15 100644
--- a/dokumente/templates/standards/incomplete_vorgaben.html
+++ b/dokumente/templates/standards/incomplete_vorgaben.html
@@ -2,166 +2,150 @@
{% block content %}
Unvollständige Vorgaben
-
-
-
-
-
-
- {% if no_references %}
-
- {% else %}
-
Alle Vorgaben haben Referenzen.
- {% endif %}
-
-
+{% if vorgaben_data %}
+
-
-
-
-
-
- {% if no_stichworte %}
-
- {% else %}
-
Alle Vorgaben haben Stichworte.
- {% endif %}
-
-
-
-
-
-
-
-
-
- {% if no_text %}
-
- {% else %}
-
Alle Vorgaben haben Kurz- oder Langtext.
- {% endif %}
-
-
-
-
-
-
-
-
-
- {% if no_checklistenfragen %}
-
- {% else %}
-
Alle Vorgaben haben Checklistenfragen.
- {% endif %}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{{ no_references|length }}
-
Ohne Referenzen
+
+
+
+
+
+
+
+
+
+
+
+
+
0
+
Ohne Checklistenfragen
+
-
-
-
{{ no_stichworte|length }}
-
Ohne Stichworte
-
-
-
-
-
{{ no_text|length }}
-
Ohne Text
-
-
-
-
-
{{ no_checklistenfragen|length }}
-
Ohne Checklistenfragen
+
+
+
Gesamt: {{ vorgaben_data|length }} unvollständige Vorgaben
-
+{% else %}
+
+
+ Alle Vorgaben sind vollständig!
+
+
Alle Vorgaben haben Referenzen, Stichworte, Text und Checklistenfragen.
+
+
+
+ Zurück zur Übersicht
+
+
+
+{% endif %}
+
+
{% endblock %}
\ No newline at end of file
diff --git a/dokumente/tests.py b/dokumente/tests.py
index 6174915..317df48 100644
--- a/dokumente/tests.py
+++ b/dokumente/tests.py
@@ -966,10 +966,13 @@ class IncompleteVorgabenTest(TestCase):
"""Test that the page contains expected content"""
response = self.client.get(reverse('incomplete_vorgaben'))
self.assertContains(response, 'Unvollständige Vorgaben')
- self.assertContains(response, 'Vorgaben ohne Referenzen')
- self.assertContains(response, 'Vorgaben ohne Stichworte')
- self.assertContains(response, 'Vorgaben ohne Kurz- oder Langtext')
- self.assertContains(response, 'Vorgaben ohne Checklistenfragen')
+ self.assertContains(response, 'Referenzen')
+ self.assertContains(response, 'Stichworte')
+ self.assertContains(response, 'Text')
+ self.assertContains(response, 'Checklistenfragen')
+ # Check for table structure
+ self.assertContains(response, '
')
+ self.assertContains(response, '| Referenzen | ')
def test_no_references_list(self):
"""Test that Vorgaben without references are listed"""
@@ -996,27 +999,34 @@ class IncompleteVorgabenTest(TestCase):
self.assertNotContains(response, 'Vollständige Vorgabe') # Should not appear
def test_vorgabe_links(self):
- """Test that Vorgaben link to their detail pages"""
+ """Test that Vorgaben link to their admin pages"""
response = self.client.get(reverse('incomplete_vorgaben'))
- # Should contain links to Vorgabe detail pages
- self.assertContains(response, f'href="/dokumente/{self.dokument.nummer}/#TEST-001.T.2"')
- self.assertContains(response, f'href="/dokumente/{self.dokument.nummer}/#TEST-001.T.3"')
- self.assertContains(response, f'href="/dokumente/{self.dokument.nummer}/#TEST-001.T.4"')
- self.assertContains(response, f'href="/dokumente/{self.dokument.nummer}/#TEST-001.T.5"')
+ # Should contain links to Vorgabe admin pages
+ self.assertContains(response, 'href="/autorenumgebung/dokumente/vorgabe/2/change/"')
+ self.assertContains(response, 'href="/autorenumgebung/dokumente/vorgabe/3/change/"')
+ self.assertContains(response, 'href="/autorenumgebung/dokumente/vorgabe/4/change/"')
+ self.assertContains(response, 'href="/autorenumgebung/dokumente/vorgabe/5/change/"')
def test_badge_counts(self):
"""Test that badge counts are correct"""
response = self.client.get(reverse('incomplete_vorgaben'))
- # Each category should have exactly 1 Vorgabe
- self.assertContains(response, '1', count=4)
+ # Check that JavaScript updates the counts correctly
+ self.assertContains(response, 'id="no-references-count"')
+ self.assertContains(response, 'id="no-stichworte-count"')
+ self.assertContains(response, 'id="no-text-count"')
+ self.assertContains(response, 'id="no-checklistenfragen-count"')
+ # Check total count
+ self.assertContains(response, 'Gesamt: 4 unvollständige Vorgaben')
def test_summary_section(self):
"""Test that summary section shows correct counts"""
response = self.client.get(reverse('incomplete_vorgaben'))
self.assertContains(response, 'Zusammenfassung')
- self.assertContains(response, '1
', count=2) # No refs, no stichworte
- self.assertContains(response, '1
') # No text
- self.assertContains(response, '1
') # No checklistenfragen
+ self.assertContains(response, 'Ohne Referenzen')
+ self.assertContains(response, 'Ohne Stichworte')
+ self.assertContains(response, 'Ohne Text')
+ self.assertContains(response, 'Ohne Checklistenfragen')
+ self.assertContains(response, 'Gesamt: 4 unvollständige Vorgaben')
def test_empty_lists_message(self):
"""Test that appropriate messages are shown when lists are empty"""
@@ -1024,10 +1034,8 @@ class IncompleteVorgabenTest(TestCase):
Vorgabe.objects.exclude(pk=self.complete_vorgabe.pk).delete()
response = self.client.get(reverse('incomplete_vorgaben'))
- self.assertContains(response, 'Alle Vorgaben haben Referenzen.')
- self.assertContains(response, 'Alle Vorgaben haben Stichworte.')
- self.assertContains(response, 'Alle Vorgaben haben Kurz- oder Langtext.')
- self.assertContains(response, 'Alle Vorgaben haben Checklistenfragen.')
+ self.assertContains(response, 'Alle Vorgaben sind vollständig!')
+ self.assertContains(response, 'Alle Vorgaben haben Referenzen, Stichworte, Text und Checklistenfragen.')
def test_back_link(self):
"""Test that back link to standard list exists"""
diff --git a/dokumente/views.py b/dokumente/views.py
index 273df9c..d0ac07d 100644
--- a/dokumente/views.py
+++ b/dokumente/views.py
@@ -64,36 +64,41 @@ def is_staff_user(user):
@user_passes_test(is_staff_user)
def incomplete_vorgaben(request):
"""
- Show lists of incomplete Vorgaben:
- 1. Ones with no references
- 2. Ones with no Stichworte
- 3. Ones without Kurz- or Langtext
- 4. Ones without Checklistenfragen
+ Show table of all Vorgaben with completeness status:
+ - References (✓ or ✗)
+ - Stichworte (✓ or ✗)
+ - Text (✓ or ✗)
+ - Checklistenfragen (✓ or ✗)
"""
# Get all active Vorgaben
- all_vorgaben = Vorgabe.objects.all().select_related('dokument', 'thema')
+ all_vorgaben = Vorgabe.objects.all().select_related('dokument', 'thema').prefetch_related(
+ 'referenzen', 'stichworte', 'checklistenfragen', 'vorgabekurztext_set', 'vorgabelangtext_set'
+ )
- # 1. Vorgaben with no references
- no_references = [v for v in all_vorgaben if not v.referenzen.exists()]
-
- # 2. Vorgaben with no Stichworte
- no_stichworte = [v for v in all_vorgaben if not v.stichworte.exists()]
-
- # 3. Vorgaben without Kurz- or Langtext
- no_text = []
+ # Build table data
+ vorgaben_data = []
for vorgabe in all_vorgaben:
- has_kurztext = VorgabeKurztext.objects.filter(abschnitt=vorgabe).exists()
- has_langtext = VorgabeLangtext.objects.filter(abschnitt=vorgabe).exists()
-
- if not has_kurztext and not has_langtext:
- no_text.append(vorgabe)
+ has_references = vorgabe.referenzen.exists()
+ has_stichworte = vorgabe.stichworte.exists()
+ has_kurztext = vorgabe.vorgabekurztext_set.exists()
+ has_langtext = vorgabe.vorgabelangtext_set.exists()
+ has_text = has_kurztext or has_langtext
+ has_checklistenfragen = vorgabe.checklistenfragen.exists()
+
+ # Only include Vorgaben that are incomplete in at least one way
+ if not (has_references and has_stichworte and has_text and has_checklistenfragen):
+ vorgaben_data.append({
+ 'vorgabe': vorgabe,
+ 'has_references': has_references,
+ 'has_stichworte': has_stichworte,
+ 'has_text': has_text,
+ 'has_checklistenfragen': has_checklistenfragen,
+ 'is_complete': has_references and has_stichworte and has_text and has_checklistenfragen
+ })
- # 4. Vorgaben without Checklistenfragen
- no_checklistenfragen = [v for v in all_vorgaben if not v.checklistenfragen.exists()]
+ # Sort by document number and Vorgabe number
+ vorgaben_data.sort(key=lambda x: (x['vorgabe'].dokument.nummer, x['vorgabe'].Vorgabennummer()))
return render(request, 'standards/incomplete_vorgaben.html', {
- 'no_references': no_references,
- 'no_stichworte': no_stichworte,
- 'no_text': no_text,
- 'no_checklistenfragen': no_checklistenfragen,
+ 'vorgaben_data': vorgaben_data,
})