calebasse/calebasse/agenda/managers.py @ cd8a83dc
| 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 ]
|