Projet

Général

Profil

0001-manager-mark-all-bookings-without-status-52813.patch

Lauréline Guérin, 08 avril 2021 15:51

Télécharger (11,8 ko)

Voir les différences:

Subject: [PATCH] manager: mark all bookings without status (#52813)

 .../static/js/chrono_events.manager.js        |  5 +-
 .../templates/chrono/manager_event_check.html | 24 +++++++
 .../manager_event_check_booking_fragment.html |  6 +-
 chrono/manager/urls.py                        | 10 +++
 chrono/manager/views.py                       | 68 +++++++++++++++++++
 tests/manager/test_event.py                   | 64 +++++++++++++++++
 6 files changed, 173 insertions(+), 4 deletions(-)
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
-