manager: account for time period weekday indexes in calendar views (#45159)

This commit is contained in:
Valentin Deniaud 2022-01-20 16:35:06 +01:00
parent 7672c6edea
commit 5f413af3d1
4 changed files with 124 additions and 1 deletions

View File

@ -2314,7 +2314,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

View File

@ -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)

View File

@ -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('<tr') == 5 # 10->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('<tr') == 8 # 10->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('<tr') == 4 # 14->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

View File

@ -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')