Projet

Général

Profil

0001-manager-show-when-an-event-is-checked-53707.patch

Lauréline Guérin, 21 mai 2021 10:34

Télécharger (17,1 ko)

Voir les différences:

Subject: [PATCH] manager: show when an event is checked (#53707)

 chrono/agendas/migrations/0090_checked.py     | 23 +++++++++
 chrono/agendas/models.py                      | 31 ++++++++++++
 chrono/api/views.py                           |  1 +
 chrono/manager/forms.py                       |  7 ++-
 .../chrono/manager_agenda_event_fragment.html |  9 +++-
 .../templates/chrono/manager_event_check.html | 10 ++++
 .../manager_events_agenda_settings.html       |  4 +-
 chrono/manager/urls.py                        |  5 ++
 chrono/manager/views.py                       | 23 ++++++---
 tests/manager/test_all.py                     |  8 +++
 tests/manager/test_event.py                   | 50 +++++++++++++++++++
 tests/test_api.py                             | 11 ++++
 12 files changed, 172 insertions(+), 10 deletions(-)
 create mode 100644 chrono/agendas/migrations/0090_checked.py
chrono/agendas/migrations/0090_checked.py
1
from django.db import migrations, models
2

  
3

  
4
class Migration(migrations.Migration):
5

  
6
    dependencies = [
7
        ('agendas', '0089_agenda_event_display_template'),
8
    ]
9

  
10
    operations = [
11
        migrations.AddField(
12
            model_name='agenda',
13
            name='mark_event_checked_auto',
14
            field=models.BooleanField(
15
                default=False, verbose_name='Automatically mark events when they are checked'
16
            ),
17
        ),
18
        migrations.AddField(
19
            model_name='event',
20
            name='checked',
21
            field=models.BooleanField(default=False),
22
        ),
23
    ]
chrono/agendas/models.py
205 205
        _('Booking form URL'), max_length=200, blank=True, validators=[django_template_validator]
206 206
    )
207 207
    desk_simple_management = models.BooleanField(default=False)
208
    mark_event_checked_auto = models.BooleanField(
209
        _('Automatically mark events when they are checked'), default=False
210
    )
208 211
    booking_check_filters = models.CharField(
209 212
        _('Filters'),
210 213
        max_length=250,
......
1206 1209
    full = models.BooleanField(default=False)
1207 1210
    cancelled = models.BooleanField(default=False)
1208 1211
    cancellation_scheduled = models.BooleanField(default=False)
1212
    checked = models.BooleanField(default=False)
1209 1213
    meeting_type = models.ForeignKey(MeetingType, null=True, on_delete=models.CASCADE)
1210 1214
    desk = models.ForeignKey('Desk', null=True, on_delete=models.CASCADE)
1211 1215
    resources = models.ManyToManyField('Resource')
......
1256 1260
        )
1257 1261
        self.almost_full = bool(self.booked_places >= 0.9 * self.places)
1258 1262

  
1263
    def set_is_checked(self):
1264
        if not self.agenda.mark_event_checked_auto:
1265
            return
1266
        if self.checked:
1267
            return
1268
        booking_qs = self.booking_set.filter(
1269
            cancellation_datetime__isnull=True,
1270
            in_waiting_list=False,
1271
            user_was_present__isnull=True,
1272
        )
1273
        if booking_qs.exists():
1274
            return
1275
        self.checked = True
1276
        self.save(update_fields=['checked'])
1277

  
1259 1278
    def in_bookable_period(self):
1260 1279
        if self.publication_date and localtime(now()).date() < self.publication_date:
1261 1280
            return False
......
1686 1705
            self.secondary_booking_set.update(in_waiting_list=True)
1687 1706
            self.save()
1688 1707

  
1708
    def mark_user_absence(self, reason=None):
1709
        self.user_absence_reason = reason
1710
        self.user_was_present = False
1711
        self.save()
1712
        self.event.set_is_checked()
1713

  
1714
    def mark_user_presence(self):
1715
        self.user_absence_reason = ''
1716
        self.user_was_present = True
1717
        self.save()
1718
        self.event.set_is_checked()
1719

  
1689 1720
    def get_user_block(self):
