api: replace intervaltree by chrono.interval (#20732)

This commit is contained in:
Benjamin Dauvergne 2017-12-16 05:37:00 +01:00 committed by Frédéric Péters
parent 38b79a368c
commit 6d4afedc47
1 changed files with 28 additions and 38 deletions

View File

@ -19,8 +19,6 @@ from copy import deepcopy
import datetime
import operator
from intervaltree import IntervalTree
from django.core.urlresolvers import reverse
from django.http import Http404
from django.shortcuts import get_object_or_404
@ -34,6 +32,7 @@ from rest_framework.views import APIView
from ..agendas.models import (Agenda, Event, Booking, MeetingType,
TimePeriod, Desk)
from ..interval import Intervals
def get_exceptions_by_desk(agenda):
@ -56,10 +55,11 @@ def get_all_slots(agenda, meeting_type):
'meeting_type': meeting_type
}
open_slots_by_desk = defaultdict(lambda: IntervalTree())
open_slots_by_desk = defaultdict(lambda: Intervals())
for time_period in TimePeriod.objects.filter(desk__agenda=agenda):
for slot in time_period.get_time_slots(**time_period_filters):
open_slots_by_desk[time_period.desk_id].addi(slot.start_datetime, slot.end_datetime, slot)
slot.full = False
open_slots_by_desk[time_period.desk_id].add(slot.start_datetime, slot.end_datetime, slot)
# remove excluded slot
excluded_slot_by_desk = get_exceptions_by_desk(agenda)
@ -67,23 +67,20 @@ def get_all_slots(agenda, meeting_type):
for interval in excluded_interval:
begin, end = interval
open_slots_by_desk[desk].remove_overlap(localtime(begin), localtime(end))
# keep a copy of all time slot before removing busy time slots
all_time_slots = reduce(operator.__or__, deepcopy(open_slots_by_desk).values())
for event in agenda.event_set.filter(
agenda=agenda, start_datetime__gte=min_datetime,
start_datetime__lte=max_datetime + datetime.timedelta(meeting_type.duration)).select_related(
'meeting_type').extra(
select={
'booking_count': """SELECT COUNT(*) FROM agendas_booking
WHERE agendas_booking.event_id = agendas_event.id
AND agendas_booking.cancellation_datetime IS NOT NULL"""}):
if event.booking_count:
continue
open_slots_by_desk[event.desk_id].remove_overlap(event.start_datetime, event.end_datetime)
'meeting_type').exclude(
booking__cancellation_datetime__isnull=False):
for slot in open_slots_by_desk[event.desk_id].search_data(event.start_datetime, event.end_datetime):
slot.full = True
open_slots = reduce(operator.__or__, open_slots_by_desk.values())
return open_slots, all_time_slots
slots = []
for desk in open_slots_by_desk:
slots.extend(open_slots_by_desk[desk].iter_data())
slots.sort(key=lambda slot: slot.start_datetime)
return slots
def get_agenda_detail(request, agenda):
@ -207,24 +204,16 @@ class MeetingDatetimes(GenericAPIView):
now_datetime = now()
open_slots, all_time_slots = get_all_slots(agenda, meeting_type)
open_entries = {}
closed_entries = {}
for interval in all_time_slots.all_intervals:
time_slot = interval.data
if time_slot.start_datetime < now_datetime:
slots = get_all_slots(agenda, meeting_type)
entries = {}
for slot in slots:
if slot.start_datetime < now_datetime:
continue
key = '%s-%s' % (time_slot.start_datetime, time_slot.end_datetime)
if open_slots.search(time_slot.start_datetime, time_slot.end_datetime, strict=True):
time_slot.full = False
open_entries[key] = time_slot
else:
time_slot.full = True
closed_entries[key] = time_slot
closed_entries.update(open_entries)
entries = sorted(closed_entries.values(), key=lambda x: x.start_datetime)
key = (slot.start_datetime, slot.end_datetime)
if key in entries and slot.full:
continue
entries[key] = slot
slots = sorted(entries.values(), key=lambda x: x.start_datetime)
fake_event_pk = '__event_id__'
fillslot_url = request.build_absolute_uri(
@ -241,7 +230,7 @@ class MeetingDatetimes(GenericAPIView):
'api': {
'fillslot_url': fillslot_url.replace(fake_event_pk, str(x.id)),
},
} for x in entries]}
} for x in slots]}
return Response(response)
meeting_datetimes = MeetingDatetimes.as_view()
@ -334,12 +323,13 @@ class Fillslot(GenericAPIView):
start_datetime=start_datetime,
full=False, places=1)
open_slots, _ = get_all_slots(agenda, MeetingType.objects.get(id=meeting_type_id))
slots = get_all_slots(agenda, MeetingType.objects.get(id=meeting_type_id))
# sort available matching slots by desk id
slot = sorted(open_slots[event.start_datetime:event.end_datetime], key=lambda x: x.data.desk.id)
if slot:
slots = [slot for slot in slots if not slot.full and slot.start_datetime == event.start_datetime]
slots.sort(key=lambda x: x.desk.id)
if slots:
# book first available desk
available_desk = slot[0].data.desk
available_desk = slots[0].desk
if not available_desk:
return Response({'err': 1, 'reason': 'no more desk available'})