api: return status in multiple agendas datetimes (#63268)
This commit is contained in:
parent
db5b7f3be7
commit
094cba528d
|
@ -1514,8 +1514,8 @@ class Event(models.Model):
|
|||
return self.start_datetime.date() <= now().date()
|
||||
|
||||
@staticmethod
|
||||
def annotate_queryset_for_user(qs, user_external_id):
|
||||
return qs.annotate(
|
||||
def annotate_queryset_for_user(qs, user_external_id, with_status=False):
|
||||
qs = qs.annotate(
|
||||
user_places_count=Count(
|
||||
'booking',
|
||||
filter=Q(
|
||||
|
@ -1533,6 +1533,25 @@ class Event(models.Model):
|
|||
),
|
||||
),
|
||||
)
|
||||
if with_status:
|
||||
qs = qs.annotate(
|
||||
user_absence_count=Count(
|
||||
'booking',
|
||||
filter=Q(
|
||||
booking__cancellation_datetime__isnull=True,
|
||||
booking__user_was_present=False,
|
||||
booking__user_external_id=user_external_id,
|
||||
),
|
||||
),
|
||||
user_cancelled_count=Count(
|
||||
'booking',
|
||||
filter=Q(
|
||||
booking__cancellation_datetime__isnull=False,
|
||||
booking__user_external_id=user_external_id,
|
||||
),
|
||||
),
|
||||
)
|
||||
return qs
|
||||
|
||||
@property
|
||||
def remaining_places(self):
|
||||
|
|
|
@ -262,6 +262,18 @@ class AgendaOrSubscribedSlugsMixin(DateRangeMixin):
|
|||
|
||||
class MultipleAgendasDatetimesSerializer(AgendaOrSubscribedSlugsMixin, DatetimesSerializer):
|
||||
show_past_events = serializers.BooleanField(default=False)
|
||||
guardian_external_id = serializers.CharField(max_length=250, required=False)
|
||||
with_status = serializers.BooleanField(default=False)
|
||||
guardian_external_id = serializers.CharField(max_length=250, required=False)
|
||||
|
||||
def validate(self, attrs):
|
||||
super().validate(attrs)
|
||||
user_external_id = attrs.get('user_external_id')
|
||||
if attrs.get('with_status') and not user_external_id:
|
||||
raise ValidationError(
|
||||
{'user_external_id': _('This field is required when using "with_status" parameter.')}
|
||||
)
|
||||
return attrs
|
||||
|
||||
|
||||
class AgendaOrSubscribedSlugsSerializer(AgendaOrSubscribedSlugsMixin, serializers.Serializer):
|
||||
|
|
|
@ -474,6 +474,7 @@ def get_event_text(event, agenda, day=None):
|
|||
return event_text
|
||||
|
||||
|
||||
# pylint: disable=too-many-arguments
|
||||
def get_event_detail(
|
||||
request,
|
||||
event,
|
||||
|
@ -485,6 +486,7 @@ def get_event_detail(
|
|||
multiple_agendas=False,
|
||||
disable_booked=True,
|
||||
bypass_delays=False,
|
||||
with_status=False,
|
||||
):
|
||||
agenda = agenda or event.agenda
|
||||
details = {
|
||||
|
@ -576,6 +578,15 @@ def get_event_detail(
|
|||
details['booked_for_external_user'] = 'main-list'
|
||||
elif getattr(event, 'user_waiting_places_count', 0) > 0:
|
||||
details['booked_for_external_user'] = 'waiting-list'
|
||||
if with_status and booked_user_external_id:
|
||||
if getattr(event, 'user_absence_count', 0) > 0:
|
||||
details['status'] = 'absence'
|
||||
elif getattr(event, 'user_places_count', 0) > 0 or getattr(event, 'user_waiting_places_count', 0) > 0:
|
||||
details['status'] = 'booked'
|
||||
elif getattr(event, 'user_cancelled_count', 0) > 0:
|
||||
details['status'] = 'cancelled'
|
||||
else:
|
||||
details['status'] = 'free'
|
||||
|
||||
return details
|
||||
|
||||
|
@ -885,6 +896,7 @@ class MultipleAgendasDatetimes(APIView):
|
|||
guardian_external_id = payload.get('guardian_external_id')
|
||||
show_past_events = bool(payload.get('show_past_events'))
|
||||
show_only_subscribed = bool('subscribed' in payload)
|
||||
with_status = bool(payload.get('with_status'))
|
||||
|
||||
entries = Event.objects.none()
|
||||
for agenda in agendas:
|
||||
|
@ -899,7 +911,7 @@ class MultipleAgendasDatetimes(APIView):
|
|||
bypass_delays=payload.get('bypass_delays'),
|
||||
show_out_of_minimal_delay=show_past_events,
|
||||
)
|
||||
entries = Event.annotate_queryset_for_user(entries, user_external_id)
|
||||
entries = Event.annotate_queryset_for_user(entries, user_external_id, with_status=with_status)
|
||||
if show_only_subscribed:
|
||||
entries = entries.filter(
|
||||
agenda__subscriptions__user_external_id=user_external_id,
|
||||
|
@ -943,6 +955,7 @@ class MultipleAgendasDatetimes(APIView):
|
|||
multiple_agendas=True,
|
||||
disable_booked=disable_booked,
|
||||
bypass_delays=payload.get('bypass_delays'),
|
||||
with_status=with_status,
|
||||
)
|
||||
for x in entries
|
||||
],
|
||||
|
|
|
@ -1176,3 +1176,153 @@ def test_datetimes_multiple_agendas_shared_custody_holiday_rules(app):
|
|||
params={'subscribed': 'all', 'user_external_id': 'child_id', 'guardian_external_id': 'mother_id'},
|
||||
)
|
||||
assert len(resp.json['data']) == 1
|
||||
|
||||
|
||||
def test_datetimes_multiple_agendas_with_status(app):
|
||||
agenda = Agenda.objects.create(label='agenda', kind='events')
|
||||
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
||||
event_booked = Event.objects.create(
|
||||
slug='event-booked',
|
||||
start_datetime=now() - datetime.timedelta(days=15),
|
||||
places=5,
|
||||
agenda=agenda,
|
||||
)
|
||||
Booking.objects.create(event=event_booked, user_external_id='xxx')
|
||||
Event.objects.create(
|
||||
slug='event-free',
|
||||
start_datetime=now() - datetime.timedelta(days=14),
|
||||
places=5,
|
||||
agenda=agenda,
|
||||
)
|
||||
event_cancelled = Event.objects.create(
|
||||
slug='event-cancelled',
|
||||
start_datetime=now() - datetime.timedelta(days=13),
|
||||
places=5,
|
||||
agenda=agenda,
|
||||
)
|
||||
Booking.objects.create(event=event_cancelled, user_external_id='xxx', cancellation_datetime=now())
|
||||
event_absence = Event.objects.create(
|
||||
slug='event-absence',
|
||||
start_datetime=now() - datetime.timedelta(days=12),
|
||||
places=5,
|
||||
agenda=agenda,
|
||||
)
|
||||
Booking.objects.create(event=event_absence, user_external_id='xxx', user_was_present=False)
|
||||
event_absence_with_reason = Event.objects.create(
|
||||
slug='event-absence_with_reason',
|
||||
start_datetime=now() - datetime.timedelta(days=11),
|
||||
places=5,
|
||||
agenda=agenda,
|
||||
)
|
||||
Booking.objects.create(
|
||||
event=event_absence_with_reason,
|
||||
user_external_id='xxx',
|
||||
user_was_present=False,
|
||||
user_absence_reason='foobar',
|
||||
)
|
||||
event_presence = Event.objects.create(
|
||||
slug='event-presence',
|
||||
start_datetime=now() - datetime.timedelta(days=10),
|
||||
places=5,
|
||||
agenda=agenda,
|
||||
)
|
||||
Booking.objects.create(event=event_presence, user_external_id='xxx', user_was_present=True)
|
||||
event_booked_future = Event.objects.create(
|
||||
slug='event-booked-future',
|
||||
start_datetime=now() + datetime.timedelta(days=1),
|
||||
places=5,
|
||||
agenda=agenda,
|
||||
)
|
||||
Booking.objects.create(event=event_booked_future, user_external_id='xxx')
|
||||
Event.objects.create(
|
||||
slug='event-free-future',
|
||||
start_datetime=now() + datetime.timedelta(days=2),
|
||||
places=5,
|
||||
agenda=agenda,
|
||||
)
|
||||
|
||||
resp = app.get(
|
||||
'/api/agendas/datetimes/',
|
||||
params={'agendas': 'agenda', 'show_past_events': True, 'user_external_id': 'xxx'},
|
||||
)
|
||||
assert [d['id'] for d in resp.json['data']] == [
|
||||
'agenda@event-booked',
|
||||
'agenda@event-free',
|
||||
'agenda@event-cancelled',
|
||||
'agenda@event-absence',
|
||||
'agenda@event-absence_with_reason',
|
||||
'agenda@event-presence',
|
||||
'agenda@event-booked-future',
|
||||
'agenda@event-free-future',
|
||||
]
|
||||
for d in resp.json['data']:
|
||||
assert 'status' not in d
|
||||
|
||||
resp = app.get(
|
||||
'/api/agendas/datetimes/',
|
||||
params={
|
||||
'agendas': 'agenda',
|
||||
'show_past_events': True,
|
||||
'user_external_id': 'xxx',
|
||||
'with_status': True,
|
||||
},
|
||||
)
|
||||
assert [d['id'] for d in resp.json['data']] == [
|
||||
'agenda@event-booked',
|
||||
'agenda@event-free',
|
||||
'agenda@event-cancelled',
|
||||
'agenda@event-absence',
|
||||
'agenda@event-absence_with_reason',
|
||||
'agenda@event-presence',
|
||||
'agenda@event-booked-future',
|
||||
'agenda@event-free-future',
|
||||
]
|
||||
assert [d['status'] for d in resp.json['data']] == [
|
||||
'booked',
|
||||
'free',
|
||||
'cancelled',
|
||||
'absence',
|
||||
'absence',
|
||||
'booked',
|
||||
'booked',
|
||||
'free',
|
||||
]
|
||||
|
||||
# other user
|
||||
resp = app.get(
|
||||
'/api/agendas/datetimes/',
|
||||
params={
|
||||
'agendas': 'agenda',
|
||||
'show_past_events': True,
|
||||
'user_external_id': 'yyy',
|
||||
'with_status': True,
|
||||
},
|
||||
)
|
||||
assert [d['id'] for d in resp.json['data']] == [
|
||||
'agenda@event-booked',
|
||||
'agenda@event-free',
|
||||
'agenda@event-cancelled',
|
||||
'agenda@event-absence',
|
||||
'agenda@event-absence_with_reason',
|
||||
'agenda@event-presence',
|
||||
'agenda@event-booked-future',
|
||||
'agenda@event-free-future',
|
||||
]
|
||||
assert [d['status'] for d in resp.json['data']] == [
|
||||
'free',
|
||||
'free',
|
||||
'free',
|
||||
'free',
|
||||
'free',
|
||||
'free',
|
||||
'free',
|
||||
'free',
|
||||
]
|
||||
|
||||
# check errors
|
||||
resp = app.get(
|
||||
'/api/agendas/datetimes/',
|
||||
params={'agendas': 'agenda', 'show_past_events': True, 'with_status': True},
|
||||
status=400,
|
||||
)
|
||||
assert 'required' in resp.json['errors']['user_external_id'][0]
|
||||
|
|
Loading…
Reference in New Issue