manager: include booking check filters in partial bookings view (#79623)
gitea/chrono/pipeline/head Build queued... Details

This commit is contained in:
Valentin Deniaud 2023-07-11 17:04:28 +02:00
parent bfea238c08
commit 0146309c4f
3 changed files with 161 additions and 38 deletions

View File

@ -8,6 +8,18 @@
<p>{% trans "No opening hours this day." %}</p>
</div>
{% else %}
<form class="check-bookings-filters">
{{ filterset.form.as_p }}
<script>
$(function() {
$('form.check-bookings-filters input').on('change',
function() {
$(this).parents('form').submit();
});
});
</script>
</form>
<div class="partial-booking" style="--nb-hours: {{ hours|length }}">
<div class="partial-booking--hours-list" aria-hidden="true">
{% for hour in hours %}
@ -16,27 +28,35 @@
</div>
<div class="partial-booking--registrant-items">
{% for booking in bookings %}
{% for booking in results %}
<section class="partial-booking--registrant">
<h3 class="registrant--name">
<a
rel="popup"
href="{% url 'chrono-manager-partial-booking-check' pk=agenda.pk booking_pk=booking.pk %}"
>{{ booking.get_user_block }}</a>
</h3>
{% spaceless %}
<h3 class="registrant--name">
{% if booking.kind == "booking" %}
<a
rel="popup"
href="{% url 'chrono-manager-partial-booking-check' pk=agenda.pk booking_pk=booking.pk %}"
>{{ booking.get_user_block }}</a>
{% else %}
<span>{{ booking.get_user_block }}</span>
{% endif %}
</h3>
{% endspaceless %}
<div class="registrant--datas">
<div class="registrant--bar-container">
<p
class="registrant--bar booking"
title="{% trans "Booked period" %}"
style="left: {{ booking.css_left }}%; width: {{ booking.css_width }}%;"
>
<strong class="sr-only">{% trans "Booked period:" %}</strong>
<time datetime="{{ booking.start_time|time:"H:i" }}">{{ booking.start_time|time:"H:i" }}</time>
<time datetime="{{ booking.end_time|time:"H:i" }}">{{ booking.end_time|time:"H:i" }}</time>
</p>
</div>
{% if booking.kind == "booking" %}
<div class="registrant--bar-container">
<p
class="registrant--bar booking"
title="{% trans "Booked period" %}"
style="left: {{ booking.css_left }}%; width: {{ booking.css_width }}%;"
>
<strong class="sr-only">{% trans "Booked period:" %}</strong>
<time datetime="{{ booking.start_time|time:"H:i" }}">{{ booking.start_time|time:"H:i" }}</time>
<time datetime="{{ booking.end_time|time:"H:i" }}">{{ booking.end_time|time:"H:i" }}</time>
</p>
</div>
{% endif %}
{% if booking.user_was_present is not None %}
<div class="registrant--bar-container">
<p

View File

@ -1465,7 +1465,7 @@ class EventChecksMixin:
context['waiting'] = waiting_qs
class AgendaDayView(AgendaDateView, DayArchiveView):
class AgendaDayView(EventChecksMixin, AgendaDateView, DayArchiveView):
kind = 'day'
def get_queryset(self):
@ -1608,6 +1608,8 @@ class AgendaDayView(AgendaDateView, DayArchiveView):
except Event.DoesNotExist:
return
self.add_filters_context(context, event)
min_time = localtime(event.start_datetime).time()
max_time = event.end_time
@ -1624,8 +1626,8 @@ class AgendaDayView(AgendaDateView, DayArchiveView):
round(100 * ((t1.hour - t2.hour) * 60 + t1.minute - t2.minute) / opening_range_minutes, 2)
)
context['bookings'] = list(event.booking_set.all())
for booking in context['bookings']:
bookings = [x for x in context['results'] if x.kind == 'booking']
for booking in bookings:
booking.css_left = get_time_ratio(booking.start_time, start_time)
booking.css_width = get_time_ratio(booking.end_time, booking.start_time)

View File

