diff --git a/members/admin/activityinvite_admin.py b/members/admin/activityinvite_admin.py
index 261f6e18..24deb6b0 100644
--- a/members/admin/activityinvite_admin.py
+++ b/members/admin/activityinvite_admin.py
@@ -1,10 +1,15 @@
import codecs
+from datetime import timedelta
from django import forms
from django.contrib import admin
+from django.contrib import messages
+from django.contrib.admin.widgets import AdminDateWidget
+from django.db import transaction
from django.db.models.functions import Lower
from django.http import HttpResponse
+from django.shortcuts import render
from django.urls import reverse
-from django.utils import timezone
+from django.utils import formats, timezone
from django.utils.safestring import mark_safe
from django.utils.html import escape
from django.db.models import Exists, OuterRef
@@ -161,7 +166,7 @@ class Meta:
"Du kan søge på forening, afdeling, aktivitet eller person.
Vandret dato-filter er for aktivitetens startdato."
)
- actions = ["export_csv_invitation_info"]
+ actions = ["export_csv_invitation_info", "extend_invitations"]
form = ActivityInviteAdminForm
@@ -326,3 +331,69 @@ def export_csv_invitation_info(self, request, queryset):
return response
export_csv_invitation_info.short_description = "Exporter Invitationsinformationer"
+
+ def extend_invitations(modelAdmin, request, queryset):
+ class ExtendInvitationsForm(forms.Form):
+ expires = forms.DateField(
+ label="Udløber",
+ widget=AdminDateWidget(),
+ initial=timezone.now() + timedelta(days=14),
+ )
+
+ invitations = queryset
+
+ context = admin.site.each_context(request)
+ context["invitations"] = invitations
+ context["queryset"] = queryset
+
+ expires = timezone.now() + timedelta(days=14)
+ context["expires"] = expires
+
+ if request.method == "POST" and "expires" in request.POST:
+ extend_invitations_form = ExtendInvitationsForm(request.POST)
+ context["extend_invitations_form"] = extend_invitations_form
+
+ if extend_invitations_form.is_valid():
+ expires = extend_invitations_form.cleaned_data["expires"]
+
+ if expires < timezone.now().date():
+ messages.error(
+ request,
+ "Fejl - den angivne udløbsdato er før dags dato.",
+ )
+ return
+
+ updated_invitations = 0
+ skipped_invitations = 0
+ try:
+ with transaction.atomic():
+ for invitation in invitations:
+ if invitation.expire_dtm > expires:
+ skipped_invitations += 1
+ continue
+
+ invitation.expire_dtm = expires
+ invitation.save()
+ updated_invitations += 1
+ except Exception as E:
+ messages.error(
+ request,
+ f"Fejl - ingen invitationer blev forlænget! Følgende fejl opstod: {E=}",
+ )
+ return
+
+ status_text = f"{updated_invitations} invitationer blev forlænget til {formats.date_format(expires, 'DATE_FORMAT')}."
+ if skipped_invitations > 0:
+ status_text += f"
{skipped_invitations} invitationer blev sprunget over, da de allerede havde en senere udløbsdato."
+ messages.success(
+ request,
+ mark_safe(status_text),
+ )
+
+ return
+ else:
+ context["extend_invitations_form"] = ExtendInvitationsForm()
+
+ return render(request, "admin/extend_invitations.html", context)
+
+ extend_invitations.short_description = "Forlæng invitationer"
diff --git a/members/templates/admin/extend_invitations.html b/members/templates/admin/extend_invitations.html
new file mode 100644
index 00000000..2152a7ff
--- /dev/null
+++ b/members/templates/admin/extend_invitations.html
@@ -0,0 +1,73 @@
+{% extends "admin/base_site.html" %}
+{% load i18n admin_urls static admin_modify %}
+
+{% block extrahead %}{{ block.super }}
+
+
+{{mass_confirmation_form.media}}
+{{ media }}
+{% endblock %}
+
+{% block extrastyle %}{{ block.super }}
+
+
+
+{% endblock %}
+
+{% block breadcrumbs %}
+