Projet

Général

Profil

0001-agendas-add-management-role-for-shared-custody-66671.patch

Valentin Deniaud, 29 juin 2022 11:03

Télécharger (10,5 ko)

Voir les différences:

Subject: [PATCH 1/2] agendas: add management role for shared custody (#66671)

 .../migrations/0131_sharedcustodysettings.py  | 36 +++++++++++++++++++
 chrono/agendas/models.py                      | 19 ++++++++++
 chrono/manager/forms.py                       | 11 ++++++
 .../templates/chrono/manager_home.html        |  3 ++
 chrono/manager/urls.py                        |  5 +++
 chrono/manager/views.py                       | 28 ++++++++++++++-
 chrono/settings.py                            |  2 ++
 tests/manager/test_shared_custody_agenda.py   | 32 +++++++++++++++++
 tests/settings.py                             |  2 ++
 9 files changed, 137 insertions(+), 1 deletion(-)
 create mode 100644 chrono/agendas/migrations/0131_sharedcustodysettings.py
chrono/agendas/migrations/0131_sharedcustodysettings.py
1
# Generated by Django 2.2.26 on 2022-06-27 16:02
2

  
3
import django.db.models.deletion
4
from django.db import migrations, models
5

  
6

  
7
class Migration(migrations.Migration):
8

  
9
    dependencies = [
10
        ('auth', '0011_update_proxy_permissions'),
11
        ('agendas', '0130_event_date_range_constraint'),
12
    ]
13

  
14
    operations = [
15
        migrations.CreateModel(
16
            name='SharedCustodySettings',
17
            fields=[
18
                (
19
                    'id',
20
                    models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
21
                ),
22
                (
23
                    'management_role',
24
                    models.ForeignKey(
25
                        blank=True,
26
                        default=None,
27
                        null=True,
28
                        on_delete=django.db.models.deletion.SET_NULL,
29
                        related_name='+',
30
                        to='auth.Group',
31
                        verbose_name='Management role',
32
                    ),
33
                ),
34
            ],
35
        ),
36
    ]
chrono/agendas/models.py
3487 3487
                date_format(self.date_end, 'SHORT_DATE_FORMAT'),
3488 3488
            )
3489 3489
        return '%s, %s' % (self.guardian, exc_repr)
3490

  
3491

  
3492
class SharedCustodySettings(models.Model):
3493
    management_role = models.ForeignKey(
3494
        Group,
3495
        blank=True,
3496
        null=True,
3497
        default=None,
3498
        related_name='+',
3499
        verbose_name=_('Management role'),
3500
        on_delete=models.SET_NULL,
3501
    )
3502

  
3503
    @classmethod
3504
    def get_singleton(cls):
3505
        try:
3506
            return cls.objects.get()
3507
        except cls.DoesNotExist:
3508
            return cls()
chrono/manager/forms.py
57 57
    SharedCustodyHolidayRule,
58 58
    SharedCustodyPeriod,
59 59
    SharedCustodyRule,
60
    SharedCustodySettings,
60 61
    Subscription,
61 62
    TimePeriod,
62 63
    TimePeriodException,
......
1550 1551
            self.add_error('date_end', _('End date must be greater than start date.'))
1551 1552

  
1552 1553
        return cleaned_data
1554

  
1555

  
1556
class SharedCustodySettingsForm(forms.ModelForm):
1557
    management_role = forms.ModelChoiceField(
1558
        label=_('Management role'), required=False, queryset=Group.objects.all().order_by('name')
1559
    )
1560

  
1561
    class Meta:
1562
        model = SharedCustodySettings
1563
        fields = '__all__'
chrono/manager/templates/chrono/manager_home.html
12 12
    <li><a rel="popup" href="{% url 'chrono-manager-agendas-export' %}" data-autoclose-dialog="true">{% trans 'Export' %}</a></li>
13 13
    <li><a href="{% url 'chrono-manager-events-type-list' %}">{% trans 'Events types' %}</a></li>
14 14
    <li><a href="{% url 'chrono-manager-check-type-list' %}">{% trans 'Check types' %}</a></li>
15
    {% if shared_custody_enabled %}
16
    <li><a rel="popup" href="{% url 'chrono-manager-shared-custody-settings' %}">{% trans 'Shared custody' %}</a></li>
17
    {% endif %}
15 18
    {% endif %}
16 19
    {% if has_access_to_unavailability_calendars %}
17 20
    <li><a href="{% url 'chrono-manager-unavailability-calendar-list' %}">{% trans 'Unavailability calendars' %}</a></li>
chrono/manager/urls.py
400 400
        views.agenda_import_events_sample_csv,
401 401
        name='chrono-manager-sample-events-csv',
402 402
    ),
403
    url(
404
        r'^shared-custody/settings/$',
405
        views.shared_custody_settings,
406
        name='chrono-manager-shared-custody-settings',
407
    ),
