manager: move event checks code to mixin (#79623)

This commit is contained in:
Valentin Deniaud 2023-07-11 17:03:35 +02:00
parent 46e60b37a1
commit bfea238c08
2 changed files with 109 additions and 108 deletions

View File

@ -246,7 +246,7 @@ urlpatterns = [
),
path(
'agendas/<int:pk>/events/<int:event_pk>/check',
views.event_check,
views.event_checks,
name='chrono-manager-event-check',
),
path(

View File

@ -1360,6 +1360,111 @@ class AgendaDateView(DateMixin, ViewableAgendaMixin):
]
class EventChecksMixin:
def get_filters(self, booked_queryset, subscription_queryset):
agenda_filters = self.agenda.get_booking_check_filters()
filters = collections.defaultdict(set)
extra_data_from_booked = booked_queryset.filter(extra_data__has_any_keys=agenda_filters).values_list(
'extra_data', flat=True
)
extra_data_from_subscriptions = subscription_queryset.filter(
extra_data__has_any_keys=agenda_filters
).values_list('extra_data', flat=True)
for extra_data in list(extra_data_from_booked) + list(extra_data_from_subscriptions):
for k, v in extra_data.items():
if not v:
continue
if k in agenda_filters and not isinstance(v, (list, dict)):
filters[k].add(v)
filters = sorted(filters.items())
filters = {k: sorted(list(v)) for k, v in filters}
return filters
def add_filters_context(self, context, event):
# booking base queryset
booking_qs_kwargs = {}
if not self.agenda.subscriptions.exists():
booking_qs_kwargs = {'cancellation_datetime__isnull': True}
booking_qs = event.booking_set
booked_qs = booking_qs.filter(
in_waiting_list=False, primary_booking__isnull=True, **booking_qs_kwargs
)
booked_qs = booked_qs.annotate(
places_count=Value(1) + Count('secondary_booking_set', filter=Q(**booking_qs_kwargs))
)
# waiting list queryset
waiting_qs = booking_qs.filter(
in_waiting_list=True, primary_booking__isnull=True, **booking_qs_kwargs
).order_by('user_last_name', 'user_first_name')
waiting_qs = waiting_qs.annotate(
places_count=Value(1)
+ Count('secondary_booking_set', filter=Q(cancellation_datetime__isnull=True))
)
# subscription base queryset
subscription_qs = (
self.agenda.subscriptions.filter(
date_start__lte=event.start_datetime, date_end__gt=event.start_datetime
)
# exclude user_external_id from booked_qs and waiting_qs
.exclude(user_external_id__in=booked_qs.values('user_external_id')).exclude(
user_external_id__in=waiting_qs.values('user_external_id')
)
)
# build filters from booked_qs and subscription_qs
filters = self.get_filters(booked_queryset=booked_qs, subscription_queryset=subscription_qs)
# and filter booked and subscriptions
booked_filterset = BookingCheckFilterSet(
data=self.request.GET or None, queryset=booked_qs, agenda=self.agenda, filters=filters
)
subscription_filterset = SubscriptionCheckFilterSet(
data=self.request.GET or None, queryset=subscription_qs, agenda=self.agenda, filters=filters
)
# build results from mixed booked and subscriptions
results = []
booked_without_status = False
for booking in booked_filterset.qs:
if booking.cancellation_datetime is None and booking.user_was_present is None:
booked_without_status = True
booking.absence_form = BookingCheckAbsenceForm(
agenda=self.agenda,
initial={'check_type': booking.user_check_type_slug},
)
booking.presence_form = BookingCheckPresenceForm(
agenda=self.agenda,
initial={'check_type': booking.user_check_type_slug},
)
booking.kind = 'booking'
results.append(booking)
for subscription in subscription_filterset.qs:
subscription.absence_form = BookingCheckAbsenceForm(
agenda=self.agenda,
)
subscription.presence_form = BookingCheckPresenceForm(
agenda=self.agenda,
)
subscription.kind = 'subscription'
results.append(subscription)
# sort results
if (
booked_filterset.form.is_valid()
and booked_filterset.form.cleaned_data.get('sort') == 'firstname,lastname'
):
sort_fields = ['user_first_name', 'user_last_name']
else:
sort_fields = ['user_last_name', 'user_first_name']
results = sorted(results, key=attrgetter(*sort_fields, 'user_external_id'))
# set context
context['booked_without_status'] = booked_without_status
context['filterset'] = booked_filterset
context['results'] = results
context['waiting'] = waiting_qs
class AgendaDayView(AgendaDateView, DayArchiveView):
kind = 'day'
@ -2605,7 +2710,7 @@ class EventDeleteView(ManagedAgendaMixin, DeleteView):
event_delete = EventDeleteView.as_view()
class EventCheckView(ViewableAgendaMixin, DetailView):
class EventChecksView(ViewableAgendaMixin, EventChecksMixin, DetailView):
template_name = 'chrono/manager_event_check.html'
model = Event
pk_url_kwarg = 'event_pk'
@ -2627,119 +2732,15 @@ class EventCheckView(ViewableAgendaMixin, DetailView):
cancelled=False,
)
def get_filters(self, booked_queryset, subscription_queryset):
agenda_filters = self.agenda.get_booking_check_filters()
filters = collections.defaultdict(set)
extra_data_from_booked = booked_queryset.filter(extra_data__has_any_keys=agenda_filters).values_list(
'extra_data', flat=True
)
extra_data_from_subscriptions = subscription_queryset.filter(
extra_data__has_any_keys=agenda_filters
).values_list('extra_data', flat=True)
for extra_data in list(extra_data_from_booked) + list(extra_data_from_subscriptions):
for k, v in extra_data.items():
if not v:
continue
if k in agenda_filters and not isinstance(v, (list, dict)):
filters[k].add(v)
filters = sorted(filters.items())
filters = {k: sorted(list(v)) for k, v in filters}
return filters
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
event = self.object
# booking base queryset
booking_qs_kwargs = {}
if not self.agenda.subscriptions.exists():
booking_qs_kwargs = {'cancellation_datetime__isnull': True}
booking_qs = event.booking_set
booked_qs = booking_qs.filter(
in_waiting_list=False, primary_booking__isnull=True, **booking_qs_kwargs
)
booked_qs = booked_qs.annotate(
places_count=Value(1) + Count('secondary_booking_set', filter=Q(**booking_qs_kwargs))
)
# waiting list queryset
waiting_qs = booking_qs.filter(
in_waiting_list=True, primary_booking__isnull=True, **booking_qs_kwargs
).order_by('user_last_name', 'user_first_name')
waiting_qs = waiting_qs.annotate(
places_count=Value(1)
+ Count('secondary_booking_set', filter=Q(cancellation_datetime__isnull=True))
)
# subscription base queryset
subscription_qs = (
self.agenda.subscriptions.filter(
date_start__lte=event.start_datetime, date_end__gt=event.start_datetime
)
# exclude user_external_id from booked_qs and waiting_qs
.exclude(user_external_id__in=booked_qs.values('user_external_id')).exclude(
user_external_id__in=waiting_qs.values('user_external_id')
)
)
# build filters from booked_qs and subscription_qs
filters = self.get_filters(booked_queryset=booked_qs, subscription_queryset=subscription_qs)
# and filter booked and subscriptions
booked_filterset = BookingCheckFilterSet(
data=self.request.GET or None, queryset=booked_qs, agenda=self.agenda, filters=filters
)
subscription_filterset = SubscriptionCheckFilterSet(
data=self.request.GET or None, queryset=subscription_qs, agenda=self.agenda, filters=filters
)
# build results from mixed booked and subscriptions
results = []
booked_without_status = False
for booking in booked_filterset.qs:
if booking.cancellation_datetime is None and booking.user_was_present is None:
booked_without_status = True
booking.absence_form = BookingCheckAbsenceForm(
agenda=self.agenda,
initial={'check_type': booking.user_check_type_slug},
)
booking.presence_form = BookingCheckPresenceForm(
agenda=self.agenda,
initial={'check_type': booking.user_check_type_slug},
)
booking.kind = 'booking'
results.append(booking)
for subscription in subscription_filterset.qs:
subscription.absence_form = BookingCheckAbsenceForm(
agenda=self.agenda,
)
subscription.presence_form = BookingCheckPresenceForm(
agenda=self.agenda,
)
subscription.kind = 'subscription'
results.append(subscription)
# sort results
if (
booked_filterset.form.is_valid()
and booked_filterset.form.cleaned_data.get('sort') == 'firstname,lastname'
):
sort_fields = ['user_first_name', 'user_last_name']
else:
sort_fields = ['user_last_name', 'user_first_name']
results = sorted(results, key=attrgetter(*sort_fields, 'user_external_id'))
# set context
context['booked_without_status'] = booked_without_status
self.add_filters_context(context, self.object)
context['absence_form'] = BookingCheckAbsenceForm(agenda=self.agenda)
context['presence_form'] = BookingCheckPresenceForm(agenda=self.agenda)
context['filterset'] = booked_filterset
context['results'] = results
context['waiting'] = waiting_qs
return context
event_check = EventCheckView.as_view()
event_checks = EventChecksView.as_view()
class EventCheckMixin: