Project

General

Profile

Download (7.14 KB) Statistics
| Branch: | Tag: | Revision:
6da3eb09 Jérôme Schneider
76974b6f Benjamin Dauvergne
from datetime import datetime, timedelta, date, time
61763791 Benjamin Dauvergne
from interval import IntervalSet
11984ab3 Jérôme Schneider
76974b6f Benjamin Dauvergne
from django.db.models import Q
from model_utils.managers import InheritanceManager, PassThroughManager, InheritanceQuerySet
6da3eb09 Jérôme Schneider
from calebasse.agenda.conf import default
4ce756c8 Benjamin Dauvergne
from calebasse.utils import weeks_since_epoch, weekday_ranks
11984ab3 Jérôme Schneider
from calebasse import agenda

__all__ = (
'EventManager',
)
6da3eb09 Jérôme Schneider

76974b6f Benjamin Dauvergne
class EventQuerySet(InheritanceQuerySet):
def for_today(self, today=None):
today = today or date.today()
a04356e2 Benjamin Dauvergne
excluded = self.filter(exceptions__exception_date=today).values_list('id', flat=True)
76974b6f Benjamin Dauvergne
weeks = weeks_since_epoch(today)
filters = [Q(start_datetime__gte=datetime.combine(today, time()),
4ce756c8 Benjamin Dauvergne
start_datetime__lte=datetime.combine(today, time(23,59,59)),
a04356e2 Benjamin Dauvergne
recurrence_periodicity__isnull=True,
canceled=False) ]
4ce756c8 Benjamin Dauvergne
base_q = Q(start_datetime__lte=datetime.combine(today, time(23,59,59)),
a04356e2 Benjamin Dauvergne
canceled=False,
2ff47024 Benjamin Dauvergne
recurrence_week_day=today.weekday(),
4ce756c8 Benjamin Dauvergne
recurrence_periodicity__isnull=False) & \
76974b6f Benjamin Dauvergne
(Q(recurrence_end_date__gte=today) |
a04356e2 Benjamin Dauvergne
Q(recurrence_end_date__isnull=True)) & \
~ Q(id__in=excluded)
4ce756c8 Benjamin Dauvergne
# week periods
76974b6f Benjamin Dauvergne
for period in range(1, 6):
filters.append(base_q & Q(recurrence_week_offset=weeks % period,
2ff47024 Benjamin Dauvergne
recurrence_week_period=period))
4ce756c8 Benjamin Dauvergne
# week parity
parity = today.isocalendar()[1] % 2
filters.append(base_q & Q(recurrence_week_parity=parity))
# week ranks
filters.append(base_q & Q(recurrence_week_rank__in=weekday_ranks(today)))
76974b6f Benjamin Dauvergne
qs = self.filter(reduce(Q.__or__, filters))
5f372104 Jérôme Schneider
return qs
11984ab3 Jérôme Schneider
5c2d0ea2 Benjamin Dauvergne
def today_occurrences(self, today=None):
76974b6f Benjamin Dauvergne
today = today or date.today()
self = self.for_today(today)
5c2d0ea2 Benjamin Dauvergne
occurences = ( e.today_occurrence(today) for e in self )
76974b6f Benjamin Dauvergne
return sorted(occurences, key=lambda e: e.start_datetime)

