api: remove user bookings on subscription date changes (#61065)

This commit is contained in:
Lauréline Guérin 2022-02-03 15:37:09 +01:00
parent b6f7d25808
commit ad103323ba
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
2 changed files with 333 additions and 12 deletions

View File

@ -2029,6 +2029,20 @@ class SubscriptionAPI(APIView):
response.update({'err': 0})
return Response(response)
def delete_out_of_period_bookings(self, date_start, date_end):
booking_qs = Booking.objects.filter(
# remove user bookings for this agenda
event__agenda=self.subscription.agenda,
user_external_id=self.subscription.user_external_id,
# in the requested period
event__start_datetime__gt=date_start,
event__start_datetime__lt=date_end + datetime.timedelta(days=1),
).filter(
# but only in the future
event__start_datetime__gt=now(),
)
booking_qs.delete()
def patch(self, request, *args, **kwargs):
serializer = self.serializer_class(self.subscription, data=request.data, partial=True)
old_date_start = self.subscription.date_start
@ -2068,21 +2082,25 @@ class SubscriptionAPI(APIView):
self.subscription.extra_data.update(extra_data)
self.subscription.save()
if old_date_start > self.subscription.date_end or old_date_end < self.subscription.date_start:
# new period does not overlaps the old one, delete all bookings in the old period
self.delete_out_of_period_bookings(old_date_start, old_date_end)
else:
if old_date_start < self.subscription.date_start:
# date start has been postponed, remove all bookings from old start to new start
self.delete_out_of_period_bookings(
old_date_start, self.subscription.date_start - datetime.timedelta(days=1)
)
if old_date_end > self.subscription.date_end:
# date end has been brought forward, remove all bookings from new end to old end
self.delete_out_of_period_bookings(
self.subscription.date_end + datetime.timedelta(days=1), old_date_end
)
return self.get(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
booking_qs = Booking.objects.filter(
# remove user bookings for this agenda
event__agenda=self.subscription.agenda,
user_external_id=self.subscription.user_external_id,
# in the period of the deleted subscription
event__start_datetime__gt=self.subscription.date_start,
event__start_datetime__lt=self.subscription.date_end + datetime.timedelta(days=1),
).filter(
# but only in the future
event__start_datetime__gt=now(),
)
booking_qs.delete()
self.delete_out_of_period_bookings(self.subscription.date_start, self.subscription.date_end)
self.subscription.delete()
response = {'err': 0}
return Response(response)

View File

@ -729,3 +729,306 @@ def test_api_patch_subscription_check_dates(app, user):
'/api/agenda/%s/subscription/%s/' % (agenda.slug, subscription.pk), params=params, status=400
)
assert resp.json['err_desc'] == 'another subscription overlapping this period already exists'
@pytest.mark.parametrize(
'date_now, event_date, user_id, in_waiting_list, cancelled, deleted',
[
# event in the future, but no booking for the user
('2021-09-04 09:59', (2021, 9, 4, 12, 0), 'yyy', False, False, False),
# event in the future
('2021-09-04 09:59', (2021, 9, 4, 12, 0), 'xxx', False, False, True),
('2021-09-04 09:59', (2021, 9, 4, 12, 0), 'xxx', True, False, True),
('2021-09-04 09:59', (2021, 9, 4, 12, 0), 'xxx', False, True, True),
# event in the past
('2021-09-04 10:00', (2021, 9, 4, 12, 0), 'xxx', False, False, False),
# event in the future, before the period
('2021-08-01 10:00', (2021, 8, 14, 12, 0), 'xxx', False, False, False),
('2021-08-01 10:00', (2021, 8, 31, 12, 0), 'xxx', False, False, False),
# event in the future, after the period
('2021-08-01 10:00', (2021, 10, 1, 12, 0), 'xxx', False, False, False),
('2021-08-01 10:00', (2021, 10, 16, 12, 0), 'xxx', False, False, False),
],
)
def test_api_patch_subscription_date_changes_delete_bookings(
app, user, freezer, date_now, event_date, user_id, in_waiting_list, cancelled, deleted
):
agenda = Agenda.objects.create(label='Foo bar', kind='events')
subscription = Subscription.objects.create(
agenda=agenda,
user_external_id='xxx',
date_start=datetime.date(year=2021, month=9, day=1),
date_end=datetime.date(year=2021, month=9, day=30),
)
Subscription.objects.create(
agenda=agenda,
user_external_id='zzz', # another user
date_start=datetime.date(year=2021, month=9, day=1),
date_end=datetime.date(year=2021, month=9, day=30),
)
other_agenda = Agenda.objects.create(label='Foo bar', kind='events')
Subscription.objects.create(
agenda=other_agenda,
user_external_id='xxx',
date_start=datetime.date(year=2021, month=9, day=1),
date_end=datetime.date(year=2021, month=10, day=1),
)
app.authorization = ('Basic', ('john.doe', 'password'))
freezer.move_to(date_now)
event = Event.objects.create(
agenda=agenda, start_datetime=make_aware(datetime.datetime(*event_date)), places=10
)
booking = Booking.objects.create(
event=event,
user_external_id=user_id,
in_waiting_list=in_waiting_list,
cancellation_datetime=(now() if cancelled else None),
)
# date_start is postponed, date_end is brought forward
params = {
'date_start': '2021-09-05',
'date_end': '2021-09-25',
}
resp = app.patch('/api/agenda/%s/subscription/%s/' % (agenda.slug, subscription.pk), params=params)
assert resp.json['err'] == 0
assert Booking.objects.filter(pk=booking.pk).exists() is not deleted
@pytest.mark.parametrize(
'event_date, deleted',
[
# just before old first day
((2021, 8, 31, 12, 00), False),
# old first day
((2021, 9, 1, 12, 00), True),
# old last day
((2021, 9, 30, 12, 00), True),
# just after old last day
((2021, 10, 1, 12, 00), False),
],
)
def test_api_patch_subscription_date_changes_delete_bookings_forwards_no_overlaps(
app, user, freezer, event_date, deleted
):
agenda = Agenda.objects.create(label='Foo bar', kind='events')
subscription = Subscription.objects.create(
agenda=agenda,
user_external_id='xxx',
date_start=datetime.date(year=2021, month=9, day=1),
date_end=datetime.date(year=2021, month=9, day=30),
)
app.authorization = ('Basic', ('john.doe', 'password'))
freezer.move_to('2021-08-01 10:00')
event = Event.objects.create(
agenda=agenda, start_datetime=make_aware(datetime.datetime(*event_date)), places=10
)
booking = Booking.objects.create(
event=event,
user_external_id='xxx',
)
# subscription moved forwards, no overlaps
params = {
'date_start': '2021-11-01',
'date_end': '2021-11-30',
}
resp = app.patch('/api/agenda/%s/subscription/%s/' % (agenda.slug, subscription.pk), params=params)
assert resp.json['err'] == 0
assert Booking.objects.filter(pk=booking.pk).exists() is not deleted
@pytest.mark.parametrize(
'event_date, deleted',
[
# just before old first day
((2021, 8, 31, 12, 00), False),
# old first day
((2021, 9, 1, 12, 00), True),
# old last day
((2021, 9, 30, 12, 00), True),
# just after old last day
((2021, 10, 1, 12, 00), False),
],
)
def test_api_patch_subscription_date_changes_delete_bookings_backwards_no_overlaps(
app, user, freezer, event_date, deleted
):
agenda = Agenda.objects.create(label='Foo bar', kind='events')
subscription = Subscription.objects.create(
agenda=agenda,
user_external_id='xxx',
date_start=datetime.date(year=2021, month=9, day=1),
date_end=datetime.date(year=2021, month=9, day=30),
)
app.authorization = ('Basic', ('john.doe', 'password'))
freezer.move_to('2021-06-01 10:00')
event = Event.objects.create(
agenda=agenda, start_datetime=make_aware(datetime.datetime(*event_date)), places=10
)
booking = Booking.objects.create(
event=event,
user_external_id='xxx',
)
# subscription moved backwards, no overlaps
params = {
'date_start': '2021-07-01',
'date_end': '2021-07-31',
}
resp = app.patch('/api/agenda/%s/subscription/%s/' % (agenda.slug, subscription.pk), params=params)
assert resp.json['err'] == 0
assert Booking.objects.filter(pk=booking.pk).exists() is not deleted
@pytest.mark.parametrize(
'event_date, deleted',
[
# just before old first day
((2021, 8, 31, 12, 00), False),
# old first day
((2021, 9, 1, 12, 00), True),
# just before new first day
((2021, 9, 4, 12, 00), True),
# new first day
((2021, 9, 5, 12, 00), False),
# new last day
((2021, 9, 25, 12, 00), False),
# just after new last day
((2021, 9, 26, 12, 00), True),
# old last day
((2021, 9, 30, 12, 00), True),
# just after old last day
((2021, 10, 1, 12, 00), False),
],
)
def test_api_patch_subscription_date_changes_delete_bookings_shorter_period(
app, user, freezer, event_date, deleted
):
agenda = Agenda.objects.create(label='Foo bar', kind='events')
subscription = Subscription.objects.create(
agenda=agenda,
user_external_id='xxx',
date_start=datetime.date(year=2021, month=9, day=1),
date_end=datetime.date(year=2021, month=9, day=30),
)
app.authorization = ('Basic', ('john.doe', 'password'))
freezer.move_to('2021-08-01 10:00')
event = Event.objects.create(
agenda=agenda, start_datetime=make_aware(datetime.datetime(*event_date)), places=10
)
booking = Booking.objects.create(
event=event,
user_external_id='xxx',
)
# date_start is postponed, date_end is brought forward
params = {
'date_start': '2021-09-05',
'date_end': '2021-09-25',
}
resp = app.patch('/api/agenda/%s/subscription/%s/' % (agenda.slug, subscription.pk), params=params)
assert resp.json['err'] == 0
assert Booking.objects.filter(pk=booking.pk).exists() is not deleted
@pytest.mark.parametrize(
'event_date, deleted',
[
# just before old first day
((2021, 8, 31, 12, 00), False),
# old first day
((2021, 9, 1, 12, 00), True),
# just before new first day
((2021, 9, 14, 12, 00), True),
# new first day
((2021, 9, 15, 12, 00), False),
# old last day
((2021, 9, 30, 12, 00), False),
# just after old last day
((2021, 10, 1, 12, 00), False),
],
)
def test_api_patch_subscription_date_changes_delete_bookings_forwards_with_overlaps(
app, user, freezer, event_date, deleted
):
agenda = Agenda.objects.create(label='Foo bar', kind='events')
subscription = Subscription.objects.create(
agenda=agenda,
user_external_id='xxx',
date_start=datetime.date(year=2021, month=9, day=1),
date_end=datetime.date(year=2021, month=9, day=30),
)
app.authorization = ('Basic', ('john.doe', 'password'))
freezer.move_to('2021-08-01 10:00')
event = Event.objects.create(
agenda=agenda, start_datetime=make_aware(datetime.datetime(*event_date)), places=10
)
booking = Booking.objects.create(
event=event,
user_external_id='xxx',
)
# subscription moved forwards, with overlaps
params = {
'date_start': '2021-09-15',
'date_end': '2021-10-15',
}
resp = app.patch('/api/agenda/%s/subscription/%s/' % (agenda.slug, subscription.pk), params=params)
assert resp.json['err'] == 0
assert Booking.objects.filter(pk=booking.pk).exists() is not deleted
@pytest.mark.parametrize(
'event_date, deleted',
[
# just before old first day
((2021, 8, 31, 12, 00), False),
# old first day
((2021, 9, 1, 12, 00), False),
# new last day
((2021, 9, 15, 12, 00), False),
# just after new last day
((2021, 9, 16, 12, 00), True),
# old last day
((2021, 9, 30, 12, 00), True),
# just after old last day
((2021, 10, 1, 12, 00), False),
],
)
def test_api_patch_subscription_date_changes_delete_bookings_backwards_with_overlaps(
app, user, freezer, event_date, deleted
):
agenda = Agenda.objects.create(label='Foo bar', kind='events')
subscription = Subscription.objects.create(
agenda=agenda,
user_external_id='xxx',
date_start=datetime.date(year=2021, month=9, day=1),
date_end=datetime.date(year=2021, month=9, day=30),
)
app.authorization = ('Basic', ('john.doe', 'password'))
freezer.move_to('2021-08-01 10:00')
event = Event.objects.create(
agenda=agenda, start_datetime=make_aware(datetime.datetime(*event_date)), places=10
)
booking = Booking.objects.create(
event=event,
user_external_id='xxx',
)
# subscription moved backwards, with overlaps
params = {
'date_start': '2021-08-15',
'date_end': '2021-09-15',
}
resp = app.patch('/api/agenda/%s/subscription/%s/' % (agenda.slug, subscription.pk), params=params)
assert resp.json['err'] == 0
assert Booking.objects.filter(pk=booking.pk).exists() is not deleted