1690 1721
        template_vars = Context(settings.TEMPLATE_VARS)
1691 1722
        template_vars.update(
chrono/api/views.py
1523 1523
        serializer.save()
1524 1524
        if 'user_was_present' in request.data:
1525 1525
            self.booking.secondary_booking_set.update(user_was_present=self.booking.user_was_present)
1526
            self.booking.event.set_is_checked()
1526 1527
        if 'user_absence_reason' in request.data:
1527 1528
            self.booking.secondary_booking_set.update(user_absence_reason=self.booking.user_absence_reason)
1528 1529
        if 'extra_data' in request.data:
chrono/manager/forms.py
784 784
class AgendaBookingCheckSettingsForm(forms.ModelForm):
785 785
    class Meta:
786 786
        model = Agenda
787
        fields = ['absence_reasons_group', 'booking_check_filters', 'booking_user_block_template']
787
        fields = [
788
            'absence_reasons_group',
789
            'booking_check_filters',
790
            'booking_user_block_template',
791
            'mark_event_checked_auto',
792
        ]
788 793
        widgets = {'booking_user_block_template': forms.Textarea(attrs={'rows': 3})}
789 794

  
790 795
    def __init__(self, *args, **kwargs):
chrono/manager/templates/chrono/manager_agenda_event_fragment.html
11 11
    ><a href="{% if view_mode == 'settings_view' %}{% url 'chrono-manager-event-edit' pk=agenda.pk event_pk=event.pk %}?next=settings{% elif event.pk %}{% url 'chrono-manager-event-view' pk=agenda.pk event_pk=event.pk %}{% else %}{% url 'chrono-manager-event-create-recurrence' pk=agenda.pk event_identifier=event.slug %}{% endif %}">
12 12
    {% if event.cancellation_status %}
13 13
    <span class="tag">{{ event.cancellation_status }}</span>
14
    {% elif event.main_list_full %}
15
    <span class="full tag">{% trans "Full" %}</span>
14
    {% else %}
15
      {% if event.main_list_full %}
16
      <span class="full tag">{% trans "Full" %}</span>
17
      {% endif %}
18
      {% if event.checked %}
19
      <span class="checked tag">{% trans "Checked" %}</span>
20
      {% endif %}
16 21
    {% endif %}
17 22
    <span class="event-info">
18 23
    {% if view_mode == 'settings_view' %}
chrono/manager/templates/chrono/manager_event_check.html
27 27
    </form>
28 28
    <table class="main check-bookings">
29 29
      <tbody>
30
      {% if booked and not event.checked %}
31
        <tr class="booking all-bookings">
32
          <td class="booking-actions">
33
            <form method="post" action="{% url 'chrono-manager-event-checked' pk=agenda.pk event_pk=object.pk %}">
34
              {% csrf_token %}
35
              <button class="submit-button">{% trans "Mark the event as checked" %}</button>
36
            </form>
37
          </td>
38
        </tr>
39
      {% endif %}
30 40
      {% if booked_without_status %}
31 41
        <tr class="booking all-bookings">
32 42
          <td colspan="2"><b>{% trans "Mark all bookings without status:" %}</b></td>
chrono/manager/templates/chrono/manager_events_agenda_settings.html
61 61
        {% endif %}
62 62
    {% endwith %}
63 63

  
64
    <p>{% trans "User block template" %}:</p>
64
    <p>{% trans "User block template:" %}</p>
65 65
    <pre>{{ agenda.get_booking_user_block_template }}</pre>
66

  
67
    <p>{% trans "Automatically mark events when they are checked:" %} {{ agenda.mark_event_checked_auto|yesno }}</p>
66 68
</div>
67 69
</div>
68 70

  
chrono/manager/urls.py
221 221
        views.event_absence,
222 222
        name='chrono-manager-event-absence',
223 223
    ),
224
    url(
225
        r'^agendas/(?P<pk>\d+)/events/(?P<event_pk>\d+)/checked$',
226
        views.event_checked,
227
        name='chrono-manager-event-checked',
228
    ),
