api: add support for subscriptions in recurring fillslots (#58446)
This commit is contained in:
parent
270daa2202
commit
5269bc60c1
|
@ -674,14 +674,6 @@ def get_start_and_end_datetime_from_request(request):
|
|||
return serializer.validated_data.get('date_start'), serializer.validated_data.get('date_end')
|
||||
|
||||
|
||||
def get_agendas_from_request(request):
|
||||
serializer = serializers.AgendaSlugsSerializer(data=request.query_params)
|
||||
if not serializer.is_valid():
|
||||
raise APIErrorBadRequest(N_('invalid payload'), errors=serializer.errors)
|
||||
|
||||
return serializer.validated_data.get('agendas')
|
||||
|
||||
|
||||
def make_booking(event, payload, extra_data, primary_booking=None, in_waiting_list=False, color=None):
|
||||
return Booking(
|
||||
event_id=event.pk,
|
||||
|
@ -1595,25 +1587,41 @@ class RecurringFillslots(APIView):
|
|||
if not start_datetime or start_datetime < now():
|
||||
start_datetime = now()
|
||||
|
||||
agenda_slugs = get_agendas_from_request(request)
|
||||
agendas = get_objects_from_slugs(agenda_slugs, qs=Agenda.objects.filter(kind='events'))
|
||||
serializer = serializers.AgendaOrSubscribedSlugsSerializer(
|
||||
data=request.query_params, context={'user_external_id': request.data.get('user_external_id')}
|
||||
)
|
||||
if not serializer.is_valid():
|
||||
raise APIErrorBadRequest(N_('invalid payload'), errors=serializer.errors)
|
||||
data = serializer.validated_data
|
||||
|
||||
context = {'allowed_agenda_slugs': agenda_slugs, 'agendas': Agenda.prefetch_recurring_events(agendas)}
|
||||
context = {
|
||||
'allowed_agenda_slugs': data['agenda_slugs'],
|
||||
'agendas': Agenda.prefetch_recurring_events(data['agendas']),
|
||||
}
|
||||
serializer = self.serializer_class(data=request.data, partial=True, context=context)
|
||||
if not serializer.is_valid():
|
||||
raise APIErrorBadRequest(N_('invalid payload'), errors=serializer.errors)
|
||||
payload = serializer.validated_data
|
||||
user_external_id = payload['user_external_id']
|
||||
agendas = Agenda.prefetch_events_and_exceptions(agendas, user_external_id=user_external_id)
|
||||
agendas = Agenda.prefetch_events_and_exceptions(data['agendas'], user_external_id=user_external_id)
|
||||
|
||||
event_filter = Q()
|
||||
for agenda_slug, days_by_event in payload['slots'].items():
|
||||
for event_slug, days in days_by_event.items():
|
||||
event_filter |= Q(
|
||||
agenda__slug=agenda_slug,
|
||||
primary_event__slug=event_slug,
|
||||
start_datetime__week_day__in=days,
|
||||
)
|
||||
lookups = {
|
||||
'agenda__slug': agenda_slug,
|
||||
'primary_event__slug': event_slug,
|
||||
'start_datetime__week_day__in': days,
|
||||
}
|
||||
if 'subscribed' in request.query_params:
|
||||
lookups.update(
|
||||
{
|
||||
'agenda__subscriptions__user_external_id': user_external_id,
|
||||
'agenda__subscriptions__date_start__lt': F('start_datetime'),
|
||||
'agenda__subscriptions__date_end__gt': F('start_datetime'),
|
||||
}
|
||||
)
|
||||
event_filter |= Q(**lookups)
|
||||
|
||||
events_to_book = Event.objects.filter(event_filter) if event_filter else Event.objects.none()
|
||||
events_to_book = events_to_book.filter(start_datetime__gte=start_datetime, cancelled=False)
|
||||
|
|
|
@ -2360,6 +2360,109 @@ def test_recurring_events_api_fillslots_change_bookings(app, user, freezer):
|
|||
assert Booking.objects.filter(user_external_id='user_id', event=normal_event).count() == 1
|
||||
|
||||
|
||||
@pytest.mark.freeze_time('2021-09-06 12:00')
|
||||
def test_recurring_events_api_fillslots_subscribed(app, user):
|
||||
category = Category.objects.create(label='Category A')
|
||||
first_agenda = Agenda.objects.create(label='First agenda', kind='events', category=category)
|
||||
Desk.objects.create(agenda=first_agenda, slug='_exceptions_holder')
|
||||
category = Category.objects.create(label='Category B')
|
||||
second_agenda = Agenda.objects.create(label='Second agenda', kind='events', category=category)
|
||||
Desk.objects.create(agenda=second_agenda, slug='_exceptions_holder')
|
||||
event = Event.objects.create(
|
||||
slug='event',
|
||||
start_datetime=now(),
|
||||
recurrence_days=[0, 1, 3, 4], # Monday, Tuesday, Thursday, Friday
|
||||
places=2,
|
||||
waiting_list_places=1,
|
||||
agenda=first_agenda,
|
||||
recurrence_end_date=now() + datetime.timedelta(days=364),
|
||||
)
|
||||
event.create_all_recurrences()
|
||||
sunday_event = Event.objects.create(
|
||||
slug='sunday-event',
|
||||
start_datetime=now(),
|
||||
recurrence_days=[6],
|
||||
places=2,
|
||||
waiting_list_places=1,
|
||||
agenda=second_agenda,
|
||||
recurrence_end_date=now() + datetime.timedelta(days=364),
|
||||
)
|
||||
sunday_event.create_all_recurrences()
|
||||
|
||||
Subscription.objects.create(
|
||||
agenda=first_agenda,
|
||||
user_external_id='xxx',
|
||||
date_start=now() + datetime.timedelta(days=16), # Wednesday 22/09
|
||||
date_end=now() + datetime.timedelta(days=44), # Wednesday 20/10
|
||||
)
|
||||
|
||||
app.authorization = ('Basic', ('john.doe', 'password'))
|
||||
params = {'user_external_id': 'xxx'}
|
||||
# book Monday and Thursday of first event, in subscription range
|
||||
params['slots'] = 'first-agenda@event:0,first-agenda@event:3'
|
||||
resp = app.post_json('/api/agendas/recurring-events/fillslots/?subscribed=category-a', params=params)
|
||||
assert resp.json['booking_count'] == 8
|
||||
assert Booking.objects.count() == 8
|
||||
assert Booking.objects.filter(event__primary_event=event).count() == 8
|
||||
assert Booking.objects.first().event.start_datetime.strftime('%d/%m') == '23/09'
|
||||
assert Booking.objects.last().event.start_datetime.strftime('%d/%m') == '18/10'
|
||||
|
||||
# wrong category
|
||||
resp = app.post_json(
|
||||
'/api/agendas/recurring-events/fillslots/?subscribed=category-b', params=params, status=400
|
||||
)
|
||||
|
||||
# not subscribed category
|
||||
params['slots'] = 'second-agenda@sunday-event:6'
|
||||
resp = app.post_json(
|
||||
'/api/agendas/recurring-events/fillslots/?subscribed=category-b', params=params, status=400
|
||||
)
|
||||
|
||||
# update bookings
|
||||
Subscription.objects.create(
|
||||
agenda=second_agenda,
|
||||
user_external_id='xxx',
|
||||
date_start=now() + datetime.timedelta(days=100), # Wednesday 15/12
|
||||
date_end=now() + datetime.timedelta(days=150), # Thursday 03/02
|
||||
)
|
||||
params['slots'] = 'first-agenda@event:1,second-agenda@sunday-event:6'
|
||||
resp = app.post_json('/api/agendas/recurring-events/fillslots/?subscribed=all', params=params)
|
||||
assert resp.json['booking_count'] == 11
|
||||
assert resp.json['cancelled_booking_count'] == 8
|
||||
assert Booking.objects.count() == 11
|
||||
booked_events_first_agenda = Event.objects.filter(primary_event=event, booking__isnull=False)
|
||||
assert [
|
||||
x.strftime('%d/%m/%Y') for x in booked_events_first_agenda.values_list('start_datetime', flat=True)
|
||||
] == ['28/09/2021', '05/10/2021', '12/10/2021', '19/10/2021']
|
||||
booked_events_second_agenda = Event.objects.filter(primary_event=sunday_event, booking__isnull=False)
|
||||
assert [
|
||||
x.strftime('%d/%m/%Y') for x in booked_events_second_agenda.values_list('start_datetime', flat=True)
|
||||
] == ['19/12/2021', '26/12/2021', '02/01/2022', '09/01/2022', '16/01/2022', '23/01/2022', '30/01/2022']
|
||||
|
||||
# other user
|
||||
Subscription.objects.create(
|
||||
agenda=second_agenda,
|
||||
user_external_id='yyy',
|
||||
date_start=now(),
|
||||
date_end=now() + datetime.timedelta(days=10),
|
||||
)
|
||||
# disjoint subscription
|
||||
Subscription.objects.create(
|
||||
agenda=second_agenda,
|
||||
user_external_id='yyy',
|
||||
date_start=now() + datetime.timedelta(days=60),
|
||||
date_end=now() + datetime.timedelta(days=70),
|
||||
)
|
||||
params = {'user_external_id': 'yyy', 'slots': 'second-agenda@sunday-event:6'}
|
||||
resp = app.post_json('/api/agendas/recurring-events/fillslots/?subscribed=category-b', params=params)
|
||||
assert resp.json['booking_count'] == 3
|
||||
assert Booking.objects.count() == 14
|
||||
booked_events_user_yyy = Event.objects.filter(primary_event=sunday_event, booking__user_external_id='yyy')
|
||||
assert [
|
||||
x.strftime('%d/%m/%Y') for x in booked_events_user_yyy.values_list('start_datetime', flat=True)
|
||||
] == ['12/09/2021', '07/11/2021', '14/11/2021']
|
||||
|
||||
|
||||
@pytest.mark.freeze_time('2021-09-06 12:00')
|
||||
def test_recurring_events_api_fillslots_multiple_agendas(app, user):
|
||||
agenda = Agenda.objects.create(label='First Agenda', kind='events')
|
||||
|
|
Loading…
Reference in New Issue