From 34a420056b157218ea6228d19d468c1bb19960df Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Thu, 20 Jan 2022 16:35:06 +0100 Subject: [PATCH 5/5] manager: account for time period weekday indexes in calendar views (#45159) --- chrono/agendas/models.py | 3 ++ chrono/manager/views.py | 8 ++++- tests/manager/test_all.py | 49 ++++++++++++++++++++++++++++ tests/test_time_periods.py | 65 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 124 insertions(+), 1 deletion(-) diff --git a/chrono/agendas/models.py b/chrono/agendas/models.py index fc37f2b2..e28fd0ff 100644 --- a/chrono/agendas/models.py +++ b/chrono/agendas/models.py @@ -2215,7 +2215,10 @@ class Desk(models.Model): def get_opening_hours(self, date): openslots = IntervalSet() + weekday_index = get_weekday_index(date) for timeperiod in self.timeperiod_set.all(): + if timeperiod.weekday_indexes and weekday_index not in timeperiod.weekday_indexes: + continue # timeperiod_set.all() are prefetched, do not filter in queryset if timeperiod.weekday != date.weekday(): continue diff --git a/chrono/manager/views.py b/chrono/manager/views.py index 45cbcf33..2176672f 100644 --- a/chrono/manager/views.py +++ b/chrono/manager/views.py @@ -84,6 +84,7 @@ from chrono.agendas.models import ( UnavailabilityCalendar, VirtualMember, ) +from chrono.utils.date import get_weekday_index from .forms import ( AbsenceReasonForm, @@ -1223,7 +1224,12 @@ class AgendaDayView(AgendaDateView, DayArchiveView): def get_timetable_infos(self): timeperiods = itertools.chain(*(d.timeperiod_set.all() for d in self.agenda.prefetched_desks)) - timeperiods = [t for t in timeperiods if t.weekday == self.date.weekday()] + timeperiods = [ + t + for t in timeperiods + if t.weekday == self.date.weekday() + and (not t.weekday_indexes or get_weekday_index(self.date) in t.weekday_indexes) + ] timeperiods = sorted(timeperiods, key=lambda t: t.start_time) interval = datetime.timedelta(minutes=60) diff --git a/tests/manager/test_all.py b/tests/manager/test_all.py index 5b161652..315a5f28 100644 --- a/tests/manager/test_all.py +++ b/tests/manager/test_all.py @@ -2828,3 +2828,52 @@ def test_agenda_booking_colors(app, admin_user, api_user, view): assert resp.text.count('Swimming') == 2 # 1 booking + legend assert 'Booking colors:' in resp.text assert len(resp.pyquery.find('div.booking-colors span.booking-color-label')) == 2 + + +@freezegun.freeze_time('2022-03-01 14:00') +def test_agenda_day_and_month_views_weekday_indexes(app, admin_user): + agenda = Agenda.objects.create(label='New Example', kind='meetings') + desk = Desk.objects.create(agenda=agenda, label='New Desk') + MeetingType.objects.create(agenda=agenda, label='Bar', duration=30) + today = datetime.date.today() + TimePeriod.objects.create( + desk=desk, + weekday=today.weekday(), + start_time=datetime.time(10, 0), + end_time=datetime.time(14, 0), + weekday_indexes=[1, 3], + ) + TimePeriod.objects.create( + desk=desk, + weekday=today.weekday(), + start_time=datetime.time(14, 0), + end_time=datetime.time(17, 0), + weekday_indexes=[3, 5], + ) + login(app) + + # check day view + resp = app.get('/manage/agendas/%s/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day)) + assert resp.text.count('14 + assert 'style="height: 400%; top: 0%;"' in resp.text + + resp = app.get('/manage/agendas/%s/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day + 7)) + assert 'No opening hours this day.' in resp.text + + resp = app.get('/manage/agendas/%s/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day + 14)) + assert resp.text.count('14, 14->17 + assert 'style="height: 700%; top: 0%;"' in resp.text + + resp = app.get('/manage/agendas/%s/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day + 21)) + assert 'No opening hours this day.' in resp.text + + resp = app.get('/manage/agendas/%s/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day + 28)) + assert resp.text.count('17 + assert 'style="height: 300%; top: 0%;"' in resp.text + + # check month view + resp = app.get('/manage/agendas/%s/%s/%s/' % (agenda.pk, today.year, today.month)) + assert resp.text.count('height:') == 3 + assert resp.text.count('height:400.0%') == 1 + assert resp.text.count('height:700.0%') == 1 + assert resp.text.count('height:300.0%') == 1 diff --git a/tests/test_time_periods.py b/tests/test_time_periods.py index f3eabed7..774b9476 100644 --- a/tests/test_time_periods.py +++ b/tests/test_time_periods.py @@ -233,6 +233,71 @@ def test_desk_opening_hours(): assert localtime(hours[2].end).time() == datetime.time(17, 0) +def test_desk_opening_hours_weekday_indexes(): + def set_prefetched_exceptions(desk): + desk.prefetched_exceptions = TimePeriodException.objects.filter( + Q(desk=desk) | Q(unavailability_calendar__desks=desk) + ) + + agenda = Agenda.objects.create(label='Foo bar', slug='bar') + desk = Desk.objects.create(label='Desk 1', agenda=agenda) + + # morning + timeperiod = TimePeriod.objects.create( + desk=desk, + weekday=0, + start_time=datetime.time(9, 0), + end_time=datetime.time(12, 0), + weekday_indexes=[4], + ) + set_prefetched_exceptions(desk) + hours = 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.objects.create( + desk=desk, + weekday=0, + start_time=datetime.time(14, 0), + end_time=datetime.time(17, 0), + weekday_indexes=[4], + ) + set_prefetched_exceptions(desk) + hours = 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) + + timeperiod.weekday_indexes = [5] + timeperiod.save() + hours = desk.get_opening_hours(datetime.date(2018, 1, 22)) + assert len(hours) == 1 + assert hours[0].begin.time() == datetime.time(14, 0) + assert hours[0].end.time() == datetime.time(17, 0) + + hours = desk.get_opening_hours(datetime.date(2018, 1, 29)) + assert len(hours) == 1 + assert hours[0].begin.time() == datetime.time(9, 0) + assert hours[0].end.time() == datetime.time(12, 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() + + set_prefetched_exceptions(desk) + hours = desk.get_opening_hours(datetime.date(2018, 1, 22)) + assert len(hours) == 0 + + def test_timeperiod_midnight_overlap_time_slots(): # https://dev.entrouvert.org/issues/29142 agenda = Agenda(label='Foo bar', slug='bar') -- 2.30.2