manager: add shared custody views (#62146)
This commit is contained in:
parent
0fd2e6a51a
commit
c0679178ba
|
@ -46,7 +46,10 @@ from chrono.agendas.models import (
|
|||
Desk,
|
||||
Event,
|
||||
MeetingType,
|
||||
Person,
|
||||
Resource,
|
||||
SharedCustodyPeriod,
|
||||
SharedCustodyRule,
|
||||
Subscription,
|
||||
TimePeriod,
|
||||
TimePeriodException,
|
||||
|
@ -1217,3 +1220,67 @@ class AgendasExportForm(forms.Form):
|
|||
)
|
||||
absence_reason_groups = forms.BooleanField(label=_('Absence reason groups'), required=False, initial=True)
|
||||
categories = forms.BooleanField(label=_('Categories'), required=False, initial=True)
|
||||
|
||||
|
||||
class SharedCustodyRuleForm(forms.ModelForm):
|
||||
guardian = forms.ModelChoiceField(label=_('Guardian'), queryset=Person.objects.none())
|
||||
days = forms.TypedMultipleChoiceField(
|
||||
choices=WEEKDAY_CHOICES,
|
||||
coerce=int,
|
||||
required=False,
|
||||
widget=WeekdaysWidget,
|
||||
label=_('Days'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = SharedCustodyRule
|
||||
fields = ['guardian', 'days', 'weeks']
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['guardian'].empty_label = None
|
||||
self.fields['guardian'].queryset = Person.objects.filter(
|
||||
pk__in=[self.instance.agenda.first_guardian_id, self.instance.agenda.second_guardian_id]
|
||||
)
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
|
||||
if self.instance.agenda.rule_overlaps(
|
||||
days=cleaned_data['days'], weeks=cleaned_data['weeks'], instance=self.instance
|
||||
):
|
||||
raise ValidationError(_('Rule overlaps existing rules.'))
|
||||
|
||||
return cleaned_data
|
||||
|
||||
|
||||
class SharedCustodyPeriodForm(forms.ModelForm):
|
||||
guardian = forms.ModelChoiceField(label=_('Guardian'), queryset=Person.objects.none())
|
||||
|
||||
class Meta:
|
||||
model = SharedCustodyPeriod
|
||||
fields = ['guardian', 'date_start', 'date_end']
|
||||
widgets = {
|
||||
'date_start': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),
|
||||
'date_end': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['guardian'].empty_label = None
|
||||
self.fields['guardian'].queryset = Person.objects.filter(
|
||||
pk__in=[self.instance.agenda.first_guardian_id, self.instance.agenda.second_guardian_id]
|
||||
)
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
|
||||
if self.instance.agenda.period_overlaps(
|
||||
date_start=cleaned_data['date_start'], date_end=cleaned_data['date_end'], instance=self.instance
|
||||
):
|
||||
raise ValidationError(_('Period overlaps existing periods.'))
|
||||
|
||||
if cleaned_data['date_end'] <= cleaned_data['date_start']:
|
||||
self.add_error('date_end', _('End date must be greater than start date.'))
|
||||
|
||||
return cleaned_data
|
||||
|
|
|
@ -270,6 +270,21 @@ table.agenda-table {
|
|||
}
|
||||
}
|
||||
|
||||
.agenda-table tbody tr td.guardian {
|
||||
vertical-align: middle;
|
||||
background-image:
|
||||
linear-gradient(
|
||||
110deg,
|
||||
hsla(0, 0%, 100%, 0.85) 0%,
|
||||
hsla(0, 0%, 100%, 0.65) 100%);
|
||||
&.first-guardian {
|
||||
background-color: hsl(30, 100%, 46%);
|
||||
}
|
||||
&.second-guardian {
|
||||
background-color: hsl(120, 57%, 35%);
|
||||
}
|
||||
}
|
||||
|
||||
.monthview tbody td div.booking {
|
||||
text-indent: -9999px;
|
||||
&:not(:hover) {
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
{% extends "chrono/manager_agenda_month_view.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
{% if agenda.is_complete %}
|
||||
{% for week, slots in slots_by_week.items %}
|
||||
{% if forloop.first %}
|
||||
<table class="agenda-table month-view single-desk">
|
||||
<tbody>
|
||||
{% endif %}
|
||||
|
||||
<tr>
|
||||
<th></th>
|
||||
{% for slot in slots %}
|
||||
<th class="weekday {% if slot.date == today %}today{% endif %}"><span>{{ slot.date|date:"l j" }}</span></th>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{% trans "Week" %} {{ week }}</th>
|
||||
{% for slot in slots %}
|
||||
<td class="guardian {% if slot.guardian == agenda.first_guardian %}first-guardian{% else %}second-guardian{% endif %}">{{ slot }}</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
|
||||
{% if forloop.last %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<div class="warningnotice">
|
||||
<p>{% trans "Configuraton is not completed yet." %}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,71 @@
|
|||
{% extends "chrono/manager_agenda_view.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
{{ block.super }}
|
||||
<a href=".">{% trans "Settings" %}</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block appbar %}
|
||||
<h2>{% trans "Settings" %}</h2>
|
||||
<span class="actions">
|
||||
<a rel="popup" href="{% url 'chrono-manager-shared-custody-agenda-add-period' pk=object.id %}">{% trans 'Add custody period' %}</a>
|
||||
<a rel="popup" href="{% url 'chrono-manager-shared-custody-agenda-add-rule' pk=object.id %}">{% trans 'Add custody rule' %}</a>
|
||||
</span>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% if not agenda.is_complete %}
|
||||
<div class="warningnotice">
|
||||
<p>{% trans "Custody rules are not complete." %}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="section">
|
||||
<h3>{% trans "Custody rules" %}</h3>
|
||||
<div>
|
||||
{% if agenda.rules.all %}
|
||||
<ul class="objects-list single-links">
|
||||
{% for rule in agenda.rules.all %}
|
||||
<li><a rel="popup" href="{% url 'chrono-manager-shared-custody-agenda-edit-rule' pk=agenda.pk rule_pk=rule.pk %}">
|
||||
<span class="rule-info">
|
||||
{{ rule.guardian.name }}, {{ rule.label }}
|
||||
</span>
|
||||
</a>
|
||||
<a rel="popup" class="delete" href="{% url 'chrono-manager-shared-custody-agenda-delete-rule' pk=agenda.pk rule_pk=rule.pk %}?next=settings">{% trans "remove" %}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<div class="big-msg-info">
|
||||
{% blocktrans %}
|
||||
This agenda doesn't have any custody rules yet.
|
||||
{% endblocktrans %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h3>{% trans "Exceptional custody periods" %}</h3>
|
||||
<div>
|
||||
{% if agenda.periods.all %}
|
||||
<ul class="objects-list single-links">
|
||||
{% for period in agenda.periods.all %}
|
||||
<li>
|
||||
<a rel="popup" href="{% url 'chrono-manager-shared-custody-agenda-edit-period' pk=agenda.pk period_pk=period.pk %}">
|
||||
{{ period }}
|
||||
<a rel="popup" class="delete" href="{% url 'chrono-manager-shared-custody-agenda-delete-period' pk=agenda.pk period_pk=period.pk %}?next=settings">{% trans "remove" %}</a>
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<div class="big-msg-info">
|
||||
{% blocktrans %}
|
||||
This agenda doesn't have any custody period. They can be used to specify explicit moments when one of the guardian should have custody, regardless of global rules.
|
||||
{% endblocktrans %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -376,5 +376,50 @@ urlpatterns = [
|
|||
views.agenda_import_events_sample_csv,
|
||||
name='chrono-manager-sample-events-csv',
|
||||
),
|
||||
url(
|
||||
r'^shared-custody/(?P<pk>\d+)/$',
|
||||
views.shared_custody_agenda_view,
|
||||
name='chrono-manager-shared-custody-agenda-view',
|
||||
),
|
||||
url(
|
||||
r'^shared-custody/(?P<pk>\d+)/(?P<year>[0-9]{4})/(?P<month>[0-9]+)/$',
|
||||
views.shared_custody_agenda_monthly_view,
|
||||
name='chrono-manager-shared-custody-agenda-month-view',
|
||||
),
|
||||
url(
|
||||
r'^shared-custody/(?P<pk>\d+)/settings/$',
|
||||
views.shared_custody_agenda_settings,
|
||||
name='chrono-manager-shared-custody-agenda-settings',
|
||||
),
|
||||
url(
|
||||
r'^shared-custody/(?P<pk>\d+)/add-rule$',
|
||||
views.shared_custody_agenda_add_rule,
|
||||
name='chrono-manager-shared-custody-agenda-add-rule',
|
||||
),
|
||||
url(
|
||||
r'^shared-custody/(?P<pk>\d+)/rules/(?P<rule_pk>\d+)/edit$',
|
||||
views.shared_custody_agenda_edit_rule,
|
||||
name='chrono-manager-shared-custody-agenda-edit-rule',
|
||||
),
|
||||
url(
|
||||
r'^shared-custody/(?P<pk>\d+)/rules/(?P<rule_pk>\d+)/delete$',
|
||||
views.shared_custody_agenda_delete_rule,
|
||||
name='chrono-manager-shared-custody-agenda-delete-rule',
|
||||
),
|
||||
url(
|
||||
r'^shared-custody/(?P<pk>\d+)/add-period$',
|
||||
views.shared_custody_agenda_add_period,
|
||||
name='chrono-manager-shared-custody-agenda-add-period',
|
||||
),
|
||||
url(
|
||||
r'^shared-custody/(?P<pk>\d+)/periods/(?P<period_pk>\d+)/edit$',
|
||||
views.shared_custody_agenda_edit_period,
|
||||
name='chrono-manager-shared-custody-agenda-edit-period',
|
||||
),
|
||||
url(
|
||||
r'^shared-custody/(?P<pk>\d+)/periods/(?P<period_pk>\d+)/delete$',
|
||||
views.shared_custody_agenda_delete_period,
|
||||
name='chrono-manager-shared-custody-agenda-delete-period',
|
||||
),
|
||||
url(r'^menu.json$', views.menu_json),
|
||||
]
|
||||
|
|
|
@ -25,6 +25,7 @@ import uuid
|
|||
from operator import attrgetter
|
||||
|
||||
import requests
|
||||
from dateutil.relativedelta import MO, relativedelta
|
||||
from django.contrib import messages
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.db import IntegrityError, transaction
|
||||
|
@ -54,6 +55,7 @@ from django.views.generic import (
|
|||
UpdateView,
|
||||
View,
|
||||
)
|
||||
from django.views.generic.dates import MonthMixin, YearMixin
|
||||
from weasyprint import HTML
|
||||
|
||||
from chrono.agendas.models import (
|
||||
|
@ -72,6 +74,9 @@ from chrono.agendas.models import (
|
|||
ICSError,
|
||||
MeetingType,
|
||||
Resource,
|
||||
SharedCustodyAgenda,
|
||||
SharedCustodyPeriod,
|
||||
SharedCustodyRule,
|
||||
TimePeriod,
|
||||
TimePeriodException,
|
||||
TimePeriodExceptionSource,
|
||||
|
@ -106,6 +111,8 @@ from .forms import (
|
|||
NewEventForm,
|
||||
NewMeetingTypeForm,
|
||||
NewTimePeriodExceptionForm,
|
||||
SharedCustodyPeriodForm,
|
||||
SharedCustodyRuleForm,
|
||||
SubscriptionCheckFilterSet,
|
||||
TimePeriodAddForm,
|
||||
TimePeriodExceptionForm,
|
||||
|
@ -3342,6 +3349,161 @@ class UnavailabilityCalendarAddUnavailabilityView(ManagedUnavailabilityCalendarM
|
|||
unavailability_calendar_add_unavailability = UnavailabilityCalendarAddUnavailabilityView.as_view()
|
||||
|
||||
|
||||
class SharedCustodyAgendaMixin:
|
||||
agenda = None
|
||||
|
||||
def set_agenda(self, **kwargs):
|
||||
self.agenda = get_object_or_404(SharedCustodyAgenda, id=kwargs.get('pk'))
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.set_agenda(**kwargs)
|
||||
if not self.check_permissions(request.user):
|
||||
raise PermissionDenied()
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def check_permissions(self, user):
|
||||
return user.is_staff
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['agenda'] = self.agenda
|
||||
context['user_can_manage'] = True
|
||||
return context
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
if not kwargs.get('instance'):
|
||||
kwargs['instance'] = self.model()
|
||||
kwargs['instance'].agenda = self.agenda
|
||||
return kwargs
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('chrono-manager-shared-custody-agenda-settings', kwargs={'pk': self.agenda.id})
|
||||
|
||||
|
||||
class SharedCustodyAgendaView(SharedCustodyAgendaMixin, RedirectView):
|
||||
def get_redirect_url(self, *args, **kwargs):
|
||||
return reverse(
|
||||
'chrono-manager-shared-custody-agenda-month-view',
|
||||
kwargs={'pk': self.agenda.pk, 'year': now().year, 'month': now().month},
|
||||
)
|
||||
|
||||
|
||||
shared_custody_agenda_view = SharedCustodyAgendaView.as_view()
|
||||
|
||||
|
||||
class SharedCustodyAgendaMonthView(SharedCustodyAgendaMixin, YearMixin, MonthMixin, DateMixin, DetailView):
|
||||
template_name = 'chrono/manager_shared_custody_agenda_month_view.html'
|
||||
model = SharedCustodyAgenda
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
try:
|
||||
self.date = datetime.date(year=int(self.get_year()), month=int(self.get_month()), day=1)
|
||||
except ValueError:
|
||||
raise Http404('invalid date')
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['today'] = localtime().date()
|
||||
|
||||
first_monday_this_month = self.date - datetime.timedelta(days=self.date.weekday())
|
||||
first_monday_next_month = self.date + relativedelta(months=1, day=1, weekday=MO(1))
|
||||
slots = self.object.get_custody_slots(first_monday_this_month, first_monday_next_month)
|
||||
|
||||
slots_by_week = collections.defaultdict(list)
|
||||
for slot in slots:
|
||||
slots_by_week[slot.date.isocalendar()[1]].append(slot)
|
||||
|
||||
context['slots_by_week'] = dict(slots_by_week)
|
||||
return context
|
||||
|
||||
def get_previous_month_url(self):
|
||||
previous_month = self.date - relativedelta(months=1)
|
||||
return reverse(
|
||||
'chrono-manager-shared-custody-agenda-month-view',
|
||||
kwargs={'pk': self.object.id, 'year': previous_month.year, 'month': previous_month.month},
|
||||
)
|
||||
|
||||
def get_next_month_url(self):
|
||||
next_month = self.date + relativedelta(months=1)
|
||||
return reverse(
|
||||
'chrono-manager-shared-custody-agenda-month-view',
|
||||
kwargs={'pk': self.object.id, 'year': next_month.year, 'month': next_month.month},
|
||||
)
|
||||
|
||||
|
||||
shared_custody_agenda_monthly_view = SharedCustodyAgendaMonthView.as_view()
|
||||
|
||||
|
||||
class SharedCustodyAgendaSettings(SharedCustodyAgendaMixin, DetailView):
|
||||
template_name = 'chrono/manager_shared_custody_agenda_settings.html'
|
||||
model = SharedCustodyAgenda
|
||||
|
||||
|
||||
shared_custody_agenda_settings = SharedCustodyAgendaSettings.as_view()
|
||||
|
||||
|
||||
class SharedCustodyAgendaAddRuleView(SharedCustodyAgendaMixin, CreateView):
|
||||
title = _('Add custody rule')
|
||||
template_name = 'chrono/manager_agenda_form.html'
|
||||
form_class = SharedCustodyRuleForm
|
||||
model = SharedCustodyRule
|
||||
|
||||
|
||||
shared_custody_agenda_add_rule = SharedCustodyAgendaAddRuleView.as_view()
|
||||
|
||||
|
||||
class SharedCustodyAgendaEditRuleView(SharedCustodyAgendaMixin, UpdateView):
|
||||
title = _('Edit custody rule')
|
||||
template_name = 'chrono/manager_agenda_form.html'
|
||||
form_class = SharedCustodyRuleForm
|
||||
model = SharedCustodyRule
|
||||
pk_url_kwarg = 'rule_pk'
|
||||
|
||||
|
||||
shared_custody_agenda_edit_rule = SharedCustodyAgendaEditRuleView.as_view()
|
||||
|
||||
|
||||
class SharedCustodyAgendaDeleteRuleView(SharedCustodyAgendaMixin, DeleteView):
|
||||
template_name = 'chrono/manager_confirm_delete.html'
|
||||
model = SharedCustodyRule
|
||||
pk_url_kwarg = 'rule_pk'
|
||||
|
||||
|
||||
shared_custody_agenda_delete_rule = SharedCustodyAgendaDeleteRuleView.as_view()
|
||||
|
||||
|
||||
class SharedCustodyAgendaAddPeriodView(SharedCustodyAgendaMixin, CreateView):
|
||||
title = _('Add custody period')
|
||||
template_name = 'chrono/manager_agenda_form.html'
|
||||
form_class = SharedCustodyPeriodForm
|
||||
model = SharedCustodyPeriod
|
||||
|
||||
|
||||
shared_custody_agenda_add_period = SharedCustodyAgendaAddPeriodView.as_view()
|
||||
|
||||
|
||||
class SharedCustodyAgendaEditPeriodView(SharedCustodyAgendaMixin, UpdateView):
|
||||
title = _('Edit custody period')
|
||||
template_name = 'chrono/manager_agenda_form.html'
|
||||
form_class = SharedCustodyPeriodForm
|
||||
model = SharedCustodyPeriod
|
||||
pk_url_kwarg = 'period_pk'
|
||||
|
||||
|
||||
shared_custody_agenda_edit_period = SharedCustodyAgendaEditPeriodView.as_view()
|
||||
|
||||
|
||||
class SharedCustodyAgendaDeletePeriodView(SharedCustodyAgendaMixin, DeleteView):
|
||||
template_name = 'chrono/manager_confirm_delete.html'
|
||||
model = SharedCustodyPeriod
|
||||
pk_url_kwarg = 'period_pk'
|
||||
|
||||
|
||||
shared_custody_agenda_delete_period = SharedCustodyAgendaDeletePeriodView.as_view()
|
||||
|
||||
|
||||
def menu_json(request):
|
||||
if not request.user.is_staff:
|
||||
homepage_view = HomepageView(request=request)
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
import datetime
|
||||
|
||||
import pytest
|
||||
|
||||
from chrono.agendas.models import Person, SharedCustodyAgenda, SharedCustodyPeriod, SharedCustodyRule
|
||||
from tests.utils import login
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
||||
|
||||
@pytest.mark.freeze_time('2022-02-22 14:00') # Tuesday
|
||||
def test_shared_custody_agenda_settings_rules(app, admin_user):
|
||||
father = Person.objects.create(user_external_id='father_id', name='John Doe')
|
||||
mother = Person.objects.create(user_external_id='mother_id', name='Jane Doe')
|
||||
agenda = SharedCustodyAgenda.objects.create(first_guardian=father, second_guardian=mother)
|
||||
|
||||
app = login(app)
|
||||
resp = app.get('/manage/shared-custody/%s/' % agenda.pk).follow()
|
||||
resp = resp.click('Settings')
|
||||
assert 'Custody agenda of John Doe and Jane Doe' in resp.text
|
||||
assert 'Custody rules are not complete.' in resp.text
|
||||
assert 'This agenda doesn\'t have any custody rules yet.' in resp.text
|
||||
|
||||
resp = resp.click('Add custody rule')
|
||||
resp.form['guardian'] = father.pk
|
||||
resp.form['days'] = list(range(7))
|
||||
resp.form['weeks'] = 'even'
|
||||
resp = resp.form.submit().follow()
|
||||
assert 'Custody rules are not complete.' in resp.text
|
||||
assert 'John Doe, daily, on even weeks' in resp.text
|
||||
|
||||
resp = resp.click('Add custody rule')
|
||||
resp.form['guardian'] = mother.pk
|
||||
resp.form['days'] = list(range(7))
|
||||
resp.form['weeks'] = 'odd'
|
||||
resp = resp.form.submit().follow()
|
||||
assert 'Custody rules are not complete.' not in resp.text
|
||||
assert 'John Doe, daily, on even weeks' in resp.text
|
||||
assert 'Jane Doe, daily, on odd weeks' in resp.text
|
||||
|
||||
resp = resp.click('John Doe, daily, on even weeks')
|
||||
resp.form['days'] = list(range(6))
|
||||
resp = resp.form.submit().follow()
|
||||
assert 'Custody rules are not complete.' in resp.text
|
||||
|
||||
resp = resp.click('John Doe, from Monday to Saturday, on even weeks')
|
||||
resp.form['days'] = [0]
|
||||
resp.form['weeks'] = 'odd'
|
||||
resp = resp.form.submit()
|
||||
assert 'Rule overlaps existing rules.' in resp.text
|
||||
|
||||
resp.form['weeks'] = 'even'
|
||||
resp = resp.form.submit().follow()
|
||||
|
||||
resp = resp.click('remove', index=1)
|
||||
resp = resp.form.submit().follow()
|
||||
assert SharedCustodyRule.objects.count() == 1
|
||||
|
||||
|
||||
@pytest.mark.freeze_time('2022-02-22 14:00') # Tuesday
|
||||
def test_shared_custody_agenda_settings_periods(app, admin_user):
|
||||
father = Person.objects.create(user_external_id='father_id', name='John Doe')
|
||||
mother = Person.objects.create(user_external_id='mother_id', name='Jane Doe')
|
||||
agenda = SharedCustodyAgenda.objects.create(first_guardian=father, second_guardian=mother)
|
||||
|
||||
app = login(app)
|
||||
resp = app.get('/manage/shared-custody/%s/settings/' % agenda.pk)
|
||||
assert 'This agenda doesn\'t have any custody period.' in resp.text
|
||||
|
||||
resp = resp.click('Add custody period')
|
||||
resp.form['guardian'] = father.pk
|
||||
resp.form['date_start'] = '2022-03-01'
|
||||
resp.form['date_end'] = '2022-03-03'
|
||||
resp = resp.form.submit().follow()
|
||||
assert 'This agenda doesn\'t have any custody period.' not in resp.text
|
||||
assert 'John Doe, 03/01/2022 → 03/03/2022' in resp.text
|
||||
|
||||
resp = resp.click('John Doe, 03/01/2022 → 03/03/2022')
|
||||
resp.form['guardian'] = mother.pk
|
||||
resp = resp.form.submit().follow()
|
||||
assert 'Jane Doe, 03/01/2022 → 03/03/2022' in resp.text
|
||||
|
||||
resp = resp.click('Add custody period')
|
||||
resp.form['guardian'] = mother.pk
|
||||
resp.form['date_start'] = '2022-03-05'
|
||||
resp.form['date_end'] = '2022-03-03'
|
||||
resp = resp.form.submit()
|
||||
assert 'End date must be greater than start date.' in resp.text
|
||||
|
||||
resp.form['date_start'] = '2022-03-02'
|
||||
resp.form['date_end'] = '2022-03-06'
|
||||
resp = resp.form.submit()
|
||||
assert 'Period overlaps existing periods.' in resp.text
|
||||
|
||||
resp = app.get('/manage/shared-custody/%s/settings/' % agenda.pk)
|
||||
resp = resp.click('remove', href='delete')
|
||||
resp = resp.form.submit().follow()
|
||||
assert not SharedCustodyPeriod.objects.exists()
|
||||
|
||||
|
||||
@pytest.mark.freeze_time('2022-02-22 14:00') # Tuesday
|
||||
def test_shared_custody_agenda_month_view(app, admin_user):
|
||||
father = Person.objects.create(user_external_id='father_id', name='John Doe')
|
||||
mother = Person.objects.create(user_external_id='mother_id', name='Jane Doe')
|
||||
agenda = SharedCustodyAgenda.objects.create(first_guardian=father, second_guardian=mother)
|
||||
SharedCustodyRule.objects.create(agenda=agenda, guardian=father, days=list(range(7)), weeks='even')
|
||||
|
||||
app = login(app)
|
||||
resp = app.get('/manage/shared-custody/%s/' % agenda.pk).follow()
|
||||
assert 'Custody agenda of John Doe and Jane Doe' in resp.text
|
||||
assert 'February 2022' in resp.text
|
||||
assert 'Configuraton is not completed yet.' in resp.text
|
||||
|
||||
SharedCustodyRule.objects.create(agenda=agenda, guardian=mother, days=list(range(7)), weeks='odd')
|
||||
resp = app.get('/manage/shared-custody/%s/' % agenda.pk).follow()
|
||||
assert 'Configuraton is not completed yet.' not in resp.text
|
||||
|
||||
assert all('Week %s' % i in resp.text for i in range(5, 10))
|
||||
assert resp.pyquery('tbody tr th.today span').text() == 'Tuesday 22'
|
||||
|
||||
days = [x.text for x in resp.pyquery('tbody tr th span')]
|
||||
assert len(days) == 7 * 5
|
||||
assert days[:3] == ['Monday 31', 'Tuesday 1', 'Wednesday 2']
|
||||
assert days[-3:] == ['Friday 4', 'Saturday 5', 'Sunday 6']
|
||||
|
||||
tds = [x.text for x in resp.pyquery('tbody tr td')]
|
||||
for week_number, i in zip(range(5, 10), range(0, 29, 7)):
|
||||
guardian = 'Jane Doe' if week_number % 2 else 'John Doe'
|
||||
assert tds[i : i + 7] == [guardian] * 7
|
||||
|
||||
SharedCustodyPeriod.objects.create(
|
||||
agenda=agenda,
|
||||
guardian=father,
|
||||
date_start=datetime.date(2022, 2, 1),
|
||||
date_end=datetime.date(2022, 2, 3),
|
||||
)
|
||||
resp = app.get('/manage/shared-custody/%s/' % agenda.pk).follow()
|
||||
tds = [x.text for x in resp.pyquery('tbody tr td')]
|
||||
assert tds[:7] == ['Jane Doe', 'John Doe', 'John Doe', 'Jane Doe', 'Jane Doe', 'Jane Doe', 'Jane Doe']
|
||||
|
||||
old_resp = resp
|
||||
resp = resp.click('→')
|
||||
assert 'March 2022' in resp.text
|
||||
assert 'today' not in resp.text
|
||||
assert all('Week %s' % i in resp.text for i in range(9, 14))
|
||||
|
||||
days = [x.text for x in resp.pyquery('tbody tr th span')]
|
||||
assert len(days) == 7 * 5
|
||||
assert days[:3] == ['Monday 28', 'Tuesday 1', 'Wednesday 2']
|
||||
assert days[-3:] == ['Friday 1', 'Saturday 2', 'Sunday 3']
|
||||
|
||||
resp = resp.click('←')
|
||||
assert resp.text == old_resp.text
|
||||
|
||||
app.get('/manage/shared-custody/%s/42/42/' % agenda.pk, status=404)
|
Loading…
Reference in New Issue