api: set date end on shared custody agenda (#71633)
This commit is contained in:
parent
aac92703b7
commit
57cb74a2ed
|
@ -3,7 +3,7 @@ import datetime
|
||||||
|
|
||||||
from django.contrib.auth.models import Group
|
from django.contrib.auth.models import Group
|
||||||
from django.db import models, transaction
|
from django.db import models, transaction
|
||||||
from django.db.models import ExpressionWrapper, F
|
from django.db.models import ExpressionWrapper, F, Q
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.exceptions import ValidationError
|
from rest_framework.exceptions import ValidationError
|
||||||
|
@ -585,7 +585,34 @@ class SubscriptionSerializer(serializers.ModelSerializer):
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
|
|
||||||
class SharedCustodyAgendaCreateSerializer(serializers.Serializer):
|
class SharedCustodyAgendaMixin:
|
||||||
|
def validate(self, attrs):
|
||||||
|
date_start = attrs['date_start']
|
||||||
|
date_end = attrs.get('date_end')
|
||||||
|
|
||||||
|
if date_end and date_start >= date_end:
|
||||||
|
raise ValidationError(_('date_start must be before date_end'))
|
||||||
|
|
||||||
|
child_id = self.get_child_id(attrs)
|
||||||
|
overlapping_agendas = SharedCustodyAgenda.objects.filter(
|
||||||
|
Q(date_end__gte=date_start) | Q(date_end__isnull=True), child__user_external_id=child_id
|
||||||
|
)
|
||||||
|
if date_end:
|
||||||
|
overlapping_agendas = overlapping_agendas.filter(date_start__lte=date_end)
|
||||||
|
if self.instance:
|
||||||
|
overlapping_agendas = overlapping_agendas.exclude(pk=self.instance.pk)
|
||||||
|
|
||||||
|
if overlapping_agendas:
|
||||||
|
request = self.context.get('request')
|
||||||
|
raise ValidationError(
|
||||||
|
_('Invalid date_start/date_end, agenda would overlap with %s.')
|
||||||
|
% request.build_absolute_uri(overlapping_agendas[0].get_absolute_url())
|
||||||
|
)
|
||||||
|
|
||||||
|
return attrs
|
||||||
|
|
||||||
|
|
||||||
|
class SharedCustodyAgendaCreateSerializer(SharedCustodyAgendaMixin, serializers.Serializer):
|
||||||
period_mirrors = {
|
period_mirrors = {
|
||||||
'even': 'odd',
|
'even': 'odd',
|
||||||
'odd': 'even',
|
'odd': 'even',
|
||||||
|
@ -606,10 +633,16 @@ class SharedCustodyAgendaCreateSerializer(serializers.Serializer):
|
||||||
child_id = serializers.CharField(max_length=250)
|
child_id = serializers.CharField(max_length=250)
|
||||||
weeks = serializers.ChoiceField(required=False, choices=['', 'even', 'odd'])
|
weeks = serializers.ChoiceField(required=False, choices=['', 'even', 'odd'])
|
||||||
date_start = serializers.DateField(required=True)
|
date_start = serializers.DateField(required=True)
|
||||||
|
date_end = serializers.DateField(required=False)
|
||||||
|
|
||||||
settings_url = serializers.SerializerMethodField()
|
settings_url = serializers.SerializerMethodField()
|
||||||
|
|
||||||
|
def get_child_id(self, attrs):
|
||||||
|
return attrs['child_id']
|
||||||
|
|
||||||
def validate(self, attrs):
|
def validate(self, attrs):
|
||||||
|
super().validate(attrs)
|
||||||
|
|
||||||
attrs['holidays'] = collections.defaultdict(dict)
|
attrs['holidays'] = collections.defaultdict(dict)
|
||||||
for key, value in self.initial_data.items():
|
for key, value in self.initial_data.items():
|
||||||
if key in attrs or ':' not in key:
|
if key in attrs or ':' not in key:
|
||||||
|
@ -675,6 +708,7 @@ class SharedCustodyAgendaCreateSerializer(serializers.Serializer):
|
||||||
second_guardian=other_guardian,
|
second_guardian=other_guardian,
|
||||||
child=child,
|
child=child,
|
||||||
date_start=validated_data['date_start'],
|
date_start=validated_data['date_start'],
|
||||||
|
date_end=validated_data.get('date_end'),
|
||||||
)
|
)
|
||||||
|
|
||||||
if validated_data.get('weeks'):
|
if validated_data.get('weeks'):
|
||||||
|
@ -723,7 +757,10 @@ class SharedCustodyAgendaCreateSerializer(serializers.Serializer):
|
||||||
return request.build_absolute_uri(obj.get_settings_url())
|
return request.build_absolute_uri(obj.get_settings_url())
|
||||||
|
|
||||||
|
|
||||||
class SharedCustodyAgendaSerializer(serializers.ModelSerializer):
|
class SharedCustodyAgendaSerializer(SharedCustodyAgendaMixin, serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SharedCustodyAgenda
|
model = SharedCustodyAgenda
|
||||||
fields = ['date_start']
|
fields = ['date_start', 'date_end']
|
||||||
|
|
||||||
|
def get_child_id(self, attrs):
|
||||||
|
return self.instance.child.user_external_id
|
||||||
|
|
|
@ -3013,7 +3013,7 @@ class SharedCustodyAgendas(APIView):
|
||||||
serializer_class = serializers.SharedCustodyAgendaCreateSerializer
|
serializer_class = serializers.SharedCustodyAgendaCreateSerializer
|
||||||
|
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
serializer = self.serializer_class(data=request.data)
|
serializer = self.serializer_class(data=request.data, context={'request': request})
|
||||||
if not serializer.is_valid():
|
if not serializer.is_valid():
|
||||||
raise APIErrorBadRequest(N_('invalid payload'), errors=serializer.errors)
|
raise APIErrorBadRequest(N_('invalid payload'), errors=serializer.errors)
|
||||||
agenda = serializer.save()
|
agenda = serializer.save()
|
||||||
|
@ -3036,7 +3036,7 @@ class SharedCustodyAgendaAPI(APIView):
|
||||||
def patch(self, request, agenda_pk):
|
def patch(self, request, agenda_pk):
|
||||||
agenda = get_object_or_404(SharedCustodyAgenda, pk=agenda_pk)
|
agenda = get_object_or_404(SharedCustodyAgenda, pk=agenda_pk)
|
||||||
|
|
||||||
serializer = self.serializer_class(agenda, data=request.data)
|
serializer = self.serializer_class(agenda, data=request.data, context={'request': request})
|
||||||
if not serializer.is_valid():
|
if not serializer.is_valid():
|
||||||
raise APIErrorBadRequest(N_('invalid payload'), errors=serializer.errors)
|
raise APIErrorBadRequest(N_('invalid payload'), errors=serializer.errors)
|
||||||
agenda = serializer.save()
|
agenda = serializer.save()
|
||||||
|
|
|
@ -45,6 +45,53 @@ def test_add_shared_custody_agenda(app, user, settings):
|
||||||
'backoffice_url': 'http://testserver/manage/shared-custody/%s/' % agenda.pk,
|
'backoffice_url': 'http://testserver/manage/shared-custody/%s/' % agenda.pk,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# cannot add agenda without date_end
|
||||||
|
params['date_start'] = '2019-01-01'
|
||||||
|
resp = app.post_json('/api/shared-custody/', params=params, status=400)
|
||||||
|
assert resp.json['errors']['non_field_errors'][0] == (
|
||||||
|
'Invalid date_start/date_end, agenda would overlap with http://testserver/manage/shared-custody/%s/.'
|
||||||
|
% agenda.pk
|
||||||
|
)
|
||||||
|
|
||||||
|
# cannot add agenda with date_end after existing agenda date_start
|
||||||
|
params['date_start'] = '2019-01-01'
|
||||||
|
params['date_end'] = '2020-11-01'
|
||||||
|
resp = app.post_json('/api/shared-custody/', params=params, status=400)
|
||||||
|
assert resp.json['errors']['non_field_errors'][0] == (
|
||||||
|
'Invalid date_start/date_end, agenda would overlap with http://testserver/manage/shared-custody/%s/.'
|
||||||
|
% agenda.pk
|
||||||
|
)
|
||||||
|
|
||||||
|
# can add agenda with date_end before existing agenda date_start
|
||||||
|
params['date_start'] = '2019-01-01'
|
||||||
|
params['date_end'] = '2020-01-01'
|
||||||
|
resp = app.post_json('/api/shared-custody/', params=params)
|
||||||
|
assert resp.json['err'] == 0
|
||||||
|
new_agenda_id = resp.json['data']['id']
|
||||||
|
|
||||||
|
# cannot add agenda that would overlap previous one
|
||||||
|
params['date_start'] = '2018-01-01'
|
||||||
|
params['date_end'] = '2019-01-01'
|
||||||
|
resp = app.post_json('/api/shared-custody/', params=params, status=400)
|
||||||
|
assert resp.json['errors']['non_field_errors'][0] == (
|
||||||
|
'Invalid date_start/date_end, agenda would overlap with http://testserver/manage/shared-custody/%s/.'
|
||||||
|
% new_agenda_id
|
||||||
|
)
|
||||||
|
|
||||||
|
params['date_start'] = '2020-01-01'
|
||||||
|
params['date_end'] = '2020-02-01'
|
||||||
|
resp = app.post_json('/api/shared-custody/', params=params, status=400)
|
||||||
|
assert resp.json['errors']['non_field_errors'][0] == (
|
||||||
|
'Invalid date_start/date_end, agenda would overlap with http://testserver/manage/shared-custody/%s/.'
|
||||||
|
% new_agenda_id
|
||||||
|
)
|
||||||
|
|
||||||
|
params['date_start'] = '2021-02-01'
|
||||||
|
params['date_end'] = '2021-01-01'
|
||||||
|
resp = app.post_json('/api/shared-custody/', params=params, status=400)
|
||||||
|
assert resp.json['errors']['non_field_errors'][0] == 'date_start must be before date_end'
|
||||||
|
|
||||||
|
# different child, no overlap check
|
||||||
params = {
|
params = {
|
||||||
'guardian_first_name': 'John',
|
'guardian_first_name': 'John',
|
||||||
'guardian_last_name': 'Doe',
|
'guardian_last_name': 'Doe',
|
||||||
|
@ -59,7 +106,7 @@ def test_add_shared_custody_agenda(app, user, settings):
|
||||||
}
|
}
|
||||||
resp = app.post_json('/api/shared-custody/', params=params)
|
resp = app.post_json('/api/shared-custody/', params=params)
|
||||||
assert resp.json['data']['id'] != agenda.pk
|
assert resp.json['data']['id'] != agenda.pk
|
||||||
assert SharedCustodyAgenda.objects.filter(first_guardian=first_guardian).count() == 2
|
assert SharedCustodyAgenda.objects.filter(first_guardian=first_guardian).count() == 3
|
||||||
|
|
||||||
|
|
||||||
def test_add_shared_custody_agenda_with_rules(app, user, settings):
|
def test_add_shared_custody_agenda_with_rules(app, user, settings):
|
||||||
|
@ -184,7 +231,7 @@ def test_add_shared_custody_agenda_with_rules(app, user, settings):
|
||||||
assert resp.json['errors']['non_field_errors'][0] == 'Short holidays cannot be cut into quarters.'
|
assert resp.json['errors']['non_field_errors'][0] == 'Short holidays cannot be cut into quarters.'
|
||||||
|
|
||||||
|
|
||||||
def test_shared_custody_agenda_update_date_start(app, user, settings):
|
def test_shared_custody_agenda_update_dates(app, user, settings):
|
||||||
father = Person.objects.create(user_external_id='father_id', first_name='John', last_name='Doe')
|
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')
|
mother = Person.objects.create(user_external_id='mother_id', first_name='Jane', last_name='Doe')
|
||||||
child = Person.objects.create(user_external_id='child_id', first_name='James', last_name='Doe')
|
child = Person.objects.create(user_external_id='child_id', first_name='James', last_name='Doe')
|
||||||
|
@ -198,6 +245,54 @@ def test_shared_custody_agenda_update_date_start(app, user, settings):
|
||||||
|
|
||||||
agenda.refresh_from_db()
|
agenda.refresh_from_db()
|
||||||
assert agenda.date_start == datetime.date(year=2020, month=10, day=20)
|
assert agenda.date_start == datetime.date(year=2020, month=10, day=20)
|
||||||
|
assert agenda.date_end is None
|
||||||
|
|
||||||
|
resp = app.patch_json(
|
||||||
|
'/api/shared-custody/%s/' % agenda.pk, params={'date_start': '2020-10-20', 'date_end': '2021-01-01'}
|
||||||
|
)
|
||||||
|
assert resp.json['err'] == 0
|
||||||
|
|
||||||
|
agenda.refresh_from_db()
|
||||||
|
assert agenda.date_start == datetime.date(year=2020, month=10, day=20)
|
||||||
|
assert agenda.date_end == datetime.date(year=2021, month=1, day=1)
|
||||||
|
|
||||||
|
resp = app.patch_json(
|
||||||
|
'/api/shared-custody/%s/' % agenda.pk, params={'date_start': '2021-01-01', 'date_end': '2022-01-01'}
|
||||||
|
)
|
||||||
|
assert resp.json['err'] == 0
|
||||||
|
|
||||||
|
agenda.refresh_from_db()
|
||||||
|
assert agenda.date_start == datetime.date(year=2021, month=1, day=1)
|
||||||
|
assert agenda.date_end == datetime.date(year=2022, month=1, day=1)
|
||||||
|
|
||||||
|
resp = app.patch_json(
|
||||||
|
'/api/shared-custody/%s/' % agenda.pk, params={'date_start': '2021-01-01', 'date_end': None}
|
||||||
|
)
|
||||||
|
assert resp.json['err'] == 0
|
||||||
|
|
||||||
|
agenda.refresh_from_db()
|
||||||
|
assert agenda.date_start == datetime.date(year=2021, month=1, day=1)
|
||||||
|
assert agenda.date_end is None
|
||||||
|
|
||||||
|
SharedCustodyAgenda.objects.create(
|
||||||
|
first_guardian=father,
|
||||||
|
second_guardian=mother,
|
||||||
|
child=child,
|
||||||
|
date_start=datetime.date(year=2020, month=1, day=1),
|
||||||
|
date_end=datetime.date(year=2020, month=6, day=1),
|
||||||
|
)
|
||||||
|
|
||||||
|
resp = app.patch_json(
|
||||||
|
'/api/shared-custody/%s/' % agenda.pk, params={'date_start': '2020-01-01'}, status=400
|
||||||
|
)
|
||||||
|
assert 'overlap' in resp.json['errors']['non_field_errors'][0]
|
||||||
|
|
||||||
|
resp = app.patch_json(
|
||||||
|
'/api/shared-custody/%s/' % agenda.pk,
|
||||||
|
params={'date_start': '2020-10-20', 'date_end': '2019-10-20'},
|
||||||
|
status=400,
|
||||||
|
)
|
||||||
|
assert resp.json['errors']['non_field_errors'][0] == 'date_start must be before date_end'
|
||||||
|
|
||||||
resp = app.patch_json('/api/shared-custody/%s/' % agenda.pk, params={'first_guardian': 'xxx'}, status=400)
|
resp = app.patch_json('/api/shared-custody/%s/' % agenda.pk, params={'first_guardian': 'xxx'}, status=400)
|
||||||
app.patch_json('/api/shared-custody/%s/' % agenda.pk, params={}, status=400)
|
app.patch_json('/api/shared-custody/%s/' % agenda.pk, params={}, status=400)
|
||||||
|
|
Loading…
Reference in New Issue