api: allow updating partial bookings in recurring events fillslots (#78084)
gitea/chrono/pipeline/head There was a failure building this commit Details

This commit is contained in:
Valentin Deniaud 2023-06-15 14:26:52 +02:00
parent f28cd4d104
commit 152110888c
2 changed files with 84 additions and 8 deletions

View File

@ -1743,11 +1743,14 @@ class RecurringFillslots(APIView):
# outdated bookings to remove (cancelled bookings to replace by an active booking)
events_cancelled_to_delete = events_to_book.filter(
pk__in=existing_bookings.filter(cancellation_datetime__isnull=False), full=False
pk__in=existing_bookings.filter(
Q(cancellation_datetime__isnull=False) | Q(start_time__isnull=False)
),
full=False,
)
# book only events without active booking for the user
events_to_book = events_to_book.exclude(
pk__in=existing_bookings.filter(cancellation_datetime__isnull=True)
pk__in=existing_bookings.filter(cancellation_datetime__isnull=True, start_time__isnull=True),
)
# exclude full events
@ -1776,11 +1779,6 @@ class RecurringFillslots(APIView):
events_by_id = {x.id: x for x in list(events_to_book) + list(events_to_unbook)}
with transaction.atomic():
# cancel existing bookings
cancellation_datetime = now()
Booking.objects.filter(primary_booking__in=bookings_to_cancel).update(
cancellation_datetime=cancellation_datetime
)
if payload.get('include_booked_events_detail'):
cancelled_events = [
get_short_event_detail(
@ -1790,7 +1788,15 @@ class RecurringFillslots(APIView):
)
for x in bookings_to_cancel
]
cancelled_count = bookings_to_cancel.update(cancellation_datetime=cancellation_datetime)
if not payload.get('start_time'):
# cancel existing bookings
cancellation_datetime = now()
Booking.objects.filter(primary_booking__in=bookings_to_cancel).update(
cancellation_datetime=cancellation_datetime
)
cancelled_count = bookings_to_cancel.update(cancellation_datetime=cancellation_datetime)
else:
cancelled_count, dummy = bookings_to_cancel.delete()
# and delete outdated cancelled bookings
Booking.objects.filter(
user_external_id=user_external_id, event__in=events_cancelled_to_delete

View File

@ -1737,3 +1737,73 @@ def test_recurring_events_api_fillslots_partial_bookings(app, user):
params['end_time'] = '09:00'
resp = app.post_json(fillslots_url, params=params, status=400)
assert resp.json['errors']['non_field_errors'][0] == 'start_time must be before end_time'
@pytest.mark.freeze_time('2023-05-01 10:00')
def test_recurring_events_api_fillslots_partial_bookings_update(app, user):
agenda = Agenda.objects.create(label='Foo bar', kind='events', partial_bookings=True)
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
start_datetime = make_aware(datetime.datetime(2023, 5, 2, 8, 0))
event = Event.objects.create(
label='Event 08-18',
start_datetime=start_datetime,
end_time=datetime.time(18, 00),
places=2,
recurrence_end_date=start_datetime + datetime.timedelta(days=30),
recurrence_days=[1, 2],
agenda=agenda,
)
event.create_all_recurrences()
app.authorization = ('Basic', ('john.doe', 'password'))
params = {
'user_external_id': 'user_id',
'slots': 'foo-bar@event-08-18:1',
'start_time': '10:00',
'end_time': '15:00',
}
fillslots_url = '/api/agendas/recurring-events/fillslots/?action=update&agendas=%s' % agenda.slug
resp = app.post_json(fillslots_url, params=params)
assert resp.json['booking_count'] == 5
assert Booking.objects.count() == 5
assert (
Booking.objects.filter(
start_time=datetime.time(10, 00),
end_time=datetime.time(15, 00),
event__start_datetime__week_day=3,
).count()
== 5
)
params['start_time'] = '10:00'
params['end_time'] = '15:00'
resp = app.post_json(fillslots_url, params=params)
assert resp.json['booking_count'] == 5
assert resp.json['cancelled_booking_count'] == 0
assert Booking.objects.count() == 5
assert (
Booking.objects.filter(
cancellation_datetime__isnull=True,
start_time=datetime.time(10, 00),
end_time=datetime.time(15, 00),
event__start_datetime__week_day=3,
).count()
== 5
)
# change day
params['slots'] = 'foo-bar@event-08-18:2'
resp = app.post_json(fillslots_url, params=params)
assert resp.json['booking_count'] == 5
assert resp.json['cancelled_booking_count'] == 5
assert Booking.objects.count() == 5
assert (
Booking.objects.filter(
cancellation_datetime__isnull=True,
start_time=datetime.time(10, 00),
end_time=datetime.time(15, 00),
event__start_datetime__week_day=4,
).count()
== 5
)