0001-api-booking-user_name-and-first-last_name-53172.patch
chrono/agendas/migrations/0079_booking_user_name.py | ||
---|---|---|
1 |
from django.db import migrations, models |
|
2 | ||
3 | ||
4 |
class Migration(migrations.Migration): |
|
5 | ||
6 |
dependencies = [ |
|
7 |
('agendas', '0078_absence_reasons'), |
|
8 |
] |
|
9 | ||
10 |
operations = [ |
|
11 |
migrations.RenameField( |
|
12 |
model_name='booking', |
|
13 |
old_name='user_name', |
|
14 |
new_name='user_last_name', |
|
15 |
), |
|
16 |
migrations.AddField( |
|
17 |
model_name='booking', |
|
18 |
name='user_first_name', |
|
19 |
field=models.CharField(blank=True, max_length=250), |
|
20 |
), |
|
21 |
] |
chrono/agendas/models.py | ||
---|---|---|
1509 | 1509 |
verbose_name=_('Label displayed to user'), max_length=250, blank=True |
1510 | 1510 |
) |
1511 | 1511 |
user_external_id = models.CharField(max_length=250, blank=True) |
1512 |
user_name = models.CharField(max_length=250, blank=True) |
|
1512 |
user_last_name = models.CharField(max_length=250, blank=True) |
|
1513 |
user_first_name = models.CharField(max_length=250, blank=True) |
|
1513 | 1514 |
user_email = models.EmailField(blank=True) |
1514 | 1515 |
user_phone_number = models.CharField(max_length=16, blank=True) |
1515 | 1516 |
user_was_present = models.NullBooleanField() |
... | ... | |
1520 | 1521 |
cancel_callback_url = models.URLField(blank=True) |
1521 | 1522 |
color = models.ForeignKey(BookingColor, null=True, on_delete=models.SET_NULL, related_name='bookings') |
1522 | 1523 | |
1524 |
@property |
|
1525 |
def user_name(self): |
|
1526 |
return ('%s %s' % (self.user_first_name.strip(), self.user_last_name.strip())).strip() |
|
1527 | ||
1523 | 1528 |
def save(self, *args, **kwargs): |
1524 | 1529 |
with transaction.atomic(): |
1525 | 1530 |
super(Booking, self).save(*args, **kwargs) |
... | ... | |
1556 | 1561 |
label='', |
1557 | 1562 |
user_display_label='', |
1558 | 1563 |
user_external_id='', |
1559 |
user_name='', |
|
1564 |
user_last_name='', |
|
1565 |
user_first_name='', |
|
1560 | 1566 |
extra_data={}, |
1561 | 1567 |
anonymization_datetime=now(), |
1562 | 1568 |
) |
chrono/api/views.py | ||
---|---|---|
852 | 852 | |
853 | 853 |
label = serializers.CharField(max_length=250, allow_blank=True) |
854 | 854 |
user_external_id = serializers.CharField(max_length=250, allow_blank=True) |
855 |
user_name = serializers.CharField(max_length=250, allow_blank=True) |
|
855 |
user_name = serializers.CharField(max_length=250, allow_blank=True) # compatibility |
|
856 |
user_first_name = serializers.CharField(max_length=250, allow_blank=True) |
|
857 |
user_last_name = serializers.CharField(max_length=250, allow_blank=True) |
|
856 | 858 |
user_display_label = serializers.CharField(max_length=250, allow_blank=True) |
857 | 859 |
user_email = serializers.CharField(max_length=250, allow_blank=True) |
858 | 860 |
user_phone_number = serializers.CharField(max_length=16, allow_blank=True) |
... | ... | |
1197 | 1199 |
in_waiting_list=in_waiting_list, |
1198 | 1200 |
label=payload.get('label', ''), |
1199 | 1201 |
user_external_id=payload.get('user_external_id', ''), |
1200 |
user_name=payload.get('user_name', ''), |
|
1202 |
user_first_name=payload.get('user_first_name', ''), |
|
1203 |
user_last_name=payload.get('user_last_name') or payload.get('user_name') or '', |
|
1201 | 1204 |
user_email=payload.get('user_email', ''), |
1202 | 1205 |
user_phone_number=payload.get('user_phone_number', ''), |
1203 | 1206 |
form_url=payload.get('form_url', ''), |
chrono/manager/views.py | ||
---|---|---|
1949 | 1949 |
event = self.object |
1950 | 1950 |
context['booked'] = event.booking_set.filter( |
1951 | 1951 |
cancellation_datetime__isnull=True, in_waiting_list=False |
1952 |
).order_by('user_name') |
|
1952 |
).order_by('user_last_name', 'user_first_name')
|
|
1953 | 1953 |
context['waiting'] = event.booking_set.filter( |
1954 | 1954 |
cancellation_datetime__isnull=True, in_waiting_list=True |
1955 |
).order_by('user_name') |
|
1955 |
).order_by('user_last_name', 'user_first_name')
|
|
1956 | 1956 |
for booking in context['booked']: |
1957 | 1957 |
booking.form = BookingAbsenceReasonForm( |
1958 | 1958 |
agenda=self.agenda, initial={'reason': booking.user_absence_reason} |
tests/manager/test_all.py | ||
---|---|---|
3195 | 3195 |
booking.creation_datetime = make_aware(datetime.datetime(2019, 12, 21, 14, 0 + i)) |
3196 | 3196 |
if i == 5: |
3197 | 3197 |
booking.creation_datetime = make_aware(datetime.datetime(2019, 12, 21, 15, 0)) |
3198 |
booking.user_name = 'Foo Bar User' |
|
3198 |
booking.user_first_name = 'Foo Bar' |
|
3199 |
booking.user_last_name = 'User' |
|
3199 | 3200 |
if i == 6: |
3200 | 3201 |
booking.creation_datetime = make_aware(datetime.datetime(2019, 12, 21, 16, 0)) |
3201 |
booking.user_name = 'Foo Bar User 2' |
|
3202 |
booking.user_first_name = 'Foo Bar' |
|
3203 |
booking.user_last_name = 'User 2' |
|
3202 | 3204 |
booking.label = 'Foo Bar Label 2' |
3203 | 3205 |
if i == 7: |
3204 | 3206 |
booking.creation_datetime = make_aware(datetime.datetime(2019, 12, 21, 17, 0)) |
tests/manager/test_event.py | ||
---|---|---|
1062 | 1062 |
waiting_list_places=5, |
1063 | 1063 |
agenda=agenda, |
1064 | 1064 |
) |
1065 |
booking1 = Booking.objects.create(event=event, user_name='User 42')
|
|
1066 |
Booking.objects.create(event=event, user_name='User 1')
|
|
1067 |
Booking.objects.create(event=event, user_name='User 17')
|
|
1068 |
Booking.objects.create(event=event, user_name='User 35')
|
|
1069 |
Booking.objects.create(event=event, user_name='User 5')
|
|
1070 |
booking6 = Booking.objects.create(event=event, user_name='User Cancelled')
|
|
1065 |
booking1 = Booking.objects.create(event=event, user_first_name='User', user_last_name='42')
|
|
1066 |
Booking.objects.create(event=event, user_first_name='User', user_last_name='01')
|
|
1067 |
Booking.objects.create(event=event, user_first_name='User', user_last_name='17')
|
|
1068 |
Booking.objects.create(event=event, user_first_name='User', user_last_name='35')
|
|
1069 |
Booking.objects.create(event=event, user_first_name='User', user_last_name='05')
|
|
1070 |
booking6 = Booking.objects.create(event=event, user_first_name='User', user_last_name=' Cancelled')
|
|
1071 | 1071 |
booking6.cancel() |
1072 |
booking7 = Booking.objects.create(event=event, user_name='User Waiting', in_waiting_list=True) |
|
1072 |
booking7 = Booking.objects.create( |
|
1073 |
event=event, user_first_name='User', user_last_name=' Waiting', in_waiting_list=True |
|
1074 |
) |
|
1073 | 1075 |
login(app) |
1074 | 1076 | |
1075 | 1077 |
# event not in past |
... | ... | |
1092 | 1094 |
assert 'Waiting List (1/5)' in resp |
1093 | 1095 |
assert ( |
1094 | 1096 |
resp.text.index('Bookings (5/10)') |
1095 |
< resp.text.index('User 1') |
|
1097 |
< resp.text.index('User 01') |
|
1098 |
< resp.text.index('User 05') |
|
1096 | 1099 |
< resp.text.index('User 17') |
1097 | 1100 |
< resp.text.index('User 35') |
1098 | 1101 |
< resp.text.index('User 42') |
1099 |
< resp.text.index('User 5') |
|
1100 | 1102 |
< resp.text.index('Waiting List (1/5)') |
1101 | 1103 |
< resp.text.index('User Waiting') |
1102 | 1104 |
) # user ordering is not optimal ... |
... | ... | |
1168 | 1170 |
waiting_list_places=5, |
1169 | 1171 |
agenda=agenda, |
1170 | 1172 |
) |
1171 |
booking = Booking.objects.create(event=event, user_name='User 42')
|
|
1173 |
booking = Booking.objects.create(event=event, user_first_name='User', user_last_name='42')
|
|
1172 | 1174 | |
1173 | 1175 |
login(app) |
1174 | 1176 |
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk)) |
... | ... | |
1242 | 1244 |
waiting_list_places=5, |
1243 | 1245 |
agenda=agenda, |
1244 | 1246 |
) |
1245 |
booking = Booking.objects.create(event=event, user_name='User 42')
|
|
1247 |
booking = Booking.objects.create(event=event, user_first_name='User', user_last_name='42')
|
|
1246 | 1248 | |
1247 | 1249 |
login(app) |
1248 | 1250 |
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk)) |
tests/test_agendas.py | ||
---|---|---|
1806 | 1806 |
label='john', |
1807 | 1807 |
user_display_label='john', |
1808 | 1808 |
user_external_id='john', |
1809 |
user_name='john', |
|
1809 |
user_first_name='john', |
|
1810 |
user_last_name='doe', |
|
1810 | 1811 |
backoffice_url='https://example.org', |
1811 | 1812 |
) |
1812 | 1813 | |
... | ... | |
1833 | 1834 |
label='', |
1834 | 1835 |
user_display_label='', |
1835 | 1836 |
user_external_id='', |
1836 |
user_name='', |
|
1837 |
user_first_name='', |
|
1838 |
user_last_name='', |
|
1837 | 1839 |
backoffice_url='https://example.org', |
1838 | 1840 |
extra_data={}, |
1839 | 1841 |
anonymization_datetime=now(), |
tests/test_api.py | ||
---|---|---|
1178 | 1178 |
) |
1179 | 1179 |
booking = Booking.objects.get(id=resp.json['booking_id']) |
1180 | 1180 |
assert booking.label == 'foo' |
1181 |
assert booking.user_name == 'bar' |
|
1181 |
assert booking.user_first_name == '' |
|
1182 |
assert booking.user_last_name == 'bar' |
|
1183 |
assert booking.backoffice_url == 'http://example.net/' |
|
1184 |
assert booking.cancel_callback_url == 'http://example.net/jump/trigger/' |
|
1185 |
assert booking.user_email == 'bar@bar.com' |
|
1186 |
assert booking.user_phone_number == '+33123456789' |
|
1187 |
assert booking.form_url == 'http://example.net/' |
|
1188 | ||
1189 |
resp = app.post_json( |
|
1190 |
'/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id), |
|
1191 |
params={ |
|
1192 |
'label': 'foo', |
|
1193 |
'user_first_name': 'foo', |
|
1194 |
'user_last_name': 'bar', |
|
1195 |
'backoffice_url': 'http://example.net/', |
|
1196 |
'cancel_callback_url': 'http://example.net/jump/trigger/', |
|
1197 |
'user_email': 'bar@bar.com', |
|
1198 |
'user_phone_number': '+33123456789', |
|
1199 |
'form_url': 'http://example.net/', |
|
1200 |
}, |
|
1201 |
) |
|
1202 |
booking = Booking.objects.get(id=resp.json['booking_id']) |
|
1203 |
assert booking.label == 'foo' |
|
1204 |
assert booking.user_first_name == 'foo' |
|
1205 |
assert booking.user_last_name == 'bar' |
|
1182 | 1206 |
assert booking.backoffice_url == 'http://example.net/' |
1183 | 1207 |
assert booking.cancel_callback_url == 'http://example.net/jump/trigger/' |
1184 | 1208 |
assert booking.user_email == 'bar@bar.com' |
... | ... | |
1188 | 1212 |
# blank data are OK |
1189 | 1213 |
resp = app.post_json( |
1190 | 1214 |
'/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id), |
1191 |
params={'label': '', 'user_name': '', 'backoffice_url': ''}, |
|
1215 |
params={'label': '', 'user_first_name': '', 'user_last_name': '', 'backoffice_url': ''},
|
|
1192 | 1216 |
) |
1193 | 1217 |
assert Booking.objects.get(id=resp.json['booking_id']).label == '' |
1194 |
assert Booking.objects.get(id=resp.json['booking_id']).user_name == '' |
|
1218 |
assert Booking.objects.get(id=resp.json['booking_id']).user_first_name == '' |
|
1219 |
assert Booking.objects.get(id=resp.json['booking_id']).user_last_name == '' |
|
1195 | 1220 |
assert Booking.objects.get(id=resp.json['booking_id']).backoffice_url == '' |
1196 | 1221 | |
1197 | 1222 |
# extra data stored in extra_data field |
1198 | 1223 |
resp = app.post_json( |
1199 | 1224 |
'/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id), |
1200 |
params={'label': 'l', 'user_name': 'u', 'backoffice_url': '', 'foo': 'bar'}, |
|
1225 |
params={'label': 'l', 'user_last_name': 'u', 'backoffice_url': '', 'foo': 'bar'},
|
|
1201 | 1226 |
) |
1202 | 1227 |
assert Booking.objects.get(id=resp.json['booking_id']).label == 'l' |
1203 |
assert Booking.objects.get(id=resp.json['booking_id']).user_name == 'u' |
|
1228 |
assert Booking.objects.get(id=resp.json['booking_id']).user_last_name == 'u'
|
|
1204 | 1229 |
assert Booking.objects.get(id=resp.json['booking_id']).backoffice_url == '' |
1205 | 1230 |
assert Booking.objects.get(id=resp.json['booking_id']).extra_data == {'foo': 'bar'} |
1206 | 1231 | |
... | ... | |
1212 | 1237 |
# test invalid data are refused |
1213 | 1238 |
resp = app.post_json( |
1214 | 1239 |
'/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id), |
1215 |
params={'user_name': {'foo': 'bar'}}, |
|
1240 |
params={'user_last_name': {'foo': 'bar'}},
|
|
1216 | 1241 |
status=400, |
1217 | 1242 |
) |
1218 | 1243 |
assert resp.json['err'] == 1 |
... | ... | |
1220 | 1245 |
assert resp.json['err_class'] == 'invalid payload' |
1221 | 1246 |
assert resp.json['err_desc'] == 'invalid payload' |
1222 | 1247 |
assert len(resp.json['errors']) == 1 |
1223 |
assert 'user_name' in resp.json['errors'] |
|
1248 |
assert 'user_last_name' in resp.json['errors']
|
|
1224 | 1249 | |
1225 | 1250 |
resp = app.post('/api/agenda/foobar/fillslot/%s/' % event.id, status=404) |
1226 | 1251 | |
... | ... | |
1366 | 1391 |
'/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id), |
1367 | 1392 |
params={ |
1368 | 1393 |
'label': 'foo', |
1369 |
'user_name': 'bar', |
|
1394 |
'user_first_name': 'foo', |
|
1395 |
'user_last_name': 'bar', |
|
1370 | 1396 |
'backoffice_url': 'http://example.net/', |
1371 | 1397 |
'url': 'http://example.com/booking', |
1372 | 1398 |
'user_display_label': 'your booking', |
... | ... | |
1375 | 1401 |
assert Booking.objects.count() == 3 |
1376 | 1402 |
booking_ics = Booking.objects.get(id=resp.json['booking_id']).get_ics() |
1377 | 1403 |
assert 'SUMMARY:your booking\r\n' in booking_ics |
1378 |
assert 'ATTENDEE:bar\r\n' in booking_ics |
|
1404 |
assert 'ATTENDEE:foo bar\r\n' in booking_ics
|
|
1379 | 1405 |
assert 'URL:http://example.com/booking\r\n' in booking_ics |
1380 | 1406 | |
1381 | 1407 |
# extra data stored in extra_data field |
... | ... | |
1383 | 1409 |
'/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id), |
1384 | 1410 |
params={ |
1385 | 1411 |
'label': 'l', |
1386 |
'user_name': 'u', |
|
1387 | 1412 |
'backoffice_url': '', |
1388 | 1413 |
'location': 'bar', |
1389 | 1414 |
'comment': 'booking comment', |
... | ... | |
1489 | 1514 |
'slots': events_ids, |
1490 | 1515 |
'label': 'foo', |
1491 | 1516 |
'user_external_id': 'some_external_id', |
1492 |
'user_name': 'bar', |
|
1517 |
'user_last_name': 'bar',
|
|
1493 | 1518 |
'user_display_label': 'foo', |
1494 | 1519 |
'backoffice_url': 'http://example.net/', |
1495 | 1520 |
}, |
... | ... | |
1498 | 1523 |
booking = Booking.objects.get(pk=booking_id) |
1499 | 1524 |
assert booking.label == 'foo' |
1500 | 1525 |
assert booking.user_external_id == 'some_external_id' |
1501 |
assert booking.user_name == 'bar' |
|
1526 |
assert booking.user_last_name == 'bar'
|
|
1502 | 1527 |
assert booking.user_display_label == 'foo' |
1503 | 1528 |
assert booking.backoffice_url == 'http://example.net/' |
1504 | 1529 |
assert Booking.objects.filter(primary_booking=booking_id, label='foo').count() == 2 |
... | ... | |
1514 | 1539 |
# extra data stored in extra_data field |
1515 | 1540 |
resp = app.post_json( |
1516 | 1541 |
'/api/agenda/%s/fillslots/' % agenda.id, |
1517 |
params={'slots': events_ids, 'label': 'l', 'user_name': 'u', 'backoffice_url': '', 'foo': 'bar'}, |
|
1542 |
params={'slots': events_ids, 'label': 'l', 'user_last_name': 'u', 'backoffice_url': '', 'foo': 'bar'},
|
|
1518 | 1543 |
) |
1519 | 1544 |
assert Booking.objects.get(id=resp.json['booking_id']).label == 'l' |
1520 |
assert Booking.objects.get(id=resp.json['booking_id']).user_name == 'u' |
|
1545 |
assert Booking.objects.get(id=resp.json['booking_id']).user_last_name == 'u'
|
|
1521 | 1546 |
assert Booking.objects.get(id=resp.json['booking_id']).backoffice_url == '' |
1522 | 1547 |
assert Booking.objects.get(id=resp.json['booking_id']).extra_data == {'foo': 'bar'} |
1523 | 1548 |
for booking in Booking.objects.filter(primary_booking=resp.json['booking_id']): |
... | ... | |
1526 | 1551 |
# test invalid data are refused |
1527 | 1552 |
resp = app.post_json( |
1528 | 1553 |
'/api/agenda/%s/fillslots/' % agenda.id, |
1529 |
params={'slots': events_ids, 'user_name': {'foo': 'bar'}}, |
|
1554 |
params={'slots': events_ids, 'user_last_name': {'foo': 'bar'}},
|
|
1530 | 1555 |
status=400, |
1531 | 1556 |
) |
1532 | 1557 |
assert resp.json['err'] == 1 |
... | ... | |
1534 | 1559 |
assert resp.json['err_class'] == 'invalid payload' |
1535 | 1560 |
assert resp.json['err_desc'] == 'invalid payload' |
1536 | 1561 |
assert len(resp.json['errors']) == 1 |
1537 |
assert 'user_name' in resp.json['errors'] |
|
1562 |
assert 'user_last_name' in resp.json['errors']
|
|
1538 | 1563 | |
1539 | 1564 |
# empty or missing slots |
1540 | 1565 |
resp = app.post_json('/api/agenda/%s/fillslots/' % agenda.id, params={'slots': []}, status=400) |
... | ... | |
1563 | 1588 |
in_bookable_period.return_value = True |
1564 | 1589 |
resp = app.post_json( |
1565 | 1590 |
'/api/agenda/%s/fillslots/' % agenda.id, |
1566 |
params={'slots': events_ids, 'label': 'l', 'user_name': 'u', 'backoffice_url': '', 'foo': 'bar'},
|
|
1591 |
params={'slots': events_ids}, |
|
1567 | 1592 |
) |
1568 | 1593 |
assert resp.json['err'] == 0 |
1569 | 1594 |
in_bookable_period.return_value = False |
1570 | 1595 |
resp = app.post_json( |
1571 | 1596 |
'/api/agenda/%s/fillslots/' % agenda.id, |
1572 |
params={'slots': events_ids, 'label': 'l', 'user_name': 'u', 'backoffice_url': '', 'foo': 'bar'},
|
|
1597 |
params={'slots': events_ids}, |
|
1573 | 1598 |
) |
1574 | 1599 |
assert resp.json['err'] == 1 |
1575 | 1600 |
assert resp.json['reason'] == 'event not bookable' # legacy |
1576 |
- |