@ -3,7 +3,7 @@ from unittest import mock
import pytest
from chrono.agendas.models import Agenda, Booking, Event
from chrono.agendas.models import Agenda, Booking, Event, Subscription
from chrono.utils.lingo import CheckType
from chrono.utils.timezone import make_aware
from tests.utils import login
@ -113,19 +113,19 @@ def test_manager_partial_bookings_day_view(app, admin_user, freezer):
)
assert len(resp.pyquery('.partial-booking--registrant')) == 3
assert resp.pyquery('.registrant--name a')[0].text == 'Jane Doe'
assert resp.pyquery('.registrant--name a')[1].text == 'Jon Doe'
assert resp.pyquery('.registrant--name a')[2].text == 'Bruce Doe'
assert resp.pyquery('.registrant--name')[0].text_content() == 'Bruce Doe'
assert resp.pyquery('.registrant--name')[1].text_content() == 'Jane Doe'
assert resp.pyquery('.registrant--name')[2].text_content() == 'Jon Doe'
assert resp.pyquery('.registrant--bar')[0].findall('time')[0].text == '11:00'
assert resp.pyquery('.registrant--bar')[0].findall('time')[1].text == '13:30'
assert resp.pyquery('.registrant--bar')[0].attrib['style'] == 'left: 30.77%; width: 19.23%;'
assert resp.pyquery('.registrant--bar')[1].findall('time')[0].text == '08:00'
assert resp.pyquery('.registrant--bar')[1].findall('time')[1].text == '10:00'
assert resp.pyquery('.registrant--bar')[1].attrib['style'] == 'left: 7.69%; width: 15.38%;'
assert resp.pyquery('.registrant--bar')[2].findall('time')[0].text == '12:00'
assert resp.pyquery('.registrant--bar')[2].findall('time')[1].text == '14:00'
assert resp.pyquery('.registrant--bar')[2].attrib['style'] == 'left: 38.46%; width: 15.38%;'
assert resp.pyquery('.registrant--bar')[0].findall('time')[0].text == '12:00'
assert resp.pyquery('.registrant--bar')[0].findall('time')[1].text == '14:00'
assert resp.pyquery('.registrant--bar')[0].attrib['style'] == 'left: 38.46%; width: 15.38%;'
assert resp.pyquery('.registrant--bar')[1].findall('time')[0].text == '11:00'
assert resp.pyquery('.registrant--bar')[1].findall('time')[1].text == '13:30'
assert resp.pyquery('.registrant--bar')[1].attrib['style'] == 'left: 30.77%; width: 19.23%;'
assert resp.pyquery('.registrant--bar')[2].findall('time')[0].text == '08:00'
assert resp.pyquery('.registrant--bar')[2].findall('time')[1].text == '10:00'
assert resp.pyquery('.registrant--bar')[2].attrib['style'] == 'left: 7.69%; width: 15.38%;'
resp = resp.click('Next day')
assert 'No opening hours this day.' in resp.text
@ -201,7 +201,7 @@ def test_manager_partial_bookings_check(check_types, app, admin_user):
assert resp.pyquery('.registrant--bar.check time')[0].text == '11:00'
assert resp.pyquery('.registrant--bar.check time')[1].text == '13:15'
assert resp.pyquery('.registrant--bar.check')[0].attrib['style'] == 'left: 30.77%; width: 17.31%;'
assert 'Bar reason' in resp.text
assert resp.pyquery('.registrant--bar span').text() == 'Bar reason'
resp = resp.click('Jane Doe')
assert resp.form['presence_check_type'].value == 'bar-reason'
@ -212,11 +212,112 @@ def test_manager_partial_bookings_check(check_types, app, admin_user):
assert len(resp.pyquery('.registrant--bar')) == 2
assert len(resp.pyquery('.registrant--bar.booking')) == 1
assert len(resp.pyquery('.registrant--bar.check.absent')) == 1
assert 'Bar reason' not in resp.text
assert resp.pyquery('.registrant--bar span').text() == ''
resp = resp.click('Jane Doe')
resp.form['user_was_present'] = ''
resp = resp.form.submit().follow()
assert len(resp.pyquery('.registrant--bar')) == 1
assert len(resp.pyquery('.registrant--bar.booking')) == 1
assert 'Bar reason' not in resp.text
assert resp.pyquery('.registrant--bar span').text() == ''
@mock.patch('chrono.manager.forms.get_agenda_check_types')
def test_manager_partial_bookings_check_filters(check_types, app, admin_user):
check_types.return_value = [
CheckType(slug='foo-reason', label='Foo reason', kind='absence'),
CheckType(slug='bar-reason', label='Bar reason', kind='presence'),
]
agenda = Agenda.objects.create(
label='Foo bar',
kind='events',
partial_bookings=True,
booking_check_filters='menu',
)
start_datetime = make_aware(datetime.datetime(2023, 5, 2, 8, 0))
event = Event.objects.create(
label='Event', start_datetime=start_datetime, end_time=datetime.time(18, 00), places=10, agenda=agenda
)
Booking.objects.create(
user_external_id='user:1',
user_first_name='User',
user_last_name='Not Checked',
start_time=datetime.time(11, 00),
end_time=datetime.time(13, 30),
event=event,
)
Booking.objects.create(
user_external_id='user:2',
user_first_name='User',
user_last_name='Present Vegan',
start_time=datetime.time(8, 00),
end_time=datetime.time(10, 00),
user_check_start_time=datetime.time(8, 00),
user_check_end_time=datetime.time(10, 00),
event=event,
extra_data={'menu': 'vegan'},
user_was_present=True,
)
Booking.objects.create(
user_external_id='user:3',
user_first_name='User',
user_last_name='Absent Meat Foo Reason',
start_time=datetime.time(12, 00),
end_time=datetime.time(14, 00),
user_check_start_time=datetime.time(12, 30),
user_check_end_time=datetime.time(14, 30),
event=event,
extra_data={'menu': 'meat'},
user_was_present=False,
user_check_type_slug='foo-reason',
)
Subscription.objects.create(
agenda=agenda,
user_external_id='user:1',
user_first_name='Subscription',
user_last_name='Present Vegan',
date_start=event.start_datetime,
date_end=event.start_datetime + datetime.timedelta(days=1),
)
Subscription.objects.create(
agenda=agenda,
user_external_id='user:4',
user_first_name='Subscription',
user_last_name='Not Booked',
date_start=event.start_datetime,
date_end=event.start_datetime + datetime.timedelta(days=1),
)
app = login(app)
today = start_datetime.date()
url = '/manage/agendas/%s/day/%d/%d/%d/' % (agenda.pk, today.year, today.month, today.day)
resp = app.get(url)
assert [x.text_content() for x in resp.pyquery('.registrant--name')] == [
'User Absent Meat Foo Reason',
'Subscription Not Booked',
'User Not Checked',
'User Present Vegan',
]
# one registrant has not booked, no bar is shown and no booking check link
assert len(resp.pyquery('.registrant--bar.booking')) == 3
assert len(resp.pyquery('.registrant--name a')) == 3
resp = app.get(url, params={'booking-status': 'booked'})
assert [x.text_content() for x in resp.pyquery('.registrant--name')] == [
'User Absent Meat Foo Reason',
'User Not Checked',
'User Present Vegan',
]
resp = app.get(url, params={'booking-status': 'presence'})
assert [x.text_content() for x in resp.pyquery('.registrant--name')] == ['User Present Vegan']
resp = app.get(url, params={'booking-status': 'presence', 'extra-data-menu': 'meat'})
assert [x.text_content() for x in resp.pyquery('.registrant--name')] == []
resp = app.get(url, params={'extra-data-menu': 'meat'})
assert [x.text_content() for x in resp.pyquery('.registrant--name')] == ['User Absent Meat Foo Reason']
resp = app.get(url, params={'booking-status': 'absence::foo-reason'})
assert [x.text_content() for x in resp.pyquery('.registrant--name')] == ['User Absent Meat Foo Reason']