chrono/tests/api/datetimes/test_virtual.py

1252 lines
47 KiB
Python

import datetime
import pytest
from django.db import connection
from django.test.utils import CaptureQueriesContext
from chrono.agendas.models import (
Agenda,
Booking,
Desk,
Event,
MeetingType,
TimePeriod,
TimePeriodException,
UnavailabilityCalendar,
VirtualMember,
)
from chrono.utils.timezone import localtime, make_aware, now
from ...utils import build_virtual_agenda
pytestmark = pytest.mark.django_db
def test_virtual_agendas_meetings_datetimes_api(app, virtual_meetings_agenda):
real_agenda = virtual_meetings_agenda.real_agendas.first()
meeting_type = real_agenda.meetingtype_set.first()
default_desk = real_agenda.desk_set.first()
# Unkown meeting
app.get('/api/agenda/%s/meetings/xxx/datetimes/' % virtual_meetings_agenda.slug, status=404)
virt_meeting_type = virtual_meetings_agenda.iter_meetingtypes()[0]
api_url = '/api/agenda/%s/meetings/%s/datetimes/' % (virtual_meetings_agenda.slug, virt_meeting_type.slug)
resp = app.get(api_url)
assert len(resp.json['data']) == 144
# cover completely to test limit condition in get_all_slots()
full_coverage = TimePeriodException.objects.create(
desk=default_desk,
start_datetime=make_aware(datetime.datetime(2017, 1, 1, 0, 0)),
end_datetime=make_aware(datetime.datetime(2018, 1, 1, 0, 0)),
)
resp = app.get(api_url)
assert len(resp.json['data']) == 0
full_coverage.delete()
virtual_meetings_agenda.minimal_booking_delay = 7
virtual_meetings_agenda.maximal_booking_delay = 28
virtual_meetings_agenda.save()
resp = app.get(api_url)
assert len(resp.json['data']) == 54
virtual_meetings_agenda.minimal_booking_delay = 1
virtual_meetings_agenda.maximal_booking_delay = 56
virtual_meetings_agenda.save()
resp = app.get(api_url)
assert len(resp.json['data']) == 144
resp = app.get(api_url)
dt = datetime.datetime.strptime(resp.json['data'][2]['id'].split(':')[1], '%Y-%m-%d-%H%M')
ev = Event(
agenda=real_agenda,
meeting_type=meeting_type,
places=1,
full=False,
start_datetime=make_aware(dt),
desk=default_desk,
)
ev.save()
booking = Booking(event=ev)
booking.save()
resp2 = app.get(api_url)
assert len(resp2.json['data']) == 144
assert resp.json['data'][0] == resp2.json['data'][0]
assert resp.json['data'][1] == resp2.json['data'][1]
assert resp.json['data'][2] != resp2.json['data'][2]
assert resp.json['data'][2]['disabled'] is False
assert resp2.json['data'][2]['disabled'] is True
assert resp.json['data'][3] == resp2.json['data'][3]
# test with a timeperiod overlapping current moment, it should get one
# datetime for the current timeperiod + two from the next week.
if localtime(now()).time().hour == 23:
# skip this part of the test as it would require support for events
# crossing midnight
return
TimePeriod.objects.filter(desk=default_desk).delete()
start_time = localtime(now()) - datetime.timedelta(minutes=10)
time_period = TimePeriod(
weekday=localtime(now()).weekday(),
start_time=start_time,
end_time=start_time + datetime.timedelta(hours=1),
desk=default_desk,
)
time_period.save()
virtual_meetings_agenda.minimal_booking_delay = 0
virtual_meetings_agenda.maximal_booking_delay = 10
virtual_meetings_agenda.save()
resp = app.get(api_url)
assert len(resp.json['data']) == 3
def test_virtual_agendas_meetings_datetimes_api_with_similar_desk(app):
agenda_foo = Agenda.objects.create(
label='Agenda Foo', kind='meetings', minimal_booking_delay=1, maximal_booking_delay=4
)
MeetingType.objects.create(agenda=agenda_foo, label='Meeting Type', duration=30)
test_1st_weekday = (localtime(now()).weekday() + 1) % 7
test_2nd_weekday = (localtime(now()).weekday() + 2) % 7
test_3rd_weekday = (localtime(now()).weekday() + 3) % 7
desk_foo = Desk.objects.create(agenda=agenda_foo, label='Desk 1')
TimePeriod.objects.create(
weekday=test_1st_weekday,
start_time=datetime.time(10, 0),
end_time=datetime.time(12, 0),
desk=desk_foo,
)
TimePeriod.objects.create(
weekday=test_2nd_weekday,
start_time=datetime.time(10, 0),
end_time=datetime.time(12, 0),
desk=desk_foo,
)
TimePeriod.objects.create(
weekday=test_3rd_weekday,
start_time=datetime.time(10, 0),
end_time=datetime.time(12, 0),
desk=desk_foo,
)
agenda_bar = Agenda.objects.create(
label='Agenda Bar', kind='meetings', minimal_booking_delay=1, maximal_booking_delay=4
)
meeting_type_bar = MeetingType.objects.create(agenda=agenda_bar, label='Meeting Type', duration=30)
desk_bar = Desk.objects.create(agenda=agenda_bar, label='Desk 1')
TimePeriod.objects.create(
weekday=test_1st_weekday,
start_time=datetime.time(10, 0),
end_time=datetime.time(12, 0),
desk=desk_bar,
)
TimePeriod.objects.create(
weekday=test_2nd_weekday,
start_time=datetime.time(10, 0),
end_time=datetime.time(12, 0),
desk=desk_bar,
)
TimePeriod.objects.create(
weekday=test_3rd_weekday,
start_time=datetime.time(10, 0),
end_time=datetime.time(12, 0),
desk=desk_bar,
)
virtual_agenda = Agenda.objects.create(
label='Agenda Virtual', kind='virtual', minimal_booking_delay=1, maximal_booking_delay=4
)
VirtualMember.objects.create(virtual_agenda=virtual_agenda, real_agenda=agenda_foo)
VirtualMember.objects.create(virtual_agenda=virtual_agenda, real_agenda=agenda_bar)
# 4 slots each day * 3 days
foo_api_url = '/api/agenda/%s/meetings/%s/datetimes/' % (agenda_foo.slug, meeting_type_bar.slug)
resp = app.get(foo_api_url)
assert len(resp.json['data']) == 12
# same thing bar agenda
bar_api_url = '/api/agenda/%s/meetings/%s/datetimes/' % (agenda_foo.slug, meeting_type_bar.slug)
resp = app.get(bar_api_url)
assert len(resp.json['data']) == 12
# same thing on the virtual agenda
virtual_api_url = '/api/agenda/%s/meetings/%s/datetimes/' % (virtual_agenda.slug, meeting_type_bar.slug)
resp = app.get(virtual_api_url)
assert len(resp.json['data']) == 12
# exclude first day
start = (localtime(now()) + datetime.timedelta(days=1)).replace(hour=0, minute=0, second=0, microsecond=0)
end = (localtime(now()) + datetime.timedelta(days=1)).replace(
hour=23, minute=59, second=59, microsecond=0
)
TimePeriodException.objects.create(start_datetime=start, end_datetime=end, desk=desk_foo)
TimePeriodException.objects.create(start_datetime=start, end_datetime=end, desk=desk_bar)
# exclude second day
start = (localtime(now()) + datetime.timedelta(days=2)).replace(hour=0, minute=0, second=0, microsecond=0)
end = (localtime(now()) + datetime.timedelta(days=2)).replace(
hour=23, minute=59, second=59, microsecond=0
)
TimePeriodException.objects.create(start_datetime=start, end_datetime=end, desk=desk_foo)
TimePeriodException.objects.create(start_datetime=start, end_datetime=end, desk=desk_bar)
# 4 slots each day * 1 day
resp = app.get(foo_api_url)
assert len(resp.json['data']) == 4
# same thing bar agenda
resp = app.get(bar_api_url)
assert len(resp.json['data']) == 4
# same thing on the virtual agenda
resp = app.get(virtual_api_url)
assert len(resp.json['data']) == 4
def test_virtual_agendas_meetings_datetimes_delays_api(app, mock_now):
foo_agenda = Agenda.objects.create(label='Foo Meeting', kind='meetings', maximal_booking_delay=7)
MeetingType.objects.create(agenda=foo_agenda, label='Meeting Type', duration=30)
foo_desk_1 = Desk.objects.create(agenda=foo_agenda, label='Foo desk 1')
TimePeriod.objects.create(
weekday=0,
start_time=datetime.time(10, 0),
end_time=datetime.time(12, 0),
desk=foo_desk_1,
)
TimePeriod.objects.create(
weekday=1,
start_time=datetime.time(10, 0),
end_time=datetime.time(12, 0),
desk=foo_desk_1,
)
bar_agenda = Agenda.objects.create(label='Bar Meeting', kind='meetings', maximal_booking_delay=7)
MeetingType.objects.create(agenda=bar_agenda, label='Meeting Type', duration=30)
bar_desk_1 = Desk.objects.create(agenda=bar_agenda, label='Bar desk 1')
TimePeriod.objects.create(
weekday=2,
start_time=datetime.time(10, 0),
end_time=datetime.time(12, 0),
desk=bar_desk_1,
)
TimePeriod.objects.create(
weekday=3,
start_time=datetime.time(10, 0),
end_time=datetime.time(12, 0),
desk=bar_desk_1,
)
virt_agenda = Agenda.objects.create(label='Virtual Agenda', kind='virtual')
VirtualMember.objects.create(virtual_agenda=virt_agenda, real_agenda=foo_agenda)
VirtualMember.objects.create(virtual_agenda=virt_agenda, real_agenda=bar_agenda)
virt_meeting_type = virt_agenda.iter_meetingtypes()[0]
api_url = '/api/agenda/%s/meetings/%s/datetimes/' % (virt_agenda.slug, virt_meeting_type.slug)
resp = app.get(api_url)
# 8 slots for m each agenda
assert len(resp.json['data']) == 16
# restrict foo's minimal_booking_delay : only bar's slots are left
foo_agenda.minimal_booking_delay = 6
foo_agenda.save()
resp = app.get(api_url)
assert len(resp.json['data']) == 8
# restrict bar's maximal_booking_delay : only half of bar's slots are left
bar_agenda.maximal_booking_delay = 5
bar_agenda.save()
resp = app.get(api_url)
assert len(resp.json['data']) == 4
# put back very slots from foo
foo_agenda.minimal_booking_delay = 1
foo_agenda.maximal_booking_delay = 7
foo_agenda.save()
resp = app.get(api_url)
assert len(resp.json['data']) == 12
def test_virtual_agendas_meetings_datetimes_exluded_periods(app, mock_now):
foo_agenda = Agenda.objects.create(label='Foo Meeting', kind='meetings', maximal_booking_delay=7)
MeetingType.objects.create(agenda=foo_agenda, label='Meeting Type', duration=30)
foo_desk_1 = Desk.objects.create(agenda=foo_agenda, label='Foo desk 1')
TimePeriod.objects.create(
weekday=0,
start_time=datetime.time(10, 0),
end_time=datetime.time(12, 0),
desk=foo_desk_1,
)
TimePeriod.objects.create(
weekday=1,
start_time=datetime.time(10, 0),
end_time=datetime.time(12, 0),
desk=foo_desk_1,
)
virt_agenda = Agenda.objects.create(label='Virtual Agenda', kind='virtual')
VirtualMember.objects.create(virtual_agenda=virt_agenda, real_agenda=foo_agenda)
api_url = '/api/agenda/%s/meetings/meeting-type/datetimes/' % (virt_agenda.slug)
resp = app.get(api_url)
# 8 slots
data = resp.json['data']
assert len(data) == 8
assert data[0]['datetime'] == '2017-05-22 10:00:00'
assert data[1]['datetime'] == '2017-05-22 10:30:00'
assert data[2]['datetime'] == '2017-05-22 11:00:00'
# exclude one hour the first day
tp1 = TimePeriod.objects.create(
weekday=0, start_time=datetime.time(11, 0), end_time=datetime.time(12, 0), agenda=virt_agenda
)
resp = app.get(api_url)
data = resp.json['data']
assert len(data) == 6
assert data[0]['datetime'] == '2017-05-22 10:00:00'
assert data[1]['datetime'] == '2017-05-22 10:30:00'
# no more slots the 22 thanks to the exclusion period
assert data[2]['datetime'] == '2017-05-23 10:00:00'
# exclude the second day
tp2 = TimePeriod.objects.create(
weekday=1, start_time=datetime.time(9, 0), end_time=datetime.time(18, 0), agenda=virt_agenda
)
resp = app.get(api_url)
data = resp.json['data']
assert len(data) == 2
assert data[0]['datetime'] == '2017-05-22 10:00:00'
assert data[1]['datetime'] == '2017-05-22 10:30:00'
# go back to no restriction
tp1.delete()
tp2.delete()
resp = app.get(api_url)
data = resp.json['data']
assert len(data) == 8
# excluded period applies to every desk
foo_desk_2 = Desk.objects.create(agenda=foo_agenda, label='Foo desk 2')
TimePeriod.objects.create(
weekday=3,
start_time=datetime.time(10, 0),
end_time=datetime.time(12, 0),
desk=foo_desk_2,
)
TimePeriod.objects.create(
weekday=4,
start_time=datetime.time(10, 0),
end_time=datetime.time(12, 0),
desk=foo_desk_2,
)
resp = app.get(api_url)
data = resp.json['data']
assert len(data) == 16
# exclude one hour the first day
tp1 = TimePeriod.objects.create(
weekday=0, start_time=datetime.time(11, 0), end_time=datetime.time(12, 0), agenda=virt_agenda
)
resp = app.get(api_url)
data = resp.json['data']
assert len(data) == 14
# exclude one hour the last day
tp2 = TimePeriod.objects.create(
weekday=4, start_time=datetime.time(11, 0), end_time=datetime.time(12, 0), agenda=virt_agenda
)
resp = app.get(api_url)
data = resp.json['data']
assert len(data) == 12
# go back to no restriction
tp1.delete()
tp2.delete()
resp = app.get(api_url)
data = resp.json['data']
assert len(data) == 16
# add a second real agenda
bar_agenda = Agenda.objects.create(label='Bar Meeting', kind='meetings', maximal_booking_delay=7)
VirtualMember.objects.create(virtual_agenda=virt_agenda, real_agenda=bar_agenda)
MeetingType.objects.create(agenda=bar_agenda, label='Meeting Type', duration=30)
bar_desk_1 = Desk.objects.create(agenda=bar_agenda, label='Bar desk 1')
bar_desk_2 = Desk.objects.create(agenda=bar_agenda, label='Bar desk 2')
TimePeriod.objects.create(
weekday=0,
start_time=datetime.time(14, 0),
end_time=datetime.time(16, 0),
desk=bar_desk_1,
)
TimePeriod.objects.create(
weekday=1,
start_time=datetime.time(14, 0),
end_time=datetime.time(16, 0),
desk=bar_desk_1,
)
TimePeriod.objects.create(
weekday=2,
start_time=datetime.time(14, 0),
end_time=datetime.time(16, 0),
desk=bar_desk_2,
)
TimePeriod.objects.create(
weekday=3,
start_time=datetime.time(14, 0),
end_time=datetime.time(16, 0),
desk=bar_desk_2,
)
resp = app.get(api_url)
data = resp.json['data']
assert len(data) == 32
# exclude the first day, 11 to 15 : 4 slots
tp1 = TimePeriod.objects.create(
weekday=0, start_time=datetime.time(11, 0), end_time=datetime.time(15, 0), agenda=virt_agenda
)
resp = app.get(api_url)
data = resp.json['data']
assert len(data) == 28
def test_virtual_agendas_meetings_exception(app, user, virtual_meetings_agenda):
app.authorization = ('Basic', ('john.doe', 'password'))
real_agenda = virtual_meetings_agenda.real_agendas.first()
desk = real_agenda.desk_set.first()
virt_meeting_type = virtual_meetings_agenda.iter_meetingtypes()[0]
datetimes_url = '/api/agenda/%s/meetings/%s/datetimes/' % (
virtual_meetings_agenda.slug,
virt_meeting_type.slug,
)
resp = app.get(datetimes_url)
# test exception at the lowest limit
excp1 = TimePeriodException.objects.create(
desk=desk,
start_datetime=make_aware(datetime.datetime(2017, 5, 22, 10, 0)),
end_datetime=make_aware(datetime.datetime(2017, 5, 22, 12, 0)),
)
resp2 = app.get(datetimes_url)
assert len(resp.json['data']) == len(resp2.json['data']) + 4
# test exception at the highest limit
excp1.end_datetime = make_aware(datetime.datetime(2017, 5, 22, 11, 0))
excp1.save()
resp2 = app.get(datetimes_url)
assert len(resp.json['data']) == len(resp2.json['data']) + 2
# add an exception with an end datetime less than excp1 end datetime
# and make sure that excp1 end datetime preveil
excp1.end_datetime = make_aware(datetime.datetime(2017, 5, 23, 11, 0))
excp1.save()
TimePeriodException.objects.create(
desk=excp1.desk,
start_datetime=make_aware(datetime.datetime(2017, 5, 22, 15, 0)),
end_datetime=make_aware(datetime.datetime(2017, 5, 23, 9, 0)),
)
resp2 = app.get(datetimes_url)
assert len(resp.json['data']) == len(resp2.json['data']) + 6
# with a second desk
desk2 = Desk.objects.create(label='Desk 2', agenda=real_agenda)
time_period = desk.timeperiod_set.first()
TimePeriod.objects.create(
desk=desk2,
start_time=time_period.start_time,
end_time=time_period.end_time,
weekday=time_period.weekday,
)
resp3 = app.get(datetimes_url)
assert len(resp.json['data']) == len(resp3.json['data']) + 2 # +2 because excp1 changed
def test_virtual_agendas_meetings_datetimes_multiple_agendas(app, mock_now):
foo_agenda = Agenda.objects.create(
label='Foo Meeting', kind='meetings', minimal_booking_delay=1, maximal_booking_delay=5
)
foo_meeting_type = MeetingType.objects.create(agenda=foo_agenda, label='Meeting Type', duration=30)
foo_desk_1 = Desk.objects.create(agenda=foo_agenda, label='Foo desk 1')
test_1st_weekday = (localtime(now()).weekday() + 2) % 7
test_2nd_weekday = (localtime(now()).weekday() + 3) % 7
test_3rd_weekday = (localtime(now()).weekday() + 4) % 7
test_4th_weekday = (localtime(now()).weekday() + 5) % 7
def create_time_perdiods(desk, end=12):
TimePeriod.objects.create(
weekday=test_1st_weekday,
start_time=datetime.time(10, 0),
end_time=datetime.time(end, 0),
desk=desk,
)
TimePeriod.objects.create(
weekday=test_2nd_weekday,
start_time=datetime.time(10, 0),
end_time=datetime.time(end, 0),
desk=desk,
)
create_time_perdiods(foo_desk_1)
virt_agenda = Agenda.objects.create(
label='Virtual Agenda', kind='virtual', minimal_booking_delay=1, maximal_booking_delay=6
)
VirtualMember.objects.create(virtual_agenda=virt_agenda, real_agenda=foo_agenda)
virt_meeting_type = virt_agenda.iter_meetingtypes()[0]
# We are saturday and we can book for next monday and tuesday, 4 slots available each day
api_url = '/api/agenda/%s/meetings/%s/datetimes/' % (virt_agenda.slug, virt_meeting_type.slug)
resp = app.get(api_url)
assert len(resp.json['data']) == 8
assert resp.json['data'][0]['id'] == 'meeting-type:2017-05-22-1000'
virt_agenda.maximal_booking_delay = 10 # another monday comes in
virt_agenda.save()
resp = app.get(api_url)
assert len(resp.json['data']) == 12
# Back to next monday and tuesday restriction
virt_agenda.maximal_booking_delay = 6
virt_agenda.save()
# Add another agenda
bar_agenda = Agenda.objects.create(
label='Bar Meeting', kind='meetings', minimal_booking_delay=1, maximal_booking_delay=5
)
bar_meeting_type = MeetingType.objects.create(agenda=bar_agenda, label='Meeting Type', duration=30)
bar_desk_1 = Desk.objects.create(agenda=bar_agenda, label='Bar desk 1')
create_time_perdiods(bar_desk_1, end=13) # bar_agenda has two more slots each day
VirtualMember.objects.create(virtual_agenda=virt_agenda, real_agenda=bar_agenda)
with CaptureQueriesContext(connection) as ctx:
resp = app.get(api_url)
assert len(resp.json['data']) == 12
assert len(ctx.captured_queries) == 13
# simulate booking
dt = datetime.datetime.strptime(resp.json['data'][2]['id'].split(':')[1], '%Y-%m-%d-%H%M')
ev = Event.objects.create(
agenda=foo_agenda,
meeting_type=foo_meeting_type,
places=1,
full=False,
start_datetime=make_aware(dt),
desk=foo_desk_1,
)
booking1 = Booking.objects.create(event=ev)
resp = app.get(api_url)
assert len(resp.json['data']) == 12
# No disabled slot, because the booked slot is still available in second agenda
for slot in resp.json['data']:
assert slot['disabled'] is False
ev = Event.objects.create(
agenda=bar_agenda,
meeting_type=bar_meeting_type,
places=1,
full=False,
start_datetime=make_aware(dt),
desk=bar_desk_1,
)
booking2 = Booking.objects.create(event=ev)
resp = app.get(api_url)
assert len(resp.json['data']) == 12
# now one slot is disabled
for i, slot in enumerate(resp.json['data']):
if i == 2:
assert slot['disabled']
else:
assert slot['disabled'] is False
# Cancel booking, every slot available
booking1.cancel()
booking2.cancel()
resp = app.get(api_url)
assert len(resp.json['data']) == 12
for slot in resp.json['data']:
assert slot['disabled'] is False
# Add new desk on foo_agenda, open on wednesday
foo_desk_2 = Desk.objects.create(agenda=foo_agenda, label='Foo desk 2')
TimePeriod.objects.create(
weekday=test_3rd_weekday,
start_time=datetime.time(10, 0),
end_time=datetime.time(12, 0),
desk=foo_desk_2,
)
resp = app.get(api_url)
assert len(resp.json['data']) == 16
# Add new desk on bar_agenda, open on thursday
bar_desk_2 = Desk.objects.create(agenda=bar_agenda, label='Bar desk 2')
TimePeriod.objects.create(
weekday=test_4th_weekday,
start_time=datetime.time(10, 0),
end_time=datetime.time(12, 0),
desk=bar_desk_2,
)
resp = app.get(api_url)
assert len(resp.json['data']) == 20
@pytest.mark.freeze_time('2021-02-25')
def test_virtual_agendas_meetings_datetimes_exclude_slots(app):
tomorrow = now() + datetime.timedelta(days=1)
agenda = Agenda.objects.create(
label='Agenda', kind='meetings', minimal_booking_delay=0, maximal_booking_delay=10
)
desk = Desk.objects.create(agenda=agenda, slug='desk')
meeting_type = MeetingType.objects.create(agenda=agenda, slug='foo-bar')
TimePeriod.objects.create(
weekday=tomorrow.date().weekday(),
start_time=datetime.time(9, 0),
end_time=datetime.time(17, 00),
desk=desk,
)
agenda2 = agenda.duplicate()
virt_agenda = Agenda.objects.create(
label='Virtual Agenda', kind='virtual', minimal_booking_delay=1, maximal_booking_delay=10
)
VirtualMember.objects.create(virtual_agenda=virt_agenda, real_agenda=agenda)
VirtualMember.objects.create(virtual_agenda=virt_agenda, real_agenda=agenda2)
event = Event.objects.create(
agenda=agenda,
meeting_type=meeting_type,
places=1,
start_datetime=localtime(tomorrow).replace(hour=9, minute=0),
desk=desk,
)
Booking.objects.create(event=event, user_external_id='42')
event2 = Event.objects.create(
agenda=agenda,
meeting_type=meeting_type,
places=1,
start_datetime=localtime(tomorrow).replace(hour=10, minute=0),
desk=desk,
)
cancelled = Booking.objects.create(event=event2, user_external_id='35')
cancelled.cancel()
resp = app.get('/api/agenda/%s/meetings/%s/datetimes/' % (virt_agenda.slug, meeting_type.slug))
assert resp.json['data'][0]['id'] == 'foo-bar:2021-02-26-0900'
assert resp.json['data'][0]['disabled'] is False
assert resp.json['data'][2]['id'] == 'foo-bar:2021-02-26-1000'
assert resp.json['data'][2]['disabled'] is False
resp = app.get(
'/api/agenda/%s/meetings/%s/datetimes/' % (virt_agenda.slug, meeting_type.slug),
params={'exclude_user_external_id': '35'},
)
assert resp.json['data'][0]['id'] == 'foo-bar:2021-02-26-0900'
assert resp.json['data'][0]['disabled'] is False
assert resp.json['data'][2]['id'] == 'foo-bar:2021-02-26-1000'
assert resp.json['data'][2]['disabled'] is False
with CaptureQueriesContext(connection) as ctx:
resp = app.get(
'/api/agenda/%s/meetings/%s/datetimes/' % (virt_agenda.slug, meeting_type.slug),
params={'exclude_user_external_id': '42'},
)
assert len(ctx.captured_queries) == 14
assert resp.json['data'][0]['id'] == 'foo-bar:2021-02-26-0900'
assert resp.json['data'][0]['disabled'] is True
assert resp.json['data'][2]['id'] == 'foo-bar:2021-02-26-1000'
assert resp.json['data'][2]['disabled'] is False
virt_agenda.minimal_booking_delay = None
virt_agenda.maximal_booking_delay = None
virt_agenda.save()
resp = app.get(
'/api/agenda/%s/meetings/%s/datetimes/' % (virt_agenda.slug, meeting_type.slug),
params={'exclude_user_external_id': '42'},
)
assert resp.json['data'][0]['id'] == 'foo-bar:2021-02-26-0900'
assert resp.json['data'][0]['disabled'] is True
assert resp.json['data'][2]['id'] == 'foo-bar:2021-02-26-1000'
assert resp.json['data'][2]['disabled'] is False
def test_unavailabilitycalendar_on_virtual_datetimes(app, user, mock_now):
foo_agenda = Agenda.objects.create(label='Foo Meeting', kind='meetings', maximal_booking_delay=7)
MeetingType.objects.create(agenda=foo_agenda, label='Meeting Type', duration=30)
foo_desk_1 = Desk.objects.create(agenda=foo_agenda, label='Foo desk 1')
TimePeriod.objects.create(
weekday=0,
start_time=datetime.time(10, 0),
end_time=datetime.time(12, 0),
desk=foo_desk_1,
)
TimePeriod.objects.create(
weekday=1,
start_time=datetime.time(10, 0),
end_time=datetime.time(12, 0),
desk=foo_desk_1,
)
virt_agenda = Agenda.objects.create(label='Virtual Agenda', kind='virtual')
VirtualMember.objects.create(virtual_agenda=virt_agenda, real_agenda=foo_agenda)
api_url = '/api/agenda/%s/meetings/meeting-type/datetimes/' % (virt_agenda.slug)
resp = app.get(api_url)
# 8 slots
data = resp.json['data']
assert len(data) == 8
assert data[0]['datetime'] == '2017-05-22 10:00:00'
assert data[1]['datetime'] == '2017-05-22 10:30:00'
assert data[2]['datetime'] == '2017-05-22 11:00:00'
# exclude one hour the first day through an unvalailability calendar on the foo agenda
unavailability_calendar = UnavailabilityCalendar.objects.create(label='foo holydays')
TimePeriodException.objects.create(
unavailability_calendar=unavailability_calendar,
start_datetime=make_aware(datetime.datetime(2017, 5, 22, 11, 0)),
end_datetime=make_aware(datetime.datetime(2017, 5, 22, 12, 0)),
)
unavailability_calendar.desks.add(foo_desk_1)
resp = app.get(api_url)
data = resp.json['data']
assert len(data) == 6
assert data[0]['datetime'] == '2017-05-22 10:00:00'
assert data[1]['datetime'] == '2017-05-22 10:30:00'
# no more slots the 22 thanks to the unavailability calendar
assert data[2]['datetime'] == '2017-05-23 10:00:00'
# exclude the second day
TimePeriodException.objects.create(
unavailability_calendar=unavailability_calendar,
start_datetime=make_aware(datetime.datetime(2017, 5, 23, 9, 0)),
end_datetime=make_aware(datetime.datetime(2017, 5, 23, 18, 0)),
)
resp = app.get(api_url)
data = resp.json['data']
assert len(data) == 2
assert data[0]['datetime'] == '2017-05-22 10:00:00'
assert data[1]['datetime'] == '2017-05-22 10:30:00'
# add a second real agenda
bar_agenda = Agenda.objects.create(label='Bar Meeting', kind='meetings', maximal_booking_delay=7)
VirtualMember.objects.create(virtual_agenda=virt_agenda, real_agenda=bar_agenda)
MeetingType.objects.create(agenda=bar_agenda, label='Meeting Type', duration=30)
bar_desk_1 = Desk.objects.create(agenda=bar_agenda, label='Bar desk 1')
bar_desk_2 = Desk.objects.create(agenda=bar_agenda, label='Bar desk 2')
TimePeriod.objects.create(
weekday=0,
start_time=datetime.time(10, 0),
end_time=datetime.time(12, 0),
desk=bar_desk_1,
)
TimePeriod.objects.create(
weekday=1,
start_time=datetime.time(10, 0),
end_time=datetime.time(12, 0),
desk=bar_desk_1,
)
TimePeriod.objects.create(
weekday=0,
start_time=datetime.time(10, 0),
end_time=datetime.time(12, 0),
desk=bar_desk_2,
)
TimePeriod.objects.create(
weekday=1,
start_time=datetime.time(10, 0),
end_time=datetime.time(12, 0),
desk=bar_desk_2,
)
# bar_agenda has the same time periods than foo_agenda, but no unavailability calendar
# so we are back at the start : 8 slots
resp = app.get(api_url)
data = resp.json['data']
assert len(data) == 8
# exclude one hour the second day through another unvalailability calendar on the bar agenda
unavailability_calendar = UnavailabilityCalendar.objects.create(label='bar holydays')
TimePeriodException.objects.create(
unavailability_calendar=unavailability_calendar,
start_datetime=make_aware(datetime.datetime(2017, 5, 23, 11, 0)),
end_datetime=make_aware(datetime.datetime(2017, 5, 23, 12, 0)),
)
unavailability_calendar.desks.add(bar_desk_1, bar_desk_2)
# 2 slots are gone
resp = app.get(api_url)
data = resp.json['data']
assert len(data) == 6
assert data[0]['datetime'] == '2017-05-22 10:00:00'
assert data[-1]['datetime'] == '2017-05-23 10:30:00'
def test_meetings_and_virtual_datetimes_date_filter(app):
agenda_foo = Agenda.objects.create(
label='Agenda Foo', kind='meetings', minimal_booking_delay=1, maximal_booking_delay=7
)
meeting_type = MeetingType.objects.create(agenda=agenda_foo, label='Meeting Type', duration=30)
desk_foo = Desk.objects.create(agenda=agenda_foo, label='Desk 1')
weekday1 = ((localtime(now())).weekday() + 1) % 7
weekday2 = ((localtime(now())).weekday() + 2) % 7
weekday3 = ((localtime(now())).weekday() + 3) % 7
weekday4 = ((localtime(now())).weekday() + 4) % 7
weekday5 = ((localtime(now())).weekday() + 5) % 7
weekday6 = ((localtime(now())).weekday() + 6) % 7
for weekday in (weekday1, weekday2, weekday3, weekday4, weekday5, weekday6):
TimePeriod.objects.create(
weekday=weekday,
start_time=datetime.time(10, 0),
end_time=datetime.time(12, 0),
desk=desk_foo,
)
virtual_agenda = Agenda.objects.create(
label='Agenda Virtual', kind='virtual', minimal_booking_delay=1, maximal_booking_delay=7
)
VirtualMember.objects.create(virtual_agenda=virtual_agenda, real_agenda=agenda_foo)
# 4 slots each day * 6 days
foo_api_url = '/api/agenda/%s/meetings/%s/datetimes/' % (agenda_foo.slug, meeting_type.slug)
resp = app.get(foo_api_url)
assert len(resp.json['data']) == 24
virtual_api_url = '/api/agenda/%s/meetings/%s/datetimes/' % (virtual_agenda.slug, meeting_type.slug)
resp = app.get(virtual_api_url)
assert len(resp.json['data']) == 24
for value in ['foo', '2017-05-42']:
params = {'date_start': value}
resp = app.get(foo_api_url, params=params, status=400)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'invalid payload'
assert resp.json['errors']['date_start'] == [
'Datetime has wrong format. Use one of these formats instead: YYYY-MM-DD, YYYY-MM-DD hh:mm, YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z].'
]
for value in ['foo', '2017-05-42']:
params = {'date_end': value}
resp = app.get(foo_api_url, params=params, status=400)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'invalid payload'
assert resp.json['errors']['date_end'] == [
'Datetime has wrong format. Use one of these formats instead: YYYY-MM-DD, YYYY-MM-DD hh:mm, YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z].'
]
# exclude weekday1 through date_start, 4 slots each day * 5 days
params = {'date_start': localtime(now() + datetime.timedelta(days=2)).date().isoformat()}
resp = app.get(foo_api_url, params=params)
assert len(resp.json['data']) == 20
resp = app.get(virtual_api_url, params=params)
assert len(resp.json['data']) == 20
params = {
'date_start': localtime(now() + datetime.timedelta(days=2))
.replace(hour=12, minute=0, second=0, microsecond=0)
.isoformat()
}
resp = app.get(foo_api_url, params=params)
assert len(resp.json['data']) == 16
resp = app.get(virtual_api_url, params=params)
assert len(resp.json['data']) == 16
params = {
'date_start': localtime(now() + datetime.timedelta(days=2))
.replace(hour=11, minute=0, second=0, microsecond=0)
.isoformat()
}
resp = app.get(foo_api_url, params=params)
assert len(resp.json['data']) == 18
resp = app.get(virtual_api_url, params=params)
assert len(resp.json['data']) == 18
# minimal_booking_delay (which exclude weekday1 and wekkday2 ) takes precedence
# 4 slots each day * 4 days
agenda_foo.minimal_booking_delay = 3
agenda_foo.save()
resp = app.get(foo_api_url, params=params)
assert len(resp.json['data']) == 16
# also on virtual agenda
virtual_agenda.minimal_booking_delay = 3
virtual_agenda.save()
resp = app.get(virtual_api_url, params=params)
assert len(resp.json['data']) == 16
# reset
agenda_foo.minimal_booking_delay = 1
virtual_agenda.minimal_booking_delay = 1
agenda_foo.save()
virtual_agenda.save()
# exclude weekday6 through date_end, 4 slots each day * 5 days
params = {'date_end': localtime(now() + datetime.timedelta(days=6)).date().isoformat()}
resp = app.get(foo_api_url, params=params)
assert len(resp.json['data']) == 20
resp = app.get(virtual_api_url, params=params)
assert len(resp.json['data']) == 20
params = {
'date_end': localtime(now() + datetime.timedelta(days=6))
.replace(hour=11, minute=0, second=0, microsecond=0)
.isoformat()
}
resp = app.get(foo_api_url, params=params)
assert len(resp.json['data']) == 22
resp = app.get(virtual_api_url, params=params)
assert len(resp.json['data']) == 22
# maximal_booking_delay (which exclude weekday5 and weekday6 ) takes precedence
# 4 slots each day * 4 days
agenda_foo.maximal_booking_delay = 5
agenda_foo.save()
resp = app.get(foo_api_url, params=params)
assert len(resp.json['data']) == 16
# also on virtual agenda
virtual_agenda.maximal_booking_delay = 5
virtual_agenda.save()
resp = app.get(virtual_api_url, params=params)
assert len(resp.json['data']) == 16
# now check with exceptions in DB
TimePeriodException.objects.create(
desk=desk_foo,
start_datetime=make_aware(datetime.datetime(2017, 5, 22, 10, 0)),
end_datetime=make_aware(datetime.datetime(2017, 5, 22, 12, 0)),
)
params = {
'date_start': localtime(now() + datetime.timedelta(days=2))
.replace(hour=12, minute=0, second=0, microsecond=0)
.isoformat()
}
resp = app.get(foo_api_url, params=params)
assert len(resp.json['data']) == 8
resp = app.get(virtual_api_url, params=params)
assert len(resp.json['data']) == 8
params = {
'date_end': localtime(now() + datetime.timedelta(days=2))
.replace(hour=11, minute=0, second=0, microsecond=0)
.isoformat()
}
resp = app.get(foo_api_url, params=params)
assert len(resp.json['data']) == 6
resp = app.get(virtual_api_url, params=params)
assert len(resp.json['data']) == 6
def test_datetimes_api_virtual_meetings_agenda_meta(app, freezer):
# 2017-05-20 -> saturday
freezer.move_to(make_aware(datetime.datetime(year=2017, month=5, day=20, hour=1, minute=12)))
meetings_agenda1 = Agenda.objects.create(label='Foo Meeting', kind='meetings', maximal_booking_delay=3)
meetings_agenda2 = Agenda.objects.create(label='Bar Meeting', kind='meetings', maximal_booking_delay=3)
virtual_agenda = Agenda.objects.create(label='Agenda Virtual', kind='virtual', maximal_booking_delay=3)
VirtualMember.objects.create(virtual_agenda=virtual_agenda, real_agenda=meetings_agenda1)
VirtualMember.objects.create(virtual_agenda=virtual_agenda, real_agenda=meetings_agenda2)
desk1 = Desk.objects.create(agenda=meetings_agenda1, label='Desk 1')
desk2 = Desk.objects.create(agenda=meetings_agenda2, label='Desk 2')
test_1st_weekday = (localtime(now()).weekday() + 2) % 7
for agenda, desk in zip((meetings_agenda1, meetings_agenda2), (desk1, desk2)):
meeting_type = MeetingType.objects.create(agenda=agenda, label='Blah', duration=30)
TimePeriod(
weekday=test_1st_weekday,
start_time=datetime.time(10, 0),
end_time=datetime.time(12, 0),
desk=desk,
).save()
virt_meeting_type = virtual_agenda.iter_meetingtypes()[0]
api_url = '/api/agenda/%s/meetings/%s/datetimes/' % (virtual_agenda.slug, virt_meeting_type.slug)
resp = app.get(api_url)
assert len(resp.json['data']) == 4
assert resp.json['data'][2]['disabled'] is False
assert resp.json['meta'] == {
'no_bookable_datetimes': False,
'bookable_datetimes_number_total': 4,
'bookable_datetimes_number_available': 4,
'first_bookable_slot': resp.json['data'][0],
}
def simulate_booking(slot, agenda, desk):
dt = datetime.datetime.strptime(slot['id'].split(':')[1], '%Y-%m-%d-%H%M')
ev = Event(
agenda=agenda,
meeting_type=meeting_type,
places=1,
full=False,
start_datetime=make_aware(dt),
desk=desk,
)
ev.save()
booking = Booking(event=ev, user_external_id='42')
booking.save()
simulate_booking(resp.json['data'][0], meetings_agenda1, desk1)
resp = app.get(api_url)
assert len(resp.json['data']) == 4
assert resp.json['data'][0]['disabled'] is False
assert resp.json['meta'] == {
'no_bookable_datetimes': False,
'bookable_datetimes_number_total': 4,
'bookable_datetimes_number_available': 4,
'first_bookable_slot': resp.json['data'][0],
}
resp = app.get(api_url, params={'exclude_user_external_id': '42'})
assert len(resp.json['data']) == 4
assert resp.json['data'][0]['disabled'] is True
assert resp.json['meta'] == {
'no_bookable_datetimes': False,
'bookable_datetimes_number_total': 4,
'bookable_datetimes_number_available': 3,
'first_bookable_slot': resp.json['data'][1],
}
simulate_booking(resp.json['data'][0], meetings_agenda2, desk2)
resp = app.get(api_url)
assert len(resp.json['data']) == 4
assert resp.json['data'][0]['disabled'] is True
assert resp.json['meta'] == {
'no_bookable_datetimes': False,
'bookable_datetimes_number_total': 4,
'bookable_datetimes_number_available': 3,
'first_bookable_slot': resp.json['data'][1],
}
for idx in range(1, 4):
simulate_booking(resp.json['data'][idx], meetings_agenda1, desk1)
simulate_booking(resp.json['data'][idx], meetings_agenda2, desk2)
resp = app.get(api_url)
assert len(resp.json['data']) == 4
assert resp.json['meta'] == {
'no_bookable_datetimes': True,
'bookable_datetimes_number_total': 4,
'bookable_datetimes_number_available': 0,
'first_bookable_slot': None,
}
def test_virtual_agendas_time_change(app, freezer):
agenda = Agenda.objects.create(
label='Foo bar Meeting', kind='meetings', minimal_booking_delay=10, maximal_booking_delay=20
)
meeting_type = MeetingType.objects.create(agenda=agenda, label='Blah', duration=15)
desk, _ = Desk.objects.get_or_create(agenda=agenda, label='Desk 1')
TimePeriodException.objects.create(
desk=desk,
start_datetime=make_aware(datetime.datetime(2022, 4, 4, 8, 0)),
end_datetime=make_aware(datetime.datetime(2022, 4, 4, 12, 0)),
)
TimePeriod.objects.create(
weekday=0,
start_time=datetime.time(8, 30),
end_time=datetime.time(12, 0),
desk=desk,
)
dt = datetime.datetime.strptime('2022-03-28-08:30', '%Y-%m-%d-%H:%M')
ev = Event.objects.create(
agenda=agenda,
meeting_type=meeting_type,
places=1,
start_datetime=make_aware(dt),
desk=desk,
)
Booking.objects.create(event=ev)
freezer.move_to(make_aware(datetime.datetime(2022, 3, 8, 7, 0)))
api_url = '/api/agenda/%s/meetings/%s/datetimes/' % (agenda.slug, meeting_type.slug)
resp = app.get(api_url)
for slot in resp.json['data']:
if slot['datetime'] == '2022-03-28 08:30:00':
assert False, 'slot should not appear due to maximal_booking_delay'
# now got through virtual agenda
virtual_agenda = Agenda.objects.create(label='Foo bar Meeting', kind='virtual')
virtual_agenda.real_agendas.add(agenda)
assert virtual_agenda.minimal_booking_delay is None
assert virtual_agenda.maximal_booking_delay is None
api_url = '/api/agenda/%s/meetings/%s/datetimes/' % (virtual_agenda.slug, meeting_type.slug)
resp = app.get(api_url)
for slot in resp.json['data']:
if slot['datetime'] == '2022-03-28 08:30:00':
assert (
False
), 'slot should not appear due to maximal_booking_delay of the real agenda (and no maximal_booking_delay) is defined on the real agenda'
@pytest.mark.freeze_time('2022-01-20 14:00') # Thursday
def test_datetimes_api_meetings_virtual_agenda_weekday_indexes(app):
agenda = Agenda.objects.create(
label='Foo bar', kind='meetings', minimal_booking_delay=0, maximal_booking_delay=60
)
desk = Desk.objects.create(agenda=agenda, label='desk')
meeting_type = MeetingType.objects.create(agenda=agenda, label='Plop', duration=30)
virtual_agenda = Agenda.objects.create(label='Foo bar Meeting', kind='virtual')
virtual_agenda.real_agendas.add(agenda)
TimePeriod.objects.create(
weekday=0,
weekday_indexes=[1, 2],
start_time=datetime.time(11, 0),
end_time=datetime.time(12, 30),
desk=desk,
)
api_url = '/api/agenda/%s/meetings/%s/datetimes/' % (virtual_agenda.slug, meeting_type.slug)
resp = app.get(api_url)
assert len(resp.json['data']) == 12
assert [x['datetime'] for x in resp.json['data']] == [
'2022-02-07 11:00:00',
'2022-02-07 11:30:00',
'2022-02-07 12:00:00',
'2022-02-14 11:00:00',
'2022-02-14 11:30:00',
'2022-02-14 12:00:00',
'2022-03-07 11:00:00',
'2022-03-07 11:30:00',
'2022-03-07 12:00:00',
'2022-03-14 11:00:00',
'2022-03-14 11:30:00',
'2022-03-14 12:00:00',
]
# add exclusion period on virtual agenda
exclusion_period = TimePeriod.objects.create(
weekday=0, start_time=datetime.time(11, 30), end_time=datetime.time(12, 30), agenda=virtual_agenda
)
resp = app.get(api_url)
assert len(resp.json['data']) == 4
assert [x['datetime'] for x in resp.json['data']] == [
'2022-02-07 11:00:00',
'2022-02-14 11:00:00',
'2022-03-07 11:00:00',
'2022-03-14 11:00:00',
]
exclusion_period.start_time = datetime.time(10, 30)
exclusion_period.end_time = datetime.time(11, 30)
exclusion_period.save()
resp = app.get(api_url)
assert len(resp.json['data']) == 8
assert [x['datetime'] for x in resp.json['data']] == [
'2022-02-07 11:30:00',
'2022-02-07 12:00:00',
'2022-02-14 11:30:00',
'2022-02-14 12:00:00',
'2022-03-07 11:30:00',
'2022-03-07 12:00:00',
'2022-03-14 11:30:00',
'2022-03-14 12:00:00',
]
# add second exclusion period on virtual agenda
TimePeriod.objects.create(
weekday=0, start_time=datetime.time(12, 00), end_time=datetime.time(12, 30), agenda=virtual_agenda
)
resp = app.get(api_url)
assert [x['datetime'] for x in resp.json['data']] == [
'2022-02-07 11:30:00',
'2022-02-14 11:30:00',
'2022-03-07 11:30:00',
'2022-03-14 11:30:00',
]
@pytest.mark.freeze_time('2022-10-24 10:00')
def test_datetimes_api_meetings_virtual_agenda_date_time_period(app):
agenda = Agenda.objects.create(
label='Foo bar', kind='meetings', minimal_booking_delay=0, maximal_booking_delay=30
)
desk = Desk.objects.create(agenda=agenda, label='desk')
meeting_type = MeetingType.objects.create(agenda=agenda, label='Plop', duration=30)
virtual_agenda = Agenda.objects.create(label='Foo bar Meeting', kind='virtual')
virtual_agenda.real_agendas.add(agenda)
TimePeriod.objects.create(
date=datetime.date(2022, 10, 24),
start_time=datetime.time(12, 0),
end_time=datetime.time(14, 0),
desk=desk,
)
api_url = '/api/agenda/%s/meetings/%s/datetimes/' % (virtual_agenda.slug, meeting_type.slug)
resp = app.get(api_url)
assert [x['datetime'] for x in resp.json['data']] == [
'2022-10-24 12:00:00',
'2022-10-24 12:30:00',
'2022-10-24 13:00:00',
'2022-10-24 13:30:00',
]
# add exclusion period on virtual agenda
TimePeriod.objects.create(
weekday=0, start_time=datetime.time(12, 00), end_time=datetime.time(13, 00), agenda=virtual_agenda
)
resp = app.get(api_url)
assert [x['datetime'] for x in resp.json['data']] == [
'2022-10-24 13:00:00',
'2022-10-24 13:30:00',
]
# add second exclusion period on virtual agenda
TimePeriod.objects.create(
weekday=0, start_time=datetime.time(13, 30), end_time=datetime.time(14, 00), agenda=virtual_agenda
)
resp = app.get(api_url)
assert [x['datetime'] for x in resp.json['data']] == [
'2022-10-24 13:00:00',
]
def test_show_available_agendas(app, user):
agenda = build_virtual_agenda(
agendas={
'Agenda 1': {
'desks': {
'Desk 1': 'monday-sunday 08:00-12:00 14:00-17:00',
'Desk 2': 'monday-sunday 08:00-12:00 14:00-17:00',
},
},
'Agenda 2': {
'desks': {
'Desk 1': 'monday-sunday 08:00-12:00 14:00-17:00',
'Desk 2': 'monday-sunday 08:00-12:00 14:00-17:00',
},
},
},
meeting_types=[30],
)
api_url = '/api/agenda/%s/meetings/mt-30/datetimes/' % agenda.slug
resp = app.get(api_url)
first_slot = resp.json['data'][0]
assert first_slot['disabled'] is False
assert len(first_slot['agendas']) == 2
assert first_slot['agendas'][0]['text'] == 'Agenda 1'
assert first_slot['agendas'][1]['text'] == 'Agenda 2'
## Make a booking directly on agenda 1, and check that nothing changed
app.authorization = ('Basic', ('john.doe', 'password'))
app.post(first_slot['agendas'][0]['api']['fillslot_url'])
resp = app.get(api_url)
first_slot = resp.json['data'][0]
assert first_slot['disabled'] is False
assert len(first_slot['agendas']) == 2
assert first_slot['agendas'][0]['text'] == 'Agenda 1'
assert first_slot['agendas'][1]['text'] == 'Agenda 2'
## Make a second booking directly on agenda 1, agenda 2 should be the only one left available
app.post(first_slot['agendas'][0]['api']['fillslot_url'])
resp = app.get(api_url)
first_slot = resp.json['data'][0]
assert first_slot['disabled'] is False
assert len(first_slot['agendas']) == 1
assert first_slot['agendas'][0]['text'] == 'Agenda 2'
## Make a booking directly on agenda 2, and check that nothing changed
app.post(first_slot['agendas'][0]['api']['fillslot_url'])
resp = app.get(api_url)
first_slot = resp.json['data'][0]
assert first_slot['disabled'] is False
assert len(first_slot['agendas']) == 1
assert first_slot['agendas'][0]['text'] == 'Agenda 2'
## Make a booking directly on agenda 2, the slots is full and no agenda available
app.post(first_slot['agendas'][0]['api']['fillslot_url'])
resp = app.get(api_url)
first_slot = resp.json['data'][0]
assert first_slot['disabled'] is True
assert len(first_slot['agendas']) == 0