From d0f516064099473a08b6922c4c63c1ac3bd102e7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Fri, 29 Oct 2021 09:10:19 +0200
Subject: [PATCH 2/3] api: bypass_delays parameter for datetimes endpoints
 (#57961)

---
 chrono/agendas/models.py    |  5 +++--
 chrono/api/serializers.py   |  1 +
 chrono/api/views.py         |  2 ++
 tests/api/test_datetimes.py | 31 +++++++++++++++++++++++++++++++
 4 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/chrono/agendas/models.py b/chrono/agendas/models.py
index dc27c56..3811cc4 100644
--- a/chrono/agendas/models.py
+++ b/chrono/agendas/models.py
@@ -650,6 +650,7 @@ class Agenda(models.Model):
         min_start=None,
         max_start=None,
         user_external_id=None,
+        bypass_delays=False,
     ):
         assert self.kind == 'events'
 
@@ -671,7 +672,7 @@ class Agenda(models.Model):
             if not include_full:
                 entries = entries.filter(Q(full=False) | Q(primary_event__isnull=False))
 
-        if self.minimal_booking_delay:
+        if not bypass_delays and self.minimal_booking_delay:
             min_start = max(self.min_booking_datetime, min_start) if min_start else self.min_booking_datetime
 
         if min_start:
@@ -680,7 +681,7 @@ class Agenda(models.Model):
             else:
                 entries = entries.filter(start_datetime__gte=min_start)
 
-        if self.maximal_booking_delay:
+        if not bypass_delays and self.maximal_booking_delay:
             max_start = min(self.max_booking_datetime, max_start) if max_start else self.max_booking_datetime
 
         if max_start:
diff --git a/chrono/api/serializers.py b/chrono/api/serializers.py
index c378313..72ebe4f 100644
--- a/chrono/api/serializers.py
+++ b/chrono/api/serializers.py
@@ -116,6 +116,7 @@ class DatetimesSerializer(DateRangeSerializer):
     exclude_user_external_id = serializers.CharField(required=False, max_length=250, allow_blank=True)
     events = serializers.CharField(required=False, max_length=32, allow_blank=True)
     hide_disabled = serializers.BooleanField(default=False)
+    bypass_delays = serializers.BooleanField(default=False)
 
     def validate(self, attrs):
         super().validate(attrs)
diff --git a/chrono/api/views.py b/chrono/api/views.py
index f81ad09..bbc9f2f 100644
--- a/chrono/api/views.py
+++ b/chrono/api/views.py
@@ -815,6 +815,7 @@ class Datetimes(APIView):
                 min_start=payload.get('date_start'),
                 max_start=payload.get('date_end'),
                 user_external_id=user_external_id,
+                bypass_delays=payload.get('bypass_delays'),
             )
 
         if payload['hide_disabled']:
@@ -897,6 +898,7 @@ class MultipleAgendasDatetimes(APIView):
                     prefetched_queryset=True,
                     min_start=payload.get('date_start'),
                     max_start=payload.get('date_end'),
+                    bypass_delays=payload.get('bypass_delays'),
                 )
             )
 
diff --git a/tests/api/test_datetimes.py b/tests/api/test_datetimes.py
index 6a2cc22..d43c468 100644
--- a/tests/api/test_datetimes.py
+++ b/tests/api/test_datetimes.py
@@ -35,12 +35,16 @@ def test_datetimes_api(app, some_data):
     resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
     assert len(resp.json['data']) == 0
     check_bookability(resp.json['data'])
+    resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug, params={'bypass_delays': True})
+    assert len(resp.json['data']) == 3
 
     agenda.minimal_booking_delay = 2
     agenda.save()
     resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
     assert len(resp.json['data']) == 2
     check_bookability(resp.json['data'])
+    resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug, params={'bypass_delays': True})
+    assert len(resp.json['data']) == 3
 
     agenda.minimal_booking_delay = 0
     agenda.maximal_booking_delay = 3
@@ -49,6 +53,8 @@ def test_datetimes_api(app, some_data):
     assert len(resp.json['data']) == 2
     check_bookability(resp.json['data'])
     assert resp.json['data'][0]['description'] is None
+    resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug, params={'bypass_delays': True})
+    assert len(resp.json['data']) == 3
 
     agenda.event_set.update(publication_datetime=now() + datetime.timedelta(minutes=1))
     resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
@@ -685,6 +691,19 @@ def test_recurring_events_api(app, user, freezer):
         app.get('/api/agenda/%s/datetimes/' % agenda.slug)
         assert len(ctx.captured_queries) == 5
 
+    # check delays
+    resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
+    assert len(resp.json['data']) == 4
+    resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug, params={'bypass_delays': True})
+    assert len(resp.json['data']) == 53
+    agenda.minimal_booking_delay = 10
+    agenda.mmaximal_booking_delay = 20
+    agenda.save()
+    resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
+    assert len(resp.json['data']) == 3
+    resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug, params={'bypass_delays': True})
+    assert len(resp.json['data']) == 53
+
 
 def test_recurring_events_api_various_times(app, user, mock_now):
     agenda = Agenda.objects.create(
@@ -1474,6 +1493,18 @@ def test_datetimes_multiple_agendas(app):
     )
     assert len(resp.json['data']) == 0
 
+    # check delays
+    Agenda.objects.update(minimal_booking_delay=6, maximal_booking_delay=14)
+    date_end = localtime() + datetime.timedelta(days=60)  # with a date end to have recurring events
+    resp = app.get('/api/agendas/datetimes/', params={'agendas': agenda_slugs, 'date_end': date_end})
+    assert len(resp.json['data']) == 2
+    resp = app.get(
+        '/api/agendas/datetimes/',
+        params={'agendas': agenda_slugs, 'date_end': date_end, 'bypass_delays': True},
+    )
+    assert len(resp.json['data']) == 5
+    Agenda.objects.update(minimal_booking_delay=0, maximal_booking_delay=45)
+
     # invalid slugs
     resp = app.get('/api/agendas/datetimes/', params={'agendas': 'xxx'}, status=400)
     assert resp.json['err_desc'] == 'invalid slugs: xxx'
-- 
2.33.0

