1252 lines
47 KiB
Python
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
|