0001-api-mark-user-as-present-or-not-38678.patch
chrono/agendas/migrations/0070_booking_attendance.py | ||
---|---|---|
1 |
# -*- coding: utf-8 -*- |
|
2 |
from __future__ import unicode_literals |
|
3 | ||
4 |
from django.db import migrations, models |
|
5 | ||
6 | ||
7 |
class Migration(migrations.Migration): |
|
8 | ||
9 |
dependencies = [ |
|
10 |
('agendas', '0069_translate_holidays'), |
|
11 |
] |
|
12 | ||
13 |
operations = [ |
|
14 |
migrations.AddField(model_name='booking', name='user_was_present', field=models.NullBooleanField(),), |
|
15 |
] |
chrono/agendas/models.py | ||
---|---|---|
1042 | 1042 |
user_name = models.CharField(max_length=250, blank=True) |
1043 | 1043 |
user_email = models.EmailField(blank=True) |
1044 | 1044 |
user_phone_number = models.CharField(max_length=16, blank=True) |
1045 |
user_was_present = models.NullBooleanField() |
|
1046 | ||
1045 | 1047 |
form_url = models.URLField(blank=True) |
1046 | 1048 |
backoffice_url = models.URLField(blank=True) |
1047 | 1049 |
cancel_callback_url = models.URLField(blank=True) |
chrono/api/views.py | ||
---|---|---|
1144 | 1144 |
fillslot = Fillslot.as_view() |
1145 | 1145 | |
1146 | 1146 | |
1147 |
class BookingSerializer(serializers.ModelSerializer): |
|
1148 |
class Meta: |
|
1149 |
model = Booking |
|
1150 |
fields = ['user_was_present'] |
|
1151 | ||
1152 | ||
1147 | 1153 |
class BookingAPI(APIView): |
1148 | 1154 |
permission_classes = (permissions.IsAuthenticated,) |
1155 |
serializer_class = BookingSerializer |
|
1149 | 1156 | |
1150 | 1157 |
def initial(self, request, *args, **kwargs): |
1151 |
super(BookingAPI, self).initial(request, *args, **kwargs) |
|
1152 |
self.booking = Booking.objects.get(id=kwargs.get('booking_pk'), cancellation_datetime__isnull=True) |
|
1158 |
super().initial(request, *args, **kwargs) |
|
1159 |
self.booking = get_object_or_404(Booking, pk=kwargs.get('booking_pk')) |
|
1160 | ||
1161 |
def check_booking(self, check_waiting_list=False): |
|
1162 |
if self.booking.cancellation_datetime: |
|
1163 |
return Response( |
|
1164 |
{'err': 1, 'err_class': 'booking is cancelled', 'err_desc': _('booking is cancelled')} |
|
1165 |
) |
|
1166 | ||
1167 |
if self.booking.primary_booking is not None: |
|
1168 |
return Response({'err': 2, 'err_class': 'secondary booking', 'err_desc': _('secondary booking')}) |
|
1169 | ||
1170 |
if check_waiting_list and self.booking.in_waiting_list: |
|
1171 |
response = { |
|
1172 |
'err': 3, |
|
1173 |
'err_class': 'booking is in waiting list', |
|
1174 |
'err_desc': _('booking is in waiting list'), |
|
1175 |
} |
|
1176 |
return Response(response) |
|
1177 | ||
1178 |
def get(self, request, *args, **kwargs): |
|
1179 |
response = self.check_booking() |
|
1180 |
if response: |
|
1181 |
return response |
|
1182 | ||
1183 |
response = { |
|
1184 |
'err': 0, |
|
1185 |
'booking_id': self.booking.pk, |
|
1186 |
'in_waiting_list': self.booking.in_waiting_list, |
|
1187 |
'user_was_present': self.booking.user_was_present, |
|
1188 |
} |
|
1189 |
return Response(response) |
|
1190 | ||
1191 |
def patch(self, request, *args, **kwargs): |
|
1192 |
response = self.check_booking(check_waiting_list=True) |
|
1193 |
if response: |
|
1194 |
return response |
|
1195 | ||
1196 |
serializer = self.serializer_class(self.booking, data=request.data, partial=True) |
|
1197 | ||
1198 |
if not serializer.is_valid(): |
|
1199 |
return Response( |
|
1200 |
{ |
|
1201 |
'err': 4, |
|
1202 |
'err_class': 'invalid payload', |
|
1203 |
'err_desc': _('invalid payload'), |
|
1204 |
'errors': serializer.errors, |
|
1205 |
}, |
|
1206 |
status=status.HTTP_400_BAD_REQUEST, |
|
1207 |
) |
|
1208 | ||
1209 |
serializer.save() |
|
1210 |
self.booking.secondary_booking_set.update(user_was_present=self.booking.user_was_present) |
|
1211 | ||
1212 |
response = {'err': 0, 'booking_id': self.booking.pk} |
|
1213 |
return Response(response) |
|
1153 | 1214 | |
1154 | 1215 |
def delete(self, request, *args, **kwargs): |
1216 |
response = self.check_booking() |
|
1217 |
if response: |
|
1218 |
return response |
|
1219 | ||
1155 | 1220 |
self.booking.cancel() |
1156 |
response = {'err': 0, 'booking_id': self.booking.id}
|
|
1221 |
response = {'err': 0, 'booking_id': self.booking.pk}
|
|
1157 | 1222 |
return Response(response) |
1158 | 1223 | |
1159 | 1224 |
tests/test_api.py | ||
---|---|---|
1804 | 1804 |
assert Booking.objects.count() == 6 |
1805 | 1805 | |
1806 | 1806 | |
1807 |
@pytest.mark.parametrize('flag', [True, False, None]) |
|
1808 |
def test_booking_api_present(app, user, flag): |
|
1809 |
agenda = Agenda.objects.create(kind='events') |
|
1810 |
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10) |
|
1811 |
booking = Booking.objects.create(event=event, user_was_present=flag) |
|
1812 | ||
1813 |
app.authorization = ('Basic', ('john.doe', 'password')) |
|
1814 |
resp = app.get('/api/booking/%s/' % booking.pk) |
|
1815 |
assert resp.json['booking_id'] == booking.pk |
|
1816 |
assert resp.json['user_was_present'] == flag |
|
1817 | ||
1818 | ||
1819 |
@pytest.mark.parametrize('flag', [True, False]) |
|
1820 |
def test_booking_api_waiting_list(app, user, flag): |
|
1821 |
agenda = Agenda.objects.create(kind='events') |
|
1822 |
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10) |
|
1823 |
booking = Booking.objects.create(event=event, in_waiting_list=flag) |
|
1824 | ||
1825 |
app.authorization = ('Basic', ('john.doe', 'password')) |
|
1826 | ||
1827 |
resp = app.get('/api/booking/%s/' % booking.pk) |
|
1828 |
assert resp.json['booking_id'] == booking.pk |
|
1829 |
assert resp.json['in_waiting_list'] == flag |
|
1830 | ||
1831 | ||
1832 |
def test_booking_api_error(app, user): |
|
1833 |
agenda = Agenda.objects.create(kind='events') |
|
1834 |
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10) |
|
1835 |
booking = Booking.objects.create(event=event) |
|
1836 | ||
1837 |
app.authorization = ('Basic', ('john.doe', 'password')) |
|
1838 | ||
1839 |
# unknown |
|
1840 |
booking.cancel() |
|
1841 |
for method in ['get', 'delete', 'patch']: |
|
1842 |
getattr(app, method)('/api/booking/0/', status=404) |
|
1843 | ||
1844 |
# cancelled |
|
1845 |
booking.cancel() |
|
1846 |
for method in ['get', 'delete', 'patch']: |
|
1847 |
resp = getattr(app, method)('/api/booking/%s/' % booking.pk) |
|
1848 |
assert resp.json['err'] == 1 |
|
1849 |
assert resp.json['err_desc'] == 'booking is cancelled' |
|
1850 | ||
1851 |
# not a primary booking |
|
1852 |
secondary = Booking.objects.create(event=event, primary_booking=booking) |
|
1853 |
for method in ['get', 'delete', 'patch']: |
|
1854 |
resp = getattr(app, method)('/api/booking/%s/' % secondary.pk) |
|
1855 |
assert resp.json['err'] == 2 |
|
1856 |
assert resp.json['err_desc'] == 'secondary booking' |
|
1857 | ||
1858 |
# in waiting list |
|
1859 |
booking.cancellation_datetime = None |
|
1860 |
booking.in_waiting_list = True |
|
1861 |
booking.save() |
|
1862 |
resp = app.get('/api/booking/%s/' % booking.pk) |
|
1863 |
assert resp.json['err'] == 0 |
|
1864 |
resp = app.patch('/api/booking/%s/' % booking.pk) |
|
1865 |
assert resp.json['err'] == 3 |
|
1866 |
assert resp.json['err_desc'] == 'booking is in waiting list' |
|
1867 |
resp = app.delete('/api/booking/%s/' % booking.pk) |
|
1868 |
assert resp.json['err'] == 0 |
|
1869 | ||
1870 | ||
1871 |
def test_booking_patch_api(app, user): |
|
1872 |
agenda = Agenda.objects.create(kind='events') |
|
1873 |
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10) |
|
1874 |
booking = Booking.objects.create(event=event) |
|
1875 | ||
1876 |
app.authorization = ('Basic', ('john.doe', 'password')) |
|
1877 | ||
1878 |
resp = app.patch('/api/booking/%s/' % booking.pk) |
|
1879 |
assert resp.json['err'] == 0 |
|
1880 |
resp = app.patch('/api/booking/%s/' % booking.pk, params={'user_was_present': 'foobar'}, status=400) |
|
1881 |
assert resp.json['err'] == 4 |
|
1882 |
assert resp.json['err_desc'] == 'invalid payload' |
|
1883 | ||
1884 | ||
1885 |
@pytest.mark.parametrize('flag', [True, False, None]) |
|
1886 |
def test_booking_patch_api_present(app, user, flag): |
|
1887 |
agenda = Agenda.objects.create(kind='events') |
|
1888 |
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10) |
|
1889 |
booking = Booking.objects.create(event=event) |
|
1890 | ||
1891 |
app.authorization = ('Basic', ('john.doe', 'password')) |
|
1892 | ||
1893 |
# set flag |
|
1894 |
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_was_present': flag}) |
|
1895 |
booking.refresh_from_db() |
|
1896 |
assert booking.user_was_present == flag |
|
1897 | ||
1898 |
# reset |
|
1899 |
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_was_present': None}) |
|
1900 |
booking.refresh_from_db() |
|
1901 |
assert booking.user_was_present is None |
|
1902 | ||
1903 |
# make secondary bookings |
|
1904 |
Booking.objects.create(event=event, primary_booking=booking) |
|
1905 |
Booking.objects.create(event=event, primary_booking=booking) |
|
1906 |
# and other booking |
|
1907 |
other_booking = Booking.objects.create(event=event) |
|
1908 | ||
1909 |
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_was_present': flag}) |
|
1910 |
booking.refresh_from_db() |
|
1911 |
assert booking.user_was_present == flag |
|
1912 |
# all secondary bookings are upadted |
|
1913 |
assert list(booking.secondary_booking_set.values_list('user_was_present', flat=True)) == [flag, flag] |
|
1914 |
other_booking.refresh_from_db() |
|
1915 |
assert other_booking.user_was_present is None # not changed |
|
1916 | ||
1917 | ||
1807 | 1918 |
def test_booking_cancellation_api(app, some_data, user): |
1808 | 1919 |
agenda = Agenda.objects.filter(label=u'Foo bar')[0] |
1809 | 1920 |
event = [x for x in Event.objects.filter(agenda=agenda) if x.in_bookable_period()][0] |
1810 |
- |