Projet

Général

Profil

0001-agenda-option-to-disable-check-update-when-event-is-.patch

Lauréline Guérin, 29 juin 2021 16:45

Télécharger (16,4 ko)

Voir les différences:

Subject: [PATCH] agenda: option to disable check update when event is checked
 (#53933)

 .../0089_agenda_event_display_template.py     | 11 +++-
 chrono/agendas/migrations/0096_checked.py     | 18 +++++++
 chrono/agendas/models.py                      |  3 ++
 chrono/api/views.py                           | 15 ++++++
 chrono/manager/forms.py                       |  1 +
 .../templates/chrono/manager_event_check.html |  2 +
 .../manager_event_check_booking_fragment.html |  2 +
 .../manager_events_agenda_settings.html       | 41 ++++++++------
 chrono/manager/views.py                       |  2 +
 tests/api/test_booking.py                     | 32 +++++++++++
 tests/manager/test_all.py                     |  8 +++
 tests/manager/test_event.py                   | 54 +++++++++++++++++++
 12 files changed, 171 insertions(+), 18 deletions(-)
 create mode 100644 chrono/agendas/migrations/0096_checked.py
chrono/agendas/migrations/0089_agenda_event_display_template.py
2 2

  
3 3
from django.db import migrations, models
4 4

  
5
import chrono.agendas.models
6

  
5 7

  
6 8
class Migration(migrations.Migration):
7 9

  
......
15 17
            name='event_display_template',
16 18
            field=models.CharField(
17 19
                blank=True,
18
                help_text='By default event labels will be displayed to users. This allows for a custom template to include additional informations. For example, "{{ event.label }} - {{ event.start_datetime }}" will show event datetime after label. Available variables: event.label (label), event.start_datetime (start date/time), event.places (places), event.remaining_places (remaining places), event.duration (duration), event.pricing (pricing).',
20
                help_text=(
21
                    'By default event labels will be displayed to users. '
22
                    'This allows for a custom template to include additional informations. '
23
                    'For example, "{{ event.label }} - {{ event.start_datetime }}" will show event datetime after label. '
24
                    'Available variables: event.label (label), event.start_datetime (start date/time), event.places (places), '
25
                    'event.remaining_places (remaining places), event.duration (duration), event.pricing (pricing).'
26
                ),
19 27
                max_length=256,
28
                validators=[chrono.agendas.models.event_template_validator],
20 29
                verbose_name='Event display template',
21 30
            ),
22 31
        ),
chrono/agendas/migrations/0096_checked.py
1
from django.db import migrations, models
2

  
3

  
4
class Migration(migrations.Migration):
5

  
6
    dependencies = [
7
        ('agendas', '0095_checked'),
8
    ]
9

  
10
    operations = [
11
        migrations.AddField(
12
            model_name='agenda',
13
            name='disable_check_update',
14
            field=models.BooleanField(
15
                default=False, verbose_name='Prevent the check of bookings when event was marked as checked'
16
            ),
17
        ),
18
    ]
chrono/agendas/models.py
222 222
    mark_event_checked_auto = models.BooleanField(
223 223
        _('Automatically mark event as checked when all bookings have been checked'), default=False
224 224
    )
225
    disable_check_update = models.BooleanField(
226
        _('Prevent the check of bookings when event was marked as checked'), default=False
227
    )
225 228
    booking_check_filters = models.CharField(
226 229
        _('Filters'),
227 230
        max_length=250,
chrono/api/views.py
1610 1610
                status=status.HTTP_400_BAD_REQUEST,
1611 1611
            )
1612 1612

  
1613
        if (
1614
            self.booking.event.checked
1615
            and self.booking.event.agenda.disable_check_update
1616
            and ('user_was_present' in request.data or 'user_absence_reason' in request.data)
1617
        ):
1618
            return Response(
1619
                {
1620
                    'err': 5,
1621
                    'err_class': 'event is marked as checked',
1622
                    'err_desc': _('event is marked as checked'),
1623
                    'errors': serializer.errors,
1624
                },
1625
                status=status.HTTP_400_BAD_REQUEST,
1626
            )
1627

  
1613 1628
        if 'extra_data' in serializer.validated_data:
1614 1629
            extra_data = self.booking.extra_data or {}
1615 1630
            extra_data.update(serializer.validated_data['extra_data'] or {})
chrono/manager/forms.py
837 837
            'booking_check_filters',
838 838
            'booking_user_block_template',
839 839
            'mark_event_checked_auto',
840
            'disable_check_update',
840 841
        ]
841 842
        widgets = {'booking_user_block_template': forms.Textarea(attrs={'rows': 3})}
842 843

  
chrono/manager/templates/chrono/manager_event_check.html
38 38
        </tr>
39 39
      {% endif %}
40 40
      {% if booked_without_status %}
41
        {% if not event.checked or not agenda.disable_check_update %}
41 42
        <tr class="booking all-bookings">
