Projet

Général

Profil

0001-api-exclude-slots-already-booked-by-user-in-fillslot.patch

Lauréline Guérin, 25 février 2021 15:33

Télécharger (10 ko)

Voir les différences:

Subject: [PATCH] api: exclude slots already booked by user in fillslot
 (#51432)

 chrono/api/views.py |  17 ++++-
 tests/test_api.py   | 158 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 173 insertions(+), 2 deletions(-)
chrono/api/views.py
851 851
    user_display_label = serializers.CharField(max_length=250, allow_blank=True)
852 852
    user_email = serializers.CharField(max_length=250, allow_blank=True)
853 853
    user_phone_number = serializers.CharField(max_length=16, allow_blank=True)
854
    exclude_user = serializers.BooleanField(default=False)
854 855
    form_url = serializers.CharField(max_length=250, allow_blank=True)
855 856
    backoffice_url = serializers.URLField(allow_blank=True)
856 857
    cancel_callback_url = serializers.URLField(allow_blank=True)
......
976 977

  
977 978
        available_desk = None
978 979
        color = None
980
        user_external_id = payload.get('user_external_id') or None
981
        exclude_user = payload.get('exclude_user')
979 982

  
980 983
        if agenda.accept_meetings():
981 984
            # slots are actually timeslot ids (meeting_type:start_datetime), not events ids.
......
1025 1028
                    http_status=status.HTTP_400_BAD_REQUEST,
1026 1029
                )
1027 1030
            all_slots = sorted(
1028
                get_all_slots(agenda, meeting_type, resources=resources),
1031
                get_all_slots(
1032
                    agenda,
1033
                    meeting_type,
1034
                    resources=resources,
1035
                    excluded_user_external_id=user_external_id if exclude_user else None,
1036
                ),
1029 1037
                key=lambda slot: slot.start_datetime,
1030 1038
            )
1031 1039

  
......
1118 1126
        else:
1119 1127
            # convert event recurrence identifiers to real event slugs
1120 1128
            for i, slot in enumerate(slots.copy()):
1121
                if not ':' in slot:
1129
                if ':' not in slot:
1122 1130
                    continue
1123 1131
                event = get_event_recurrence(agenda, slot)
1124 1132
                slots[i] = event.slug
......
1133 1141
                    raise APIError(_('event not bookable'), err_class='event not bookable')
1134 1142
                if event.cancelled:
1135 1143
                    raise APIError(_('event is cancelled'), err_class='event is cancelled')
1144
                if exclude_user and user_external_id:
1145
                    if event.booking_set.filter(user_external_id=user_external_id).exists():
1146
                        raise APIError(
1147
                            _('event is already booked by user'), err_class='event is already booked by user'
1148
                        )
1136 1149

  
1137 1150
            if not events.count():
1138 1151
                raise APIError(
tests/test_api.py
1145 1145
    resp = app.post('/api/agenda/0/fillslot/%s/' % event.id, status=404)
1146 1146

  
1147 1147

  
1148
@pytest.mark.freeze_time('2021-02-23')
1149
def test_booking_api_exclude_slots(app, user):
1150
    agenda = Agenda.objects.create(
1151
        label='Foo bar', kind='events', minimal_booking_delay=0, maximal_booking_delay=7
1152
    )
1153
    event = Event.objects.create(
1154
        slug='event-slug',
1155
        start_datetime=localtime().replace(hour=10, minute=0),
1156
        places=5,
1157
        agenda=agenda,
1158
    )
1159
    Booking.objects.create(event=event, user_external_id='42')
1160

  
1161
    app.authorization = ('Basic', ('john.doe', 'password'))
1162
    resp = app.post(
1163
        '/api/agenda/%s/fillslot/%s/' % (agenda.slug, event.slug), params={'user_external_id': '42'}
1164
    )
1165
    assert resp.json['err'] == 0
1166
    resp = app.post(
1167
        '/api/agenda/%s/fillslot/%s/' % (agenda.slug, event.slug),
1168
        params={'user_external_id': '42', 'exclude_user': True},
1169
    )
1170
    assert resp.json['err'] == 1
1171
    assert resp.json['err_class'] == 'event is already booked by user'
1172
    resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda.slug, event.slug), params={'exclude_user': True})