def daily_disponibilities(self, date, events, participants, time_tables,
holidays):
'''Slice the day into quarters between 8:00 and 19:00, and returns the
list of particpants with their status amon free, busy and away for each
hour and quarters.

date - the date of day we slice
occurences - a dictionnary of iterable of events indexed by participants
participants - an iterable of participants
time_tables - a dictionnaty of timetable applying for this day indexed by participants
holidays - a dictionnary of holidays applying for this day indexed by participants
'''
f8ad3b42 Jérôme Schneider
result = dict()
7a339eec Frédéric Péters
quarter = 0
76974b6f Benjamin Dauvergne
events_set = {}
d8468991 Jérôme Schneider
timetables_set = {}
1eab6c73 Frédéric Péters
holidays_set = {}
6ee3f66b Jérôme Schneider
for participant in participants:
76974b6f Benjamin Dauvergne
events_set[participant.id] = IntervalSet((o.to_interval() for o in events[participant.id] if not o.is_event_absence()))
d8468991 Jérôme Schneider
timetables_set[participant.id] = IntervalSet((t.to_interval(date) for t in time_tables[participant.id]))
1eab6c73 Frédéric Péters
holidays_set[participant.id] = IntervalSet((h.to_interval(date) for h in holidays[participant.id]))
6ee3f66b Jérôme Schneider
start_datetime = datetime(date.year, date.month, date.day, 8, 0)
end_datetime = datetime(date.year, date.month, date.day, 8, 15)
f8ad3b42 Jérôme Schneider
while (start_datetime.hour <= 19):
for participant in participants:
if not result.has_key(start_datetime.hour):
76974b6f Benjamin Dauvergne
result[start_datetime.hour] = [[], [], [], []]
7a339eec Frédéric Péters
quarter = 0
816a0a9d Jérôme Schneider
interval = IntervalSet.between(start_datetime, end_datetime, False)
76974b6f Benjamin Dauvergne
if interval.intersection(events_set[participant.id]):
7a339eec Frédéric Péters
result[start_datetime.hour][quarter].append({'id': participant.id, 'dispo': 'busy'})
1eab6c73 Frédéric Péters
elif interval.intersection(holidays_set[participant.id]):
7a339eec Frédéric Péters
result[start_datetime.hour][quarter].append({'id': participant.id, 'dispo': 'busy'})
816a0a9d Jérôme Schneider
elif not interval.intersection(timetables_set[participant.id]):
7a339eec Frédéric Péters
result[start_datetime.hour][quarter].append({'id': participant.id, 'dispo': 'away'})
d8468991 Jérôme Schneider
else:
7a339eec Frédéric Péters
result[start_datetime.hour][quarter].append({'id': participant.id, 'dispo': 'free'})
quarter += 1
f8ad3b42 Jérôme Schneider
start_datetime += timedelta(minutes=15)
end_datetime += timedelta(minutes=15)
return result
ad9330e1 Jérôme Schneider
76974b6f Benjamin Dauvergne
class EventManager(PassThroughManager.for_queryset_class(EventQuerySet),
InheritanceManager):
""" This class allows you to manage events, appointment, ...
"""

def create_event(self, creator, title, event_type, participants=[], description='',
services=[], start_datetime=None, end_datetime=None, room=None, note=None, periodicity=1, until=False, **kwargs):
"""
Convenience function to create an ``Event``, optionally create an
``EventType``.

Args:
event_type: can be either an ``EventType`` object or the label
is either created or retrieved.
participants: List of CalebasseUser
start_datetime: will default to the current hour if ``None``
end_datetime: will default to ``start_datetime`` plus
default.DEFAULT_EVENT_DURATION hour if ``None``
Returns:
Event object
"""
if isinstance(event_type, str):
event_type, created = agenda.models.EventType.objects.get_or_create(
label=event_type
)
if not start_datetime:
now = datetime.now()
start_datetime = datetime.combine(now.date, time(now.hour))
if not end_datetime:
end_datetime = start_datetime + default.DEFAULT_EVENT_DURATION
if until is False:
until = start_datetime.date()
event = self.create(creator=creator,
title=title, start_datetime=start_datetime,
end_datetime=end_datetime, event_type=event_type,
4ce756c8 Benjamin Dauvergne
room=room, recurrence_periodicity=periodicity,
recurrence_end_date=until, **kwargs)
76974b6f Benjamin Dauvergne
event.services = services
event.participants = participants
return event

def next_appointment(self, patient_record):
qs = self.next_appointments(patient_record)
008479a2 Jérôme Schneider
if qs:
return qs[0]
else:
return None

76974b6f Benjamin Dauvergne
def next_appointments(self, patient_record, today=None):
from calebasse.actes.models import Act
acts = Act.objects.next_acts(patient_record, today=today) \
.filter(parent_event__isnull=False) \
.select_related()
5c2d0ea2 Benjamin Dauvergne
return [ a.parent_event.today_occurrence(a.date) for a in acts ]
008479a2 Jérôme Schneider
76974b6f Benjamin Dauvergne
def last_appointment(self, patient_record):
qs = self.last_appointments(patient_record)
ca4afcae Jérôme Schneider
if qs:
return qs[0]
else:
return None

76974b6f Benjamin Dauvergne
def last_appointments(self, patient_record, today=None):
from calebasse.actes.models import Act
acts = Act.objects.last_acts(patient_record, today=today) \
.filter(parent_event__isnull=False) \
.select_related()
5c2d0ea2 Benjamin Dauvergne
return [ a.parent_event.today_occurrence(a.date) for a in acts ]