Projet

Général

Profil

0001-api-booking-user_name-and-first-last_name-53172.patch

Lauréline Guérin, 16 avril 2021 10:30

Télécharger (18,5 ko)

Voir les différences:

Subject: [PATCH 1/2] api: booking, user_name and first/last_name (#53172)

 .../migrations/0079_booking_user_name.py      | 21 +++++++
 chrono/agendas/models.py                      | 10 ++-
 chrono/api/views.py                           |  7 ++-
 chrono/manager/views.py                       |  4 +-
 tests/manager/test_all.py                     |  6 +-
 tests/manager/test_event.py                   | 24 ++++----
 tests/test_agendas.py                         |  6 +-
 tests/test_api.py                             | 61 +++++++++++++------
 8 files changed, 100 insertions(+), 39 deletions(-)
 create mode 100644 chrono/agendas/migrations/0079_booking_user_name.py
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
-