manager: include booking check filters in partial bookings view (#79623)
gitea/chrono/pipeline/head Build queued...
Details
gitea/chrono/pipeline/head Build queued...
Details
This commit is contained in:
parent
bfea238c08
commit
0146309c4f
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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']
|
||||
|
|
Loading…
Reference in New Issue