403 408
    url(
404 409
        r'^shared-custody/(?P<pk>\d+)/$',
405 410
        views.shared_custody_agenda_view,
chrono/manager/views.py
26 26

  
27 27
import requests
28 28
from dateutil.relativedelta import MO, relativedelta
29
from django.conf import settings
29 30
from django.contrib import messages
30 31
from django.core.exceptions import PermissionDenied
31 32
from django.db import IntegrityError, transaction
......
80 81
    SharedCustodyHolidayRule,
81 82
    SharedCustodyPeriod,
82 83
    SharedCustodyRule,
84
    SharedCustodySettings,
83 85
    TimePeriod,
84 86
    TimePeriodException,
85 87
    TimePeriodExceptionSource,
......
122 124
    SharedCustodyHolidayRuleForm,
123 125
    SharedCustodyPeriodForm,
124 126
    SharedCustodyRuleForm,
127
    SharedCustodySettingsForm,
125 128
    SubscriptionCheckFilterSet,
126 129
    TimePeriodAddForm,
127 130
    TimePeriodExceptionForm,
......
163 166
    def get_context_data(self, **kwargs):
164 167
        context = super().get_context_data(**kwargs)
165 168
        context['has_access_to_unavailability_calendars'] = self.has_access_to_unavailability_calendars()
169
        context['shared_custody_enabled'] = settings.SHARED_CUSTODY_ENABLED
166 170
        return context
167 171

  
168 172
    def get(self, request, *args, **kwargs):
......
3685 3689
        return super().dispatch(request, *args, **kwargs)
3686 3690

  
3687 3691
    def check_permissions(self, user):
3688
        return user.is_staff
3692
        if user.is_staff:
3693
            return True
3694
        management_role = SharedCustodySettings.get_singleton().management_role
3695
        return bool(management_role in user.groups.all())
3689 3696

  
3690 3697
    def get_context_data(self, **kwargs):
3691 3698
        context = super().get_context_data(**kwargs)
......
3863 3870
shared_custody_agenda_delete_period = SharedCustodyAgendaDeletePeriodView.as_view()
3864 3871

  
3865 3872

  
3873
class SharedCustodySettingsView(UpdateView):
3874
    title = _('Shared custody settings')
3875
    template_name = 'chrono/manager_agenda_form.html'
3876
    form_class = SharedCustodySettingsForm
3877
    model = SharedCustodySettings
3878
    success_url = reverse_lazy('chrono-manager-homepage')
3879

  
3880
    def dispatch(self, request, *args, **kwargs):
3881
        if not request.user.is_staff:
3882
            raise PermissionDenied()
3883
        return super().dispatch(request, *args, **kwargs)
3884

  
3885
    def get_object(self):
3886
        return SharedCustodySettings.get_singleton()
3887

  
3888

  
3889
shared_custody_settings = SharedCustodySettingsView.as_view()
3890

  
3891

  
3866 3892
def menu_json(request):
3867 3893
    if not request.user.is_staff:
3868 3894
        homepage_view = HomepageView(request=request)
chrono/settings.py
195 195

  
196 196
REST_FRAMEWORK = {'EXCEPTION_HANDLER': 'chrono.api.utils.exception_handler'}
197 197

  
198
SHARED_CUSTODY_ENABLED = False
199

  
198 200
local_settings_file = os.environ.get(
199 201
    'CHRONO_SETTINGS_FILE', os.path.join(os.path.dirname(__file__), 'local_settings.py')
200 202
)
tests/manager/test_shared_custody_agenda.py
286 286

  
287 287
    resp = app.get('/manage/shared-custody/%s/2022/12/' % agenda.pk)
288 288
    assert 'John Doe (Vacances de Noël)' in resp.text
289

  
290

  
291
def test_shared_custody_settings_feature_flag(app, admin_user, settings):
292
    settings.SHARED_CUSTODY_ENABLED = False
293
    app = login(app)
294
    resp = app.get('/manage/')
295
    assert 'Shared custody' not in resp.text
296

  
297
    settings.SHARED_CUSTODY_ENABLED = True
298
    resp = app.get('/manage/')
299
    assert 'Shared custody' in resp.text
300

  
301

  
302
def test_shared_custody_settings_management_role(app, admin_user, manager_user):
303
    father = Person.objects.create(user_external_id='father_id', first_name='John', last_name='Doe')
304
    mother = Person.objects.create(user_external_id='mother_id', first_name='Jane', last_name='Doe')
305
    agenda = SharedCustodyAgenda.objects.create(first_guardian=father, second_guardian=mother)
306

  
307
    app = login(app, username='manager', password='manager')
308
    app.get('/manage/shared-custody/%s/settings/' % agenda.pk, status=403)
309

  
310
    app.reset()
311
    app = login(app)
312
    resp = app.get('/manage/')
313
    resp = resp.click('Shared custody')
314
    resp.form['management_role'] = manager_user.groups.all()[0].pk
315
    resp.form.submit()
316

  
317
    app.reset()
318
    app = login(app, username='manager', password='manager')
319
    resp = app.get('/manage/shared-custody/%s/settings/' % agenda.pk)
320
    assert 'Custody agenda of John Doe and Jane Doe' in resp.text
tests/settings.py
34 34
EXCEPTIONS_SOURCES = {}
35 35

  
36 36
SITE_BASE_URL = 'https://example.com'
37

  
38
SHARED_CUSTODY_ENABLED = True
37
-