Skip to content

Commit

Permalink
Merge pull request #872 from CodingPirates/feature/Inviter-Fra-Ventel…
Browse files Browse the repository at this point in the history
…ister

Inviter fra Ventelister og Deltagere
  • Loading branch information
lakridserne authored Jun 18, 2023
2 parents 5e1f73d + ad808f1 commit 493c57b
Show file tree
Hide file tree
Showing 7 changed files with 427 additions and 164 deletions.
3 changes: 3 additions & 0 deletions members/admin/activityparticipant_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
Union,
)

from members.admin.admin_actions import AdminActions


class ActivityParticipantDepartmentFilter(admin.SimpleListFilter):
title = "Afdeling"
Expand Down Expand Up @@ -210,6 +212,7 @@ class ActivityParticipantAdmin(admin.ModelAdmin):
)

actions = [
AdminActions.invite_many_to_activity_action,
"export_csv_full",
]

Expand Down
282 changes: 282 additions & 0 deletions members/admin/admin_actions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
from datetime import timedelta
from dateutil.relativedelta import relativedelta
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.utils import timezone
from django.utils.safestring import mark_safe
from django.utils.html import escape
from django.shortcuts import render

from members.models import (
Activity,
ActivityInvite,
ActivityParticipant,
Department,
Person,
WaitingList,
)


class AdminActions(admin.ModelAdmin):
def invite_many_to_activity_action(modelAdmin, request, queryset):
# Get list of available departments
if request.user.is_superuser or request.user.has_perm(
"members.view_all_persons"
):
department_list_query = Department.objects.all()
else:
department_list_query = Department.objects.filter(
adminuserinformation__user=request.user
)
department_list = [("-", "-")]
for department in department_list_query:
department_list.append((department.id, department.name))

# Get list of active and future activities
department_ids = department_list_query.values_list("id", flat=True)
activity_list_query = Activity.objects.filter(end_date__gt=timezone.now())
if not request.user.is_superuser:
activity_list_query = activity_list_query.filter(
department__in=department_ids
)
activity_list = [("-", "-")]
for activity in activity_list_query:
activity_list.append(
(activity.id, activity.department.name + ", " + activity.name)
)

# Form used to select department and activity - redundant department is for double check
class MassInvitationForm(forms.Form):
department = forms.ChoiceField(label="Afdeling", choices=department_list)
activity = forms.ChoiceField(label="Aktivitet", choices=activity_list)
expire = forms.DateField(
label="Udløber",
widget=AdminDateWidget(),
initial=timezone.now() + timedelta(days=30 * 3),
)

# Lookup all the selected persons - to show confirmation list
# Check if it's called from Waiting List
if queryset.model is WaitingList:
q = [wl.person.pk for wl in queryset]
persons = Person.objects.filter(pk__in=q)
# or if it's called from the Participants list
elif queryset.model is ActivityParticipant:
q = [pa.person.pk for pa in queryset]
persons = Person.objects.filter(pk__in=q)
else:
persons = queryset

context = admin.site.each_context(request)
if persons is None:
q = [wl.person.pk for wl in queryset]
persons = Person.objects.filter(pk__in=q)
# queryset = persons

context["persons"] = persons
context["queryset"] = queryset

if request.method == "POST" and "activity" in request.POST:
# Post request with data
mass_invitation_form = MassInvitationForm(request.POST)
context["mass_invitation_form"] = mass_invitation_form

if (
mass_invitation_form.is_valid()
and mass_invitation_form.cleaned_data["activity"] != "-"
and mass_invitation_form.cleaned_data["department"] != "-"
):
# Department and Activity selected
activity = Activity.objects.get(
pk=mass_invitation_form.cleaned_data["activity"]
)

# validate activity belongs to user and matches selected department
if (
int(mass_invitation_form.cleaned_data["department"])
in department_ids
):
if activity.department.id == int(
mass_invitation_form.cleaned_data["department"]
):
invited_counter = 0
persons_too_young = []
persons_too_old = []
persons_already_invited = []
persons_already_participant = []
persons_invited = []

