general: add method to get opening hours of a desk on a given day (#21244)
This commit is contained in:
parent
0f0b25f17d
commit
b364bdb1d6
|
@ -35,6 +35,9 @@ from django.utils.translation import ugettext_lazy as _
|
|||
|
||||
from jsonfield import JSONField
|
||||
|
||||
from ..interval import Intervals
|
||||
|
||||
|
||||
AGENDA_KINDS = (
|
||||
('events', _('Events')),
|
||||
('meetings', _('Meetings')),
|
||||
|
@ -513,6 +516,22 @@ class Desk(models.Model):
|
|||
|
||||
return total_created
|
||||
|
||||
def get_opening_hours(self, date):
|
||||
openslots = Intervals()
|
||||
for timeperiod in self.timeperiod_set.filter(weekday=date.weekday()):
|
||||
start_datetime = make_aware(datetime.datetime.combine(date, timeperiod.start_time))
|
||||
end_datetime = make_aware(datetime.datetime.combine(date, timeperiod.end_time))
|
||||
openslots.add(start_datetime, end_datetime)
|
||||
|
||||
aware_date = make_aware(datetime.datetime(date.year, date.month, date.day))
|
||||
aware_next_date = aware_date + datetime.timedelta(days=1)
|
||||
for exception in self.timeperiodexception_set.filter(
|
||||
start_datetime__lt=aware_next_date,
|
||||
end_datetime__gt=aware_date):
|
||||
openslots.remove(exception.start_datetime, exception.end_datetime)
|
||||
|
||||
return openslots.search(aware_date, aware_next_date)
|
||||
|
||||
|
||||
class TimePeriodException(models.Model):
|
||||
desk = models.ForeignKey(Desk)
|
||||
|
|
|
@ -26,6 +26,9 @@ class Interval(object):
|
|||
self.end = end
|
||||
self.data = data
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.begin == other.begin and self.end == other.end and self.data == other.data
|
||||
|
||||
def overlap(self, begin, end):
|
||||
if end <= self.begin:
|
||||
return False
|
||||
|
@ -69,6 +72,20 @@ class Intervals(object):
|
|||
yield self.points[i], interval
|
||||
i += 1
|
||||
|
||||
def remove(self, begin, end):
|
||||
'Substract interval'
|
||||
for interval in list(self.iter()):
|
||||
# create interval with new borders
|
||||
if interval.overlap(begin, end):
|
||||
if begin > interval.begin and end < interval.end:
|
||||
self.add(interval.begin, begin)
|
||||
self.add(end, interval.end)
|
||||
elif interval.begin < begin:
|
||||
self.add(interval.begin, begin)
|
||||
elif interval.end > end:
|
||||
self.add(end, interval.end)
|
||||
self.__remove_interval(interval)
|
||||
|
||||
def remove_overlap(self, begin, end):
|
||||
'Remove all overlapping intervals'
|
||||
for point, interval in self.__iter_interval(begin, end, modify=True):
|
||||
|
|
|
@ -55,3 +55,18 @@ def test_intervals():
|
|||
assert not intervals.overlap(i, i + 1)
|
||||
for i in range(15, 20):
|
||||
assert intervals.overlap(i, i + 1)
|
||||
|
||||
def test_interval_remove():
|
||||
intervals = Intervals()
|
||||
intervals.add(9, 12)
|
||||
intervals.add(14, 17)
|
||||
intervals.remove(11, 24)
|
||||
assert list(intervals.search(0, 24)) == [Interval(9, 11)]
|
||||
intervals.remove(8, 10)
|
||||
assert list(intervals.search(0, 24)) == [Interval(10, 11)]
|
||||
|
||||
intervals = Intervals()
|
||||
intervals.add(9, 12)
|
||||
intervals.add(14, 17)
|
||||
intervals.remove(10, 11)
|
||||
assert list(intervals.search(0, 24)) == [Interval(9, 10), Interval(11, 12), Interval(14, 17)]
|
||||
|
|
|
@ -4,7 +4,7 @@ import datetime
|
|||
import pytest
|
||||
|
||||
from django.test import override_settings
|
||||
from django.utils.timezone import make_aware
|
||||
from django.utils.timezone import localtime, make_aware
|
||||
|
||||
from chrono.agendas.models import Agenda, TimePeriod, TimePeriodException, MeetingType, Desk
|
||||
|
||||
|
@ -126,3 +126,67 @@ def test_time_period_exception_as_string():
|
|||
start_datetime=make_aware(datetime.datetime(2018, 1, 18, 10, 0)),
|
||||
end_datetime=make_aware(datetime.datetime(2018, 1, 20, 12, 0)))
|
||||
) == u'18 jan. 2018 10:00 → 20 jan. 2018 12:00'
|
||||
|
||||
|
||||
def test_desk_opening_hours():
|
||||
agenda = Agenda(label=u'Foo bar', slug='bar')
|
||||
agenda.save()
|
||||
desk = Desk.objects.create(label='Desk 1', agenda=agenda)
|
||||
|
||||
# nothing yet
|
||||
hours = list(desk.get_opening_hours(datetime.date(2018, 1, 22)))
|
||||
assert len(hours) == 0
|
||||
|
||||
# morning
|
||||
TimePeriod(desk=desk, weekday=0,
|
||||
start_time=datetime.time(9, 0),
|
||||
end_time=datetime.time(12, 0)).save()
|
||||
hours = list(desk.get_opening_hours(datetime.date(2018, 1, 22)))
|
||||
assert len(hours) == 1
|
||||
assert hours[0].begin.time() == datetime.time(9, 0)
|
||||
assert hours[0].end.time() == datetime.time(12, 0)
|
||||
|
||||
# and afternoon
|
||||
TimePeriod(desk=desk, weekday=0,
|
||||
start_time=datetime.time(14, 0),
|
||||
end_time=datetime.time(17, 0)).save()
|
||||
hours = list(desk.get_opening_hours(datetime.date(2018, 1, 22)))
|
||||
assert len(hours) == 2
|
||||
assert hours[0].begin.time() == datetime.time(9, 0)
|
||||
assert hours[0].end.time() == datetime.time(12, 0)
|
||||
|
||||
assert hours[1].begin.time() == datetime.time(14, 0)
|
||||
assert hours[1].end.time() == datetime.time(17, 0)
|
||||
|
||||
# full day exception
|
||||
exception = TimePeriodException(
|
||||
desk=desk,
|
||||
start_datetime=make_aware(datetime.datetime(2018, 1, 22)),
|
||||
end_datetime=make_aware(datetime.datetime(2018, 1, 23)))
|
||||
exception.save()
|
||||
|
||||
hours = list(desk.get_opening_hours(datetime.date(2018, 1, 22)))
|
||||
assert len(hours) == 0
|
||||
|
||||
# closed from 11am
|
||||
exception.start_datetime = make_aware(datetime.datetime(2018, 1, 22, 11, 0))
|
||||
exception.save()
|
||||
hours = list(desk.get_opening_hours(datetime.date(2018, 1, 22)))
|
||||
assert len(hours) == 1
|
||||
assert localtime(hours[0].begin).time() == datetime.time(9, 0)
|
||||
assert localtime(hours[0].end).time() == datetime.time(11, 0)
|
||||
|
||||
# closed in the middle
|
||||
exception.start_datetime = make_aware(datetime.datetime(2018, 1, 22, 10, 0))
|
||||
exception.end_datetime = make_aware(datetime.datetime(2018, 1, 22, 11, 0))
|
||||
exception.save()
|
||||
hours = list(desk.get_opening_hours(datetime.date(2018, 1, 22)))
|
||||
assert len(hours) == 3
|
||||
assert localtime(hours[0].begin).time() == datetime.time(9, 0)
|
||||
assert localtime(hours[0].end).time() == datetime.time(10, 0)
|
||||
|
||||
assert localtime(hours[1].begin).time() == datetime.time(11, 0)
|
||||
assert localtime(hours[1].end).time() == datetime.time(12, 0)
|
||||
|
||||
assert localtime(hours[2].begin).time() == datetime.time(14, 0)
|
||||
assert localtime(hours[2].end).time() == datetime.time(17, 0)
|
||||
|
|
Loading…
Reference in New Issue