42 43
          <td colspan="2"><b>{% trans "Mark all bookings without status:" %}</b></td>
43 44
          <td class="booking-actions">
......
60 61
            </form>
61 62
          </td>
62 63
        </tr>
64
        {% endif %}
63 65
      {% endif %}
64 66
      {% for booking in booked %}
65 67
        <tr class="booking">
chrono/manager/templates/chrono/manager_event_check_booking_fragment.html
7 7
    ({{ booking.user_absence_reason }})
8 8
  {% endif %}
9 9
</td>
10
{% if not event.checked or not agenda.disable_check_update %}
10 11
<td class="booking-actions" data-booking-id="{{ booking.id }}">
11 12
  <form method="post" action="{% url 'chrono-manager-booking-presence' pk=agenda.pk booking_pk=booking.pk %}" class="with-ajax">
12 13
    {% csrf_token %}
......
30 31
    </script>
31 32
  </form>
32 33
</td>
34
{% endif %}
chrono/manager/templates/chrono/manager_events_agenda_settings.html
35 35
    <a rel="popup" class="button" href="{% url 'chrono-manager-agenda-booking-check-settings' pk=object.pk %}">{% trans 'Configure' %}</a>
36 36
</h3>
37 37
<div>
38
    <ul>
38 39
    {% if has_absence_reasons %}
39 40
        {% if agenda.absence_reasons_group %}
40
        <p>{% trans "Absence reasons group:" %} {{ agenda.absence_reasons_group }}</p>
41
        <ul>
42
          {% for reason in agenda.absence_reasons_group.absence_reasons.all %}
43
          <li>{{ reason }}</li>
44
          {% endfor %}
45
        </ul>
41
        <li>{% trans "Absence reasons group:" %} {{ agenda.absence_reasons_group }}
42
            <ul>
43
              {% for reason in agenda.absence_reasons_group.absence_reasons.all %}
44
              <li>{{ reason }}</li>
45
              {% endfor %}
46
            </ul>
47
        </li>
46 48
        {% else %}
47
        <p>{% trans "No absence reasons configured for this agenda." %}</p>
49
        <li>{% trans "No absence reasons configured for this agenda." %}</li>
48 50
        {% endif %}
49 51
    {% endif %}
50 52

  
51 53
    {% with agenda.get_booking_check_filters as check_filters %}
52 54
        {% if check_filters %}
53
        <p>{% trans "Filters:" %}</p>
54
        <ul>
55
            {% for key in check_filters %}
56
            <li>{{ key }}</li>
57
            {% endfor %}
58
        </ul>
55
        <li>{% trans "Filters:" %}
56
            <ul>
57
                {% for key in check_filters %}
58
                <li>{{ key }}</li>
59
                {% endfor %}
60
            </ul>
61
        </li>
59 62
        {% else %}
60
        <p>{% trans "No filters configured for this agenda." %}</p>
63
        <li>{% trans "No filters configured for this agenda." %}</li>
61 64
        {% endif %}
62 65
    {% endwith %}
63 66

  
64
    <p>{% trans "User block template:" %}</p>
65
    <pre>{{ agenda.get_booking_user_block_template }}</pre>
67
        <li>
68
            {% trans "User block template:" %}
69
            <pre>{{ agenda.get_booking_user_block_template }}</pre>
70
        </li>
66 71

  
67
    <p>{% trans "Automatically mark events when they are checked:" %} {{ agenda.mark_event_checked_auto|yesno }}</p>
72
        <li>{% trans "Automatically mark event as checked when all bookings have been checked:" %} {{ agenda.mark_event_checked_auto|yesno }}</li>
73
        <li>{% trans "Prevent the check of bookings when event was marked as checked:" %} {{ agenda.disable_check_update|yesno }}</li>
74
    </ul>
68 75
</div>
69 76
</div>
70 77

  
chrono/manager/views.py
1995 1995
        )
