api: recurring fillslots and booking delays (#61329)

This commit is contained in:
Lauréline Guérin 2022-02-03 17:59:44 +01:00
parent 5b9f887ef9
commit 9789a77771
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
2 changed files with 101 additions and 15 deletions

View File

@ -1633,18 +1633,18 @@ class RecurringFillslots(APIView):
if data['action'] == 'update':
events_to_book = self.get_event_recurrences(
payload['slots'], start_datetime, end_datetime, user_external_id
agendas, payload['slots'], start_datetime, end_datetime, user_external_id
)
events_to_unbook = self.get_events_to_unbook(agendas, events_to_book)
elif data['action'] == 'book':
events_to_book = self.get_event_recurrences(
payload['slots'], start_datetime, end_datetime, user_external_id
agendas, payload['slots'], start_datetime, end_datetime, user_external_id
)
events_to_unbook = []
elif data['action'] == 'unbook':
events_to_book = Event.objects.none()
events_to_unbook = self.get_event_recurrences(
payload['slots'], start_datetime, end_datetime, user_external_id
agendas, payload['slots'], start_datetime, end_datetime, user_external_id
).values_list('pk', flat=True)
events_to_book = events_to_book.exclude(booking__user_external_id=user_external_id)
@ -1680,15 +1680,21 @@ class RecurringFillslots(APIView):
]
return Response(response)
def get_event_recurrences(self, slots, start_datetime, end_datetime, user_external_id):
def get_event_recurrences(self, agendas, slots, start_datetime, end_datetime, user_external_id):
event_filter = Q()
agendas_by_slug = {a.slug: a for a in agendas}
for agenda_slug, days_by_event in slots.items():
agenda = agendas_by_slug[agenda_slug]
for event_slug, days in days_by_event.items():
lookups = {
'agenda__slug': agenda_slug,
'primary_event__slug': event_slug,
'start_datetime__week_day__in': days,
}
if agenda.minimal_booking_delay:
lookups.update({'start_datetime__gte': agenda.min_booking_datetime})
if agenda.maximal_booking_delay:
lookups.update({'start_datetime__lte': agenda.max_booking_datetime})
if 'subscribed' in self.request.query_params:
lookups.update(
{
@ -1716,6 +1722,8 @@ class RecurringFillslots(APIView):
if (e.user_places_count or e.user_waiting_places_count)
and e.primary_event_id
and e.pk not in events_to_book_ids
and (not agenda.minimal_booking_delay or e.start_datetime >= agenda.min_booking_datetime)
and (not agenda.maximal_booking_delay or e.start_datetime <= agenda.max_booking_datetime)
]
return events_to_unbook

View File

@ -2222,7 +2222,12 @@ def test_fillslot_past_events_recurring_event(app, user):
@pytest.mark.parametrize('action', ['book', 'update'])
def test_recurring_events_api_fillslots(app, user, freezer, action):
freezer.move_to('2021-09-06 12:00')
agenda = Agenda.objects.create(label='Foo bar', kind='events')
agenda = Agenda.objects.create(
label='Foo bar',
kind='events',
minimal_booking_delay=7,
maximal_booking_delay=35, # only 4 bookable weeks
)
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
event = Event.objects.create(
label='Event',
@ -2254,7 +2259,23 @@ def test_recurring_events_api_fillslots(app, user, freezer, action):
# Book Monday and Thursday of first event and Sunday of second event
params['slots'] = 'foo-bar@event:0,foo-bar@event:3,foo-bar@sunday-event:6'
resp = app.post_json(fillslots_url, params=params)
assert resp.json['booking_count'] == 156
assert resp.json['booking_count'] == 12
assert 'booked_events' not in resp.json
assert Booking.objects.count() == 12
assert Booking.objects.filter(event__primary_event=event).count() == 8
assert Booking.objects.filter(event__primary_event=sunday_event).count() == 4
events = Event.objects.filter(primary_event__isnull=False)
assert events.filter(booked_places=1).count() == 12
# remove delays
agenda.minimal_booking_delay = 0
agenda.maximal_booking_delay = 0
agenda.save()
resp = app.post_json(fillslots_url, params=params)
assert resp.json['booking_count'] == 144
assert 'booked_events' not in resp.json
assert Booking.objects.count() == 156
@ -2342,7 +2363,9 @@ def test_recurring_events_api_fillslots(app, user, freezer, action):
def test_recurring_events_api_fillslots_waiting_list(app, user, freezer):
freezer.move_to('2021-09-06 12:00')
agenda = Agenda.objects.create(label='Foo bar', kind='events')
agenda = Agenda.objects.create(
label='Foo bar', kind='events', minimal_booking_delay=0, maximal_booking_delay=0
)
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
event = Event.objects.create(
label='Event',
@ -2373,7 +2396,9 @@ def test_recurring_events_api_fillslots_waiting_list(app, user, freezer):
def test_recurring_events_api_fillslots_change_bookings(app, user, freezer):
freezer.move_to('2021-09-06 12:00')
agenda = Agenda.objects.create(label='Foo bar', kind='events')
agenda = Agenda.objects.create(
label='Foo bar', kind='events', minimal_booking_delay=0, maximal_booking_delay=0
)
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
event = Event.objects.create(
label='Event',
@ -2408,11 +2433,30 @@ def test_recurring_events_api_fillslots_change_bookings(app, user, freezer):
assert Booking.objects.filter(event__start_datetime__week_day=5).count() == 52
assert Booking.objects.filter(event__start_datetime__week_day=6).count() == 52
# set booking delays - only 4 weeks bookable
agenda.minimal_booking_delay = 7
agenda.maximal_booking_delay = 35
agenda.save()
# Change booking to Monday and Tuesday
params['slots'] = 'foo-bar@event:0,foo-bar@event:1'
resp = app.post_json(fillslots_url, params=params)
assert resp.json['booking_count'] == 52
assert resp.json['cancelled_booking_count'] == 104
assert resp.json['booking_count'] == 4
assert resp.json['cancelled_booking_count'] == 8
assert Booking.objects.count() == 152
assert Booking.objects.filter(event__start_datetime__week_day=2).count() == 52
assert Booking.objects.filter(event__start_datetime__week_day=3).count() == 4
assert Booking.objects.filter(event__start_datetime__week_day=5).count() == 48
assert Booking.objects.filter(event__start_datetime__week_day=6).count() == 48
# remove delays
agenda.minimal_booking_delay = 0
agenda.maximal_booking_delay = 0
agenda.save()
resp = app.post_json(fillslots_url, params=params)
assert resp.json['booking_count'] == 48
assert resp.json['cancelled_booking_count'] == 96
assert Booking.objects.count() == 104
assert Booking.objects.filter(event__start_datetime__week_day=2).count() == 52
assert Booking.objects.filter(event__start_datetime__week_day=3).count() == 52
@ -2479,7 +2523,9 @@ def test_recurring_events_api_fillslots_change_bookings(app, user, freezer):
def test_recurring_events_api_unbook(app, user, freezer):
freezer.move_to('2021-09-06 12:00')
agenda = Agenda.objects.create(label='Foo bar', kind='events')
agenda = Agenda.objects.create(
label='Foo bar', kind='events', minimal_booking_delay=0, maximal_booking_delay=0
)
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
event = Event.objects.create(
label='Event',
@ -2513,10 +2559,28 @@ def test_recurring_events_api_unbook(app, user, freezer):
assert Booking.objects.filter(event__primary_event=event).count() == 104
assert Booking.objects.filter(event__primary_event=sunday_event).count() == 52
# set booking delays - only 4 weeks bookable
agenda.minimal_booking_delay = 7
agenda.maximal_booking_delay = 35
agenda.save()
params['slots'] = 'foo-bar@event:0'
resp = app.post_json(fillslots_url + '&action=unbook', params=params)
assert resp.json['booking_count'] == 0
assert resp.json['cancelled_booking_count'] == 52
assert resp.json['cancelled_booking_count'] == 4
assert Booking.objects.count() == 152
assert Booking.objects.filter(event__primary_event=event).count() == 100
assert Booking.objects.filter(event__primary_event=sunday_event).count() == 52
# remove delays
agenda.minimal_booking_delay = 0
agenda.maximal_booking_delay = 0
agenda.save()
resp = app.post_json(fillslots_url + '&action=unbook', params=params)
assert resp.json['booking_count'] == 0
assert resp.json['cancelled_booking_count'] == 48
assert Booking.objects.count() == 104
assert Booking.objects.filter(event__primary_event=event).count() == 52
@ -2564,10 +2628,22 @@ def test_recurring_events_api_unbook(app, user, freezer):
@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)
first_agenda = Agenda.objects.create(
label='First agenda',
kind='events',
category=category,
minimal_booking_delay=0,
maximal_booking_delay=0,
)
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)
second_agenda = Agenda.objects.create(
label='Second agenda',
kind='events',
category=category,
minimal_booking_delay=0,
maximal_booking_delay=0,
)
Desk.objects.create(agenda=second_agenda, slug='_exceptions_holder')
event = Event.objects.create(
slug='event',
@ -2665,7 +2741,9 @@ def test_recurring_events_api_fillslots_subscribed(app, user):
@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')
agenda = Agenda.objects.create(
label='First Agenda', kind='events', minimal_booking_delay=0, maximal_booking_delay=0
)
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
start, end = now(), now() + datetime.timedelta(days=30)
event_a = Event.objects.create(