0001-manager-mark-all-bookings-without-status-52813.patch
chrono/manager/static/js/chrono_events.manager.js | ||
---|---|---|
30 | 30 |
}); |
31 | 31 |
} |
32 | 32 | |
33 |
$(document).on('submit', '.booking form', function(event) { |
|
33 |
$(document).on('submit', '.booking form.with-ajax', function(event) {
|
|
34 | 34 |
var $form = $(this); |
35 | 35 |
var formData = { |
36 | 36 |
'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]', $form).val() |
... | ... | |
45 | 45 |
data: formData |
46 | 46 |
}).done(function(html) { |
47 | 47 |
$form.parent().parent().html(html); |
48 |
if (!$('.booking-status.without-status').length) { |
|
49 |
$('tr.booking.all-bookings').hide(); |
|
50 |
} |
|
48 | 51 |
}).fail(function() { |
49 | 52 |
location.reload(); |
50 | 53 |
}); |
chrono/manager/templates/chrono/manager_event_check.html | ||
---|---|---|
16 | 16 |
<div> |
17 | 17 |
<table class="main check-bookings"> |
18 | 18 |
<tbody> |
19 |
{% if booked_without_status %} |
|
20 |
<tr class="booking all-bookings"> |
|
21 |
<td colspan="2"><b>{% trans "Mark all bookings without status:" %}</b></td> |
|
22 |
<td class="booking-actions"> |
|
23 |
<form method="post" action="{% url 'chrono-manager-event-presence' pk=agenda.pk event_pk=object.pk %}"> |
|
24 |
{% csrf_token %} |
|
25 |
<button class="submit-button">{% trans "Presence" %}</button> |
|
26 |
</form> |
|
27 |
<form method="post" action="{% url 'chrono-manager-event-absence' pk=agenda.pk event_pk=object.pk %}" id="all-bookings-absence"> |
|
28 |
{% csrf_token %} |
|
29 |
<button class="submit-button">{% trans "Absence" %}</button> |
|
30 |
{% if absence_form.reason.field.choices.1 %}{{ absence_form.reason }}{% endif %} |
|
31 |
<script> |
|
32 |
$(function() { |
|
33 |
$('#all-bookings-absence select').on('change', |
|
34 |
function() { |
|
35 |
$('#all-bookings-absence').submit(); |
|
36 |
}); |
|
37 |
}); |
|
38 |
</script> |
|
39 |
</form> |
|
40 |
</td> |
|
41 |
</tr> |
|
42 |
{% endif %} |
|
19 | 43 |
{% for booking in booked %} |
20 | 44 |
<tr class="booking"> |
21 | 45 |
{% include "chrono/manager_event_check_booking_fragment.html" %} |
chrono/manager/templates/chrono/manager_event_check_booking_fragment.html | ||
---|---|---|
1 | 1 |
{% load i18n %} |
2 | 2 | |
3 | 3 |
<td class="booking-username">{{ booking.user_name|default:booking.label|default:_('Unknown') }}</td> |
4 |
<td class="booking-status"> |
|
4 |
<td class="booking-status {% if booking.user_was_present is None %}without-status{% endif %}">
|
|
5 | 5 |
{{ booking.user_was_present|yesno:_('Present,Absent,-') }} |
6 | 6 |
{% if booking.user_was_present is False and booking.user_absence_reason %} |
7 | 7 |
({{ booking.user_absence_reason }}) |
8 | 8 |
{% endif %} |
9 | 9 |
</td> |
10 | 10 |
<td class="booking-actions" data-booking-id="{{ booking.id }}"> |
11 |
<form method="post" action="{% url 'chrono-manager-booking-presence' pk=agenda.pk booking_pk=booking.pk %}"> |
|
11 |
<form method="post" action="{% url 'chrono-manager-booking-presence' pk=agenda.pk booking_pk=booking.pk %}" class="with-ajax">
|
|
12 | 12 |
{% csrf_token %} |
13 | 13 |
<button class="submit-button" |
14 | 14 |
{% if booking.user_was_present is True %}disabled{% endif %} |
15 | 15 |
>{% trans "Presence" %}</button> |
16 | 16 |
</form> |
17 |
<form method="post" action="{% url 'chrono-manager-booking-absence' pk=agenda.pk booking_pk=booking.pk %}"> |
|
17 |
<form method="post" action="{% url 'chrono-manager-booking-absence' pk=agenda.pk booking_pk=booking.pk %}" class="with-ajax">
|
|
18 | 18 |
{% csrf_token %} |
19 | 19 |
<button class="submit-button" |
20 | 20 |
{% if booking.user_was_present is False %}disabled{% endif %} |
chrono/manager/urls.py | ||
---|---|---|
211 | 211 |
views.event_check, |
212 | 212 |
name='chrono-manager-event-check', |
213 | 213 |
), |
214 |
url( |
|
215 |
r'^agendas/(?P<pk>\d+)/events/(?P<event_pk>\d+)/presence$', |
|
216 |
views.event_presence, |
|
217 |
name='chrono-manager-event-presence', |
|
218 |
), |
|
219 |
url( |
|
220 |
r'^agendas/(?P<pk>\d+)/events/(?P<event_pk>\d+)/absence$', |
|
221 |
views.event_absence, |
|
222 |
name='chrono-manager-event-absence', |
|
223 |
), |
|
214 | 224 |
url( |
215 | 225 |
r'^agendas/(?P<pk>\d+)/event_cancellation_report/(?P<report_pk>\d+)/$', |
216 | 226 |
views.event_cancellation_report, |
chrono/manager/views.py | ||
---|---|---|
1947 | 1947 |
context['booked'] = event.booking_set.filter( |
1948 | 1948 |
cancellation_datetime__isnull=True, in_waiting_list=False |
1949 | 1949 |
).order_by('user_name') |
1950 |
context['booked_without_status'] = any(e.user_was_present is None for e in context['booked']) |
|
1951 |
if context['booked_without_status']: |
|
1952 |
context['absence_form'] = BookingAbsenceReasonForm(agenda=self.agenda) |
|
1950 | 1953 |
context['waiting'] = event.booking_set.filter( |
1951 | 1954 |
cancellation_datetime__isnull=True, in_waiting_list=True |
1952 | 1955 |
).order_by('user_name') |
... | ... | |
1960 | 1963 |
event_check = EventCheckView.as_view() |
1961 | 1964 | |
1962 | 1965 | |
1966 |
class EventCheckMixin(object): |
|
1967 |
def set_agenda(self, **kwargs): |
|
1968 |
self.agenda = get_object_or_404( |
|
1969 |
Agenda, |
|
1970 |
pk=kwargs.get('pk'), |
|
1971 |
kind='events', |
|
1972 |
) |
|
1973 |
self.event = get_object_or_404( |
|
1974 |
Event, |
|
1975 |
pk=kwargs.get('event_pk'), |
|
1976 |
agenda=self.agenda, |
|
1977 |
start_datetime__date__lte=now().date(), |
|
1978 |
cancelled=False, |
|
1979 |
) |
|
1980 | ||
1981 |
def get_bookings(self): |
|
1982 |
return self.event.booking_set.filter( |
|
1983 |
event__agenda=self.agenda, |
|
1984 |
event__start_datetime__date__lte=now().date(), |
|
1985 |
event__cancelled=False, |
|
1986 |
cancellation_datetime__isnull=True, |
|
1987 |
in_waiting_list=False, |
|
1988 |
user_was_present__isnull=True, |
|
1989 |
) |
|
1990 | ||
1991 |
def response(self, request): |
|
1992 |
return HttpResponseRedirect( |
|
1993 |
reverse( |
|
1994 |
'chrono-manager-event-check', |
|
1995 |
kwargs={'pk': self.agenda.pk, 'event_pk': self.event.pk}, |
|
1996 |
) |
|
1997 |
) |
|
1998 | ||
1999 | ||
2000 |
class EventPresenceView(EventCheckMixin, ViewableAgendaMixin, View): |
|
2001 |
def post(self, request, *args, **kwargs): |
|
2002 |
bookings = self.get_bookings() |
|
2003 |
bookings.update(user_absence_reason='', user_was_present=True) |
|
2004 |
return self.response(request) |
|
2005 | ||
2006 | ||
2007 |
event_presence = EventPresenceView.as_view() |
|
2008 | ||
2009 | ||
2010 |
class EventAbsenceView(EventCheckMixin, ViewableAgendaMixin, FormView): |
|
2011 |
form_class = BookingAbsenceReasonForm |
|
2012 | ||
2013 |
def get_form_kwargs(self): |
|
2014 |
kwargs = super().get_form_kwargs() |
|
2015 |
kwargs['agenda'] = self.agenda |
|
2016 |
return kwargs |
|
2017 | ||
2018 |
def post(self, request, *args, **kwargs): |
|
2019 |
form = self.get_form() |
|
2020 |
qs_kwargs = {} |
|
2021 |
if form.is_valid(): |
|
2022 |
qs_kwargs['user_absence_reason'] = form.cleaned_data['reason'] |
|
2023 |
bookings = self.get_bookings() |
|
2024 |
bookings.update(user_was_present=False, **qs_kwargs) |
|
2025 |
return self.response(request) |
|
2026 | ||
2027 | ||
2028 |
event_absence = EventAbsenceView.as_view() |
|
2029 | ||
2030 | ||
1963 | 2031 |
class AgendaAddResourceView(ManagedAgendaMixin, FormView): |
1964 | 2032 |
template_name = 'chrono/manager_agenda_resource_form.html' |
1965 | 2033 |
form_class = AgendaResourceForm |
tests/manager/test_event.py | ||
---|---|---|
1269 | 1269 |
assert len(resp.pyquery.find('td.booking-actions button[disabled]')) == 1 |
1270 | 1270 |
assert resp.pyquery.find('td.booking-actions button[disabled]')[0].text.startswith('Absence') |
1271 | 1271 |
assert '<option value="Foo reason" selected>Foo reason</option>' in resp |
1272 | ||
1273 | ||
1274 |
def test_event_check_all_bookings(app, admin_user): |
|
1275 |
group = AbsenceReasonGroup.objects.create(label='Foo bar') |
|
1276 |
AbsenceReason.objects.create(label='Foo reason', group=group) |
|
1277 |
agenda = Agenda.objects.create(label='Events', kind='events', absence_reasons_group=group) |
|
1278 |
event = Event.objects.create( |
|
1279 |
label='xyz', |
|
1280 |
start_datetime=now() - datetime.timedelta(days=1), |
|
1281 |
places=10, |
|
1282 |
waiting_list_places=5, |
|
1283 |
agenda=agenda, |
|
1284 |
) |
|
1285 |
booking1 = Booking.objects.create(event=event, user_name='User 42') |
|
1286 | ||
1287 |
login(app) |
|
1288 |
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk)) |
|
1289 |
token = resp.context['csrf_token'] |
|
1290 |
assert 'Mark all bookings without status' in resp |
|
1291 |
assert '/manage/agendas/%s/events/%s/presence' % (agenda.pk, event.pk) in resp |
|
1292 |
assert '/manage/agendas/%s/events/%s/absence' % (agenda.pk, event.pk) in resp |
|
1293 | ||
1294 |
resp = app.post( |
|
1295 |
'/manage/agendas/%s/events/%s/absence' % (agenda.pk, event.pk), params={'csrfmiddlewaretoken': token} |
|
1296 |
) |
|
1297 |
booking1.refresh_from_db() |
|
1298 |
assert booking1.user_was_present is False |
|
1299 |
assert booking1.user_absence_reason == '' |
|
1300 | ||
1301 |
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk)) |
|
1302 |
assert 'Mark all bookings without status' not in resp |
|
1303 |
assert '/manage/agendas/%s/events/%s/presence' % (agenda.pk, event.pk) not in resp |
|
1304 |
assert '/manage/agendas/%s/events/%s/absence' % (agenda.pk, event.pk) not in resp |
|
1305 | ||
1306 |
booking2 = Booking.objects.create(event=event, user_name='User 35') |
|
1307 |
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk)) |
|
1308 |
assert 'Mark all bookings without status' in resp |
|
1309 |
assert '/manage/agendas/%s/events/%s/presence' % (agenda.pk, event.pk) in resp |
|
1310 |
assert '/manage/agendas/%s/events/%s/absence' % (agenda.pk, event.pk) in resp |
|
1311 | ||
1312 |
app.post( |
|
1313 |
'/manage/agendas/%s/events/%s/presence' % (agenda.pk, event.pk), params={'csrfmiddlewaretoken': token} |
|
1314 |
) |
|
1315 |
booking1.refresh_from_db() |
|
1316 |
assert booking1.user_was_present is False |
|
1317 |
assert booking1.user_absence_reason == '' |
|
1318 |
booking2.refresh_from_db() |
|
1319 |
assert booking2.user_was_present is True |
|
1320 |
assert booking2.user_absence_reason == '' |
|
1321 | ||
1322 |
booking3 = Booking.objects.create(event=event, user_name='User 51') |
|
1323 |
app.post( |
|
1324 |
'/manage/agendas/%s/events/%s/absence' % (agenda.pk, event.pk), |
|
1325 |
params={'csrfmiddlewaretoken': token, 'reason': 'Foo reason'}, |
|
1326 |
) |
|
1327 |
booking1.refresh_from_db() |
|
1328 |
assert booking1.user_was_present is False |
|
1329 |
assert booking1.user_absence_reason == '' |
|
1330 |
booking2.refresh_from_db() |
|
1331 |
assert booking2.user_was_present is True |
|
1332 |
assert booking2.user_absence_reason == '' |
|
1333 |
booking3.refresh_from_db() |
|
1334 |
assert booking3.user_was_present is False |
|
1335 |
assert booking3.user_absence_reason == 'Foo reason' |
|
1272 |
- |