1173
    assert resp.json['err'] == 0
1174

  
1175
    event.delete()
1176

  
1177
    # recurrent event
1178
    event = Event.objects.create(
1179
        slug='recurrent',
1180
        start_datetime=localtime().replace(hour=12, minute=0),
1181
        repeat='weekly',
1182
        places=2,
1183
        agenda=agenda,
1184
    )
1185
    first_recurrence = event.get_or_create_event_recurrence(event.start_datetime)
1186
    Booking.objects.create(event=first_recurrence, user_external_id='42')
1187
    resp = app.post(
1188
        '/api/agenda/%s/fillslot/%s/' % (agenda.slug, event.slug), params={'user_external_id': '42'}
1189
    )
1190
    assert resp.json['err'] == 0
1191
    resp = app.post(
1192
        '/api/agenda/%s/fillslot/%s/' % (agenda.slug, event.slug),
1193
        params={'user_external_id': '42', 'exclude_user': True},
1194
    )
1195
    assert resp.json['err'] == 1
1196
    assert resp.json['err_class'] == 'event is already booked by user'
1197
    resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda.slug, event.slug), params={'exclude_user': True})
1198
    assert resp.json['err'] == 0
1199

  
1200

  
1201
@pytest.mark.freeze_time('2021-02-25')
1202
def test_booking_api_meetings_agenda_exclude_slots(app, user):
1203
    tomorrow = now() + datetime.timedelta(days=1)
1204
    agenda = Agenda.objects.create(
1205
        label='Agenda', kind='meetings', minimal_booking_delay=0, maximal_booking_delay=10
1206
    )
1207
    desk = Desk.objects.create(agenda=agenda, slug='desk')
1208
    meeting_type = MeetingType.objects.create(agenda=agenda, slug='foo-bar')
1209
    TimePeriod.objects.create(
1210
        weekday=tomorrow.date().weekday(),
1211
        start_time=datetime.time(9, 0),
1212
        end_time=datetime.time(17, 00),
1213
        desk=desk,
1214
    )
1215
    desk.duplicate()
1216
    desk.duplicate()
1217
    event = Event.objects.create(
1218
        agenda=agenda,
1219
        meeting_type=meeting_type,
1220
        places=1,
1221
        start_datetime=localtime(tomorrow).replace(hour=9, minute=0),
1222
        desk=desk,
1223
    )
1224
    Booking.objects.create(event=event, user_external_id='42')
1225

  
1226
    app.authorization = ('Basic', ('john.doe', 'password'))
1227
    resp = app.post(
1228
        '/api/agenda/%s/fillslot/%s:2021-02-26-0900/' % (agenda.slug, meeting_type.slug),
1229
        params={'user_external_id': '42'},
1230
    )
1231
    assert resp.json['err'] == 0
1232
    resp = app.post(
1233
        '/api/agenda/%s/fillslot/%s:2021-02-26-0900/' % (agenda.slug, meeting_type.slug),
1234
        params={'user_external_id': '42', 'exclude_user': True},
1235
    )
1236
    assert resp.json['err'] == 1
1237
    assert resp.json['err_class'] == 'no more desk available'
1238
    resp = app.post(
1239
        '/api/agenda/%s/fillslot/%s:2021-02-26-0900/' % (agenda.slug, meeting_type.slug),
1240
        params={'exclude_user': True},
1241
    )
1242
    assert resp.json['err'] == 0
1243

  
1244

  
1148 1245
def test_booking_ics(app, some_data, meetings_agenda, user):
1149 1246
    agenda = Agenda.objects.filter(label=u'Foo bar')[0]
