Projet

Général

Profil

0002-api-replace-intervaltree-by-chrono.interval-20732.patch

Frédéric Péters, 18 décembre 2017 22:03

Télécharger (6,1 ko)

Voir les différences:

Subject: [PATCH 2/3] api: replace intervaltree by chrono.interval (#20732)

 chrono/api/views.py | 66 +++++++++++++++++++++++------------------------------
 1 file changed, 28 insertions(+), 38 deletions(-)
chrono/api/views.py
19 19
import datetime
20 20
import operator
21 21

  
22
from intervaltree import IntervalTree
23

  
24 22
from django.core.urlresolvers import reverse
25 23
from django.http import Http404
26 24
from django.shortcuts import get_object_or_404
......
34 32

  
35 33
from ..agendas.models import (Agenda, Event, Booking, MeetingType,
36 34
                              TimePeriod, Desk)
35
from ..interval import Intervals
37 36

  
38 37

  
39 38
def get_exceptions_by_desk(agenda):
......
56 55
        'meeting_type': meeting_type
57 56
    }
58 57

  
59
    open_slots_by_desk = defaultdict(lambda: IntervalTree())
58
    open_slots_by_desk = defaultdict(lambda: Intervals())
60 59
    for time_period in TimePeriod.objects.filter(desk__agenda=agenda):
61 60
        for slot in time_period.get_time_slots(**time_period_filters):
62
            open_slots_by_desk[time_period.desk_id].addi(slot.start_datetime, slot.end_datetime, slot)
61
            slot.full = False
62
            open_slots_by_desk[time_period.desk_id].add(slot.start_datetime, slot.end_datetime, slot)
63 63

  
64 64
    # remove excluded slot
65 65
    excluded_slot_by_desk = get_exceptions_by_desk(agenda)
......
67 67
        for interval in excluded_interval:
68 68
            begin, end = interval
69 69
            open_slots_by_desk[desk].remove_overlap(localtime(begin), localtime(end))
70
    # keep a copy of all time slot before removing busy time slots
71
    all_time_slots = reduce(operator.__or__, deepcopy(open_slots_by_desk).values())
72 70

  
73 71
    for event in agenda.event_set.filter(
74 72
            agenda=agenda, start_datetime__gte=min_datetime,
75 73
            start_datetime__lte=max_datetime + datetime.timedelta(meeting_type.duration)).select_related(
76
                'meeting_type').extra(
77
                    select={
78
                        'booking_count': """SELECT COUNT(*) FROM agendas_booking
79
                                            WHERE agendas_booking.event_id = agendas_event.id
80
                                            AND agendas_booking.cancellation_datetime IS NOT NULL"""}):
81
        if event.booking_count:
82
            continue
83
        open_slots_by_desk[event.desk_id].remove_overlap(event.start_datetime, event.end_datetime)
74
                'meeting_type').exclude(
75
                        booking__cancellation_datetime__isnull=False):
76
        for slot in open_slots_by_desk[event.desk_id].search_data(event.start_datetime, event.end_datetime):
77
            slot.full = True
84 78

  
85
    open_slots = reduce(operator.__or__, open_slots_by_desk.values())
86
    return open_slots, all_time_slots
79
    slots = []
80
    for desk in open_slots_by_desk:
81
        slots.extend(open_slots_by_desk[desk].iter_data())
82
    slots.sort(key=lambda slot: slot.start_datetime)
83
    return slots
87 84

  
88 85

  
89 86
def get_agenda_detail(request, agenda):
......
207 204

  
208 205
        now_datetime = now()
209 206

  
210
        open_slots, all_time_slots = get_all_slots(agenda, meeting_type)
211
        open_entries = {}
212
        closed_entries = {}
213

  
214
        for interval in all_time_slots.all_intervals:
215
            time_slot = interval.data
216
            if time_slot.start_datetime < now_datetime:
207
        slots = get_all_slots(agenda, meeting_type)
208
        entries = {}
209
        for slot in slots:
210
            if slot.start_datetime < now_datetime:
217 211
                continue
218
            key = '%s-%s' % (time_slot.start_datetime, time_slot.end_datetime)
219
            if open_slots.search(time_slot.start_datetime, time_slot.end_datetime, strict=True):
220
                time_slot.full = False
221
                open_entries[key] = time_slot
222
            else:
223
                time_slot.full = True
224
                closed_entries[key] = time_slot
225

  
226
        closed_entries.update(open_entries)
227
        entries = sorted(closed_entries.values(), key=lambda x: x.start_datetime)
212
            key = (slot.start_datetime, slot.end_datetime)
213
            if key in entries and slot.full:
214
                continue
215
            entries[key] = slot
216
        slots = sorted(entries.values(), key=lambda x: x.start_datetime)
228 217

  
229 218
        fake_event_pk = '__event_id__'
230 219
        fillslot_url = request.build_absolute_uri(
......
241 230
                              'api': {
242 231
                                'fillslot_url': fillslot_url.replace(fake_event_pk, str(x.id)),
243 232
                              },
244
                             } for x in entries]}
233
                             } for x in slots]}
245 234
        return Response(response)
246 235

  
247 236
meeting_datetimes = MeetingDatetimes.as_view()
......
334 323
                    start_datetime=start_datetime,
335 324
                    full=False, places=1)
336 325

  
337
            open_slots, _ = get_all_slots(agenda, MeetingType.objects.get(id=meeting_type_id))
326
            slots = get_all_slots(agenda, MeetingType.objects.get(id=meeting_type_id))
338 327
            # sort available matching slots by desk id
339
            slot = sorted(open_slots[event.start_datetime:event.end_datetime], key=lambda x: x.data.desk.id)
340
            if slot:
328
            slots = [slot for slot in slots if not slot.full and slot.start_datetime >= event.start_datetime and slot.end_datetime <= event.end_datetime]
329
            slots.sort(key=lambda x: x.desk.id)
330
            if slots:
341 331
                # book first available desk
342
                available_desk = slot[0].data.desk
332
                available_desk = slots[0].desk
343 333

  
344 334
            if not available_desk:
345 335
                return Response({'err': 1, 'reason': 'no more desk available'})
346
-