diff --git a/app/apps/cases/admin.py b/app/apps/cases/admin.py index 82de7ae51..d317b6b04 100644 --- a/app/apps/cases/admin.py +++ b/app/apps/cases/admin.py @@ -1,4 +1,4 @@ -from datetime import date +from datetime import date, timedelta from apps.cases.models import ( Advertisement, @@ -20,6 +20,11 @@ from django import forms from django.contrib import admin from django.contrib.contenttypes.models import ContentType +from django.db.models import Exists, OuterRef +from django.http import HttpResponse +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ +from openpyxl import Workbook class LabelThemeModelChoiceField(forms.ModelChoiceField): @@ -98,6 +103,45 @@ def remove_advertisement_linklist_items(modeladmin, request, queryset): citizen_report.save() +def export_queryset_to_excel(modeladmin, request, queryset): + wb = Workbook() + ws = wb.active + ws.title = "Zaken" + headers = ["Zaak ID", "Address", "Thema", "Aanleiding", "Startdatum", "Einddatum"] + ws.append(headers) + + for case in queryset: + # Format the dates in 'DD-MM-YYYY' format + start_date_formatted = ( + case.start_date.strftime("%d-%m-%Y") if case.start_date else "" + ) + end_date_formatted = case.end_date.strftime("%d-%m-%Y") if case.end_date else "" + + ws.append( + [ + case.id, + case.address.full_address, + case.theme.name, + case.reason.name, + start_date_formatted, + end_date_formatted, + ] + ) + + # Create an HTTP response with the Excel file + response = HttpResponse( + content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + ) + response["Content-Disposition"] = "attachment; filename=aza_cases_export.xlsx" + + wb.save(response) + return response + + +# Short description for the action, which will be displayed in the admin action dropdown +export_queryset_to_excel.short_description = "Export Cases to Excel" + + @admin.register(CaseDocument) class CaseDocumentAdmin(admin.ModelAdmin): list_display = ( @@ -109,6 +153,43 @@ class CaseDocumentAdmin(admin.ModelAdmin): search_fields = ("case__id",) +class BewaartermijnFilter(admin.SimpleListFilter): + title = _("Verlopen Bewaartermijnen") + parameter_name = "bewaartermijn" + + def lookups(self, request, model_admin): + """Options that will appear in the filter dropdown.""" + return ( + ("toezicht_5_jaar", _("Toezicht bewaartermijn (5 jaar)")), + ("handhaving_10_jaar", _("Handhaving bewaartermijn (10 jaar)")), + ) + + def queryset(self, request, queryset): + """Filter the queryset based on the selected filter option.""" + if self.value() == "toezicht_5_jaar": + # Filter cases that ended more than 5 years ago and have NO status HANDHAVING + five_years_ago = timezone.now().date() - timedelta(days=5 * 365) + return queryset.exclude( + Exists( + CaseState.objects.filter( + case=OuterRef("pk"), status=CaseState.CaseStateChoice.HANDHAVING + ) + ) + ).filter(end_date__lt=five_years_ago) + elif self.value() == "handhaving_10_jaar": + # Filter cases that ended more than 10 years ago and have a status HANDHAVING + ten_years_ago = timezone.now().date() - timedelta(days=10 * 365) + return queryset.filter( + Exists( + CaseState.objects.filter( + case=OuterRef("pk"), status=CaseState.CaseStateChoice.HANDHAVING + ) + ), + end_date__lt=ten_years_ago, + ) + return queryset + + @admin.register(Case) class CaseAdmin(admin.ModelAdmin): form = CaseAdminForm @@ -122,6 +203,7 @@ class CaseAdmin(admin.ModelAdmin): ) list_filter = ( "theme", + BewaartermijnFilter, "start_date", "end_date", "address__housing_corporation", @@ -138,9 +220,7 @@ class CaseAdmin(admin.ModelAdmin): "address__street_name", "address__postal_code", ) - actions = [ - create_main_worflow_for_case, - ] + actions = [create_main_worflow_for_case, export_queryset_to_excel] @admin.register(CaseTheme) diff --git a/app/requirements.txt b/app/requirements.txt index 62a7a29bc..b1647ec23 100644 --- a/app/requirements.txt +++ b/app/requirements.txt @@ -51,6 +51,7 @@ jsonschema==4.4.0 kombu<6.0 model-bakery==1.18.1 mozilla-django-oidc==4.0.1 +openpyxl packaging prompt-toolkit==3.0.19 psycopg2==2.9.1