diff --git a/chrono/agendas/migrations/0131_sharedcustodysettings.py b/chrono/agendas/migrations/0131_sharedcustodysettings.py
new file mode 100644
index 00000000..0ae519d8
--- /dev/null
+++ b/chrono/agendas/migrations/0131_sharedcustodysettings.py
@@ -0,0 +1,36 @@
+# Generated by Django 2.2.26 on 2022-06-27 16:02
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('auth', '0011_update_proxy_permissions'),
+ ('agendas', '0130_event_date_range_constraint'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='SharedCustodySettings',
+ fields=[
+ (
+ 'id',
+ models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+ ),
+ (
+ 'management_role',
+ models.ForeignKey(
+ blank=True,
+ default=None,
+ null=True,
+ on_delete=django.db.models.deletion.SET_NULL,
+ related_name='+',
+ to='auth.Group',
+ verbose_name='Management role',
+ ),
+ ),
+ ],
+ ),
+ ]
diff --git a/chrono/agendas/models.py b/chrono/agendas/models.py
index 424931ec..73b2501a 100644
--- a/chrono/agendas/models.py
+++ b/chrono/agendas/models.py
@@ -3487,3 +3487,22 @@ class SharedCustodyPeriod(models.Model):
date_format(self.date_end, 'SHORT_DATE_FORMAT'),
)
return '%s, %s' % (self.guardian, exc_repr)
+
+
+class SharedCustodySettings(models.Model):
+ management_role = models.ForeignKey(
+ Group,
+ blank=True,
+ null=True,
+ default=None,
+ related_name='+',
+ verbose_name=_('Management role'),
+ on_delete=models.SET_NULL,
+ )
+
+ @classmethod
+ def get_singleton(cls):
+ try:
+ return cls.objects.get()
+ except cls.DoesNotExist:
+ return cls()
diff --git a/chrono/manager/forms.py b/chrono/manager/forms.py
index dfb7e6a9..21410f5a 100644
--- a/chrono/manager/forms.py
+++ b/chrono/manager/forms.py
@@ -57,6 +57,7 @@ from chrono.agendas.models import (
SharedCustodyHolidayRule,
SharedCustodyPeriod,
SharedCustodyRule,
+ SharedCustodySettings,
Subscription,
TimePeriod,
TimePeriodException,
@@ -1550,3 +1551,13 @@ class SharedCustodyPeriodForm(forms.ModelForm):
self.add_error('date_end', _('End date must be greater than start date.'))
return cleaned_data
+
+
+class SharedCustodySettingsForm(forms.ModelForm):
+ management_role = forms.ModelChoiceField(
+ label=_('Management role'), required=False, queryset=Group.objects.all().order_by('name')
+ )
+
+ class Meta:
+ model = SharedCustodySettings
+ fields = '__all__'
diff --git a/chrono/manager/templates/chrono/manager_home.html b/chrono/manager/templates/chrono/manager_home.html
index 78ea9796..5d356746 100644
--- a/chrono/manager/templates/chrono/manager_home.html
+++ b/chrono/manager/templates/chrono/manager_home.html
@@ -12,6 +12,9 @@
{% trans 'Export' %}
{% trans 'Events types' %}
{% trans 'Check types' %}
+ {% if shared_custody_enabled %}
+ {% trans 'Shared custody' %}
+ {% endif %}
{% endif %}
{% if has_access_to_unavailability_calendars %}
{% trans 'Unavailability calendars' %}
diff --git a/chrono/manager/urls.py b/chrono/manager/urls.py
index 8e999ea5..49634127 100644
--- a/chrono/manager/urls.py
+++ b/chrono/manager/urls.py
@@ -400,6 +400,11 @@ urlpatterns = [
views.agenda_import_events_sample_csv,
name='chrono-manager-sample-events-csv',
),
+ url(
+ r'^shared-custody/settings/$',
+ views.shared_custody_settings,
+ name='chrono-manager-shared-custody-settings',
+ ),
url(
r'^shared-custody/(?P\d+)/$',
views.shared_custody_agenda_view,
diff --git a/chrono/manager/views.py b/chrono/manager/views.py
index 282abd49..0f4ad4fc 100644
--- a/chrono/manager/views.py
+++ b/chrono/manager/views.py
@@ -26,6 +26,7 @@ from operator import attrgetter
import requests
from dateutil.relativedelta import MO, relativedelta
+from django.conf import settings
from django.contrib import messages
from django.core.exceptions import PermissionDenied
from django.db import IntegrityError, transaction
@@ -80,6 +81,7 @@ from chrono.agendas.models import (
SharedCustodyHolidayRule,
SharedCustodyPeriod,
SharedCustodyRule,
+ SharedCustodySettings,
TimePeriod,
TimePeriodException,
TimePeriodExceptionSource,
@@ -122,6 +124,7 @@ from .forms import (
SharedCustodyHolidayRuleForm,
SharedCustodyPeriodForm,
SharedCustodyRuleForm,
+ SharedCustodySettingsForm,
SubscriptionCheckFilterSet,
TimePeriodAddForm,
TimePeriodExceptionForm,
@@ -163,6 +166,7 @@ class HomepageView(ListView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['has_access_to_unavailability_calendars'] = self.has_access_to_unavailability_calendars()
+ context['shared_custody_enabled'] = settings.SHARED_CUSTODY_ENABLED
return context
def get(self, request, *args, **kwargs):
@@ -3685,7 +3689,10 @@ class SharedCustodyAgendaMixin:
return super().dispatch(request, *args, **kwargs)
def check_permissions(self, user):
- return user.is_staff
+ if user.is_staff:
+ return True
+ management_role = SharedCustodySettings.get_singleton().management_role
+ return bool(management_role in user.groups.all())
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
@@ -3863,6 +3870,25 @@ class SharedCustodyAgendaDeletePeriodView(SharedCustodyAgendaMixin, DeleteView):
shared_custody_agenda_delete_period = SharedCustodyAgendaDeletePeriodView.as_view()
+class SharedCustodySettingsView(UpdateView):
+ title = _('Shared custody settings')
+ template_name = 'chrono/manager_agenda_form.html'
+ form_class = SharedCustodySettingsForm
+ model = SharedCustodySettings
+ success_url = reverse_lazy('chrono-manager-homepage')
+
+ def dispatch(self, request, *args, **kwargs):
+ if not request.user.is_staff:
+ raise PermissionDenied()
+ return super().dispatch(request, *args, **kwargs)
+
+ def get_object(self):
+ return SharedCustodySettings.get_singleton()
+
+
+shared_custody_settings = SharedCustodySettingsView.as_view()
+
+
def menu_json(request):
if not request.user.is_staff:
homepage_view = HomepageView(request=request)
diff --git a/chrono/settings.py b/chrono/settings.py
index 0ffd2406..2c118413 100644
--- a/chrono/settings.py
+++ b/chrono/settings.py
@@ -195,6 +195,8 @@ SMS_SENDER = ''
REST_FRAMEWORK = {'EXCEPTION_HANDLER': 'chrono.api.utils.exception_handler'}
+SHARED_CUSTODY_ENABLED = False
+
local_settings_file = os.environ.get(
'CHRONO_SETTINGS_FILE', os.path.join(os.path.dirname(__file__), 'local_settings.py')
)
diff --git a/tests/manager/test_shared_custody_agenda.py b/tests/manager/test_shared_custody_agenda.py
index b2ab2a54..97723cae 100644
--- a/tests/manager/test_shared_custody_agenda.py
+++ b/tests/manager/test_shared_custody_agenda.py
@@ -286,3 +286,35 @@ def test_shared_custody_agenda_holiday_rules(app, admin_user):
resp = app.get('/manage/shared-custody/%s/2022/12/' % agenda.pk)
assert 'John Doe (Vacances de Noël)' in resp.text
+
+
+def test_shared_custody_settings_feature_flag(app, admin_user, settings):
+ settings.SHARED_CUSTODY_ENABLED = False
+ app = login(app)
+ resp = app.get('/manage/')
+ assert 'Shared custody' not in resp.text
+
+ settings.SHARED_CUSTODY_ENABLED = True
+ resp = app.get('/manage/')
+ assert 'Shared custody' in resp.text
+
+
+def test_shared_custody_settings_management_role(app, admin_user, manager_user):
+ father = Person.objects.create(user_external_id='father_id', first_name='John', last_name='Doe')
+ mother = Person.objects.create(user_external_id='mother_id', first_name='Jane', last_name='Doe')
+ agenda = SharedCustodyAgenda.objects.create(first_guardian=father, second_guardian=mother)
+
+ app = login(app, username='manager', password='manager')
+ app.get('/manage/shared-custody/%s/settings/' % agenda.pk, status=403)
+
+ app.reset()
+ app = login(app)
+ resp = app.get('/manage/')
+ resp = resp.click('Shared custody')
+ resp.form['management_role'] = manager_user.groups.all()[0].pk
+ resp.form.submit()
+
+ app.reset()
+ app = login(app, username='manager', password='manager')
+ resp = app.get('/manage/shared-custody/%s/settings/' % agenda.pk)
+ assert 'Custody agenda of John Doe and Jane Doe' in resp.text
diff --git a/tests/settings.py b/tests/settings.py
index c7257967..52a56b75 100644
--- a/tests/settings.py
+++ b/tests/settings.py
@@ -34,3 +34,5 @@ LEGACY_URLS_MAPPING = {'old.org': 'new.org'}
EXCEPTIONS_SOURCES = {}
SITE_BASE_URL = 'https://example.com'
+
+SHARED_CUSTODY_ENABLED = True