manager: reset user_was_present on booking check page (#75276)
gitea/chrono/pipeline/head There was a failure building this commit Details

This commit is contained in:
Lauréline Guérin 2023-03-14 11:56:51 +01:00
parent 6c134bfa3f
commit 970ba42075
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
6 changed files with 114 additions and 8 deletions

View File

@ -2195,6 +2195,18 @@ class Booking(models.Model):
self.secondary_booking_set.update(in_waiting_list=True) self.secondary_booking_set.update(in_waiting_list=True)
self.save() self.save()
def reset_user_was_present(self):
self.user_check_type_slug = None
self.user_check_type_label = None
self.user_was_present = None
with transaction.atomic():
self.secondary_booking_set.update(user_check_type_slug=None)
self.secondary_booking_set.update(user_check_type_label=None)
self.secondary_booking_set.update(user_was_present=None)
self.save()
self.event.checked = False
self.event.save(update_fields=['checked'])
def mark_user_absence(self, check_type_slug=None, check_type_label=None): def mark_user_absence(self, check_type_slug=None, check_type_label=None):
self.user_check_type_slug = check_type_slug self.user_check_type_slug = check_type_slug
self.user_check_type_label = check_type_label self.user_check_type_label = check_type_label

View File

@ -47,6 +47,8 @@ $(function() {
$form.parent().parent().html(html); $form.parent().parent().html(html);
if (!$('.booking-status.without-status').length) { if (!$('.booking-status.without-status').length) {
$('tr.booking.all-bookings').hide(); $('tr.booking.all-bookings').hide();
} else {
$('tr.booking.all-bookings').show();
} }
}).fail(function() { }).fail(function() {
location.reload(); location.reload();

View File

@ -1,7 +1,7 @@
{% load i18n %} {% load i18n %}
<td class="booking-username main-list">{{ booking.get_user_block }}{% if booking.places_count > 1 %} ({{ booking.places_count }} {% trans "places" %}){% endif %}</td> <td class="booking-username main-list">{{ booking.get_user_block }}{% if booking.places_count > 1 %} ({{ booking.places_count }} {% trans "places" %}){% endif %}</td>
<td class="booking-status {% if booking.kind != "subscription" and booking.cancellation_datetime is None and booking.user_was_present is None %}without-status{% endif %}"> <td class="booking-status {% if booking.kind != "subscription" and booking.cancellation_datetime is None and booking.user_was_present is None %}without-status{% endif %}" data-{{ booking.kind }}-id="{{ booking.id }}">
{% if booking.kind == "subscription" %} {% if booking.kind == "subscription" %}
({% trans "Not booked" %}) ({% trans "Not booked" %})
{% elif booking.cancellation_datetime is None %} {% elif booking.cancellation_datetime is None %}
@ -12,6 +12,23 @@
{% else %} {% else %}
({% trans "Cancelled" %}) ({% trans "Cancelled" %})
{% endif %} {% endif %}
{% if not event.checked or not agenda.disable_check_update %}
{% if booking.user_was_present is not None %}
<form method="post" action="{% url 'chrono-manager-booking-reset' pk=agenda.pk booking_pk=booking.pk %}" class="with-ajax reset">
{% csrf_token %}
<a href="#">{% trans "Reset" context "check" %}</a>
<script>
$(function() {
$('td.booking-status[data-{{ booking.kind }}-id="{{ booking.id }}"] form.reset a').on('click',
function(e) {
e.preventDefault();
$(this).parents('form.reset').submit();
});
});
</script>
</form>
{% endif %}
{% endif %}
</td> </td>
{% if not event.checked or not agenda.disable_check_update %} {% if not event.checked or not agenda.disable_check_update %}
<td class="booking-actions" data-{{ booking.kind }}-id="{{ booking.id }}"> <td class="booking-actions" data-{{ booking.kind }}-id="{{ booking.id }}">
@ -27,7 +44,7 @@
{% if booking.presence_form.check_type.field.choices.1 %}{{ booking.presence_form.check_type }}{% endif %} {% if booking.presence_form.check_type.field.choices.1 %}{{ booking.presence_form.check_type }}{% endif %}
<script> <script>
$(function() { $(function() {
$('td[data-{{ booking.kind }}-id="{{ booking.id }}"] form.presence select').on('change', $('td.booking-actions[data-{{ booking.kind }}-id="{{ booking.id }}"] form.presence select').on('change',
function() { function() {
$(this).parents('form.presence').submit(); $(this).parents('form.presence').submit();
}); });
@ -46,7 +63,7 @@
{% if booking.absence_form.check_type.field.choices.1 %}{{ booking.absence_form.check_type }}{% endif %} {% if booking.absence_form.check_type.field.choices.1 %}{{ booking.absence_form.check_type }}{% endif %}
<script> <script>
$(function() { $(function() {
$('td[data-{{ booking.kind }}-id="{{ booking.id }}"] form.absence select').on('change', $('td.booking-actions[data-{{ booking.kind }}-id="{{ booking.id }}"] form.absence select').on('change',
function() { function() {
$(this).parents('form.absence').submit(); $(this).parents('form.absence').submit();
}); });

View File

@ -409,6 +409,11 @@ urlpatterns = [
views.booking_absence, views.booking_absence,
name='chrono-manager-booking-absence', name='chrono-manager-booking-absence',
), ),
path(
'agendas/<int:pk>/bookings/<int:booking_pk>/reset',
views.booking_reset,
name='chrono-manager-booking-reset',
),
path( path(
'agendas/<int:pk>/subscriptions/<int:subscription_pk>/presence/<int:event_pk>', 'agendas/<int:pk>/subscriptions/<int:subscription_pk>/presence/<int:event_pk>',
views.subscription_presence, views.subscription_presence,

View File

@ -3577,6 +3577,16 @@ class BookingAbsenceView(ViewableAgendaMixin, BookingCheckMixin, AbsenceViewMixi
booking_absence = BookingAbsenceView.as_view() booking_absence = BookingAbsenceView.as_view()
class BookingResetView(ViewableAgendaMixin, BookingCheckMixin, FormView):
def post(self, request, *args, **kwargs):
booking = self.get_booking(**kwargs)
booking.reset_user_was_present()
return self.response(request, booking)
booking_reset = BookingResetView.as_view()
class SubscriptionCheckMixin(BookingCheckMixin): class SubscriptionCheckMixin(BookingCheckMixin):
def get_booking(self, **kwargs): def get_booking(self, **kwargs):
event = get_object_or_404( event = get_object_or_404(

View File

@ -2167,12 +2167,32 @@ def test_event_check_booking(check_types, app, admin_user):
) )
assert agenda.mark_event_checked_auto is False assert agenda.mark_event_checked_auto is False
def _test_reset():
resp = app.post(
'/manage/agendas/%s/bookings/%s/reset' % (agenda.pk, booking.pk),
params={'csrfmiddlewaretoken': token},
).follow()
assert '/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk) in resp
assert '/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk) in resp
assert '/manage/agendas/%s/bookings/%s/reset' % (agenda.pk, booking.pk) not in resp
booking.refresh_from_db()
assert booking.user_was_present is None
assert booking.user_check_type_slug is None
assert booking.user_check_type_label is None
secondary_booking.refresh_from_db()
assert secondary_booking.user_was_present is None
assert secondary_booking.user_check_type_slug is None
assert secondary_booking.user_check_type_label is None
event.refresh_from_db()
assert event.checked is False
login(app) login(app)
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk)) resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
assert resp.pyquery.find('td.booking-status')[0].text.strip() == '-' assert resp.pyquery.find('td.booking-status')[0].text.strip() == '-'
assert len(resp.pyquery.find('td.booking-actions button[disabled]')) == 0 assert len(resp.pyquery.find('td.booking-actions button[disabled]')) == 0
assert '/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk) in resp assert '/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk) in resp
assert '/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk) in resp assert '/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk) in resp
assert '/manage/agendas/%s/bookings/%s/reset' % (agenda.pk, booking.pk) not in resp
# set as present # set as present
token = resp.context['csrf_token'] token = resp.context['csrf_token']
@ -2183,6 +2203,9 @@ def test_event_check_booking(check_types, app, admin_user):
assert resp.pyquery.find('td.booking-status')[0].text.strip() == 'Present' assert resp.pyquery.find('td.booking-status')[0].text.strip() == 'Present'
assert len(resp.pyquery.find('td.booking-actions button[disabled]')) == 1 assert len(resp.pyquery.find('td.booking-actions button[disabled]')) == 1
assert resp.pyquery.find('td.booking-actions button[disabled]')[0].text == 'Presence' assert resp.pyquery.find('td.booking-actions button[disabled]')[0].text == 'Presence'
assert '/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk) in resp
assert '/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk) in resp
assert '/manage/agendas/%s/bookings/%s/reset' % (agenda.pk, booking.pk) in resp
booking.refresh_from_db() booking.refresh_from_db()
assert booking.user_was_present is True assert booking.user_was_present is True
assert booking.user_check_type_slug is None assert booking.user_check_type_slug is None
@ -2194,6 +2217,9 @@ def test_event_check_booking(check_types, app, admin_user):
event.refresh_from_db() event.refresh_from_db()
assert event.checked is False assert event.checked is False
# reset
_test_reset()
agenda.mark_event_checked_auto = True agenda.mark_event_checked_auto = True
agenda.save() agenda.save()
@ -2223,6 +2249,9 @@ def test_event_check_booking(check_types, app, admin_user):
assert len(resp.pyquery.find('td.booking-actions form.absence select')) == 1 assert len(resp.pyquery.find('td.booking-actions form.absence select')) == 1
assert len(resp.pyquery.find('td.booking-actions form.presence select')) == 0 assert len(resp.pyquery.find('td.booking-actions form.presence select')) == 0
# reset
_test_reset()
# set as absent with check_type # set as absent with check_type
resp = app.post( resp = app.post(
'/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk), '/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk),
@ -2237,6 +2266,11 @@ def test_event_check_booking(check_types, app, admin_user):
assert secondary_booking.user_was_present is False assert secondary_booking.user_was_present is False
assert secondary_booking.user_check_type_slug == 'foo-reason' assert secondary_booking.user_check_type_slug == 'foo-reason'
assert secondary_booking.user_check_type_label == 'Foo reason' assert secondary_booking.user_check_type_label == 'Foo reason'
event.refresh_from_db()
assert event.checked is True
# reset
_test_reset()
# set as present without check_type # set as present without check_type
resp = app.post( resp = app.post(
@ -2269,6 +2303,9 @@ def test_event_check_booking(check_types, app, admin_user):
assert len(resp.pyquery.find('td.booking-actions form.absence select')) == 1 assert len(resp.pyquery.find('td.booking-actions form.absence select')) == 1
assert len(resp.pyquery.find('td.booking-actions form.presence select')) == 1 assert len(resp.pyquery.find('td.booking-actions form.presence select')) == 1
# reset
_test_reset()
# set as present with check_type # set as present with check_type
resp = app.post( resp = app.post(
'/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk), '/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk),
@ -2283,14 +2320,20 @@ def test_event_check_booking(check_types, app, admin_user):
assert secondary_booking.user_was_present is True assert secondary_booking.user_was_present is True
assert secondary_booking.user_check_type_slug == 'bar-reason' assert secondary_booking.user_check_type_slug == 'bar-reason'
assert secondary_booking.user_check_type_label == 'Bar reason' assert secondary_booking.user_check_type_label == 'Bar reason'
event.refresh_from_db()
assert event.checked is True
# mark the event as checked # event is checked
event.checked = True
event.save()
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk)) resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
assert '/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk) in resp assert '/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk) in resp
assert '/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk) in resp assert '/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk) in resp
resp = app.post( assert '/manage/agendas/%s/bookings/%s/reset' % (agenda.pk, booking.pk) in resp
app.post(
'/manage/agendas/%s/bookings/%s/reset' % (agenda.pk, booking.pk),
params={'csrfmiddlewaretoken': token},
status=302,
)
app.post(
'/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk), '/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk),
params={'csrfmiddlewaretoken': token}, params={'csrfmiddlewaretoken': token},
status=302, status=302,
@ -2307,7 +2350,8 @@ def test_event_check_booking(check_types, app, admin_user):
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk)) resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
assert '/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk) not in resp assert '/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk) not in resp
assert '/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk) not in resp assert '/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk) not in resp
resp = app.post( assert '/manage/agendas/%s/bookings/%s/reset' % (agenda.pk, booking.pk) not in resp
app.post(
'/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk), '/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk),
params={'csrfmiddlewaretoken': token}, params={'csrfmiddlewaretoken': token},
status=404, status=404,
@ -2317,6 +2361,11 @@ def test_event_check_booking(check_types, app, admin_user):
params={'csrfmiddlewaretoken': token}, params={'csrfmiddlewaretoken': token},
status=404, status=404,
) )
app.post(
'/manage/agendas/%s/bookings/%s/reset' % (agenda.pk, booking.pk),
params={'csrfmiddlewaretoken': token},
status=404,
)
@mock.patch('chrono.manager.forms.get_agenda_check_types') @mock.patch('chrono.manager.forms.get_agenda_check_types')
@ -2343,6 +2392,7 @@ def test_event_check_cancelled_booking(check_types, app, admin_user):
assert len(resp.pyquery.find('td.booking-status')) == 1 assert len(resp.pyquery.find('td.booking-status')) == 1
assert '/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk) not in resp assert '/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk) not in resp
assert '/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk) not in resp assert '/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk) not in resp
assert '/manage/agendas/%s/bookings/%s/reset' % (agenda.pk, booking.pk) not in resp
token = resp.context['csrf_token'] token = resp.context['csrf_token']
resp = app.post( resp = app.post(
'/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk), '/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk),
@ -2370,6 +2420,7 @@ def test_event_check_cancelled_booking(check_types, app, admin_user):
assert len(resp.pyquery.find('td.booking-actions button[disabled]')) == 0 assert len(resp.pyquery.find('td.booking-actions button[disabled]')) == 0
assert '/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk) in resp assert '/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk) in resp
assert '/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk) in resp assert '/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk) in resp
assert '/manage/agendas/%s/bookings/%s/reset' % (agenda.pk, booking.pk) not in resp
resp = app.post( resp = app.post(
'/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk), '/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk),
@ -2445,6 +2496,15 @@ def test_event_check_booking_ajax(check_types, app, admin_user):
assert resp.pyquery.find('td.booking-actions button[disabled]')[0].text.startswith('Absence') assert resp.pyquery.find('td.booking-actions button[disabled]')[0].text.startswith('Absence')
assert '<option value="foo-reason" selected>Foo reason</option>' in resp assert '<option value="foo-reason" selected>Foo reason</option>' in resp
# reset
resp = app.post(
'/manage/agendas/%s/bookings/%s/reset' % (agenda.pk, booking.pk),
params={'csrfmiddlewaretoken': token},
extra_environ={'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'},
)
assert '<tr>' not in resp # because this is a fragment
assert resp.pyquery.find('td.booking-status')[0].text.strip() == '-'
@mock.patch('chrono.manager.forms.get_agenda_check_types') @mock.patch('chrono.manager.forms.get_agenda_check_types')
def test_event_check_subscription(check_types, app, admin_user): def test_event_check_subscription(check_types, app, admin_user):