From 37dd89c6450ff71d3e32d5e629c4c8339f31d7c0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Fri, 11 Jun 2021 14:36:33 +0200
Subject: [PATCH 2/2] api: endpoint to check an event (#53932)

---
 chrono/api/urls.py      |  5 ++++
 chrono/api/views.py     | 35 ++++++++++++++++++++++++-
 tests/api/test_event.py | 57 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 96 insertions(+), 1 deletion(-)

diff --git a/chrono/api/urls.py b/chrono/api/urls.py
index ef15bd1..d55895d 100644
--- a/chrono/api/urls.py
+++ b/chrono/api/urls.py
@@ -38,6 +38,11 @@ urlpatterns = [
         views.slot_bookings,
         name='api-event-bookings',
     ),
+    url(
+        r'^agenda/(?P<agenda_identifier>[\w-]+)/check/(?P<event_identifier>[\w:-]+)/$',
+        views.slot_check,
+        name='api-event-check',
+    ),
     url(
         r'^agenda/meetings/(?P<meeting_identifier>[\w-]+)/datetimes/$',
         views.meeting_datetimes,
diff --git a/chrono/api/views.py b/chrono/api/views.py
index cb4d705..77ac38a 100644
--- a/chrono/api/views.py
+++ b/chrono/api/views.py
@@ -451,7 +451,7 @@ def get_event_detail(request, event, agenda=None, min_places=1):
             event.label,
             date_format(localtime(event.start_datetime), 'DATETIME_FORMAT'),
         )
-    return {
+    details = {
         'id': event.slug,
         'slug': event.slug,  # kept for compatibility
         'text': event_text,
@@ -479,9 +479,16 @@ def get_event_detail(request, event, agenda=None, min_places=1):
                     kwargs={'agenda_identifier': agenda.slug, 'event_identifier': event.slug},
                 )
             ),
+            'check_url': request.build_absolute_uri(
+                reverse(
+                    'api-event-check',
+                    kwargs={'agenda_identifier': agenda.slug, 'event_identifier': event.slug},
+                )
+            ),
         },
         'places': get_event_places(event),
     }
+    return details
 
 
 def get_events_meta_detail(request, events, agenda=None, min_places=1):
@@ -1965,6 +1972,32 @@ class SlotStatus(APIView):
 slot_status = SlotStatus.as_view()
 
 
+class SlotCheck(APIView):
+    permission_classes = (permissions.IsAuthenticated,)
+
+    def get_object(self, agenda_identifier, event_identifier):
+        agenda = get_object_or_404(Agenda, slug=agenda_identifier, kind='events')
+        if ':' in event_identifier:
+            return get_event_recurrence(agenda, event_identifier)
+        try:
+            return agenda.event_set.get(slug=event_identifier)
+        except Event.DoesNotExist:
+            raise Http404()
+
+    def post(self, request, agenda_identifier=None, event_identifier=None, format=None):
+        event = self.get_object(agenda_identifier, event_identifier)
+        if not event.checked:
+            event.checked = True
+            event.save(update_fields=['checked'])
+        response = {
+            'err': 0,
+        }
+        return Response(response)
+
+
+slot_check = SlotCheck.as_view()
+
+
 class SlotBookings(APIView):
     permission_classes = (permissions.IsAuthenticated,)
 
diff --git a/tests/api/test_event.py b/tests/api/test_event.py
index c88c38d..8cf77cd 100644
--- a/tests/api/test_event.py
+++ b/tests/api/test_event.py
@@ -50,6 +50,7 @@ def test_status(app, user):
             'bookings_url': 'http://testserver/api/agenda/foo-bar/bookings/event-slug/',
             'fillslot_url': 'http://testserver/api/agenda/foo-bar/fillslot/event-slug/',
             'status_url': 'http://testserver/api/agenda/foo-bar/status/event-slug/',
+            'check_url': 'http://testserver/api/agenda/foo-bar/check/event-slug/',
         },
         'places': {'available': 9, 'reserved': 1, 'total': 10, 'full': False, 'has_waiting_list': False},
     }
@@ -71,6 +72,7 @@ def test_status(app, user):
         app.get('/api/agenda/%s/status/%s/' % (agenda.slug, event.slug), status=404)
 
 
+@pytest.mark.freeze_time('2021-02-23')
 def test_status_url(app, user):
     agenda = Agenda.objects.create(label='Foo bar', kind='events', minimal_booking_delay=0)
     event = Event.objects.create(
@@ -98,3 +100,58 @@ def test_status_url(app, user):
     app.get('/api/agenda/%s/status/%s/' % (0, event.slug), status=404)
     app.get('/api/agenda/%s/status/%s/' % ('foobar', event.pk), status=404)
     app.get('/api/agenda/%s/status/%s/' % ('foobar', event.slug), status=404)
+
+    # recurring event
+    event = Event.objects.create(
+        slug='recurrent',
+        start_datetime=localtime().replace(hour=12, minute=0),
+        repeat='weekly',
+        places=2,
+        agenda=agenda,
+    )
+    app.get('/api/agenda/%s/status/%s/' % (agenda.slug, 'recurrent--2021-02-23-1200'), status=404)
+    app.get('/api/agenda/%s/status/%s/' % (agenda.slug, 'recurrent:2021-02-23-1200'), status=200)
+    app.get('/api/agenda/%s/status/%s/' % (agenda.slug, 'recurrent--2021-02-23-1200'), status=200)
+
+
+@pytest.mark.freeze_time('2021-02-23')
+def test_event_checked(app, user):
+    agenda = Agenda.objects.create(label='Events', kind='events')
+    event = Event.objects.create(
+        label='xyz',
+        start_datetime=now() - datetime.timedelta(days=1),
+        places=10,
+        agenda=agenda,
+    )
+    assert event.checked is False
+
+    app.authorization = ('Basic', ('john.doe', 'password'))
+
+    app.post('/api/agenda/%s/check/%s/' % (agenda.slug, event.slug))
+    event.refresh_from_db()
+    assert event.checked is True
+
+    # already checked
+    app.post('/api/agenda/%s/check/%s/' % (agenda.slug, event.slug))
+    event.refresh_from_db()
+    assert event.checked is True
+
+    # recurring event
+    event = Event.objects.create(
+        slug='recurrent',
+        start_datetime=localtime().replace(hour=12, minute=0),
+        repeat='weekly',
+        places=2,
+        agenda=agenda,
+    )
+    app.post('/api/agenda/%s/check/%s/' % (agenda.slug, 'recurrent--2021-02-23-1200'), status=404)
+    app.post('/api/agenda/%s/check/%s/' % (agenda.slug, 'recurrent:2021-02-23-1200'), status=200)
+    app.post('/api/agenda/%s/check/%s/' % (agenda.slug, 'recurrent--2021-02-23-1200'), status=200)
+
+    # wrong kind
+    agenda.kind = 'meetings'
+    agenda.save()
+    app.post('/api/agenda/%s/check/%s/' % (agenda.slug, event.slug), status=404)
+    agenda.kind = 'virtual'
+    agenda.save()
+    app.post('/api/agenda/%s/check/%s/' % (agenda.slug, event.slug), status=404)
-- 
2.30.2