224 229
    url(
225 230
        r'^agendas/(?P<pk>\d+)/event_cancellation_report/(?P<report_pk>\d+)/$',
226 231
        views.event_cancellation_report,
chrono/manager/views.py
2024 2024
    def post(self, request, *args, **kwargs):
2025 2025
        bookings = self.get_bookings()
2026 2026
        bookings.update(user_absence_reason='', user_was_present=True)
2027
        self.event.set_is_checked()
2027 2028
        return self.response(request)
2028 2029

  
2029 2030

  
......
2045 2046
            qs_kwargs['user_absence_reason'] = form.cleaned_data['reason']
2046 2047
        bookings = self.get_bookings()
2047 2048
        bookings.update(user_was_present=False, **qs_kwargs)
2049
        self.event.set_is_checked()
2048 2050
        return self.response(request)
2049 2051

  
2050 2052

  
2051 2053
event_absence = EventAbsenceView.as_view()
2052 2054

  
2053 2055

  
2056
class EventCheckedView(EventCheckMixin, ViewableAgendaMixin, View):
2057
    def post(self, request, *args, **kwargs):
2058
        if not self.event.checked:
2059
            self.event.checked = True
2060
            self.event.save(update_fields=['checked'])
2061
        return self.response(request)
2062

  
2063

  
2064
event_checked = EventCheckedView.as_view()
2065

  
2066

  
2054 2067
class AgendaAddResourceView(ManagedAgendaMixin, FormView):
2055 2068
    template_name = 'chrono/manager_agenda_resource_form.html'
2056 2069
    form_class = AgendaResourceForm
......
2750 2763
class BookingPresenceView(ViewableAgendaMixin, BookingCheckMixin, View):
2751 2764
    def post(self, request, *args, **kwargs):
2752 2765
        booking = self.get_booking(**kwargs)
2753
        booking.user_absence_reason = ''
2754
        booking.user_was_present = True
2755
        booking.save()
2766
        booking.mark_user_presence()
2756 2767
        return self.response(request, booking)
2757 2768

  
2758 2769

  
......
2770 2781
    def post(self, request, *args, **kwargs):
2771 2782
        booking = self.get_booking(**kwargs)
2772 2783
        form = self.get_form()
2784
        reason = None
2773 2785
        if form.is_valid():
2774
            booking.user_absence_reason = form.cleaned_data['reason']
2775
        booking.user_was_present = False
2776
        booking.save()
2786
            reason = form.cleaned_data['reason']
2787
        booking.mark_user_absence(reason=reason)
2777 2788
        return self.response(request, booking)
2778 2789

  
2779 2790

  
tests/manager/test_all.py
562 562
    assert agenda.booking_check_filters == 'foo,bar,baz'
563 563
    assert agenda.get_booking_check_filters() == ['foo', 'bar', 'baz']
564 564

  
565
    # check auto checked
566
    assert agenda.mark_event_checked_auto is False
567
    resp = app.get(url)
568
    resp.form['mark_event_checked_auto'] = True
569
    resp = resp.form.submit()
570
    agenda.refresh_from_db()
571
    assert agenda.mark_event_checked_auto is True
572

  
565 573
    # check kind
566 574
    agenda.kind = 'meetings'
567 575
    agenda.save()
tests/manager/test_event.py
1178 1178
    event.cancellation_datetime = None
1179 1179

  
1180 1180

  
1181
def test_event_checked(app, admin_user):
1182
    agenda = Agenda.objects.create(label='Events', kind='events', booking_check_filters='foo,bar')
1183
    event = Event.objects.create(
1184
        label='xyz',
1185
        start_datetime=now() - datetime.timedelta(days=1),
1186
        places=10,
1187
        agenda=agenda,
1188
    )
1189
    login(app)
1190

  
1191
    resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
1192
    assert 'Mark the event as checked' not in resp
1193

  
1194
    Booking.objects.create(event=event, user_first_name='User')
1195
    resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
1196
    assert 'Mark the event as checked' in resp
1197
    assert event.checked is False
1198
    resp = app.get('/manage/agendas/%s/settings' % agenda.id)
1199
    assert 'checked tag' not in resp
1200

  
1201
    token = resp.context['csrf_token']
1202
    resp = app.post(
1203
        '/manage/agendas/%s/events/%s/checked' % (agenda.pk, event.pk),
1204
        params={'csrfmiddlewaretoken': token},
1205
    )
1206
    assert resp.location.endswith('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
1207
    event.refresh_from_db()
1208
    assert event.checked is True
1209
    resp = resp.follow()
1210
    assert 'Mark the event as checked' not in resp
1211
    resp = app.get('/manage/agendas/%s/settings' % agenda.id)
1212
    assert 'checked tag' in resp
1213

  
1214

  
1181 1215
def test_event_check_filters(app, admin_user):
1182 1216
    agenda = Agenda.objects.create(label='Events', kind='events', booking_check_filters='foo,bar')
1183 1217
    event = Event.objects.create(
......
1274 1308
        agenda=agenda,
1275 1309
    )
1276 1310
    booking = Booking.objects.create(event=event, user_first_name='User', user_last_name='42')
1311
    assert agenda.mark_event_checked_auto is False
1277 1312

  
1278 1313
    login(app)
1279 1314
    resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
......
1294 1329
    booking.refresh_from_db()
1295 1330
    assert booking.user_was_present is True
1296 1331
    assert booking.user_absence_reason == ''
1332
    event.refresh_from_db()
1333
    assert event.checked is False
1334

  
1335
    agenda.mark_event_checked_auto = True
1336
    agenda.save()
1297 1337

  
1298 1338
    # set as absent without reason
1299 1339
    resp = app.post(
......
1306 1346
    booking.refresh_from_db()
1307 1347
    assert booking.user_was_present is False
1308 1348
    assert booking.user_absence_reason == ''
1349
    event.refresh_from_db()
1350
    assert event.checked is True
1309 1351

  
1310 1352
    agenda.absence_reasons_group = group
1311 1353
    agenda.save()
......
1388 1430
        agenda=agenda,
1389 1431
    )
1390 1432
    booking1 = Booking.objects.create(event=event, user_first_name='User', user_last_name='42')
1433
    assert agenda.mark_event_checked_auto is False
1391 1434

  
1392 1435
    login(app)
1393 1436
    resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
......
1402 1445
    booking1.refresh_from_db()
1403 1446
    assert booking1.user_was_present is False
1404 1447
    assert booking1.user_absence_reason == ''
1448
    event.refresh_from_db()
1449
    assert event.checked is False
1450

  
1451
    agenda.mark_event_checked_auto = True
1452
    agenda.save()
1405 1453

  
1406 1454
    resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
1407 1455
    assert 'Mark all bookings without status' not in resp
......
1423 1471
    booking2.refresh_from_db()
1424 1472
    assert booking2.user_was_present is True
1425 1473
    assert booking2.user_absence_reason == ''
1474
    event.refresh_from_db()
1475
    assert event.checked is True
1426 1476

  
1427 1477
    booking3 = Booking.objects.create(event=event, user_first_name='User', user_last_name='51')
1428 1478
    app.post(
tests/test_api.py
2646 2646
    agenda = Agenda.objects.create(kind='events')
2647 2647
    event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
2648 2648
    booking = Booking.objects.create(event=event)
2649
    assert agenda.mark_event_checked_auto is False
2649 2650

  
2650 2651
    app.authorization = ('Basic', ('john.doe', 'password'))
2651 2652

  
......
2653 2654
    app.patch_json('/api/booking/%s/' % booking.pk, params={'user_was_present': flag})
2654 2655
    booking.refresh_from_db()
2655 2656
    assert booking.user_was_present == flag
2657
    event.refresh_from_db()
2658
    assert event.checked is False
2659

  
2660
    agenda.mark_event_checked_auto = True
2661
    agenda.save()
2662
    app.patch_json('/api/booking/%s/' % booking.pk, params={'user_was_present': flag})
2663
    booking.refresh_from_db()
2664
    assert booking.user_was_present == flag
2665
    event.refresh_from_db()
2666
    assert event.checked == (flag is not None)
2656 2667

  
2657 2668
    # reset
2658 2669
    app.patch_json('/api/booking/%s/' % booking.pk, params={'user_was_present': None})
2659
-