api: update user bookings extra_data on subscription update (#61065)

This commit is contained in:
Lauréline Guérin 2022-02-03 16:50:21 +01:00
parent ad103323ba
commit b6e141b9c3
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
2 changed files with 102 additions and 5 deletions

View File

@ -18,11 +18,13 @@ import collections
import copy
import datetime
import itertools
import json
import uuid
from django.conf import settings
from django.db import transaction
from django.db.models import BooleanField, Count, ExpressionWrapper, F, Prefetch, Q
from django.db.models.expressions import RawSQL
from django.db.models.functions import TruncDay
from django.http import Http404, HttpResponse
from django.shortcuts import get_object_or_404
@ -2076,11 +2078,6 @@ class SubscriptionAPI(APIView):
raise APIErrorBadRequest(N_('it is not possible to change user_external_id value'))
serializer.save()
extra_data = {k: v for k, v in request.data.items() if k not in serializer.validated_data}
if extra_data:
self.subscription.extra_data = self.subscription.extra_data or {}
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
@ -2097,6 +2094,26 @@ class SubscriptionAPI(APIView):
self.subscription.date_end + datetime.timedelta(days=1), old_date_end
)
extra_data = {k: v for k, v in request.data.items() if k not in serializer.validated_data}
if extra_data:
self.subscription.extra_data = self.subscription.extra_data or {}
self.subscription.extra_data.update(extra_data)
self.subscription.save()
# update bookings inside the new period (other bookings were deleted)
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 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(),
).update(
extra_data=RawSQL("COALESCE(extra_data, '{}'::jsonb) || %s::jsonb", (json.dumps(extra_data),))
)
return self.get(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):

View File

@ -1032,3 +1032,83 @@ def test_api_patch_subscription_date_changes_delete_bookings_backwards_with_over
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(
'date_now, event_date, user_id, in_waiting_list, cancelled, updated',
[
# event in the future, but no booking for the user
('2021-09-01 09:59', (2021, 9, 1, 12, 0), 'yyy', False, False, False),
# event in the future
('2021-09-01 09:59', (2021, 9, 1, 12, 0), 'xxx', False, False, True),
('2021-09-01 09:59', (2021, 9, 1, 12, 0), 'xxx', True, False, True),
('2021-09-01 09:59', (2021, 9, 1, 12, 0), 'xxx', False, True, True),
# event in the past
('2021-09-01 10:00', (2021, 9, 1, 12, 0), 'xxx', False, False, False),
# event in the future
('2021-08-01 10:00', (2021, 9, 1, 12, 0), 'xxx', False, False, True),
('2021-08-01 10:00', (2021, 9, 30, 12, 0), 'xxx', False, False, True),
# event in the future, before the period
('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),
],
)
def test_api_patch_subscription_update_bookings_extra_data(
app, user, freezer, date_now, event_date, user_id, in_waiting_list, cancelled, updated
):
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(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),
)
# extra_data is None
params = {
'foo': 'bar',
}
resp = app.patch('/api/agenda/%s/subscription/%s/' % (agenda.slug, subscription.pk), params=params)
assert resp.json['err'] == 0
booking.refresh_from_db()
if updated:
assert booking.extra_data == {'foo': 'bar'}
else:
assert booking.extra_data is None
booking.extra_data = {'some': 'thing'}
booking.save()
# extra_data is not None, update
resp = app.patch('/api/agenda/%s/subscription/%s/' % (agenda.slug, subscription.pk), params=params)
assert resp.json['err'] == 0
booking.refresh_from_db()
if updated:
assert booking.extra_data == {'foo': 'bar', 'some': 'thing'}
else:
assert booking.extra_data == {'some': 'thing'}
# extra_data is not None, merge
params = {
'foo': 'bar2',
}
resp = app.patch('/api/agenda/%s/subscription/%s/' % (agenda.slug, subscription.pk), params=params)
assert resp.json['err'] == 0
booking.refresh_from_db()
if updated:
assert booking.extra_data == {'foo': 'bar2', 'some': 'thing'}
else:
assert booking.extra_data == {'some': 'thing'}