api: cancel booking in recurring fillslot - instead of delete (#61066)

This commit is contained in:
Lauréline Guérin 2022-02-04 16:34:38 +01:00
parent 7eb1fcf7e4
commit f65717725b
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
2 changed files with 630 additions and 52 deletions

View File

@ -1647,8 +1647,22 @@ class RecurringFillslots(APIView):
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)
# outdated bookings to remove (cancelled bookings to replace by an active booking)
events_cancelled_to_delete = events_to_book.filter(
booking__user_external_id=user_external_id,
booking__cancellation_datetime__isnull=False,
full=False,
)
# book only events without active booking for the user
events_to_book = events_to_book.exclude(
pk__in=Booking.objects.filter(
event__in=events_to_book,
user_external_id=user_external_id,
cancellation_datetime__isnull=True,
).values('event')
)
# exclude full events
full_events = list(events_to_book.filter(full=True))
events_to_book = events_to_book.filter(full=False)
@ -1662,16 +1676,28 @@ class RecurringFillslots(APIView):
extra_data = {k: v for k, v in request.data.items() if k not in payload}
bookings = [make_booking(event, payload, extra_data) for event in events_to_book]
bookings_to_cancel = Booking.objects.filter(
user_external_id=user_external_id, event__in=events_to_unbook, cancellation_datetime__isnull=True
)
with transaction.atomic():
deleted_count = Booking.objects.filter(
user_external_id=user_external_id, event__in=events_to_unbook
).delete()[0]
# 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)
# and delete outdated cancelled bookings
Booking.objects.filter(
user_external_id=user_external_id, event__in=events_cancelled_to_delete
).delete()
# create missing bookings
Booking.objects.bulk_create(bookings)
response = {
'err': 0,
'booking_count': len(bookings),
'cancelled_booking_count': deleted_count,
'cancelled_booking_count': cancelled_count,
'full_events': [get_event_detail(request, x, multiple_agendas=True) for x in full_events],
}
if payload.get('include_booked_events_detail'):

View File

