diff --git a/chrono/agendas/models.py b/chrono/agendas/models.py index 727696e4..f682a486 100644 --- a/chrono/agendas/models.py +++ b/chrono/agendas/models.py @@ -1340,9 +1340,11 @@ class Event(models.Model): return None return rrule - def has_recurrences_booked(self): + def has_recurrences_booked(self, after=None): return Booking.objects.filter( - event__primary_event=self, event__start_datetime__gt=now(), cancellation_datetime__isnull=True + event__primary_event=self, + event__start_datetime__gt=after or now(), + cancellation_datetime__isnull=True, ).exists() def create_all_recurrences(self, excluded_datetimes=None): diff --git a/chrono/manager/forms.py b/chrono/manager/forms.py index 2772911e..65ca93b9 100644 --- a/chrono/manager/forms.py +++ b/chrono/manager/forms.py @@ -212,6 +212,13 @@ class EventForm(forms.ModelForm): 'This field cannot be modified because some recurrences have bookings attached to them.' ) + def clean(self): + super().clean() + if 'recurrence_end_date' in self.changed_data and self.instance.has_recurrences_booked( + after=self.cleaned_data['recurrence_end_date'] + ): + raise ValidationError(_('Bookings exist after this date.')) + def save(self, *args, **kwargs): with transaction.atomic(): if any(field for field in self.changed_data if field in self.protected_fields): diff --git a/tests/test_manager.py b/tests/test_manager.py index d029842a..b7a4a92e 100644 --- a/tests/test_manager.py +++ b/tests/test_manager.py @@ -1547,6 +1547,9 @@ def test_edit_recurring_event_with_end_date(settings, app, admin_user, freezer): # old recurrences were deleted assert not Event.objects.filter(primary_event=event, start_datetime=now()).exists() + # editing recurrence_end_date is permitted as long as bookings are not impacted + event_recurrence = Event.objects.get(primary_event=event, start_datetime__day=15) + Booking.objects.create(event=event_recurrence) resp = app.get('/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id)) resp.form['recurrence_end_date'] = (localtime() + datetime.timedelta(days=6)).strftime('%Y-%m-%d') resp = resp.form.submit() @@ -1557,6 +1560,12 @@ def test_edit_recurring_event_with_end_date(settings, app, admin_user, freezer): resp = resp.form.submit() assert Event.objects.filter(primary_event=event).count() == 4 + resp = app.get('/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id)) + resp.form['recurrence_end_date'] = (localtime() + datetime.timedelta(days=2)).strftime('%Y-%m-%d') + resp = resp.form.submit() + assert Event.objects.filter(primary_event=event).count() == 4 + assert 'Bookings exist after this date' in resp.text + def test_booked_places(app, admin_user): agenda = Agenda(label=u'Foo bar')