From e8e96fc4a6b3f48d1e2c66c7867287a56b701141 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Thu, 21 Jan 2021 10:47:59 +0100
Subject: [PATCH] manager: it is not possible to cancel secondary booking
 (#50116)

---
 .../chrono/manager_event_detail_fragment.html |  9 +++++++--
 chrono/manager/views.py                       |  6 +++++-
 tests/test_manager.py                         | 20 +++++++++++++++++++
 3 files changed, 32 insertions(+), 3 deletions(-)

diff --git a/chrono/manager/templates/chrono/manager_event_detail_fragment.html b/chrono/manager/templates/chrono/manager_event_detail_fragment.html
index f6ce4ba..d72e665 100644
--- a/chrono/manager/templates/chrono/manager_event_detail_fragment.html
+++ b/chrono/manager/templates/chrono/manager_event_detail_fragment.html
@@ -28,8 +28,13 @@
 
   <ul class="objects-list single-links">
     {% for booking in booked %}
-    <li><a {% if booking.backoffice_url %}href="{{ booking.backoffice_url }}"{% endif %}>{{ booking.events_display }}</a>
-    <a rel="popup" class="delete" href="{% url 'chrono-manager-booking-cancel' pk=agenda.id booking_pk=booking.id %}?next={{ request.path }}">{% trans "Cancel" %}</a>
+    <li>
+    <a {% if booking.backoffice_url %}href="{{ booking.backoffice_url }}"{% endif %}>{{ booking.events_display }}</a>
+    {% if not booking.primary_booking %}
+    <a rel="popup" class="delete {% if booking.primary_booking %}disabled{% endif %}" href="{% url 'chrono-manager-booking-cancel' pk=agenda.id booking_pk=booking.id %}?next={{ request.path }}">{% trans "Cancel" %}</a>
+    {% else %}
+    <a class="delete disabled" title="{% trans "Can not cancel a secondary booking" %}" href="#">{% trans "Cancel" %}</a>
+    {% endif %}
     </li>
     {% endfor %}
   </ul>
diff --git a/chrono/manager/views.py b/chrono/manager/views.py
index faade1c..36d1df8 100644
--- a/chrono/manager/views.py
+++ b/chrono/manager/views.py
@@ -2238,11 +2238,15 @@ class BookingCancelView(ViewableAgendaMixin, UpdateView):
         self.booking = self.get_object()
         return super().dispatch(request, *args, **kwargs)
 
+    def get_queryset(self):
+        queryset = super().get_queryset()
+        return queryset.filter(cancellation_datetime__isnull=True, primary_booking__isnull=True)
+
     def form_valid(self, form):
         trigger_callback = not form.cleaned_data['disable_trigger']
         try:
             self.booking.cancel(trigger_callback)
-        except requests.RequestException as e:
+        except requests.RequestException:
             form.add_error(None, _('There has been an error sending cancellation notification to form.'))
             form.add_error(None, _('Check this box if you are sure you want to proceed anyway.'))
             form.show_trigger_checkbox()
diff --git a/tests/test_manager.py b/tests/test_manager.py
index 31db5f9..1a943da 100644
--- a/tests/test_manager.py
+++ b/tests/test_manager.py
@@ -4546,6 +4546,9 @@ def test_booking_cancellation_meetings_agenda(app, admin_user, manager_user, api
     booking4 = Booking.objects.get(pk=booking_json4['booking_id'])
     assert booking4.cancellation_datetime
 
+    # again
+    app.get('/manage/agendas/%s/bookings/%s/cancel' % (agenda.pk, booking4.pk), status=404)
+
 
 def test_booking_cancellation_events_agenda(app, admin_user):
     agenda = Agenda.objects.create(label='Events', kind='events')
@@ -4567,6 +4570,23 @@ def test_booking_cancellation_events_agenda(app, admin_user):
     resp = resp.follow()
     assert 'Bookings (0/10)' in resp.text
 
+    # again
+    app.get('/manage/agendas/%s/bookings/%s/cancel' % (agenda.pk, booking.pk), status=404)
+
+    # test secondary booking
+    primary = Booking.objects.create(event=event)
+    secondary = Booking.objects.create(event=event, primary_booking=primary)
+    resp = app.get('/manage/agendas/%s/events/%s/' % (agenda.pk, event.pk))
+    assert 'Bookings (2/10)' in resp.text
+    assert '/manage/agendas/%s/bookings/%s/cancel' % (agenda.pk, primary.pk) in resp.text
+    assert '/manage/agendas/%s/bookings/%s/cancel' % (agenda.pk, secondary.pk) not in resp.text
+    app.get('/manage/agendas/%s/bookings/%s/cancel' % (agenda.pk, secondary.pk), status=404)
+    app.get('/manage/agendas/%s/bookings/%s/cancel' % (agenda.pk, primary.pk)).form.submit()
+    primary.refresh_from_db()
+    secondary.refresh_from_db()
+    assert primary.cancellation_datetime
+    assert secondary.cancellation_datetime
+
 
 def test_event_cancellation(app, admin_user):
     agenda = Agenda.objects.create(label='Events', kind='events')
-- 
2.29.2