# get list of already created invitations on selected persons
already_invited = Person.objects.filter(
activityinvite__activity=mass_invitation_form.cleaned_data[
"activity"
],
activityinvite__person__in=persons,
).all()
list(already_invited) # force lookup
already_invited_ids = already_invited.values_list(
"id", flat=True
)

# get list of current participants on selected persons
already_participant = Person.objects.filter(
activityparticipant__activity=mass_invitation_form.cleaned_data[
"activity"
],
activityparticipant__person__in=persons,
).all()
list(already_participant) # force lookup
already_participant_ids = already_participant.values_list(
"id", flat=True
)

# only save if all succeeds
invitation = []
try:
with transaction.atomic():
# for current_person in queryset:
for current_person in persons:
# check for already participant
if current_person.id in already_participant_ids:
persons_already_participant.append(
current_person.name
)

# Check for already invited
elif current_person.id in already_invited_ids:
persons_already_invited.append(
current_person.name
)

# Check for age constraint: too young ?
elif (
current_person.birthday
> activity.start_date
- relativedelta(years=activity.min_age)
):
persons_too_young.append(current_person.name)
# Check for age constraint: too old ?
elif (
current_person.birthday
< activity.start_date
- relativedelta(
years=activity.max_age + 1, days=-1
)
):
persons_too_old.append(current_person.name)
# Otherwise - person can be invited
else:
invited_counter = invited_counter + 1
invitation = ActivityInvite(
activity=activity,
person=current_person,
expire_dtm=mass_invitation_form.cleaned_data[
"expire"
],
)
invitation.save()
persons_invited.append(current_person.name)

except Exception:
messages.error(
request,
"Fejl - ingen personer blev inviteret! Der var problemer med "
+ (invitation.person.name if invitation else "(n/a)")
+ ". Vær sikker på personen ikke allerede er inviteret og opfylder alderskravet.",
)
return

# Message about new invites:
invited_text = (
"<u>"
+ str(invited_counter)
+ " af "
+ str(persons.count())
+ " valgte personer blev inviteret til "
+ escape(str(activity))
+ "</u>"
+ (":<br>" if invited_counter else "")
+ escape(", ".join(persons_invited))
)

# Message about persons that are already participating in activity:
already_participating_text = ""
if len(persons_already_participant) > 0:
already_participating_text = (
"<br><u>"
+ str(len(persons_already_participant))
+ " deltager allerede:</u><br> "
+ escape(", ".join(persons_already_participant))
)

# Message about persons that are already invited (and not found as participant)
already_invited_text = ""
if len(persons_already_invited) > 0:
already_invited_text = (
"<br><u>"
+ str(len(persons_already_invited))
+ " er allerede inviteret:</u><br> "
+ escape(", ".join(persons_already_invited))
)

# Message about person too young to get invited:
persons_too_young_text = ""
if len(persons_too_young) > 0:
persons_too_young_text = (
"<br><u>"
+ str(len(persons_too_young))
+ " er under minimumsalder for aktiviteten "
+ "("
+ str(activity.min_age)
+ " år)"
+ ":</u><br> "
+ escape(", ".join(persons_too_young))
)

# Message about person too old to get invited:
persons_too_old_text = ""
if len(persons_too_old) > 0:
persons_too_old_text = (
"<br><u>"
+ str(len(persons_too_old))
+ " er over maximumsalder for aktiviteten "
+ "("
+ str(activity.max_age)
+ " år) "
+ ":</u><br> "
+ escape(", ".join(persons_too_old))
)

messages.success(
request,
mark_safe(
invited_text
+ already_participating_text
+ already_invited_text
+ persons_too_young_text
+ persons_too_old_text,
),
)
return

else:
messages.error(
request,
"Valgt aktivitet stemmer ikke overens med valgt afdeling",
)
return
else:
messages.error(request, "Du kan kun invitere til egne afdelinger")
return
else:
context["mass_invitation_form"] = MassInvitationForm()

return render(request, "admin/invite_many_to_activity.html", context)

invite_many_to_activity_action.short_description = (
"Inviter valgte personer til en aktivitet"
)
Loading

0 comments on commit 493c57b

Please sign in to comment.