manager: regroup partial booking check operations in one form (#82231)

This commit is contained in:
Valentin Deniaud 2023-11-13 14:42:16 +01:00
parent 8a8bea24a6
commit b7c5d4f675
6 changed files with 300 additions and 161 deletions

View File

@ -780,6 +780,15 @@ div#main-content.partial-booking-dayview {
}
}
.partial-booking--check-icon {
border: 0;
&::before {
content: "\f017"; /* clock */
font-family: FontAwesome;
padding-left: 1ex;
}
}
/* ants-hub */
ul.objects-list.single-links li.ants-setting-not-configured a.edit {
color: red;

View File

@ -7,28 +7,69 @@
{% endblock %}
{% block appbar %}
<h2>{% trans "Check booking" %}</h2>
<h2>
{% blocktrans trimmed with user=view.bookings.0.user_name %}
Check booking for {{ user }}
{% endblocktrans %}
</h2>
{% endblock %}
{% block content %}
{% if multiple_bookings %}
<div class="pk-tabs">
<div class="pk-tabs--tab-list" role="tablist" aria-label="{% trans "Booking tabs" %}">
{% for booking in view.bookings %}
<button role="tab"
aria-selected="{{ forloop.first|yesno:"true,false" }}"
aria-controls="panel-{{ booking.pk }}"
id="tab-{{ booking.pk }}"
tabindex="{{ forloop.first|yesno:"0,-1" }}"
>
{{ booking.start_time|time:"H:i" }} - {{ booking.end_time|time:"H:i" }}
</button>
{% endfor %}
</div>
{% endif %}
<form
method="post"
enctype="multipart/form-data"
data-fill-start_time="{{ object.booking.start_time|time:"H:i" }}"
data-fill-end_time="{{ object.booking.end_time|time:"H:i" }}"
{% if multiple_bookings %}class="pk-tabs--container"{% endif %}
>
{% if allow_adding_check %}
<p>
<a
rel="popup"
href="{% url 'chrono-manager-partial-booking-check' pk=agenda.pk booking_pk=object.booking.pk %}"
>
{% trans "Add second booking check" %}
</a>
</p>
{% endif %}
{% csrf_token %}
{{ form|with_template }}
{% for booking in view.bookings %}
<div
class="booking-check-forms"
data-fill-start_time="{{ booking.start_time|time:"H:i" }}"
data-fill-end_time="{{ booking.end_time|time:"H:i" }}"
{% if multiple_bookings %}
id="panel-{{ booking.pk }}"
role="tabpanel" tabindex="0" {% if not forloop.first %}hidden{% endif %}
data-tab-slug="{{ booking.pk }}"
aria-labelledby="tab-{{ booking.pk }}"
{% endif %}
>
<div class="booking-check-form">
{{ booking.check_forms.0|with_template }}
</div>
{% if forms|length > 1 %}
<fieldset
class="gadjo-foldable {% if not forms.1.instance.pk and not forms.1.errors %}gadjo-folded{% endif %}"
>
<legend class="gadjo-foldable-widget">{% trans "Second booking check" %}</legend>
<div class="booking-check-form gadjo-folding">
{{ booking.check_forms.1|with_template }}
</div>
</fieldset>
{% endif %}
</div>
{% endfor %}
<div class="buttons">
<button class="submit-button">{% trans "Save" %}</button>
<a class="cancel" href="{{ agenda.get_absolute_url }}">{% trans 'Cancel' %}</a>
@ -36,28 +77,37 @@
<script>
$(function () {
presence_check_type_select = $('.widget[id=id_presence_check_type_p]');
absence_check_type_select = $('.widget[id=id_absence_check_type_p]');
$('input[type=radio][name=presence]').change(function() {
if (!this.checked)
return;
if (this.value == 'True') {
$(this).parents('.widget').siblings('.widget').show();
absence_check_type_select.hide();
} else if (this.value == 'False') {
$(this).parents('.widget').siblings('.widget').show();
presence_check_type_select.hide();
} else {
$(this).parents('.widget').siblings('.widget').hide();
}
}).change();
// Tabs are not loaded if form is in popup, remove this block when fixed in gadjo
$(document.querySelectorAll('.pk-tabs')).each(function(i, el) {
el.tabs = new gadjo_js.Tabs(el);
});
$('.booking-check-form').each(function () {
let presence_check_type_select = $(this).children('.widget[id*=presence_check_type]');
let absence_check_type_select = $(this).children('.widget[id*=absence_check_type]');
$(this).find('input[type=radio][name*=presence]').change(function() {
if (!this.checked)
return;
if (this.value == 'True') {
$(this).parents('.widget').siblings('.widget').show();
absence_check_type_select.hide();
} else if (this.value == 'False') {
$(this).parents('.widget').siblings('.widget').show();
presence_check_type_select.hide();
} else {
$(this).parents('.widget').siblings('.widget').hide();
}
}).change();
});
$('.time-widget-button').on('click', function() {
var widget_name = $(this).data('related-widget');
var value = $(this).parents('form').data('fill-' + widget_name);
var widget_id = widget_name.split('-').at(-1);
var value = $(this).parents('.booking-check-forms').data('fill-' + widget_id);
$('[name="' + widget_name + '"]').val(value);
});
});
</script>
</form>
{% if multiple_bookings %}</div>{% endif %}
{% endblock %}

View File

@ -83,13 +83,14 @@
<section class="partial-booking--registrant">
{% spaceless %}
<h3 class="registrant--name">
{% if allow_check and user.check_url %}
<span class="registrant--name-label">{{ user.name }}</span>
{% if allow_check %}
<a
class="partial-booking--check-icon"
rel="popup"
{% if user.bookings|length > 1 %}data-selector=".pk-tabs"{% endif %}
href="{{ user.check_url }}"
>{{ user.name }}</a>
{% else %}
<span>{{ user.name }}</span>
><span class="sr-only">{% trans "Check" %}</span></a>
{% endif %}
</h3>
{% endspaceless %}
@ -97,33 +98,25 @@
<div class="registrant--bar-container">
{% for booking in user.bookings %}
{% if booking.start_time %}
<a
<p
class="registrant--bar booking"
title="{% trans "Booked period" %}"
style="left: {{ booking.css_left }}%; width: {{ booking.css_width }}%;"
{% if allow_check and not booking.user_check %}
rel="popup"
href="{% url 'chrono-manager-partial-booking-check' pk=agenda.pk booking_pk=booking.pk %}"
{% endif %}
>
<strong class="sr-only">{% trans "Booked period:" %}</strong>
<time class="start-time" datetime="{{ booking.start_time|time:"H:i" }}">{{ booking.start_time|time:"H:i" }}</time>
<time class="end-time" datetime="{{ booking.end_time|time:"H:i" }}">{{ booking.end_time|time:"H:i" }}</time>
</a>
</p>
{% endif %}
{% endfor %}
</div>
{% if user.bookings %}
<div class="registrant--bar-container">
{% for check in user.booking_checks %}
<a
<p
class="registrant--bar check {{ check.css_class }}"
title="{% trans "Checked period" %}"
style="left: {{ check.css_left }}%;{% if check.css_width %} width: {{ check.css_width }}%;{% endif %}"
{% if allow_check %}
rel="popup"
href="{% url 'chrono-manager-partial-booking-update-check' pk=agenda.pk check_pk=check.pk %}"
{% endif %}
>
<strong class="sr-only">{% trans "Checked period:" %}</strong>
{% if check.start_time %}
@ -133,7 +126,7 @@
<time class="end-time" datetime="{{ check.end_time|time:"H:i" }}">{{ check.end_time|time:"H:i" }}</time>
{% endif %}
{% if check.type_label %}<span>{{ check.type_label }}</span>{% endif %}
</a>
</p>
{% endfor %}
</div>
<div class="registrant--bar-container">

View File

@ -435,20 +435,10 @@ urlpatterns = [
name='chrono-manager-booking-extra-user-block',
),
path(
'agendas/<int:pk>/bookings/<int:booking_pk>/check',
'agendas/<int:pk>/events/<int:event_pk>/check-bookings/<str:user_external_id>',
views.partial_booking_check_view,
name='chrono-manager-partial-booking-check',
),
path(
'agendas/<int:pk>/booking-checks/<int:check_pk>',
views.partial_booking_update_check_view,
name='chrono-manager-partial-booking-update-check',
),
path(
'agendas/<int:pk>/subscriptions/<int:subscription_pk>/check/<int:event_pk>',
views.partial_booking_subscription_check_view,
name='chrono-manager-partial-booking-subscription-check',
),
path(
'agendas/<int:pk>/subscriptions/<int:subscription_pk>/extra-user-block',
views.subscription_extra_user_block,

View File

@ -1693,13 +1693,17 @@ class AgendaDayView(EventChecksMixin, AgendaDateView, DayArchiveView):
'name': result.user_name,
'bookings': [],
'booking_checks': [],
'check_url': reverse(
'chrono-manager-partial-booking-check',
kwargs={
'pk': self.agenda.pk,
'event_pk': event.pk,
'user_external_id': result.user_external_id,
},
),
},
)
if result.kind == 'subscription':
user_info['check_url'] = reverse(
'chrono-manager-partial-booking-subscription-check',
kwargs={'pk': self.agenda.pk, 'event_pk': event.pk, 'subscription_pk': result.pk},
)
continue
user_info['bookings'].append(result)
user_info['booking_checks'].extend(result.user_check_list)
@ -4534,61 +4538,123 @@ class SharedCustodySettingsView(UpdateView):
shared_custody_settings = SharedCustodySettingsView.as_view()
class PartialBookingCheckMixin(ViewableAgendaMixin):
class PartialBookingCheckView(ViewableAgendaMixin, TemplateView):
template_name = 'chrono/manager_partial_booking_form.html'
form_class = PartialBookingCheckForm
def get_object(self):
booking = self.get_booking(**self.kwargs)
return BookingCheck(booking=booking)
def dispatch(self, *args, **kwargs):
self.set_agenda(**kwargs)
self.event = get_object_or_404(
Event,
Q(checked=False) | Q(agenda__disable_check_update=False),
pk=kwargs['event_pk'],
agenda=self.agenda,
check_locked=False,
)
self.bookings = Booking.objects.filter(
event=self.event, user_external_id=kwargs['user_external_id']
).order_by('start_time')
if not self.bookings:
subscription = get_object_or_404(
Subscription,
agenda=self.agenda,
user_external_id=kwargs['user_external_id'],
date_start__lte=self.event.start_datetime,
date_end__gt=self.event.start_datetime,
)
# create dummy booking to allow check
booking = self.event.booking_set.create(
user_external_id=subscription.user_external_id,
user_last_name=subscription.user_last_name,
user_first_name=subscription.user_first_name,
user_email=subscription.user_email,
user_phone_number=subscription.user_phone_number,
extra_data=subscription.extra_data,
)
self.bookings = [booking]
self.multiple_bookings = bool(len(self.bookings) > 1)
return super().dispatch(*args, **kwargs)
def get_context_data(self, forms=None, **kwargs):
context = super().get_context_data(**kwargs)
context['forms'] = forms or self.get_forms()
context['multiple_bookings'] = self.multiple_bookings
return context
def get_forms(self):
kwargs = {'agenda': self.agenda}
if self.request.method == 'POST':
kwargs['data'] = self.request.POST
forms = []
for i, booking in enumerate(self.bookings):
checks = booking.user_checks.all()
first_check = checks[0] if len(checks) > 0 else BookingCheck(booking=booking)
second_check = checks[1] if len(checks) > 1 else BookingCheck(booking=booking)
first_check_initial = {}
if i == 0 and first_check.presence is None:
first_check_initial['presence'] = True
booking.check_forms = [
PartialBookingCheckForm(
instance=first_check,
prefix=self.get_prefix(booking),
initial=first_check_initial,
**kwargs,
),
]
# do not show second form if checking subscription
if booking.start_time:
booking.check_forms.append(
PartialBookingCheckForm(
instance=second_check,
prefix=self.get_prefix(booking, second_check=True),
**kwargs,
)
)
forms.extend(booking.check_forms)
return forms
def get_prefix(self, booking, second_check=False):
parts = []
if self.multiple_bookings:
parts.append('booking-%s' % booking.pk)
if second_check:
parts.append('check-2')
return '-'.join(parts)
def post(self, *args, **kwargs):
forms = self.get_forms()
all_valid = all(form.is_valid() for form in forms)
if all_valid:
for form in forms:
form.save()
return HttpResponseRedirect(self.get_success_url())
return self.render_to_response(self.get_context_data(forms=forms))
def get_success_url(self):
date = self.object.booking.event.start_datetime
date = self.event.start_datetime
return reverse(
'chrono-manager-agenda-day-view',
kwargs={'pk': self.agenda.pk, 'year': date.year, 'month': date.month, 'day': date.day},
)
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['agenda'] = self.agenda
return kwargs
class PartialBookingCheckView(PartialBookingCheckMixin, BookingCheckMixin, UpdateView):
pass
partial_booking_check_view = PartialBookingCheckView.as_view()
class PartialBookingSubscriptionCheckView(PartialBookingCheckMixin, SubscriptionCheckMixin, UpdateView):
def get_object(self):
if self.request.method == 'POST':
return super().get_object()
else:
return BookingCheck(booking=Booking())
partial_booking_subscription_check_view = PartialBookingSubscriptionCheckView.as_view()
class PartialBookingUpdateCheckView(PartialBookingCheckMixin, UpdateView):
model = BookingCheck
pk_url_kwarg = 'check_pk'
def get_object(self):
return super(PartialBookingCheckMixin, self).get_object()
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['allow_adding_check'] = bool(self.object.booking.user_checks.count() == 1)
return context
partial_booking_update_check_view = PartialBookingUpdateCheckView.as_view()
def menu_json(request):
if not request.user.is_staff:
homepage_view = HomepageView(request=request)