1996 1996
        self.event = get_object_or_404(
1997 1997
            Event,
1998
            Q(checked=False) | Q(agenda__disable_check_update=False),
1998 1999
            pk=kwargs.get('event_pk'),
1999 2000
            agenda=self.agenda,
2000 2001
            start_datetime__date__lte=now().date(),
......
2734 2735
    def get_booking(self, **kwargs):
2735 2736
        return get_object_or_404(
2736 2737
            Booking,
2738
            Q(event__checked=False) | Q(event__agenda__disable_check_update=False),
2737 2739
            pk=kwargs['booking_pk'],
2738 2740
            event__agenda=self.agenda,
2739 2741
            event__start_datetime__date__lte=now().date(),
tests/api/test_booking.py
448 448
    other_booking.refresh_from_db()
449 449
    assert other_booking.user_was_present is None  # not changed
450 450

  
451
    # mark the event as checked
452
    event.checked = True
453
    event.save()
454
    resp = app.patch_json('/api/booking/%s/' % booking.pk, params={'user_was_present': flag})
455
    assert resp.json['err'] == 0
456

  
457
    # now disable check update
458
    agenda.disable_check_update = True
459
    agenda.save()
460
    resp = app.patch_json('/api/booking/%s/' % booking.pk, params={'user_was_present': flag}, status=400)
461
    assert resp.json['err'] == 5
462
    assert resp.json['err_desc'] == 'event is marked as checked'
463
    resp = app.patch_json('/api/booking/%s/' % booking.pk)
464
    assert resp.json['err'] == 0
465

  
451 466

  
452 467
def test_booking_patch_api_absence_reason(app, user):
453 468
    agenda = Agenda.objects.create(kind='events')
......
514 529
    other_booking.refresh_from_db()
515 530
    assert other_booking.user_absence_reason == ''  # not changed
516 531

  
532
    # mark the event as checked
533
    event.checked = True
534
    event.save()
535
    resp = app.patch_json('/api/booking/%s/' % booking.pk, params={'user_absence_reason': reason.slug})
536
    assert resp.json['err'] == 0
537

  
538
    # now disable check update
539
    agenda.disable_check_update = True
540
    agenda.save()
541
    resp = app.patch_json(
542
        '/api/booking/%s/' % booking.pk, params={'user_absence_reason': reason.slug}, status=400
543
    )
544
    assert resp.json['err'] == 5
545
    assert resp.json['err_desc'] == 'event is marked as checked'
546
    resp = app.patch_json('/api/booking/%s/' % booking.pk)
547
    assert resp.json['err'] == 0
548

  
517 549

  
518 550
def test_booking_patch_api_extra_data(app, user):
519 551
    agenda = Agenda.objects.create(kind='events')
tests/manager/test_all.py
570 570
    agenda.refresh_from_db()
571 571
    assert agenda.mark_event_checked_auto is True
572 572

  
573
    # check disable check
574
    assert agenda.disable_check_update is False
575
    resp = app.get(url)
576
    resp.form['disable_check_update'] = True
577
    resp = resp.form.submit()
578
    agenda.refresh_from_db()
579
    assert agenda.disable_check_update is True
580

  
573 581
    # check kind
574 582
    agenda.kind = 'meetings'
575 583
    agenda.save()
tests/manager/test_event.py
1385 1385
    assert booking.user_was_present is True
1386 1386
    assert booking.user_absence_reason == ''
1387 1387

  
1388
    # mark the event as checked
1389
    event.checked = True
1390
    event.save()
1391
    resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
1392
    assert '/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk) in resp
1393
    assert '/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk) in resp
1394
    resp = app.post(
1395
        '/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk),
1396
        params={'csrfmiddlewaretoken': token},
1397
        status=302,
1398
    )
1399
    app.post(
1400
        '/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk),
1401
        params={'csrfmiddlewaretoken': token},
1402
        status=302,
1403
    )
1404

  
1405
    # now disable check update
1406
    agenda.disable_check_update = True
1407
    agenda.save()
1408
    resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
1409
    assert '/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk) not in resp
1410
    assert '/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk) not in resp
1411
    resp = app.post(
1412
        '/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk),
1413
        params={'csrfmiddlewaretoken': token},
1414
        status=404,
1415
    )
1416
    app.post(
1417
        '/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk),
1418
        params={'csrfmiddlewaretoken': token},
1419
        status=404,
1420
    )
1421

  
1388 1422

  
1389 1423
def test_event_check_booking_ajax(app, admin_user):
1390 1424
    group = AbsenceReasonGroup.objects.create(label='Foo bar')
......
1482 1516
    event.refresh_from_db()
1483 1517
    assert event.checked is True
1484 1518

  
1519
    # event is checked
1485 1520
    booking3 = Booking.objects.create(event=event, user_first_name='User', user_last_name='51')
1521
    resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
1522
    assert 'Mark all bookings without status' in resp
1486 1523
    app.post(
1487 1524
        '/manage/agendas/%s/events/%s/absence' % (agenda.pk, event.pk),
1488 1525
        params={'csrfmiddlewaretoken': token, 'reason': 'Foo reason'},
......
1496 1533
    booking3.refresh_from_db()
1497 1534
    assert booking3.user_was_present is False
1498 1535
    assert booking3.user_absence_reason == 'Foo reason'
1536

  
1537
    # now disable check update
1538
    agenda.disable_check_update = True
1539
    agenda.save()
1540
    Booking.objects.create(event=event, user_first_name='User', user_last_name='52')
1541
    resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
1542
    assert 'Mark all bookings without status' not in resp
1543
    app.post(
1544
        '/manage/agendas/%s/events/%s/absence' % (agenda.pk, event.pk),
1545
        params={'csrfmiddlewaretoken': token, 'reason': 'Foo reason'},
1546
        status=404,
1547
    )
1548
    resp = app.post(
1549
        '/manage/agendas/%s/events/%s/absence' % (agenda.pk, event.pk),
1550
        params={'csrfmiddlewaretoken': token},
1551
        status=404,
1552
    )
1499
-