0005-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 |
... | ... | |
2014 | 2016 |
raise APIErrorBadRequest(N_('it is not possible to change user_external_id value')) |
2015 | 2017 | |
2016 | 2018 |
serializer.save() |
2017 |
extra_data = {k: v for k, v in request.data.items() if k not in serializer.validated_data} |
|
2018 |
if extra_data: |
|
2019 |
self.subscription.extra_data = self.subscription.extra_data or {} |
|
2020 |
self.subscription.extra_data.update(extra_data) |
|
2021 |
self.subscription.save() |
|
2022 | 2019 | |
2023 | 2020 |
if old_date_start > self.subscription.date_end or old_date_end < self.subscription.date_start: |
2024 | 2021 |
# new period does not overlaps the old one, delete all bookings in the old period |
... | ... | |
2035 | 2032 |
self.subscription.date_end + datetime.timedelta(days=1), old_date_end |
2036 | 2033 |
) |
2037 | 2034 | |
2035 |
extra_data = {k: v for k, v in request.data.items() if k not in serializer.validated_data} |
|
2036 |
if extra_data: |
|
2037 |
self.subscription.extra_data = self.subscription.extra_data or {} |
|
2038 |
self.subscription.extra_data.update(extra_data) |
|
2039 |
self.subscription.save() |
|
2040 |
# update bookings inside the new period (other bookings were deleted) |
|
2041 |
Booking.objects.filter( |
|
2042 |
# remove user bookings for this agenda |
|
2043 |
event__agenda=self.subscription.agenda, |
|
2044 |
user_external_id=self.subscription.user_external_id, |
|
2045 |
# in the period of the subscription |
|
2046 |
event__start_datetime__gt=self.subscription.date_start, |
|
2047 |
event__start_datetime__lt=self.subscription.date_end + datetime.timedelta(days=1), |
|
2048 |
).filter( |
|
2049 |
# but only in the future |
|
2050 |
event__start_datetime__gt=now(), |
|
2051 |
).update( |
|
2052 |
extra_data=RawSQL("COALESCE(extra_data, '{}'::jsonb) || %s::jsonb", (json.dumps(extra_data),)) |
|
2053 |
) |
|
2054 | ||
2038 | 2055 |
return self.get(request, *args, **kwargs) |
2039 | 2056 | |
2040 | 2057 |
def delete(self, request, *args, **kwargs): |
tests/api/test_subscription.py | ||
---|---|---|
1032 | 1032 |
resp = app.patch('/api/agenda/%s/subscription/%s/' % (agenda.slug, subscription.pk), params=params) |
1033 | 1033 |
assert resp.json['err'] == 0 |
1034 | 1034 |
assert Booking.objects.filter(pk=booking.pk).exists() is not deleted |
1035 | ||
1036 | ||
1037 |
@pytest.mark.parametrize( |
|
1038 |
'date_now, event_date, user_id, in_waiting_list, cancelled, updated', |
|
1039 |
[ |
|
1040 |
# event in the future, but no booking for the user |
|
1041 |
('2021-09-01 09:59', (2021, 9, 1, 12, 0), 'yyy', False, False, False), |
|
1042 |
# event in the future |
|
1043 |
('2021-09-01 09:59', (2021, 9, 1, 12, 0), 'xxx', False, False, True), |
|
1044 |
('2021-09-01 09:59', (2021, 9, 1, 12, 0), 'xxx', True, False, True), |
|
1045 |
('2021-09-01 09:59', (2021, 9, 1, 12, 0), 'xxx', False, True, True), |
|
1046 |
# event in the past |
|
1047 |
('2021-09-01 10:00', (2021, 9, 1, 12, 0), 'xxx', False, False, False), |
|
1048 |
# event in the future |
|
1049 |
('2021-08-01 10:00', (2021, 9, 1, 12, 0), 'xxx', False, False, True), |
|
1050 |
('2021-08-01 10:00', (2021, 9, 30, 12, 0), 'xxx', False, False, True), |
|
1051 |
# event in the future, before the period |
|
1052 |
('2021-08-01 10:00', (2021, 8, 31, 12, 0), 'xxx', False, False, False), |
|
1053 |
# event in the future, after the period |
|
1054 |
('2021-08-01 10:00', (2021, 10, 1, 12, 0), 'xxx', False, False, False), |
|
1055 |
], |
|
1056 |
) |
|
1057 |
def test_api_patch_subscription_update_bookings_extra_data( |
|
1058 |
app, user, freezer, date_now, event_date, user_id, in_waiting_list, cancelled, updated |
|
1059 |
): |
|
1060 |
agenda = Agenda.objects.create(label='Foo bar', kind='events') |
|
1061 |
subscription = Subscription.objects.create( |
|
1062 |
agenda=agenda, |
|
1063 |
user_external_id='xxx', |
|
1064 |
date_start=datetime.date(year=2021, month=9, day=1), |
|
1065 |
date_end=datetime.date(year=2021, month=9, day=30), |
|
1066 |
) |
|
1067 | ||
1068 |
app.authorization = ('Basic', ('john.doe', 'password')) |
|
1069 | ||
1070 |
freezer.move_to(date_now) |
|
1071 |
event = Event.objects.create( |
|
1072 |
agenda=agenda, start_datetime=make_aware(datetime.datetime(*event_date)), places=10 |
|
1073 |
) |
|
1074 |
booking = Booking.objects.create( |
|
1075 |
event=event, |
|
1076 |
user_external_id=user_id, |
|
1077 |
in_waiting_list=in_waiting_list, |
|
1078 |
cancellation_datetime=(now() if cancelled else None), |
|
1079 |
) |
|
1080 | ||
1081 |
# extra_data is None |
|
1082 |
params = { |
|
1083 |
'foo': 'bar', |
|
1084 |
} |
|
1085 |
resp = app.patch('/api/agenda/%s/subscription/%s/' % (agenda.slug, subscription.pk), params=params) |
|
1086 |
assert resp.json['err'] == 0 |
|
1087 |
booking.refresh_from_db() |
|
1088 |
if updated: |
|
1089 |
assert booking.extra_data == {'foo': 'bar'} |
|
1090 |
else: |
|
1091 |
assert booking.extra_data is None |
|
1092 |
booking.extra_data = {'some': 'thing'} |
|
1093 |
booking.save() |
|
1094 | ||
1095 |
# extra_data is not None, update |
|
1096 |
resp = app.patch('/api/agenda/%s/subscription/%s/' % (agenda.slug, subscription.pk), params=params) |
|
1097 |
assert resp.json['err'] == 0 |
|
1098 |
booking.refresh_from_db() |
|
1099 |
if updated: |
|
1100 |
assert booking.extra_data == {'foo': 'bar', 'some': 'thing'} |
|
1101 |
else: |
|
1102 |
assert booking.extra_data == {'some': 'thing'} |
|
1103 | ||
1104 |
# extra_data is not None, merge |
|
1105 |
params = { |
|
1106 |
'foo': 'bar2', |
|
1107 |
} |
|
1108 |
resp = app.patch('/api/agenda/%s/subscription/%s/' % (agenda.slug, subscription.pk), params=params) |
|
1109 |
assert resp.json['err'] == 0 |
|
1110 |
booking.refresh_from_db() |
|
1111 |
if updated: |
|
1112 |
assert booking.extra_data == {'foo': 'bar2', 'some': 'thing'} |
|
1113 |
else: |
|
1114 |
assert booking.extra_data == {'some': 'thing'} |
|
1035 |
- |