View File

@ -194,9 +194,9 @@ def test_manager_partial_bookings_day_view(app, admin_user, freezer):
)
assert len(resp.pyquery('.partial-booking--registrant')) == 3
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--name-label')[0].text_content() == 'Bruce Doe'
assert resp.pyquery('.registrant--name-label')[1].text_content() == 'Jane Doe'
assert resp.pyquery('.registrant--name-label')[2].text_content() == 'Jon Doe'
assert resp.pyquery('.registrant--bar')[0].findall('time')[0].text == '12:00'
assert resp.pyquery('.registrant--bar')[0].findall('time')[1].text == '14:00'
@ -271,7 +271,7 @@ def test_manager_partial_bookings_day_view_multiple_bookings(app, admin_user, fr
event = Event.objects.create(
label='Event', start_datetime=start_datetime, end_time=datetime.time(18, 00), places=10, agenda=agenda
)
Booking.objects.create(
first_booking = Booking.objects.create(
user_external_id='xxx',
user_first_name='Jane',
user_last_name='Doe',
@ -279,7 +279,7 @@ def test_manager_partial_bookings_day_view_multiple_bookings(app, admin_user, fr
end_time=datetime.time(12, 00),
event=event,
)
Booking.objects.create(
second_booking = Booking.objects.create(
user_external_id='xxx',
user_first_name='Jane',
user_last_name='Doe',
@ -300,10 +300,22 @@ def test_manager_partial_bookings_day_view_multiple_bookings(app, admin_user, fr
assert resp.pyquery('.registrant--bar')[1].findall('time')[1].text == '18:00'
# check first booking
resp = resp.click('Booked period', index=0)
resp.form['start_time'] = '09:30'
resp.form['end_time'] = '12:00'
resp.form['presence'] = 'True'
resp = resp.click('Check')
assert len(resp.pyquery('.pk-tabs')) == 1
assert resp.pyquery('#tab-%s' % first_booking.pk).text() == '09:00 - 12:00'
assert resp.pyquery('#tab-%s' % second_booking.pk).text() == '15:00 - 18:00'
first_prefix = 'booking-%s-' % first_booking.pk
second_prefix = 'booking-%s-' % second_booking.pk
# first booking inital check value is "Present", second booking is "Not checked"
assert resp.form[first_prefix + 'presence'].value == 'True'
assert resp.form[second_prefix + 'presence'].value == ''
resp.form[first_prefix + 'start_time'] = '09:30'
resp.form[first_prefix + 'end_time'] = '12:00'
resp.form[first_prefix + 'presence'] = 'True'
resp = resp.form.submit().follow()
assert len(resp.pyquery('.partial-booking--registrant')) == 1
@ -314,10 +326,10 @@ def test_manager_partial_bookings_day_view_multiple_bookings(app, admin_user, fr
assert resp.pyquery('.registrant--bar.check')[0].findall('time')[1].text == '12:00'
# check second booking
resp = resp.click('Booked period')
resp.form['start_time'] = '15:00'
resp.form['end_time'] = '17:00'
resp.form['presence'] = 'True'
resp = resp.click('Check')
resp.form[second_prefix + 'start_time'] = '15:00'
resp.form[second_prefix + 'end_time'] = '17:00'
resp.form[second_prefix + 'presence'] = 'True'
resp = resp.form.submit().follow()
assert len(resp.pyquery('.partial-booking--registrant')) == 1
@ -356,20 +368,21 @@ def test_manager_partial_bookings_check(check_types, app, admin_user):
assert resp.pyquery('.registrant--bar time')[1].text == '13:30'
assert resp.pyquery('.registrant--bar')[0].attrib['style'] == 'left: 30.77%; width: 19.23%;'
resp = resp.click('Booked period')
resp = resp.click('Check')
assert 'presence_check_type' not in resp.form.fields
assert 'absence_check_type' not in resp.form.fields
assert resp.pyquery('form').attr('data-fill-start_time') == '11:00'
assert resp.pyquery('form').attr('data-fill-end_time') == '13:30'
assert len(resp.pyquery('.pk-tabs')) == 0
assert resp.pyquery('.booking-check-forms').attr('data-fill-start_time') == '11:00'
assert resp.pyquery('.booking-check-forms').attr('data-fill-end_time') == '13:30'
assert resp.pyquery('.time-widget-button')[0].text == 'Fill with booking start time'
assert resp.pyquery('.time-widget-button')[1].text == 'Fill with booking end time'
# submitting empty form works
assert resp.form['presence'].value == ''
resp.form['presence'] = ''
resp = resp.form.submit().follow()
resp = resp.click('Booked period')
resp = resp.click('Check')
resp.form['start_time'] = '11:01'
resp.form['end_time'] = '11:00'
resp.form['presence'] = 'True'
@ -414,7 +427,7 @@ def test_manager_partial_bookings_check(check_types, app, admin_user):
CheckType(slug='bar-reason', label='Bar reason', kind='presence'),
CheckType(slug='baz-reason', label='Baz reason', kind='presence'),
]
resp = resp.click('Checked period')
resp = resp.click('Check')
assert resp.form['presence_check_type'].options == [
('', True, '---------'),
('bar-reason', False, 'Bar reason'),
@ -439,7 +452,7 @@ def test_manager_partial_bookings_check(check_types, app, admin_user):
assert resp.pyquery('.registrant--bar.computed time')[1].text == '13:30'
assert resp.pyquery('.registrant--bar.computed')[0].attrib['style'] == 'left: 30.77%; width: 19.23%;'
resp = resp.click('Checked period')
resp = resp.click('Check')
assert resp.form['presence_check_type'].value == 'bar-reason'
resp.form['presence'] = 'False'
@ -451,7 +464,7 @@ def test_manager_partial_bookings_check(check_types, app, admin_user):
assert len(resp.pyquery('.registrant--bar.computed.absent')) == 1
assert resp.pyquery('.registrant--bar span').text() == ''
resp = resp.click('Checked period')
resp = resp.click('Check')
resp.form['presence'] = ''
resp = resp.form.submit().follow()
assert len(resp.pyquery('.registrant--bar')) == 1
@ -463,15 +476,15 @@ def test_manager_partial_bookings_check(check_types, app, admin_user):
event.save()
assert agenda.disable_check_update is False
resp = app.get('/manage/agendas/%s/day/%d/%d/%d/' % (agenda.pk, today.year, today.month, today.day))
assert '/manage/agendas/%s/bookings/%s/check' % (agenda.pk, booking.pk) in resp
app.get('/manage/agendas/%s/bookings/%s/check' % (agenda.pk, booking.pk), status=200)
assert '/manage/agendas/%s/events/%s/check-bookings/xxx' % (agenda.pk, event.pk) in resp
app.get('/manage/agendas/%s/events/%s/check-bookings/xxx' % (agenda.pk, event.pk), status=200)
# event check is locked
event.check_locked = True
event.save()
resp = app.get('/manage/agendas/%s/day/%d/%d/%d/' % (agenda.pk, today.year, today.month, today.day))
assert '/manage/agendas/%s/bookings/%s/check' % (agenda.pk, booking.pk) not in resp
app.get('/manage/agendas/%s/bookings/%s/check' % (agenda.pk, booking.pk), status=404)
assert '/manage/agendas/%s/events/%s/check-bookings/xxx' % (agenda.pk, event.pk) not in resp
app.get('/manage/agendas/%s/events/%s/check-bookings/xxx' % (agenda.pk, event.pk), status=404)
# now disable check update
event.check_locked = False
@ -479,8 +492,8 @@ def test_manager_partial_bookings_check(check_types, app, admin_user):
agenda.disable_check_update = True
agenda.save()
resp = app.get('/manage/agendas/%s/day/%d/%d/%d/' % (agenda.pk, today.year, today.month, today.day))
assert '/manage/agendas/%s/bookings/%s/check' % (agenda.pk, booking.pk) not in resp
app.get('/manage/agendas/%s/bookings/%s/check' % (agenda.pk, booking.pk), status=404)
assert '/manage/agendas/%s/events/%s/check-bookings/xxx' % (agenda.pk, event.pk) not in resp
app.get('/manage/agendas/%s/events/%s/check-bookings/xxx' % (agenda.pk, event.pk), status=404)
def test_manager_partial_bookings_multiple_checks(app, admin_user):
@ -502,8 +515,11 @@ def test_manager_partial_bookings_multiple_checks(app, admin_user):
today = start_datetime.date()
resp = app.get('/manage/agendas/%s/day/%d/%d/%d/' % (agenda.pk, today.year, today.month, today.day))
resp = resp.click('Booked period')
assert 'Add second booking check' not in resp.text
resp = resp.click('Check')
# main check inital value is "Present", second check is "Not checked"
assert resp.form['presence'].value == 'True'
assert resp.form['check-2-presence'].value == ''
resp.form['start_time'] = '09:30'
resp.form['end_time'] = '12:00'
@ -516,12 +532,12 @@ def test_manager_partial_bookings_multiple_checks(app, admin_user):
assert resp.pyquery('.registrant--bar.check')[0].findall('time')[0].text == '09:30'
assert resp.pyquery('.registrant--bar.check')[0].findall('time')[1].text == '12:00'
resp = resp.click('Checked period')
resp = resp.click('Add second booking check')
resp = resp.click('Check')
assert 'gadjo-folded' in resp.text
resp.form['start_time'] = '12:30'
resp.form['end_time'] = '17:30'
resp.form['presence'] = 'False'
resp.form['check-2-start_time'] = '12:30'
resp.form['check-2-end_time'] = '17:30'
resp.form['check-2-presence'] = 'False'
resp = resp.form.submit().follow()
assert len(resp.pyquery('.registrant--bar')) == 5
@ -530,20 +546,20 @@ def test_manager_partial_bookings_multiple_checks(app, admin_user):
assert resp.pyquery('.registrant--bar.check')[1].findall('time')[0].text == '12:30'
assert resp.pyquery('.registrant--bar.check')[1].findall('time')[1].text == '17:30'
resp = resp.click('Checked period', index=1)
assert 'Add second booking check' not in resp.text
resp = resp.click('Check')
assert 'gadjo-folded' not in resp.text
resp.form['start_time'] = '11:30'
resp.form['end_time'] = ''
resp.form['check-2-start_time'] = '11:30'
resp.form['check-2-end_time'] = ''
resp = resp.form.submit()
assert 'Booking check hours overlap existing check.' in resp.text
resp.form['end_time'] = '17:30'
resp.form['check-2-end_time'] = '17:30'
resp = resp.form.submit()
assert 'Booking check hours overlap existing check.' in resp.text
resp.form['start_time'] = '12:30'
resp.form['presence'] = ''
resp.form['check-2-start_time'] = '12:30'
resp.form['check-2-presence'] = ''
resp = resp.form.submit().follow()
assert len(resp.pyquery('.registrant--bar')) == 3
@ -552,6 +568,16 @@ def test_manager_partial_bookings_multiple_checks(app, admin_user):
assert resp.pyquery('.registrant--bar.check')[0].findall('time')[0].text == '09:30'
assert resp.pyquery('.registrant--bar.check')[0].findall('time')[1].text == '12:00'
resp = resp.click('Check')
assert 'gadjo-folded' in resp.text
resp.form['check-2-presence'] = 'False'
resp.form['check-2-start_time'] = '11:30'
resp.form['check-2-end_time'] = '11:29'
resp = resp.form.submit()
assert 'Arrival must be before departure.' in resp.text
assert 'gadjo-folded' not in resp.text
@pytest.mark.parametrize('subscription_only', (True, False))
def test_manager_partial_bookings_incomplete_check(subscription_only, app, admin_user):
@ -582,10 +608,10 @@ def test_manager_partial_bookings_incomplete_check(subscription_only, app, admin
app = login(app)
today = start_datetime.date()
resp = app.get('/manage/agendas/%s/day/%d/%d/%d/' % (agenda.pk, today.year, today.month, today.day))
if subscription_only:
resp = resp.click('Jane Doe')
else:
resp = resp.click('Booked period')
resp = resp.click('Check')
resp = resp.form.submit()
assert 'Both arrival and departure cannot not be empty.' in resp.text
resp.form['start_time'] = '11:01'
resp.form['presence'] = 'True'
@ -601,7 +627,7 @@ def test_manager_partial_bookings_incomplete_check(subscription_only, app, admin
assert resp.pyquery('.registrant--bar.check.present')[0].attrib['style'] == 'left: 30.9%;'
assert resp.pyquery('.registrant--bar.check time').text() == '11:01'
resp = resp.click('Checked period')
resp = resp.click('Check')
resp.form['start_time'] = ''
resp.form['end_time'] = '13:15'
resp = resp.form.submit().follow()
@ -616,7 +642,7 @@ def test_manager_partial_bookings_incomplete_check(subscription_only, app, admin
assert resp.pyquery('.registrant--bar.check.present')[0].attrib['style'] == 'left: 0%; width: 48.08%;'
assert resp.pyquery('.registrant--bar.check time').text() == '13:15'
resp = resp.click('Checked period')
resp = resp.click('Check')
resp.form['start_time'] = ''
resp.form['end_time'] = ''
resp = resp.form.submit()
@ -654,21 +680,21 @@ def test_manager_partial_bookings_check_subscription(check_types, app, admin_use
assert len(resp.pyquery('.registrant--bar')) == 0
assert len(resp.pyquery('.registrant--name a')) == 1
resp = resp.click('Jane Doe')
resp = resp.click('Check')
assert 'Fill with booking start time' not in resp.text
assert 'absence_check_type' not in resp.form.fields
assert resp.form['presence'].options == [
('', True, None),
('True', False, None),
('', False, None),
('True', True, None),
] # no 'False' option
assert not Booking.objects.exists()
assert 'check-2-presence' not in resp.form.fields
resp.form['start_time'] = '10:00'
resp.form['end_time'] = '16:00'
resp.form['presence'] = 'True'
resp = resp.form.submit().follow()
assert len(resp.pyquery('.registrant--name a')) == 0
assert len(resp.pyquery('.registrant--name-label a')) == 0
assert len(resp.pyquery('.registrant--bar')) == 2
assert len(resp.pyquery('.registrant--bar.check.present')) == 1
assert len(resp.pyquery('.registrant--bar.computed.present')) == 1
@ -680,7 +706,7 @@ def test_manager_partial_bookings_check_subscription(check_types, app, admin_use
assert booking.user_first_name == 'Jane'
assert booking.user_last_name == 'Doe'
resp = resp.click('Checked period')
resp = resp.click('Check')
assert 'Fill with booking start time' not in resp.text
assert 'absence_check_type' not in resp.form.fields
assert resp.form['presence'].options == [
@ -761,7 +787,7 @@ def test_manager_partial_bookings_check_filters(check_types, app, admin_user):
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')] == [
assert [x.text_content() for x in resp.pyquery('.registrant--name-label')] == [
'User Absent Meat Foo Reason',
'Subscription Not Booked',
'User Not Checked',
@ -772,23 +798,27 @@ def test_manager_partial_bookings_check_filters(check_types, app, admin_user):
assert len(resp.pyquery('.registrant--bar.booking')) == 3
resp = app.get(url, params={'booking-status': 'booked'})
assert [x.text_content() for x in resp.pyquery('.registrant--name')] == [
assert [x.text_content() for x in resp.pyquery('.registrant--name-label')] == [
'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']
assert [x.text_content() for x in resp.pyquery('.registrant--name-label')] == ['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')] == []
assert [x.text_content() for x in resp.pyquery('.registrant--name-label')] == []
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']
assert [x.text_content() for x in resp.pyquery('.registrant--name-label')] == [
'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']
assert [x.text_content() for x in resp.pyquery('.registrant--name-label')] == [
'User Absent Meat Foo Reason'
]
def test_manager_partial_bookings_event_checked(app, admin_user):
@ -810,6 +840,7 @@ def test_manager_partial_bookings_event_checked(app, admin_user):
for i in range(8):
booking = Booking.objects.create(
event=event,
user_external_id='xxx',
start_time=datetime.time(8, 00),
end_time=datetime.time(10, 00),
presence_callback_url='https://example.invalid/presence/%s' % i,