1150 1247
    event = [x for x in Event.objects.filter(agenda=agenda) if x.in_bookable_period()][0]
......
4764 4861
    assert resp_booking.json['err_desc'] == 'no more desk available'
4765 4862

  
4766 4863

  
4864
@pytest.mark.freeze_time('2021-02-25')
4865
def test_virtual_agendas_meetings_booking_exclude_slots(app, user):
4866
    tomorrow = now() + datetime.timedelta(days=1)
4867
    agenda = Agenda.objects.create(
4868
        label='Agenda', kind='meetings', minimal_booking_delay=0, maximal_booking_delay=10
4869
    )
4870
    desk = Desk.objects.create(agenda=agenda, slug='desk')
4871
    meeting_type = MeetingType.objects.create(agenda=agenda, slug='foo-bar')
4872
    TimePeriod.objects.create(
4873
        weekday=tomorrow.date().weekday(),
4874
        start_time=datetime.time(9, 0),
4875
        end_time=datetime.time(17, 00),
4876
        desk=desk,
4877
    )
4878
    agenda2 = agenda.duplicate()
4879
    agenda3 = agenda.duplicate()
4880
    virt_agenda = Agenda.objects.create(
4881
        label='Virtual Agenda', kind='virtual', minimal_booking_delay=1, maximal_booking_delay=10
4882
    )
4883
    VirtualMember.objects.create(virtual_agenda=virt_agenda, real_agenda=agenda)
4884
    VirtualMember.objects.create(virtual_agenda=virt_agenda, real_agenda=agenda2)
4885
    VirtualMember.objects.create(virtual_agenda=virt_agenda, real_agenda=agenda3)
4886

  
4887
    event = Event.objects.create(
4888
        agenda=agenda,
4889
        meeting_type=meeting_type,
4890
        places=1,
4891
        start_datetime=localtime(tomorrow).replace(hour=9, minute=0),
4892
        desk=desk,
4893
    )
4894
    Booking.objects.create(event=event, user_external_id='42')
4895

  
4896
    app.authorization = ('Basic', ('john.doe', 'password'))
4897
    resp = app.post(
4898
        '/api/agenda/%s/fillslot/%s:2021-02-26-0900/' % (virt_agenda.slug, meeting_type.slug),
4899
        params={'user_external_id': '42'},
4900
    )
4901
    assert resp.json['err'] == 0
4902
    resp = app.post(
4903
        '/api/agenda/%s/fillslot/%s:2021-02-26-0900/' % (virt_agenda.slug, meeting_type.slug),
4904
        params={'user_external_id': '42', 'exclude_user': True},
4905
    )
4906
    assert resp.json['err'] == 1
4907
    assert resp.json['err_class'] == 'no more desk available'
4908
    resp = app.post(
4909
        '/api/agenda/%s/fillslot/%s:2021-02-26-0900/' % (virt_agenda.slug, meeting_type.slug),
4910
        params={'exclude_user': True},
4911
    )
4912
    assert resp.json['err'] == 0
4913

  
4914
    virt_agenda.minimal_booking_delay = None
4915
    virt_agenda.maximal_booking_delay = None
4916
    virt_agenda.save()
4917
    resp = app.post(
4918
        '/api/agenda/%s/fillslot/%s:2021-02-26-0900/' % (virt_agenda.slug, meeting_type.slug),
4919
        params={'user_external_id': '42', 'exclude_user': True},
4920
    )
4921
    assert resp.json['err'] == 1
4922
    assert resp.json['err_class'] == 'no more desk available'
4923

  
4924

  
4767 4925
def test_virtual_agendas_meetings_booking_default_policy(app, mock_now, user):
4768 4926
    foo_agenda = Agenda.objects.create(
4769 4927
        label='Foo Meeting', kind='meetings', minimal_booking_delay=1, maximal_booking_delay=5
4770
-