0003-api-update-user-bookings-extra_data-on-subscription-.patch
chrono/api/views.py | ||
---|---|---|
18 | 18 |
import copy |
19 | 19 |
import datetime |
20 | 20 |
import itertools |
21 |
import json |
|
21 | 22 |
import uuid |
22 | 23 | |
23 | 24 |
from django.conf import settings |
24 | 25 |
from django.db import transaction |
25 | 26 |
from django.db.models import BooleanField, Count, ExpressionWrapper, F, Prefetch, Q |
27 |
from django.db.models.expressions import RawSQL |
|
26 | 28 |
from django.db.models.functions import TruncDay |
27 | 29 |
from django.http import Http404, HttpResponse |
28 | 30 |
from django.shortcuts import get_object_or_404 |
... | ... | |
1986 | 1988 |
raise APIErrorBadRequest(N_('invalid payload'), errors=serializer.errors, err=4) |
1987 | 1989 | |
1988 | 1990 |
serializer.save() |
1989 |
extra_data = {k: v for k, v in request.data.items() if k not in serializer.validated_data} |
|
1990 |
if extra_data: |
|
1991 |
self.subscription.extra_data = self.subscription.extra_data or {} |
|
1992 |
self.subscription.extra_data.update(extra_data) |
|
1993 |
self.subscription.save() |
|
1994 | 1991 | |
1995 | 1992 |
if old_date_start > self.subscription.date_end or old_date_end < self.subscription.date_start: |
1996 | 1993 |
# new period does not overlaps the old one, delete all bookings in the old period |
... | ... | |
2007 | 2004 |
self.subscription.date_end + datetime.timedelta(days=1), old_date_end |
2008 | 2005 |
) |
2009 | 2006 | |
2007 |
extra_data = {k: v for k, v in request.data.items() if k not in serializer.validated_data} |
|
2008 |
if extra_data: |
|
2009 |
self.subscription.extra_data = self.subscription.extra_data or {} |
|
2010 |
self.subscription.extra_data.update(extra_data) |
|
2011 |
self.subscription.save() |
|
2012 |
# update bookings inside the new period (other bookings were deleted) |
|
2013 |
Booking.objects.filter( |
|
2014 |
# remove user bookings for this agenda |
|
2015 |
event__agenda=self.subscription.agenda, |
|
2016 |
user_external_id=self.subscription.user_external_id, |
|
2017 |
# in the period of the deleted subscription |
|
2018 |
event__start_datetime__gt=self.subscription.date_start, |
|
2019 |
event__start_datetime__lt=self.subscription.date_end + datetime.timedelta(days=1), |
|
2020 |
).filter( |
|
2021 |
# but only in the future |
|
2022 |
event__start_datetime__gt=now(), |
|
2023 |
).update( |
|
2024 |
extra_data=RawSQL("COALESCE(extra_data, '{}'::jsonb) || %s::jsonb", (json.dumps(extra_data),)) |
|
2025 |
) |
|
2026 | ||
2010 | 2027 |
return self.get(request, *args, **kwargs) |
2011 | 2028 | |
2012 | 2029 |
def delete(self, request, *args, **kwargs): |
tests/api/test_subscription.py | ||
---|---|---|
870 | 870 |
resp = app.patch('/api/agenda/%s/subscription/%s/' % (agenda.slug, subscription.pk), params=params) |
871 | 871 |
assert resp.json['err'] == 0 |
872 | 872 |
assert Booking.objects.filter(pk=booking.pk).exists() is not deleted |
873 | ||
874 | ||
875 |
@pytest.mark.parametrize( |
|
876 |
'date_now, event_date, user_id, in_waiting_list, cancelled, updated', |
|
877 |
[ |
|
878 |
# event in the future, but no booking for the user |
|
879 |
('2021-09-01 09:59', (2021, 9, 1, 12, 0), 'yyy', False, False, False), |
|
880 |
# event in the future |
|
881 |
('2021-09-01 09:59', (2021, 9, 1, 12, 0), 'xxx', False, False, True), |
|
882 |
('2021-09-01 09:59', (2021, 9, 1, 12, 0), 'xxx', True, False, True), |
|
883 |
('2021-09-01 09:59', (2021, 9, 1, 12, 0), 'xxx', False, True, True), |
|
884 |
# event in the past |
|
885 |
('2021-09-01 10:00', (2021, 9, 1, 12, 0), 'xxx', False, False, False), |
|
886 |
# event in the future |
|
887 |
('2021-08-01 10:00', (2021, 9, 1, 12, 0), 'xxx', False, False, True), |
|
888 |
('2021-08-01 10:00', (2021, 9, 30, 12, 0), 'xxx', False, False, True), |
|
889 |
# event in the future, before the period |
|
890 |
('2021-08-01 10:00', (2021, 8, 31, 12, 0), 'xxx', False, False, False), |
|
891 |
# event in the future, after the period |
|
892 |
('2021-08-01 10:00', (2021, 10, 1, 12, 0), 'xxx', False, False, False), |
|
893 |
], |
|
894 |
) |
|
895 |
def test_api_patch_subscription_update_bookings_extra_data( |
|
896 |
app, user, freezer, date_now, event_date, user_id, in_waiting_list, cancelled, updated |
|
897 |
): |
|
898 |
agenda = Agenda.objects.create(label='Foo bar', kind='events') |
|
899 |
subscription = Subscription.objects.create( |
|
900 |
agenda=agenda, |
|
901 |
user_external_id='xxx', |
|
902 |
date_start=datetime.date(year=2021, month=9, day=1), |
|
903 |
date_end=datetime.date(year=2021, month=9, day=30), |
|
904 |
) |
|
905 | ||
906 |
app.authorization = ('Basic', ('john.doe', 'password')) |
|
907 | ||
908 |
freezer.move_to(date_now) |
|
909 |
event = Event.objects.create( |
|
910 |
agenda=agenda, start_datetime=make_aware(datetime.datetime(*event_date)), places=10 |
|
911 |
) |
|
912 |
booking = Booking.objects.create( |
|
913 |
event=event, |
|
914 |
user_external_id=user_id, |
|
915 |
in_waiting_list=in_waiting_list, |
|
916 |
cancellation_datetime=(now() if cancelled else None), |
|
917 |
) |
|
918 | ||
919 |
# extra_data is None |
|
920 |
params = { |
|
921 |
'foo': 'bar', |
|
922 |
} |
|
923 |
resp = app.patch('/api/agenda/%s/subscription/%s/' % (agenda.slug, subscription.pk), params=params) |
|
924 |
assert resp.json['err'] == 0 |
|
925 |
booking.refresh_from_db() |
|
926 |
if updated: |
|
927 |
assert booking.extra_data == {'foo': 'bar'} |
|
928 |
else: |
|
929 |
assert booking.extra_data is None |
|
930 |
booking.extra_data = {'some': 'thing'} |
|
931 |
booking.save() |
|
932 | ||
933 |
# extra_data is not None, update |
|
934 |
resp = app.patch('/api/agenda/%s/subscription/%s/' % (agenda.slug, subscription.pk), params=params) |
|
935 |
assert resp.json['err'] == 0 |
|
936 |
booking.refresh_from_db() |
|
937 |
if updated: |
|
938 |
assert booking.extra_data == {'foo': 'bar', 'some': 'thing'} |
|
939 |
else: |
|
940 |
assert booking.extra_data == {'some': 'thing'} |
|
941 | ||
942 |
# extra_data is not None, merge |
|
943 |
params = { |
|
944 |
'foo': 'bar2', |
|
945 |
} |
|
946 |
resp = app.patch('/api/agenda/%s/subscription/%s/' % (agenda.slug, subscription.pk), params=params) |
|
947 |
assert resp.json['err'] == 0 |
|
948 |
booking.refresh_from_db() |
|
949 |
if updated: |
|
950 |
assert booking.extra_data == {'foo': 'bar2', 'some': 'thing'} |
|
951 |
else: |
|
952 |
assert booking.extra_data == {'some': 'thing'} |
|
873 |
- |