virtual agendas: use real agendas booking delays (#40121)

If booking delays are defined on the virtual agenda, they will take
precedence.
This commit is contained in:
Emmanuel Cazenave 2020-02-25 10:30:47 +01:00 committed by Frédéric Péters
parent 2111a1872b
commit 55f6d0e47d
2 changed files with 85 additions and 10 deletions

View File

@ -49,13 +49,24 @@ def get_exceptions_by_desk(agenda):
return exceptions_by_desk
def get_all_slots(agenda, meeting_type):
def get_min_datetime(agenda):
if agenda.minimal_booking_delay is None:
return None
min_datetime = now() + datetime.timedelta(days=agenda.minimal_booking_delay)
max_datetime = now() + datetime.timedelta(days=agenda.maximal_booking_delay)
min_datetime = min_datetime.replace(hour=0, minute=0, second=0, microsecond=0)
max_datetime = max_datetime.replace(hour=0, minute=0, second=0, microsecond=0)
max_datetime = max_datetime + datetime.timedelta(days=1)
return min_datetime.replace(hour=0, minute=0, second=0, microsecond=0)
def get_max_datetime(agenda):
if agenda.maximal_booking_delay is None:
return None
max_datetime = now() + datetime.timedelta(days=agenda.maximal_booking_delay)
max_datetime = max_datetime.replace(hour=0, minute=0, second=0, microsecond=0)
return max_datetime + datetime.timedelta(days=1)
def get_all_slots(agenda, meeting_type):
min_datetime = get_min_datetime(agenda)
max_datetime = get_max_datetime(agenda)
time_period_filters = {
'min_datetime': min_datetime,
'max_datetime': max_datetime,
@ -71,6 +82,12 @@ def get_all_slots(agenda, meeting_type):
open_slots[agenda] = defaultdict(lambda: Intervals())
for agenda in agendas:
used_time_period_filters = time_period_filters.copy()
if used_time_period_filters['min_datetime'] is None:
used_time_period_filters['min_datetime'] = get_min_datetime(agenda)
if used_time_period_filters['max_datetime'] is None:
used_time_period_filters['max_datetime'] = get_max_datetime(agenda)
for time_period in TimePeriod.objects.filter(desk__agenda=agenda):
duration = (
datetime.datetime.combine(base_date, time_period.end_time)
@ -79,7 +96,7 @@ def get_all_slots(agenda, meeting_type):
if duration < meeting_type.duration:
# skip time period that can't even hold a single meeting
continue
for slot in time_period.get_time_slots(**time_period_filters):
for slot in time_period.get_time_slots(**used_time_period_filters):
slot.full = False
open_slots[agenda][time_period.desk_id].add(slot.start_datetime, slot.end_datetime, slot)
@ -93,11 +110,18 @@ def get_all_slots(agenda, meeting_type):
open_slots[agenda][desk].remove_overlap(localtime(begin), localtime(end))
for agenda in agendas:
used_min_datetime = min_datetime
if used_min_datetime is None:
used_min_datetime = get_min_datetime(agenda)
used_max_datetime = max_datetime
if used_max_datetime is None:
used_max_datetime = get_max_datetime(agenda)
for event in (
agenda.event_set.filter(
agenda=agenda,
start_datetime__gte=min_datetime,
start_datetime__lte=max_datetime + datetime.timedelta(meeting_type.duration),
start_datetime__gte=used_min_datetime,
start_datetime__lte=used_max_datetime + datetime.timedelta(meeting_type.duration),
)
.select_related('meeting_type')
.exclude(booking__cancellation_datetime__isnull=False)

View File

@ -2465,8 +2465,8 @@ def test_virtual_agenda_detail(app, virtual_meetings_agenda):
'text': 'Virtual Agenda',
'id': 'virtual-agenda',
'slug': 'virtual-agenda',
'minimal_booking_delay': 1,
'maximal_booking_delay': 56,
'minimal_booking_delay': None,
'maximal_booking_delay': None,
'kind': 'virtual',
'api': {
'meetings_url': 'http://testserver/api/agenda/%s/meetings/' % virtual_meetings_agenda.slug,
@ -2625,6 +2625,57 @@ def test_virtual_agendas_meetings_datetimes_api(app, virtual_meetings_agenda):
assert len(resp.json['data']) == 3
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 = 4
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_exception(app, user, virtual_meetings_agenda):
app.authorization = ('Basic', ('john.doe', 'password'))
real_agenda = virtual_meetings_agenda.real_agendas.first()