From 749979a1ea5d34d04db33c229a7280f083f7f245 Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Wed, 23 Mar 2022 14:22:53 +0100 Subject: [PATCH 2/2] agendas: allow exception sources in unavailability calendars (#52370) --- .../migrations/0112_auto_20220323_1320.py | 28 +++ chrono/agendas/models.py | 4 +- chrono/manager/forms.py | 19 +- ...ager_unavailability_calendar_settings.html | 1 + chrono/manager/urls.py | 5 + chrono/manager/views.py | 80 ++++++-- tests/manager/test_exception.py | 176 ++++++++++++++++++ 7 files changed, 290 insertions(+), 23 deletions(-) create mode 100644 chrono/agendas/migrations/0112_auto_20220323_1320.py diff --git a/chrono/agendas/migrations/0112_auto_20220323_1320.py b/chrono/agendas/migrations/0112_auto_20220323_1320.py new file mode 100644 index 00000000..f9e68c2f --- /dev/null +++ b/chrono/agendas/migrations/0112_auto_20220323_1320.py @@ -0,0 +1,28 @@ +# Generated by Django 2.2.19 on 2022-03-23 12:20 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('agendas', '0111_timeperiod_weekday_indexes'), + ] + + operations = [ + migrations.AddField( + model_name='timeperiodexceptionsource', + name='unavailability_calendar', + field=models.ForeignKey( + null=True, on_delete=django.db.models.deletion.CASCADE, to='agendas.UnavailabilityCalendar' + ), + ), + migrations.AlterField( + model_name='timeperiodexceptionsource', + name='desk', + field=models.ForeignKey( + null=True, on_delete=django.db.models.deletion.CASCADE, to='agendas.Desk' + ), + ), + ] diff --git a/chrono/agendas/models.py b/chrono/agendas/models.py index 759d6dc0..e1c91855 100644 --- a/chrono/agendas/models.py +++ b/chrono/agendas/models.py @@ -2421,7 +2421,8 @@ def ics_directory_path(instance, filename): class TimePeriodExceptionSource(models.Model): - desk = models.ForeignKey(Desk, on_delete=models.CASCADE) + desk = models.ForeignKey(Desk, on_delete=models.CASCADE, null=True) + unavailability_calendar = models.ForeignKey('UnavailabilityCalendar', on_delete=models.CASCADE, null=True) ics_filename = models.CharField(null=True, max_length=256) ics_file = models.FileField(upload_to=ics_directory_path, blank=True, null=True) ics_url = models.URLField(null=True, max_length=500) @@ -2607,6 +2608,7 @@ class TimePeriodExceptionSource(models.Model): 'end_datetime': end_dt, 'label': summary, 'desk_id': self.desk_id, + 'unavailability_calendar_id': self.unavailability_calendar_id, 'source': self, 'recurrence_id': 0, } diff --git a/chrono/manager/forms.py b/chrono/manager/forms.py index f81b5a1c..77c79676 100644 --- a/chrono/manager/forms.py +++ b/chrono/manager/forms.py @@ -1104,6 +1104,14 @@ class ExceptionsImportForm(forms.ModelForm): required=False, help_text=_('URL to remote calendar which will be synchronised hourly.'), ) + + def clean(self, *args, **kwargs): + cleaned_data = super().clean(*args, **kwargs) + if not cleaned_data.get('ics_file') and not cleaned_data.get('ics_url'): + raise forms.ValidationError(_('Please provide an ICS File or an URL.')) + + +class DeskExceptionsImportForm(ExceptionsImportForm): all_desks = forms.BooleanField(label=_('Apply exceptions on all desks of the agenda'), required=False) class Meta: @@ -1117,10 +1125,11 @@ class ExceptionsImportForm(forms.ModelForm): elif self.instance.agenda.desk_simple_management: del self.fields['all_desks'] - def clean(self, *args, **kwargs): - cleaned_data = super().clean(*args, **kwargs) - if not cleaned_data.get('ics_file') and not cleaned_data.get('ics_url'): - raise forms.ValidationError(_('Please provide an ICS File or an URL.')) + +class UnavailabilityCalendarExceptionsImportForm(ExceptionsImportForm): + class Meta: + model = UnavailabilityCalendar + fields = [] class TimePeriodExceptionSourceReplaceForm(forms.ModelForm): @@ -1145,7 +1154,7 @@ class TimePeriodExceptionSourceReplaceForm(forms.ModelForm): old_filename = self.instance.ics_filename store_source(self.instance) - if self.instance.desk.agenda.desk_simple_management: + if self.instance.desk and self.instance.desk.agenda.desk_simple_management: for desk in self.instance.desk.agenda.desk_set.exclude(pk=self.instance.desk_id): source = desk.timeperiodexceptionsource_set.filter(ics_filename=old_filename).first() if source is not None: diff --git a/chrono/manager/templates/chrono/manager_unavailability_calendar_settings.html b/chrono/manager/templates/chrono/manager_unavailability_calendar_settings.html index 0692c9f1..cd2d8f21 100644 --- a/chrono/manager/templates/chrono/manager_unavailability_calendar_settings.html +++ b/chrono/manager/templates/chrono/manager_unavailability_calendar_settings.html @@ -12,6 +12,7 @@ {% block agenda-extra-management-actions %} + {% trans 'Manage unavailabilities from ICS' %} {% trans 'Add Unavailability' %} {% endblock %}