@ -2394,7 +2394,115 @@ def test_recurring_events_api_fillslots_waiting_list(app, user, freezer):
assert events.filter(booked_waiting_list_places=2).count() == 5
def test_recurring_events_api_fillslots_change_bookings(app, user, freezer):
def test_recurring_events_api_fillslots_book_with_cancelled(app, user, freezer):
freezer.move_to('2021-09-06 12:00')
agenda = Agenda.objects.create(label='Foo bar', kind='events', minimal_booking_delay=0)
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
event = Event.objects.create(
label='Event',
start_datetime=now(),
recurrence_days=[0, 1], # Monday, Tuesday
places=1,
waiting_list_places=1,
agenda=agenda,
recurrence_end_date=now() + datetime.timedelta(days=21),
)
event.create_all_recurrences()
# create cancelled bookings for the user
event_1_0 = event.get_or_create_event_recurrence(event.start_datetime)
booking_1_0 = Booking.objects.create(event=event_1_0, user_external_id='user_id')
booking_1_0.cancel()
assert booking_1_0.cancellation_datetime is not None
event_1_1 = event.get_or_create_event_recurrence(event.start_datetime + datetime.timedelta(days=1))
booking_1_1 = Booking.objects.create(event=event_1_1, user_external_id='user_id')
booking_1_1.cancel()
assert booking_1_1.cancellation_datetime is not None
# and non cancelled bookings for the user
event_2_0 = event.get_or_create_event_recurrence(event.start_datetime + datetime.timedelta(days=7))
booking_2_0 = Booking.objects.create(event=event_2_0, user_external_id='user_id')
assert booking_2_0.cancellation_datetime is None
event_2_1 = event.get_or_create_event_recurrence(event.start_datetime + datetime.timedelta(days=8))
booking_2_1 = Booking.objects.create(event=event_2_1, user_external_id='user_id')
assert booking_2_1.cancellation_datetime is None
# and bookings for another user
Booking.objects.create(event=event_1_0, user_external_id='user_id_foobar')
other_booking = Booking.objects.create(event=event_2_0, user_external_id='user_id_foobar')
other_booking.cancel()
app.authorization = ('Basic', ('john.doe', 'password'))
fillslots_url = '/api/agendas/recurring-events/fillslots/?agendas=%s&action=book' % agenda.slug
params = {'user_external_id': 'user_id'}
# Book Monday
params['slots'] = 'foo-bar@event:0'
resp = app.post_json(fillslots_url, params=params)
assert resp.json['booking_count'] == 2
assert resp.json['cancelled_booking_count'] == 0
assert Booking.objects.filter(user_external_id='user_id').count() == 5
assert Booking.objects.filter(user_external_id='user_id', cancellation_datetime__isnull=True).count() == 4
assert Booking.objects.filter(user_external_id='user_id', event__start_datetime__week_day=2).count() == 3
assert (
Booking.objects.filter(
user_external_id='user_id',
event__start_datetime__week_day=2,
cancellation_datetime__isnull=True,
).count()
== 3
)
assert Booking.objects.filter(user_external_id='user_id', event__start_datetime__week_day=3).count() == 2
assert (
Booking.objects.filter(
user_external_id='user_id',
event__start_datetime__week_day=3,
cancellation_datetime__isnull=True,
).count()
== 1
)
assert Booking.objects.filter(pk=booking_1_0.pk).exists() is False # cancelled booking deleted
booking_1_1.refresh_from_db()
booking_2_0.refresh_from_db()
booking_2_1.refresh_from_db()
assert booking_1_1.cancellation_datetime is not None
assert booking_2_0.cancellation_datetime is None
assert booking_2_1.cancellation_datetime is None
# Book Tuesday
params['slots'] = 'foo-bar@event:1'
resp = app.post_json(fillslots_url, params=params)
assert resp.json['booking_count'] == 2
assert resp.json['cancelled_booking_count'] == 0
assert Booking.objects.filter(user_external_id='user_id').count() == 6
assert Booking.objects.filter(user_external_id='user_id', cancellation_datetime__isnull=True).count() == 6
assert Booking.objects.filter(user_external_id='user_id', event__start_datetime__week_day=2).count() == 3
assert (
Booking.objects.filter(
user_external_id='user_id',
event__start_datetime__week_day=2,
cancellation_datetime__isnull=True,
).count()
== 3
)
assert Booking.objects.filter(user_external_id='user_id', event__start_datetime__week_day=3).count() == 3
assert (
Booking.objects.filter(
user_external_id='user_id',
event__start_datetime__week_day=3,
cancellation_datetime__isnull=True,
).count()
== 3
)
assert Booking.objects.filter(pk=booking_1_0.pk).exists() is False # cancelled booking deleted
assert Booking.objects.filter(pk=booking_1_1.pk).exists() is False # cancelled booking deleted
booking_2_0.refresh_from_db()
booking_2_1.refresh_from_db()
assert booking_2_0.cancellation_datetime is None
assert booking_2_1.cancellation_datetime is None
def test_recurring_events_api_fillslots_update(app, user, freezer):
freezer.move_to('2021-09-06 12:00')
agenda = Agenda.objects.create(
label='Foo bar', kind='events', minimal_booking_delay=0, maximal_booking_delay=0
@ -2443,11 +2551,35 @@ def test_recurring_events_api_fillslots_change_bookings(app, user, freezer):
resp = app.post_json(fillslots_url, params=params)
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
assert Booking.objects.filter(cancellation_datetime__isnull=True).count() == 152
assert (
Booking.objects.filter(
event__start_datetime__week_day=2,
cancellation_datetime__isnull=True,
).count()
== 52
)
assert (
Booking.objects.filter(
event__start_datetime__week_day=3,
cancellation_datetime__isnull=True,
).count()
== 4
)
assert (
Booking.objects.filter(
event__start_datetime__week_day=5,
cancellation_datetime__isnull=True,
).count()
== 48
)
assert (
Booking.objects.filter(
event__start_datetime__week_day=6,
cancellation_datetime__isnull=True,
).count()
== 48
)
# remove delays
agenda.minimal_booking_delay = 0
@ -2457,24 +2589,55 @@ def test_recurring_events_api_fillslots_change_bookings(app, user, freezer):
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
assert Booking.objects.filter(cancellation_datetime__isnull=True).count() == 104
assert (
Booking.objects.filter(
event__start_datetime__week_day=2,
cancellation_datetime__isnull=True,
).count()
== 52
)
assert (
Booking.objects.filter(
event__start_datetime__week_day=3,
cancellation_datetime__isnull=True,
).count()
== 52
)
# Booking again does nothing
resp = app.post_json(fillslots_url, params=params)
assert resp.json['booking_count'] == 0
assert resp.json['cancelled_booking_count'] == 0
assert Booking.objects.count() == 104
assert Booking.objects.filter(cancellation_datetime__isnull=True).count() == 104
params = {'user_external_id': 'user_id_2'}
params['slots'] = 'foo-bar@event:0,foo-bar@event:3'
resp = app.post_json(fillslots_url, params=params)
assert resp.json['booking_count'] == 104
assert resp.json['cancelled_booking_count'] == 0
assert Booking.objects.count() == 208
assert Booking.objects.filter(event__start_datetime__week_day=2).count() == 104
assert Booking.objects.filter(event__start_datetime__week_day=5).count() == 52
assert Booking.objects.filter(cancellation_datetime__isnull=True).count() == 208
assert (
Booking.objects.filter(
event__start_datetime__week_day=2,
cancellation_datetime__isnull=True,
).count()
== 104
)
assert (
Booking.objects.filter(
event__start_datetime__week_day=3,
cancellation_datetime__isnull=True,
).count()
== 52
)
assert (
Booking.objects.filter(
event__start_datetime__week_day=5,
cancellation_datetime__isnull=True,
).count()
== 52
)
events = Event.objects.filter(primary_event__isnull=False)
assert events.filter(booked_places=1).count() == 156
assert events.filter(booked_waiting_list_places=1).count() == 52
@ -2483,9 +2646,28 @@ def test_recurring_events_api_fillslots_change_bookings(app, user, freezer):
resp = app.post_json(fillslots_url, params=params)
assert resp.json['booking_count'] == 104
assert resp.json['cancelled_booking_count'] == 104
assert Booking.objects.count() == 208
assert Booking.objects.filter(event__start_datetime__week_day=3).count() == 104
assert Booking.objects.filter(event__start_datetime__week_day=6).count() == 52
assert Booking.objects.filter(cancellation_datetime__isnull=True).count() == 208
assert (
Booking.objects.filter(
event__start_datetime__week_day=2,
cancellation_datetime__isnull=True,
).count()
== 52
)
assert (
Booking.objects.filter(
event__start_datetime__week_day=3,
cancellation_datetime__isnull=True,
).count()
== 104
)
assert (
Booking.objects.filter(
event__start_datetime__week_day=6,
cancellation_datetime__isnull=True,
).count()
== 52
)
events = Event.objects.filter(primary_event__isnull=False)
assert events.filter(booked_places=1).count() == 156
assert events.filter(booked_waiting_list_places=1).count() == 52
@ -2494,7 +2676,13 @@ def test_recurring_events_api_fillslots_change_bookings(app, user, freezer):
resp = app.post_json(fillslots_url + '&date_end=2022-01-01', params=params)
assert resp.json['booking_count'] == 0
assert resp.json['cancelled_booking_count'] == 70
assert Booking.objects.filter(user_external_id='user_id_2').count() == 34
assert (
Booking.objects.filter(
user_external_id='user_id_2',
cancellation_datetime__isnull=True,
).count()
== 34
)
# past bookings are left in place
freezer.move_to('2021-10-04 12:00') # first Monday of october
@ -2502,14 +2690,33 @@ def test_recurring_events_api_fillslots_change_bookings(app, user, freezer):
resp = app.post_json(fillslots_url + '&date_start=2021-10-11&date_end=2022-01-01', params=params)
assert resp.json['booking_count'] == 0
assert resp.json['cancelled_booking_count'] == 2 # only first week of october was cancelled
assert Booking.objects.filter(user_external_id='user_id_2').count() == 32
assert (
Booking.objects.filter(
user_external_id='user_id_2',
cancellation_datetime__isnull=True,
).count()
== 32
)
# passing empty slots cancels all bookings
params['slots'] = ''
resp = app.post_json(fillslots_url, params=params)
assert resp.json['cancelled_booking_count'] == 24
assert Booking.objects.filter(user_external_id='user_id_2').count() == 8
assert Booking.objects.filter(user_external_id='user_id_2', event__start_datetime__gt=now()).count() == 0
assert (
Booking.objects.filter(
user_external_id='user_id_2',
cancellation_datetime__isnull=True,
).count()
== 8
)
assert (
Booking.objects.filter(
user_external_id='user_id_2',
event__start_datetime__gt=now(),
cancellation_datetime__isnull=True,
).count()
== 0
)
# only recurring events are impacted
normal_event = Event.objects.create(
@ -2521,7 +2728,121 @@ 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
def test_recurring_events_api_unbook(app, user, freezer):
def test_recurring_events_api_fillslots_update_with_cancelled(app, user, freezer):
freezer.move_to('2021-09-06 12:00')
agenda = Agenda.objects.create(label='Foo bar', kind='events', minimal_booking_delay=0)
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
event = Event.objects.create(
label='Event',
start_datetime=now(),
recurrence_days=[0, 1], # Monday, Tuesday
places=1,
waiting_list_places=1,
agenda=agenda,
recurrence_end_date=now() + datetime.timedelta(days=21),
)
event.create_all_recurrences()
# create cancelled bookings for the user
event_1_0 = event.get_or_create_event_recurrence(event.start_datetime)
booking_1_0 = Booking.objects.create(event=event_1_0, user_external_id='user_id')
booking_1_0.cancel()
assert booking_1_0.cancellation_datetime is not None
event_1_1 = event.get_or_create_event_recurrence(event.start_datetime + datetime.timedelta(days=1))
booking_1_1 = Booking.objects.create(event=event_1_1, user_external_id='user_id')
booking_1_1.cancel()
assert booking_1_1.cancellation_datetime is not None
# and non cancelled bookings for the user
event_2_0 = event.get_or_create_event_recurrence(event.start_datetime + datetime.timedelta(days=7))
booking_2_0 = Booking.objects.create(event=event_2_0, user_external_id='user_id')
assert booking_2_0.cancellation_datetime is None
event_2_1 = event.get_or_create_event_recurrence(event.start_datetime + datetime.timedelta(days=8))
booking_2_1 = Booking.objects.create(event=event_2_1, user_external_id='user_id')
assert booking_2_1.cancellation_datetime is None
# secondary booking for this one
booking_2_1_secondary = Booking.objects.create(event=event_2_1, primary_booking=booking_2_1)
# and bookings for another user
Booking.objects.create(event=event_1_0, user_external_id='user_id_foobar')
other_booking = Booking.objects.create(event=event_2_0, user_external_id='user_id_foobar')
other_booking.cancel()
app.authorization = ('Basic', ('john.doe', 'password'))
fillslots_url = '/api/agendas/recurring-events/fillslots/?agendas=%s&action=update' % agenda.slug
params = {'user_external_id': 'user_id'}
# Book Monday
params['slots'] = 'foo-bar@event:0'
resp = app.post_json(fillslots_url, params=params)
assert resp.json['booking_count'] == 2
assert resp.json['cancelled_booking_count'] == 1
assert Booking.objects.filter(user_external_id='user_id').count() == 5
assert Booking.objects.filter(user_external_id='user_id', cancellation_datetime__isnull=True).count() == 3
assert Booking.objects.filter(user_external_id='user_id', event__start_datetime__week_day=2).count() == 3
assert (
Booking.objects.filter(
user_external_id='user_id',
event__start_datetime__week_day=2,
cancellation_datetime__isnull=True,
).count()
== 3
)
assert (
Booking.objects.filter(event__start_datetime__week_day=3, primary_booking__isnull=True).count() == 2
)
assert (
Booking.objects.filter(
user_external_id='user_id',
event__start_datetime__week_day=3,
cancellation_datetime__isnull=True,
).count()
== 0
)
assert Booking.objects.filter(pk=booking_1_0.pk).exists() is False # cancelled booking deleted
booking_1_1.refresh_from_db()
booking_2_0.refresh_from_db()
booking_2_1.refresh_from_db()
booking_2_1_secondary.refresh_from_db()
assert booking_1_1.cancellation_datetime is not None
assert booking_2_0.cancellation_datetime is None
assert booking_2_1.cancellation_datetime is not None
assert booking_2_1_secondary.cancellation_datetime is not None
# Book Tuesday
params['slots'] = 'foo-bar@event:1'
resp = app.post_json(fillslots_url, params=params)
assert resp.json['booking_count'] == 3
assert resp.json['cancelled_booking_count'] == 3
assert Booking.objects.filter(user_external_id='user_id').count() == 6
assert Booking.objects.filter(user_external_id='user_id', cancellation_datetime__isnull=True).count() == 3
assert Booking.objects.filter(user_external_id='user_id', event__start_datetime__week_day=2).count() == 3
assert (
Booking.objects.filter(
user_external_id='user_id',
event__start_datetime__week_day=2,
cancellation_datetime__isnull=True,
).count()
== 0
)
assert Booking.objects.filter(user_external_id='user_id', event__start_datetime__week_day=3).count() == 3
assert (
Booking.objects.filter(
user_external_id='user_id',
event__start_datetime__week_day=3,
cancellation_datetime__isnull=True,
).count()
== 3
)
assert Booking.objects.filter(pk=booking_1_0.pk).exists() is False # cancelled booking deleted
assert Booking.objects.filter(pk=booking_1_1.pk).exists() is False # cancelled booking deleted
assert Booking.objects.filter(pk=booking_2_1.pk).exists() is False # cancelled booking deleted
assert Booking.objects.filter(pk=booking_2_1_secondary.pk).exists() is False # cancelled booking deleted
booking_2_0.refresh_from_db()
assert booking_2_0.cancellation_datetime is not None
def test_recurring_events_api_fillslots_unbook(app, user, freezer):
freezer.move_to('2021-09-06 12:00')
agenda = Agenda.objects.create(
label='Foo bar', kind='events', minimal_booking_delay=0, maximal_booking_delay=0
@ -2569,9 +2890,21 @@ def test_recurring_events_api_unbook(app, user, freezer):
assert resp.json['booking_count'] == 0
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
assert Booking.objects.filter(cancellation_datetime__isnull=True).count() == 152
assert (
Booking.objects.filter(
event__primary_event=event,
cancellation_datetime__isnull=True,
).count()
== 100
)
assert (
Booking.objects.filter(
event__primary_event=sunday_event,
cancellation_datetime__isnull=True,
).count()
== 52
)
# remove delays
agenda.minimal_booking_delay = 0
@ -2582,9 +2915,28 @@ def test_recurring_events_api_unbook(app, user, freezer):
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
assert Booking.objects.filter(event__primary_event=sunday_event).count() == 52
assert Booking.objects.filter(cancellation_datetime__isnull=True).count() == 104
assert (
Booking.objects.filter(
event__primary_event=event,
cancellation_datetime__isnull=True,
).count()
== 52
)
assert (
Booking.objects.filter(
event__primary_event=event,
cancellation_datetime__isnull=False,
).count()
== 52
)
assert (
Booking.objects.filter(
event__primary_event=sunday_event,
cancellation_datetime__isnull=True,
).count()
== 52
)
params['slots'] = 'foo-bar@sunday-event:6'
resp = app.post_json(
@ -2593,15 +2945,42 @@ def test_recurring_events_api_unbook(app, user, freezer):
assert resp.json['booking_count'] == 0
assert resp.json['cancelled_booking_count'] == 9
assert Booking.objects.count() == 95
assert Booking.objects.filter(event__primary_event=event).count() == 52
assert Booking.objects.filter(event__primary_event=sunday_event).count() == 43
assert Booking.objects.filter(cancellation_datetime__isnull=True).count() == 95
assert (
Booking.objects.filter(
event__primary_event=event,
cancellation_datetime__isnull=True,
).count()
== 52
)
assert (
Booking.objects.filter(
event__primary_event=event,
cancellation_datetime__isnull=False,
).count()
== 52
)
assert (
Booking.objects.filter(
event__primary_event=sunday_event,
cancellation_datetime__isnull=True,
).count()
== 43
)
assert (
Booking.objects.filter(
event__primary_event=sunday_event,
cancellation_datetime__isnull=False,
).count()
== 9
)
assert not Booking.objects.filter(
event__primary_event=sunday_event,
event__start_datetime__range=(
datetime.date(year=2022, month=1, day=1),
datetime.date(year=2022, month=3, day=1),
),
cancellation_datetime__isnull=True,
).exists()
freezer.move_to('2022-01-01 12:00')
@ -2611,12 +2990,26 @@ def test_recurring_events_api_unbook(app, user, freezer):
assert resp.json['booking_count'] == 0
assert resp.json['cancelled_booking_count'] == 35
assert Booking.objects.count() == 60
assert Booking.objects.filter(event__primary_event=event).count() == 17
assert Booking.objects.filter(cancellation_datetime__isnull=True).count() == 60
assert (
Booking.objects.filter(
event__primary_event=event,
cancellation_datetime__isnull=True,
).count()
== 17
)
assert not Booking.objects.filter(
event__primary_event=event, event__start_datetime__gt=datetime.date(year=2022, month=1, day=1)
event__primary_event=event,
event__start_datetime__gt=datetime.date(year=2022, month=1, day=1),
cancellation_datetime__isnull=True,
).exists()
assert Booking.objects.filter(event__primary_event=sunday_event).count() == 43
assert (
Booking.objects.filter(
event__primary_event=sunday_event,
cancellation_datetime__isnull=True,
).count()
== 43
)
# unbooking when there are no bookings does nothing
params['user_external_id'] = 'user_id_2'
@ -2625,6 +3018,117 @@ def test_recurring_events_api_unbook(app, user, freezer):
assert resp.json['cancelled_booking_count'] == 0
def test_recurring_events_api_fillslots_unbook_with_cancelled(app, user, freezer):
freezer.move_to('2021-09-06 12:00')
agenda = Agenda.objects.create(label='Foo bar', kind='events')
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
event = Event.objects.create(
label='Event',
start_datetime=now(),
recurrence_days=[0, 1], # Monday, Tuesday
places=1,
waiting_list_places=1,
agenda=agenda,
recurrence_end_date=now() + datetime.timedelta(days=21),
)
event.create_all_recurrences()
# create cancelled bookings for the user
event_1_0 = event.get_or_create_event_recurrence(event.start_datetime)
booking_1_0 = Booking.objects.create(event=event_1_0, user_external_id='user_id')
booking_1_0.cancel()
assert booking_1_0.cancellation_datetime is not None
event_1_1 = event.get_or_create_event_recurrence(event.start_datetime + datetime.timedelta(days=1))
booking_1_1 = Booking.objects.create(event=event_1_1, user_external_id='user_id')
booking_1_1.cancel()
assert booking_1_1.cancellation_datetime is not None
# and non cancelled bookings for the user
event_2_0 = event.get_or_create_event_recurrence(event.start_datetime + datetime.timedelta(days=7))
booking_2_0 = Booking.objects.create(event=event_2_0, user_external_id='user_id')
assert booking_2_0.cancellation_datetime is None
event_2_1 = event.get_or_create_event_recurrence(event.start_datetime + datetime.timedelta(days=8))
booking_2_1 = Booking.objects.create(event=event_2_1, user_external_id='user_id')
assert booking_2_1.cancellation_datetime is None
# and bookings for another user
Booking.objects.create(event=event_1_0, user_external_id='user_id_foobar')
other_booking = Booking.objects.create(event=event_2_0, user_external_id='user_id_foobar')
other_booking.cancel()
app.authorization = ('Basic', ('john.doe', 'password'))
fillslots_url = '/api/agendas/recurring-events/fillslots/?agendas=%s&action=unbook' % agenda.slug
params = {'user_external_id': 'user_id'}
# unbook Monday
params['slots'] = 'foo-bar@event:0'
resp = app.post_json(fillslots_url, params=params)
assert resp.json['booking_count'] == 0
assert resp.json['cancelled_booking_count'] == 1
assert Booking.objects.filter(user_external_id='user_id').count() == 4
assert Booking.objects.filter(user_external_id='user_id', cancellation_datetime__isnull=True).count() == 1
assert Booking.objects.filter(user_external_id='user_id', event__start_datetime__week_day=2).count() == 2
assert (
Booking.objects.filter(
user_external_id='user_id',
event__start_datetime__week_day=2,
cancellation_datetime__isnull=True,
).count()
== 0
)
assert Booking.objects.filter(user_external_id='user_id', event__start_datetime__week_day=3).count() == 2
assert (
Booking.objects.filter(
user_external_id='user_id',
event__start_datetime__week_day=3,
cancellation_datetime__isnull=True,
).count()
== 1
)
booking_1_0.refresh_from_db()
booking_1_1.refresh_from_db()
booking_2_0.refresh_from_db()
booking_2_1.refresh_from_db()
assert booking_1_0.cancellation_datetime is not None
assert booking_1_1.cancellation_datetime is not None
assert booking_2_0.cancellation_datetime is not None
assert booking_2_1.cancellation_datetime is None
# unbook Tuesday
params['slots'] = 'foo-bar@event:1'
resp = app.post_json(fillslots_url, params=params)
assert resp.json['booking_count'] == 0
assert resp.json['cancelled_booking_count'] == 1
assert Booking.objects.filter(user_external_id='user_id').count() == 4
assert Booking.objects.filter(user_external_id='user_id', cancellation_datetime__isnull=True).count() == 0
assert Booking.objects.filter(user_external_id='user_id', event__start_datetime__week_day=2).count() == 2
assert (
Booking.objects.filter(
user_external_id='user_id',
event__start_datetime__week_day=2,
cancellation_datetime__isnull=True,
).count()
== 0
)
assert Booking.objects.filter(user_external_id='user_id', event__start_datetime__week_day=3).count() == 2
assert (
Booking.objects.filter(
user_external_id='user_id',
event__start_datetime__week_day=3,
cancellation_datetime__isnull=True,
).count()
== 0
)
booking_1_0.refresh_from_db()
booking_1_1.refresh_from_db()
booking_2_0.refresh_from_db()
booking_2_1.refresh_from_db()
assert booking_1_0.cancellation_datetime is not None
assert booking_1_1.cancellation_datetime is not None
assert booking_2_0.cancellation_datetime is not None
assert booking_2_1.cancellation_datetime is not None
@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')
@ -2705,12 +3209,20 @@ def test_recurring_events_api_fillslots_subscribed(app, user):
resp = app.post_json(fillslots_url % 'all', params=params)
assert resp.json['booking_count'] == 12
assert resp.json['cancelled_booking_count'] == 10
assert Booking.objects.count() == 12
booked_events_first_agenda = Event.objects.filter(primary_event=event, booking__isnull=False)
assert Booking.objects.filter(cancellation_datetime__isnull=True).count() == 12
booked_events_first_agenda = Event.objects.filter(
primary_event=event,
booking__isnull=False,
booking__cancellation_datetime__isnull=True,
)
assert [
x.strftime('%d/%m/%Y') for x in booked_events_first_agenda.values_list('start_datetime', flat=True)
] == ['21/09/2021', '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)
booked_events_second_agenda = Event.objects.filter(
primary_event=sunday_event,
booking__isnull=False,
booking__cancellation_datetime__isnull=True,
)
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']
@ -2732,8 +3244,12 @@ def test_recurring_events_api_fillslots_subscribed(app, user):
params = {'user_external_id': 'yyy', 'slots': 'second-agenda@sunday-event:6'}
resp = app.post_json(fillslots_url % 'category-b', params=params)
assert resp.json['booking_count'] == 3
assert Booking.objects.count() == 15
booked_events_user_yyy = Event.objects.filter(primary_event=sunday_event, booking__user_external_id='yyy')
assert Booking.objects.filter(cancellation_datetime__isnull=True).count() == 15
booked_events_user_yyy = Event.objects.filter(
primary_event=sunday_event,
booking__user_external_id='yyy',
booking__cancellation_datetime__isnull=True,
)
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']
@ -2805,10 +3321,28 @@ def test_recurring_events_api_fillslots_multiple_agendas(app, user):
assert resp.json['booking_count'] == 0
assert resp.json['cancelled_booking_count'] == 2
assert Booking.objects.count() == 19
assert Booking.objects.filter(event__primary_event=event_a).count() == 12
assert Booking.objects.filter(event__primary_event=event_b).count() == 0
assert Booking.objects.filter(event__primary_event=event_c).count() == 7
assert Booking.objects.filter(cancellation_datetime__isnull=True).count() == 19
assert (
Booking.objects.filter(
event__primary_event=event_a,
cancellation_datetime__isnull=True,
).count()
== 12
)
assert (
Booking.objects.filter(
event__primary_event=event_b,
cancellation_datetime__isnull=True,
).count()
== 0
)
assert (
Booking.objects.filter(
event__primary_event=event_c,
cancellation_datetime__isnull=True,
).count()
== 7
)
# update bookings
params = {'user_external_id': 'user_id', 'slots': 'first-agenda@b:1'}
@ -2816,9 +3350,27 @@ def test_recurring_events_api_fillslots_multiple_agendas(app, user):
assert resp.json['booking_count'] == 5
assert resp.json['cancelled_booking_count'] == 19
assert Booking.objects.filter(event__primary_event=event_a).count() == 0
assert Booking.objects.filter(event__primary_event=event_b).count() == 5
assert Booking.objects.filter(event__primary_event=event_c).count() == 0
assert (
Booking.objects.filter(
event__primary_event=event_a,
cancellation_datetime__isnull=True,
).count()
== 0
)
assert (
Booking.objects.filter(
event__primary_event=event_b,
cancellation_datetime__isnull=True,
).count()
== 5
)
assert (
Booking.objects.filter(
event__primary_event=event_c,
cancellation_datetime__isnull=True,
).count()
== 0
)
# error if slot's agenda is not in querystring
resp = app.post_json(fillslots_url % ('update', 'second-agenda'), params=params, status=400)
@ -2850,7 +3402,7 @@ def test_recurring_events_api_fillslots_multiple_agendas_queries(app, user):
params={'slots': events_to_book, 'user_external_id': 'user'},
)
assert resp.json['booking_count'] == 180
assert len(ctx.captured_queries) == 16
assert len(ctx.captured_queries) == 17
@pytest.mark.freeze_time('2021-09-06 12:00')