manager: mark all bookings without status (#52813)
This commit is contained in:
parent
c771a154f6
commit
cf6a9c3ece
|
@ -30,7 +30,7 @@ $(function() {
|
|||
});
|
||||
}
|
||||
|
||||
$(document).on('submit', '.booking form', function(event) {
|
||||
$(document).on('submit', '.booking form.with-ajax', function(event) {
|
||||
var $form = $(this);
|
||||
var formData = {
|
||||
'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]', $form).val()
|
||||
|
@ -45,6 +45,9 @@ $(function() {
|
|||
data: formData
|
||||
}).done(function(html) {
|
||||
$form.parent().parent().html(html);
|
||||
if (!$('.booking-status.without-status').length) {
|
||||
$('tr.booking.all-bookings').hide();
|
||||
}
|
||||
}).fail(function() {
|
||||
location.reload();
|
||||
});
|
||||
|
|
|
@ -16,6 +16,30 @@
|
|||
<div>
|
||||
<table class="main check-bookings">
|
||||
<tbody>
|
||||
{% if booked_without_status %}
|
||||
<tr class="booking all-bookings">
|
||||
<td colspan="2"><b>{% trans "Mark all bookings without status:" %}</b></td>
|
||||
<td class="booking-actions">
|
||||
<form method="post" action="{% url 'chrono-manager-event-presence' pk=agenda.pk event_pk=object.pk %}">
|
||||
{% csrf_token %}
|
||||
<button class="submit-button">{% trans "Presence" %}</button>
|
||||
</form>
|
||||
<form method="post" action="{% url 'chrono-manager-event-absence' pk=agenda.pk event_pk=object.pk %}" id="all-bookings-absence">
|
||||
{% csrf_token %}
|
||||
<button class="submit-button">{% trans "Absence" %}</button>
|
||||
{% if absence_form.reason.field.choices.1 %}{{ absence_form.reason }}{% endif %}
|
||||
<script>
|
||||
$(function() {
|
||||
$('#all-bookings-absence select').on('change',
|
||||
function() {
|
||||
$('#all-bookings-absence').submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% for booking in booked %}
|
||||
<tr class="booking">
|
||||
{% include "chrono/manager_event_check_booking_fragment.html" %}
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
{% load i18n %}
|
||||
|
||||
<td class="booking-username">{{ booking.user_name|default:booking.label|default:_('Unknown') }}</td>
|
||||
<td class="booking-status">
|
||||
<td class="booking-status {% if booking.user_was_present is None %}without-status{% endif %}">
|
||||
{{ booking.user_was_present|yesno:_('Present,Absent,-') }}
|
||||
{% if booking.user_was_present is False and booking.user_absence_reason %}
|
||||
({{ booking.user_absence_reason }})
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="booking-actions" data-booking-id="{{ booking.id }}">
|
||||
<form method="post" action="{% url 'chrono-manager-booking-presence' pk=agenda.pk booking_pk=booking.pk %}">
|
||||
<form method="post" action="{% url 'chrono-manager-booking-presence' pk=agenda.pk booking_pk=booking.pk %}" class="with-ajax">
|
||||
{% csrf_token %}
|
||||
<button class="submit-button"
|
||||
{% if booking.user_was_present is True %}disabled{% endif %}
|
||||
>{% trans "Presence" %}</button>
|
||||
</form>
|
||||
<form method="post" action="{% url 'chrono-manager-booking-absence' pk=agenda.pk booking_pk=booking.pk %}">
|
||||
<form method="post" action="{% url 'chrono-manager-booking-absence' pk=agenda.pk booking_pk=booking.pk %}" class="with-ajax">
|
||||
{% csrf_token %}
|
||||
<button class="submit-button"
|
||||
{% if booking.user_was_present is False %}disabled{% endif %}
|
||||
|
|
|
@ -211,6 +211,16 @@ urlpatterns = [
|
|||
views.event_check,
|
||||
name='chrono-manager-event-check',
|
||||
),
|
||||
url(
|
||||
r'^agendas/(?P<pk>\d+)/events/(?P<event_pk>\d+)/presence$',
|
||||
views.event_presence,
|
||||
name='chrono-manager-event-presence',
|
||||
),
|
||||
url(
|
||||
r'^agendas/(?P<pk>\d+)/events/(?P<event_pk>\d+)/absence$',
|
||||
views.event_absence,
|
||||
name='chrono-manager-event-absence',
|
||||
),
|
||||
url(
|
||||
r'^agendas/(?P<pk>\d+)/event_cancellation_report/(?P<report_pk>\d+)/$',
|
||||
views.event_cancellation_report,
|
||||
|
|
|
@ -1960,6 +1960,9 @@ class EventCheckView(ViewableAgendaMixin, DetailView):
|
|||
context['booked'] = event.booking_set.filter(
|
||||
cancellation_datetime__isnull=True, in_waiting_list=False
|
||||
).order_by('user_name')
|
||||
context['booked_without_status'] = any(e.user_was_present is None for e in context['booked'])
|
||||
if context['booked_without_status']:
|
||||
context['absence_form'] = BookingAbsenceReasonForm(agenda=self.agenda)
|
||||
context['waiting'] = event.booking_set.filter(
|
||||
cancellation_datetime__isnull=True, in_waiting_list=True
|
||||
).order_by('user_name')
|
||||
|
@ -1973,6 +1976,71 @@ class EventCheckView(ViewableAgendaMixin, DetailView):
|
|||
event_check = EventCheckView.as_view()
|
||||
|
||||
|
||||
class EventCheckMixin(object):
|
||||
def set_agenda(self, **kwargs):
|
||||
self.agenda = get_object_or_404(
|
||||
Agenda,
|
||||
pk=kwargs.get('pk'),
|
||||
kind='events',
|
||||
)
|
||||
self.event = get_object_or_404(
|
||||
Event,
|
||||
pk=kwargs.get('event_pk'),
|
||||
agenda=self.agenda,
|
||||
start_datetime__date__lte=now().date(),
|
||||
cancelled=False,
|
||||
)
|
||||
|
||||
def get_bookings(self):
|
||||
return self.event.booking_set.filter(
|
||||
event__agenda=self.agenda,
|
||||
event__start_datetime__date__lte=now().date(),
|
||||
event__cancelled=False,
|
||||
cancellation_datetime__isnull=True,
|
||||
in_waiting_list=False,
|
||||
user_was_present__isnull=True,
|
||||
)
|
||||
|
||||
def response(self, request):
|
||||
return HttpResponseRedirect(
|
||||
reverse(
|
||||
'chrono-manager-event-check',
|
||||
kwargs={'pk': self.agenda.pk, 'event_pk': self.event.pk},
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class EventPresenceView(EventCheckMixin, ViewableAgendaMixin, View):
|
||||
def post(self, request, *args, **kwargs):
|
||||
bookings = self.get_bookings()
|
||||
bookings.update(user_absence_reason='', user_was_present=True)
|
||||
return self.response(request)
|
||||
|
||||
|
||||
event_presence = EventPresenceView.as_view()
|
||||
|
||||
|
||||
class EventAbsenceView(EventCheckMixin, ViewableAgendaMixin, FormView):
|
||||
form_class = BookingAbsenceReasonForm
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs['agenda'] = self.agenda
|
||||
return kwargs
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
form = self.get_form()
|
||||
qs_kwargs = {}
|
||||
if form.is_valid():
|
||||
qs_kwargs['user_absence_reason'] = form.cleaned_data['reason']
|
||||
bookings = self.get_bookings()
|
||||
bookings.update(user_was_present=False, **qs_kwargs)
|
||||
return self.response(request)
|
||||
|
||||
|
||||
event_absence = EventAbsenceView.as_view()
|
||||
|
||||
|
||||
class AgendaAddResourceView(ManagedAgendaMixin, FormView):
|
||||
template_name = 'chrono/manager_agenda_resource_form.html'
|
||||
form_class = AgendaResourceForm
|
||||
|
|
|
@ -1275,3 +1275,67 @@ def test_event_check_booking_ajax(app, admin_user):
|
|||
assert len(resp.pyquery.find('td.booking-actions button[disabled]')) == 1
|
||||
assert resp.pyquery.find('td.booking-actions button[disabled]')[0].text.startswith('Absence')
|
||||
assert '<option value="Foo reason" selected>Foo reason</option>' in resp
|
||||
|
||||
|
||||
def test_event_check_all_bookings(app, admin_user):
|
||||
group = AbsenceReasonGroup.objects.create(label='Foo bar')
|
||||
AbsenceReason.objects.create(label='Foo reason', group=group)
|
||||
agenda = Agenda.objects.create(label='Events', kind='events', absence_reasons_group=group)
|
||||
event = Event.objects.create(
|
||||
label='xyz',
|
||||
start_datetime=now() - datetime.timedelta(days=1),
|
||||
places=10,
|
||||
waiting_list_places=5,
|
||||
agenda=agenda,
|
||||
)
|
||||
booking1 = Booking.objects.create(event=event, user_name='User 42')
|
||||
|
||||
login(app)
|
||||
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
|
||||
token = resp.context['csrf_token']
|
||||
assert 'Mark all bookings without status' in resp
|
||||
assert '/manage/agendas/%s/events/%s/presence' % (agenda.pk, event.pk) in resp
|
||||
assert '/manage/agendas/%s/events/%s/absence' % (agenda.pk, event.pk) in resp
|
||||
|
||||
resp = app.post(
|
||||
'/manage/agendas/%s/events/%s/absence' % (agenda.pk, event.pk), params={'csrfmiddlewaretoken': token}
|
||||
)
|
||||
booking1.refresh_from_db()
|
||||
assert booking1.user_was_present is False
|
||||
assert booking1.user_absence_reason == ''
|
||||
|
||||
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
|
||||
assert 'Mark all bookings without status' not in resp
|
||||
assert '/manage/agendas/%s/events/%s/presence' % (agenda.pk, event.pk) not in resp
|
||||
assert '/manage/agendas/%s/events/%s/absence' % (agenda.pk, event.pk) not in resp
|
||||
|
||||
booking2 = Booking.objects.create(event=event, user_name='User 35')
|
||||
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
|
||||
assert 'Mark all bookings without status' in resp
|
||||
assert '/manage/agendas/%s/events/%s/presence' % (agenda.pk, event.pk) in resp
|
||||
assert '/manage/agendas/%s/events/%s/absence' % (agenda.pk, event.pk) in resp
|
||||
|
||||
app.post(
|
||||
'/manage/agendas/%s/events/%s/presence' % (agenda.pk, event.pk), params={'csrfmiddlewaretoken': token}
|
||||
)
|
||||
booking1.refresh_from_db()
|
||||
assert booking1.user_was_present is False
|
||||
assert booking1.user_absence_reason == ''
|
||||
booking2.refresh_from_db()
|
||||
assert booking2.user_was_present is True
|
||||
assert booking2.user_absence_reason == ''
|
||||
|
||||
booking3 = Booking.objects.create(event=event, user_name='User 51')
|
||||
app.post(
|
||||
'/manage/agendas/%s/events/%s/absence' % (agenda.pk, event.pk),
|
||||
params={'csrfmiddlewaretoken': token, 'reason': 'Foo reason'},
|
||||
)
|
||||
booking1.refresh_from_db()
|
||||
assert booking1.user_was_present is False
|
||||
assert booking1.user_absence_reason == ''
|
||||
booking2.refresh_from_db()
|
||||
assert booking2.user_was_present is True
|
||||
assert booking2.user_absence_reason == ''
|
||||
booking3.refresh_from_db()
|
||||
assert booking3.user_was_present is False
|
||||
assert booking3.user_absence_reason == 'Foo reason'
|
||||
|
|
Loading…
Reference in New Issue