api: replace intervaltree by chrono.interval (#20732)
This commit is contained in:
parent
38b79a368c
commit
6d4afedc47
|
@ -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'})
|
||||
|
|
Loading…
Reference in New Issue