passerelle/tests/test_toulouse_axel.py

4516 lines
190 KiB
Python

# passerelle - uniform access to multiple data sources and services
# Copyright (C) 2020 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import copy
import datetime
import decimal
import json
import os
import xml.etree.ElementTree as ET
from contextlib import contextmanager
from unittest import mock
import freezegun
import jsonschema
import pytest
import xmlschema
from django.core.cache import cache
import tests.utils
from passerelle.contrib.toulouse_axel import schemas
from passerelle.contrib.toulouse_axel.models import Link, Lock, ToulouseAxel
from passerelle.contrib.toulouse_axel.utils import (
csp_mapping,
lien_parente_mapping,
regime_mapping,
situation_familiale_mapping,
type_regime_mapping,
upperize,
)
from passerelle.contrib.utils.axel import AxelError, OperationResult
from passerelle.utils.jsonresponse import APIError
from passerelle.utils.soap import SOAPError
@pytest.fixture
def resource(db):
return tests.utils.make_resource(
ToulouseAxel, slug='test', wsdl_url='http://example.net/AXEL_WS/AxelWS.php?wsdl'
)
@pytest.fixture
def link_params():
return {
'IDDUI': 'XXX',
'PRENOM': 'John',
'NOM': 'Doe',
'NAISSANCE': '2010-10-10',
}
@pytest.fixture
def update_params():
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/update_family_info.json')
with open(filepath) as jsonfile:
content = jsonfile.read()
return json.loads(content)
@pytest.fixture
def family_data():
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/family_info.xml')
with open(filepath) as xml:
content = xml.read()
resp = (
'''
<?xml version="1.0"?>
<PORTAILSERVICE>
<RESULTAT>
<TYPE>RefFamilleDui</TYPE>
<STATUS>OK</STATUS>
<DATE>10/10/2010 10:10:01</DATE>
<COMMENTAIRES><![CDATA[]]></COMMENTAIRES>
</RESULTAT>
<DATA>
%s
</DATA>
</PORTAILSERVICE>
'''.strip()
% content
)
return schemas.ref_famille_dui.response_converter.decode(ET.fromstring(resp))['DATA']['PORTAIL']['DUI']
@pytest.fixture
def child_activities_data():
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/child_activities.xml')
with open(filepath) as xml:
content = xml.read()
resp = (
'''
<?xml version="1.0"?>
<PORTAILSERVICE>
<RESULTAT>
<TYPE>EnfantsActivites</TYPE>
<STATUS>OK</STATUS>
<DATE>10/10/2010 10:10:01</DATE>
<COMMENTAIRES><![CDATA[]]></COMMENTAIRES>
</RESULTAT>
<DATA>
%s
</DATA>
</PORTAILSERVICE>
'''.strip()
% content
)
return schemas.enfants_activites.response_converter.decode(ET.fromstring(resp))['DATA']['PORTAIL']['DUI']
@pytest.fixture
def flat_update_params():
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/flat_update_family_info.json')
with open(filepath) as jsonfile:
content = jsonfile.read()
return json.loads(content)
@pytest.fixture
def booking_params():
return {
'booking_start_date': '2020-04-13',
'booking_end_date': '2020-04-17',
'booking_list_MAT': [
'3535:MAT:A19P1M1:2020-04-13',
'3535:MAT:A19P1M1:2020-04-14',
'3535:MAT:A19P1M1:2020-04-16',
'3535:MAT:A19P1M1:2020-04-17',
],
'booking_list_MIDI': [
'3535:MIDI:A19P1M2:2020-04-13',
'3535:MIDI:A19P1M2:2020-04-14',
'3535:MIDI:A19P1M2:2020-04-16',
'3535:MIDI:A19P1M2:2020-04-17',
],
'booking_list_SOIR': ['3535:SOIR:A19P1M3:2020-04-13'],
'booking_list_GARD': ['3535:GARD:A19P1M4:2020-04-15'],
'child_id': '3535',
'regime': 'AV',
}
@pytest.fixture
def annual_booking_params():
return {
'booking_list_MAT': [
'3535:MAT:A19P1M1:monday',
'3535:MAT:A19P1M1:tuesday',
'3535:MAT:A19P1M1:thursday',
'3535:MAT:A19P1M1:friday',
],
'booking_list_MIDI': [
'3535:MIDI:A19P1M2:monday',
'3535:MIDI:A19P1M2:tuesday',
'3535:MIDI:A19P1M2:thursday',
'3535:MIDI:A19P1M2:friday',
],
'booking_list_SOIR': ['3535:SOIR:A19P1M3:monday'],
'booking_list_GARD': ['3535:GARD:A19P1M4:wednesday'],
'child_id': '3535',
'regime': 'AV',
'booking_date': '2019-08-01',
}
def test_lock(app, resource):
resp = app.get('/toulouse-axel/test/lock?key=&locker=', status=400)
assert resp.json['err_desc'] == "key is empty"
assert resp.json['err'] == 'bad-request'
assert Lock.objects.count() == 0
resp = app.get('/toulouse-axel/test/lock?key=foobar&locker=')
assert resp.json['err'] == 0
assert resp.json['key'] == 'foobar'
assert resp.json['locked'] is True
assert resp.json['locker'] == ''
assert resp.json['lock_date'] is not None
lock_date = resp.json['lock_date']
lock = Lock.objects.latest('pk')
assert lock.resource == resource
assert lock.key == 'foobar'
assert lock.locker == ''
# again
resp = app.get('/toulouse-axel/test/lock?key=foobar&locker=')
assert resp.json['err'] == 0
assert resp.json['key'] == 'foobar'
assert resp.json['locked'] is True
assert Lock.objects.count() == 1
assert resp.json['locker'] == ''
assert resp.json['lock_date'] == lock_date
def test_lock_with_locker(app, resource):
assert Lock.objects.count() == 0
resp = app.get('/toulouse-axel/test/lock?key=foobar&locker=something')
assert resp.json['err'] == 0
assert resp.json['key'] == 'foobar'
assert resp.json['locked'] is True
assert resp.json['locker'] == 'something'
assert resp.json['lock_date'] is not None
lock_date = resp.json['lock_date']
lock = Lock.objects.latest('pk')
assert lock.resource == resource
assert lock.key == 'foobar'
assert lock.locker == 'something'
# again
resp = app.get('/toulouse-axel/test/lock?key=foobar&locker=')
assert resp.json['err'] == 0
assert resp.json['key'] == 'foobar'
assert resp.json['locked'] is True
assert Lock.objects.count() == 1
assert resp.json['locker'] == 'something'
assert resp.json['lock_date'] == lock_date
def test_unlock(app, resource):
Lock.objects.create(resource=resource, key='foobar', locker='something')
resp = app.get('/toulouse-axel/test/unlock?key=foobar')
assert resp.json['err'] == 0
assert resp.json['key'] == 'foobar'
assert resp.json['locked'] is False
assert resp.json['locker'] == 'something'
assert resp.json['lock_date'] is not None
assert Lock.objects.count() == 0
# again
resp = app.get('/toulouse-axel/test/unlock?key=foobar')
assert resp.json['err'] == 0
assert resp.json['key'] == 'foobar'
assert resp.json['locked'] is False
assert 'locker' not in resp.json
assert 'lock_date' not in resp.json
assert Lock.objects.count() == 0
def test_locked(app, resource):
assert Lock.objects.count() == 0
resp = app.get('/toulouse-axel/test/locked?key=foobar')
assert resp.json['err'] == 0
assert resp.json['key'] == 'foobar'
assert resp.json['locked'] is False
assert 'locker' not in resp.json
assert 'lock_date' not in resp.json
Lock.objects.create(resource=resource, key='foobar', locker='something')
resp = app.get('/toulouse-axel/test/locked?key=foobar')
assert resp.json['err'] == 0
assert resp.json['key'] == 'foobar'
assert resp.json['locked'] is True
assert resp.json['locker'] == 'something'
assert resp.json['lock_date'] is not None
def test_operation_status_error(resource):
resp = '''
<?xml version="1.0"?>
<PORTAILSERVICE>
<RESULTAT>
<TYPE>RefVerifDui</TYPE>
<STATUS>NOK</STATUS>
<COMMENTAIRES><![CDATA[Foo reason]]></COMMENTAIRES>
</RESULTAT>
<DATA>
<PORTAIL/>
</DATA>
</PORTAILSERVICE>
'''.strip()
with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.soap_client') as client:
client.return_value.service.getData.return_value = resp
with pytest.raises(AxelError, match='Foo reason'):
schemas.ref_verif_dui(
resource,
{
'PORTAIL': {
'DUI': {
'IDDUI': 'XXX',
'IDPERSONNE': '42',
'PRENOM': 'John',
'NOM': 'Doe',
'NAISSANCE': '2010-10-10',
}
}
},
)
@contextmanager
def mock_getdata(content, operation):
with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.soap_client') as client:
resp = '''
<?xml version="1.0"?>
<PORTAILSERVICE>
<RESULTAT>
<TYPE>%s</TYPE>
<STATUS>OK</STATUS>
<DATE>10/10/2010 10:10:01</DATE>
<COMMENTAIRES><![CDATA[]]></COMMENTAIRES>
</RESULTAT>
<DATA>
%s
</DATA>
</PORTAILSERVICE>
'''.strip() % (
operation,
content,
)
client.return_value.service.getData.return_value = resp
yield
@pytest.mark.parametrize(
'content',
[
'<PORTAIL><DUIDATEGESTION/></PORTAIL>',
],
)
def test_operation_ref_date_gestion_dui(resource, content):
with mock_getdata(content, 'RefDateGestionDui'):
with pytest.raises(AxelError):
schemas.ref_date_gestion_dui(resource)
@pytest.mark.parametrize(
'content',
[
'<PORTAIL><DUI/></PORTAIL>',
'<PORTAIL><DUI><CODE>foo</CODE></DUI></PORTAIL>',
'<PORTAIL><DUI><CODE>42</CODE></DUI></PORTAIL>',
],
)
def test_operation_ref_verif_dui(resource, content):
with mock_getdata(content, 'RefVerifDui'):
with pytest.raises(AxelError):
schemas.ref_verif_dui(
resource,
{
'PORTAIL': {
'DUI': {
'PRENOM': 'John',
'NOM': 'Doe',
'NAISSANCE': '2010-10-10',
}
}
},
)
@pytest.mark.parametrize(
'content',
[
'<PORTAIL><DUI/></PORTAIL>',
],
)
def test_operation_ref_famille_dui(resource, content):
with mock_getdata(content, 'RefFamilleDui'):
with pytest.raises(AxelError):
schemas.ref_famille_dui(
resource,
{
'PORTAIL': {
'DUI': {
'IDDUI': 'XXX',
}
}
},
)
@pytest.mark.parametrize(
'content',
[
'<PORTAIL><DUI/></PORTAIL>',
],
)
def test_operation_form_maj_famille_dui(resource, content):
with mock_getdata(content, 'FormMajFamilleDui'):
with pytest.raises(AxelError):
schemas.form_maj_famille_dui(
resource,
{
'PORTAIL': {
'DUI': {
'IDDUI': 'XXX',
}
}
},
)
@pytest.mark.parametrize(
'content',
[
'<PORTAIL><DUI/></PORTAIL>',
],
)
def test_operation_ref_facture_a_payer(resource, content):
with mock_getdata(content, 'RefFactureAPayer'):
with pytest.raises(AxelError):
schemas.ref_facture_a_payer(
resource,
{
'PORTAIL': {
'DUI': {
'IDDUI': 'XXX',
}
}
},
)
@pytest.mark.parametrize(
'content',
[
'<PORTAIL><LISTFACTURE/></PORTAIL>',
],
)
def test_operation_list_dui_factures(resource, content):
with mock_getdata(content, 'ListeDuiFacturesPayeesRecettees'):
with pytest.raises(AxelError):
schemas.list_dui_factures(resource, {'LISTFACTURE': {'NUMDUI': 'XXX', 'DEBUT': '1970-01-01'}})
@pytest.mark.parametrize(
'content',
[
"<PORTAIL><PDF FOO='BAR'></PDF></PORTAIL>",
],
)
def test_operation_ref_facture_pdf(resource, content):
with mock_getdata(content, 'RefFacturePDF'):
with pytest.raises(AxelError):
schemas.ref_facture_pdf(
resource,
{
'PORTAIL': {
'FACTUREPDF': {
'IDFACTURE': 42,
}
}
},
)
@pytest.mark.parametrize(
'content',
[
'<PORTAIL><DUI/></PORTAIL>',
],
)
def test_operation_form_paiement_dui(resource, content):
with mock_getdata(content, 'FormPaiementDui'):
with pytest.raises(AxelError):
schemas.form_paiement_dui(
resource,
{
'PORTAIL': {
'DUI': {
'IDFACTURE': '42',
'IDREGIEENCAISSEMENT': '',
'MONTANTPAYE': '42.42',
'DATEPAIEMENT': '01/01/2020 12:12:12',
'REFERENCE': '42',
}
}
},
)
@pytest.mark.parametrize(
'content',
[
'<PORTAIL><DUI/></PORTAIL>',
],
)
def test_operation_enfants_activites(resource, content):
with mock_getdata(content, 'EnfantsActivites'):
with pytest.raises(AxelError):
schemas.enfants_activites(
resource,
{
'DUI': {
'IDDUI': 'XXX',
'ANNEEREFERENCE': '2042',
'TYPESACTIVITES': 'MAT,MIDI,SOIR,GARD',
}
},
)
@pytest.mark.parametrize(
'content',
[
'<PORTAIL><DUI/></PORTAIL>',
],
)
def test_operation_reservation_periode(resource, content):
with mock_getdata(content, 'ReservationPeriode'):
with pytest.raises(AxelError):
schemas.reservation_periode(
resource,
{
'PORTAIL': {
'DUI': {
'IDDUI': 'XXX',
}
}
},
)
def test_management_dates_endpoint_axel_error(app, resource):
with mock.patch('passerelle.contrib.toulouse_axel.schemas.ref_date_gestion_dui') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get('/toulouse-axel/test/management_dates')
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
assert resp.json['data'] == {'xml_request': None, 'xml_response': None}
def test_management_dates_endpoint(app, resource):
content = '''<PORTAIL>
<DUIDATEGESTION>
<REPORT-REVENUS>08/08/2019</REPORT-REVENUS>
<EXTRACTION-FAMILLES>18/10/2019</EXTRACTION-FAMILLES>
<EXTRACTION-CAFPRO>18/01/2020</EXTRACTION-CAFPRO>
</DUIDATEGESTION>
</PORTAIL>'''
with mock_getdata(content, 'RefDateGestionDui'):
resp = app.get('/toulouse-axel/test/management_dates')
assert set(resp.json.keys()) == {'err', 'data'}
assert resp.json['err'] == 0
assert set(resp.json['data'].keys()) == {
'REPORT-REVENUS',
'report_revenus',
'EXTRACTION-FAMILLES',
'extraction_familles',
'EXTRACTION-CAFPRO',
'extraction_cafpro',
}
# again - data are in cache
resp = app.get('/toulouse-axel/test/management_dates')
assert set(resp.json.keys()) == {'err', 'data'}
assert resp.json['err'] == 0
assert set(resp.json['data'].keys()) == {
'REPORT-REVENUS',
'report_revenus',
'EXTRACTION-FAMILLES',
'extraction_familles',
'EXTRACTION-CAFPRO',
'extraction_cafpro',
}
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_management_dates'
) as management_dates:
management_dates.return_value = {'foo': 'bar'}
resp = app.get('/toulouse-axel/test/management_dates')
assert set(resp.json.keys()) == {'err', 'data'}
assert resp.json['err'] == 0
assert resp.json['data'] == {'foo': 'bar'}
def test_link_endpoint_nameid_empty(app, resource, link_params):
resp = app.post_json('/toulouse-axel/test/link?NameID=', params=link_params, status=400)
assert resp.json['err_desc'] == "NameID is empty"
assert resp.json['err'] == 'bad-request'
def test_link_endpoint_axel_error(app, resource, link_params):
with mock.patch('passerelle.contrib.toulouse_axel.schemas.ref_verif_dui') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.post_json('/toulouse-axel/test/link?NameID=yyy', params=link_params)
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
assert resp.json['data'] == {'xml_request': None, 'xml_response': None}
# test xml_request and xml_response only for this endpoint
xml_request = """<PORTAIL>
<DUI>
<IDDUI>XXX</IDDUI>
<IDPERSONNE />
<NOM>Doe</NOM>
<PRENOM>John</PRENOM>
<NAISSANCE>10/10/2010</NAISSANCE>
</DUI>
</PORTAIL>
"""
with mock_getdata('', 'RefVerifDui'):
with mock.patch('xmlschema.XMLSchema.validate') as xml_validate:
xml_validate.side_effect = xmlschema.XMLSchemaValidationError(None, None)
resp = app.post_json('/toulouse-axel/test/link?NameID=yyy', params=link_params)
assert resp.json['err_desc'].startswith("Axel error: invalid request")
assert resp.json['err'] == 'error'
assert resp.json['data']['xml_request'] == xml_request
assert resp.json['data']['xml_response'] is None
xml_response = """<PORTAILSERVICE>
<RESULTAT>
<TYPE>RefVerifDui</TYPE>
<STATUS>NOK</STATUS>
<COMMENTAIRES>Foo reason</COMMENTAIRES>
</RESULTAT>
<DATA>
<PORTAIL />
</DATA>
</PORTAILSERVICE>"""
response = """
<?xml version="1.0"?>
<PORTAILSERVICE>
<RESULTAT>
<TYPE>RefVerifDui</TYPE>
<STATUS>NOK</STATUS>
<COMMENTAIRES><![CDATA[Foo reason]]></COMMENTAIRES>
</RESULTAT>
<DATA>
<PORTAIL/>
</DATA>
</PORTAILSERVICE>
""".strip()
with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.soap_client') as client:
client.return_value.service.getData.return_value = response
resp = app.post_json('/toulouse-axel/test/link?NameID=yyy', params=link_params)
assert resp.json['err_desc'] == 'Axel error: Foo reason'
assert resp.json['err'] == 'error'
assert resp.json['data']['xml_request'] == xml_request
assert resp.json['data']['xml_response'] == xml_response
content = """<PORTAIL>
<DUI>
<IDDUI>XXX</IDDUI>
<IDPERSONNE>42</IDPERSONNE>
<CODE>2</CODE>
</DUI>
</PORTAIL>"""
xml_response = (
"""<PORTAILSERVICE>
<RESULTAT>
<TYPE>RefVerifDui</TYPE>
<STATUS>OK</STATUS>
<DATE>10/10/2010 10:10:01</DATE>
<COMMENTAIRES />
</RESULTAT>
<DATA>
%s
</DATA>
</PORTAILSERVICE>"""
% content
)
with mock_getdata(content, 'RefVerifDui'):
with mock.patch('passerelle.contrib.utils.axel.AxelSchema.decode') as decode:
decode.side_effect = xmlschema.XMLSchemaValidationError(None, None)
resp = app.post_json('/toulouse-axel/test/link?NameID=yyy', params=link_params)
assert resp.json['err_desc'].startswith("Axel error: invalid response")
assert resp.json['err'] == 'error'
assert resp.json['data']['xml_request'] == xml_request
assert resp.json['data']['xml_response'] == xml_response
with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.soap_client') as client:
client.side_effect = SOAPError('SOAP service is down')
resp = app.post_json('/toulouse-axel/test/link?NameID=yyy', params=link_params)
assert resp.json['err_desc'] == "SOAP service is down"
@pytest.mark.parametrize(
'xml_response',
[
'<IDDUI>XXX</IDDUI><IDPERSONNE/><CODE>0</CODE>',
'<IDDUI>XXX</IDDUI><IDPERSONNE>42</IDPERSONNE><CODE>1</CODE>',
'<IDDUI>XXX</IDDUI><IDPERSONNE>42</IDPERSONNE><CODE>4</CODE>',
],
)
def test_link_endpoint_no_result(app, resource, link_params, xml_response):
content = (
'''<PORTAIL>
<DUI>
%s
</DUI>
</PORTAIL>'''
% xml_response
)
with mock_getdata(content, 'RefVerifDui'):
resp = app.post_json('/toulouse-axel/test/link?NameID=yyy', params=link_params)
assert resp.json['err_desc'] == "Person not found"
assert resp.json['err'] == 'not-found'
def test_link_endpoint_conflict(app, resource, link_params):
content = '''<PORTAIL>
<DUI>
<IDDUI>XXX</IDDUI>
<IDPERSONNE>42</IDPERSONNE>
<CODE>2</CODE>
</DUI>
</PORTAIL>'''
# existing link but dui is wrong
link = Link.objects.create(resource=resource, name_id='yyy', dui='YYY', person_id='42')
with mock_getdata(content, 'RefVerifDui'):
resp = app.post_json('/toulouse-axel/test/link?NameID=yyy', params=link_params)
assert resp.json['err_desc'] == "Data conflict"
assert resp.json['err'] == 'conflict'
# existing link but person_id is wrong
link.dui = 'XXX'
link.person_id = '35'
link.save()
with mock_getdata(content, 'RefVerifDui'):
resp = app.post_json('/toulouse-axel/test/link?NameID=yyy', params=link_params)
assert resp.json['err_desc'] == "Data conflict"
assert resp.json['err'] == 'conflict'
@pytest.mark.parametrize('code', [2, 3])
def test_link_endpoint(app, resource, link_params, code):
content = (
'''<PORTAIL>
<DUI>
<IDDUI>XXX</IDDUI>
<IDPERSONNE>42</IDPERSONNE>
<CODE>%s</CODE>
</DUI>
</PORTAIL>'''
% code
)
with mock_getdata(content, 'RefVerifDui'):
resp = app.post_json('/toulouse-axel/test/link?NameID=yyy', params=link_params)
assert set(resp.json.keys()) == {'err', 'link', 'created', 'dui', 'data'}
assert resp.json['err'] == 0
assert resp.json['dui'] == 'XXX'
assert resp.json['created'] is True
assert 'xml_request' in resp.json['data']
assert 'xml_response' in resp.json['data']
# again
with mock_getdata(content, 'RefVerifDui'):
resp = app.post_json('/toulouse-axel/test/link?NameID=yyy', params=link_params)
assert set(resp.json.keys()) == {'err', 'link', 'created', 'dui', 'data'}
assert resp.json['err'] == 0
assert resp.json['dui'] == 'XXX'
assert resp.json['created'] is False # link already exists
assert 'xml_request' in resp.json['data']
assert 'xml_response' in resp.json['data']
def test_unlink_endpoint_no_result(app, resource):
resp = app.post('/toulouse-axel/test/unlink?NameID=yyy')
assert resp.json['err_desc'] == "Person not found"
assert resp.json['err'] == 'not-found'
def test_unlink_endpoint(app, resource):
link = Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
resp = app.post('/toulouse-axel/test/unlink?NameID=yyy')
assert Link.objects.exists() is False
assert resp.json['err'] == 0
assert resp.json['link'] == link.pk
assert resp.json['dui'] == 'XXX'
assert resp.json['deleted'] is True
def test_active_dui_endpoint_axel_error(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with mock.patch('passerelle.contrib.toulouse_axel.schemas.ref_famille_dui') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get('/toulouse-axel/test/active_dui?NameID=yyy')
assert resp.json['err_desc'] == "No family info"
assert resp.json['err'] == 'no-family-info'
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/family_info.xml')
with open(filepath) as xml:
content = xml.read()
with mock_getdata(content, 'RefFamilleDui'):
with mock.patch('passerelle.contrib.toulouse_axel.schemas.ref_verif_dui') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get('/toulouse-axel/test/active_dui?NameID=yyy')
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
def test_active_dui_endpoint_no_result(app, resource, family_data):
resp = app.get('/toulouse-axel/test/active_dui?NameID=yyy')
assert resp.json['err_desc'] == "Unknown NameID"
assert resp.json['err'] == 'unknown'
def test_active_dui_endpoint_wrong_rl(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='1234')
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/family_info.xml')
with open(filepath) as xml:
content = xml.read()
with mock_getdata(content, 'RefFamilleDui'):
resp = app.get('/toulouse-axel/test/active_dui?NameID=yyy')
assert resp.json['err_desc'] == "No corresponding RL"
assert resp.json['err'] == 'no-rl'
@pytest.mark.parametrize(
'xml_response,code',
[
('<IDDUI>XXX</IDDUI><IDPERSONNE/><CODE>0</CODE>', 0),
('<IDDUI>XXX</IDDUI><IDPERSONNE>42</IDPERSONNE><CODE>1</CODE>', 1),
('<IDDUI>XXX</IDDUI><IDPERSONNE>42</IDPERSONNE><CODE>4</CODE>', 4),
],
)
def test_active_dui_endpoint_wrong_dui_code(app, resource, family_data, xml_response, code):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
content = (
'''<PORTAIL>
<DUI>
%s
</DUI>
</PORTAIL>'''
% xml_response
)
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data
):
with mock_getdata(content, 'RefVerifDui'):
resp = app.get('/toulouse-axel/test/active_dui?NameID=yyy')
assert resp.json['err_desc'] == "Wrong DUI status"
assert resp.json['err'] == 'dui-code-error-%s' % code
@pytest.mark.parametrize('code', [2, 3])
def test_active_dui_endpoint(app, resource, family_data, code):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
content = (
'''<PORTAIL>
<DUI>
<IDDUI>XXX</IDDUI>
<IDPERSONNE>42</IDPERSONNE>
<CODE>%s</CODE>
</DUI>
</PORTAIL>'''
% code
)
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data
):
with mock_getdata(content, 'RefVerifDui'):
resp = app.get('/toulouse-axel/test/active_dui?NameID=yyy')
assert resp.json['err'] == 0
assert set(resp.json['data'].keys()) == {
'ADRESSE',
'CODEMISEAJOUR',
'DEMATFACTURES',
'ENFANT',
'IDDUI',
'NBENFANTACTIF',
'NBRLACTIF',
'REACTUALISATIONENLIGNE',
'REVENUS',
'RL1',
'RL2',
'SITUATIONFAMILIALE',
'TELFIXE',
}
def test_referential_endpoint_no_result(app, resource):
resp = app.get('/toulouse-axel/test/referential/foo/')
assert resp.json['err_desc'] == "Referential not found"
assert resp.json['err'] == 'not-found'
@pytest.mark.parametrize(
'code, mapping',
[
('situation_familiale', situation_familiale_mapping),
('csp', csp_mapping),
('lien_parente', lien_parente_mapping),
('type_regime', type_regime_mapping),
('regime', regime_mapping),
],
)
def test_referential_endpoint(app, resource, code, mapping):
resp = app.get('/toulouse-axel/test/referential/%s/' % code)
expected = [{'id': k, 'text': v} for k, v in mapping.items()]
assert resp.json['data'] == expected
def test_family_info_endpoint_axel_error(app, resource, family_data):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with mock.patch('passerelle.contrib.toulouse_axel.schemas.ref_famille_dui') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get('/toulouse-axel/test/family_info?NameID=yyy')
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/family_info.xml')
with open(filepath) as xml:
content = xml.read()
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_management_dates'
) as management_dates:
management_dates.side_effect = APIError('Axel error: FooBar')
with mock_getdata(content, 'RefFamilleDui'):
resp = app.get('/toulouse-axel/test/family_info?NameID=yyy')
assert resp.json['err_desc'] == "Axel error: FooBar"
def test_family_info_endpoint_no_result(app, resource):
resp = app.get('/toulouse-axel/test/family_info?NameID=yyy')
assert resp.json['err_desc'] == "Person not found"
assert resp.json['err'] == 'not-found'
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with mock.patch('passerelle.contrib.toulouse_axel.schemas.ref_famille_dui') as operation:
operation.return_value = OperationResult(
json_response={'DATA': {'PORTAIL': None}}, xml_request='', xml_response=''
)
resp = app.get('/toulouse-axel/test/family_info?NameID=yyy')
assert resp.json['err_desc'] == "Family not found"
assert resp.json['err'] == 'not-found'
@freezegun.freeze_time('2020-06-30')
def test_family_info_endpoint(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/family_info.xml')
with open(filepath) as xml:
content = xml.read()
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_management_dates'
) as management_dates:
management_dates.return_value = {'foo': 'bar'}
with mock_getdata(content, 'RefFamilleDui'):
resp = app.get('/toulouse-axel/test/family_info?NameID=yyy')
assert resp.json['err'] == 0
assert set(resp.json['data'].keys()) == {
'ADRESSE',
'CODEMISEAJOUR',
'DEMATFACTURES',
'ENFANT',
'IDDUI',
'NBENFANTACTIF',
'NBRLACTIF',
'REACTUALISATIONENLIGNE',
'REVENUS',
'RL1',
'RL2',
'SITUATIONFAMILIALE',
'SITUATIONFAMILIALE_label',
'TELFIXE',
'management_dates',
'annee_reference',
'annee_reference_short',
'annee_reference_label',
}
assert resp.json['data']['ENFANT'][0]['id'] == '4242'
assert resp.json['data']['ENFANT'][0]['text'] == 'foo foo'
assert resp.json['data']['ENFANT'][0]['CONTACT'][0]['id'] == 0
assert resp.json['data']['ENFANT'][0]['CONTACT'][0]['text'] == 'foo foo'
assert resp.json['data']['ENFANT'][0]['CONTACT'][1]['id'] == 1
assert resp.json['data']['ENFANT'][0]['CONTACT'][1]['text'] == 'foo2 foo2'
assert resp.json['data']['ENFANT'][0]['CONTACT'][2]['id'] == 2
assert resp.json['data']['ENFANT'][0]['CONTACT'][2]['text'] == 'foo3 foo3'
assert resp.json['data']['ENFANT'][1]['id'] == '3535'
assert resp.json['data']['ENFANT'][1]['text'] == 'foo foo'
assert resp.json['data']['management_dates'] == {'foo': 'bar'}
assert resp.json['data']['annee_reference'] == 2019
assert resp.json['data']['annee_reference_short'] == '19'
assert resp.json['data']['annee_reference_label'] == '2019/2020'
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.are_children_registered'
) as registered:
registered.return_value = {'4242': True}
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_management_dates'
) as management_dates:
management_dates.return_value = {'foo': 'bar'}
with mock_getdata(content, 'RefFamilleDui'):
resp = app.get('/toulouse-axel/test/family_info?NameID=yyy')
assert resp.json['err'] == 0
assert resp.json['data']['ENFANT'][0]['clae_cantine_current'] is True
assert resp.json['data']['ENFANT'][1]['clae_cantine_current'] is None
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.are_children_registered'
) as registered:
registered.return_value = {}
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_management_dates'
) as management_dates:
management_dates.return_value = {'foo': 'bar'}
with mock_getdata(content, 'RefFamilleDui'):
resp = app.get('/toulouse-axel/test/family_info?NameID=yyy')
assert resp.json['err'] == 0
assert resp.json['data']['ENFANT'][0]['clae_cantine_current'] is None
assert resp.json['data']['ENFANT'][1]['clae_cantine_current'] is None
assert resp.json['data']['SITUATIONFAMILIALE'] == 'S'
assert resp.json['data']['SITUATIONFAMILIALE_label'] == 'Séparé (e)'
assert resp.json['data']['RL1']['CSP'] == 'ETU'
assert resp.json['data']['RL1']['CSP_label'] == 'Etudiants'
assert resp.json['data']['RL2']['CSP'] == 'EMP'
assert resp.json['data']['RL2']['CSP_label'] == 'Employés'
assert resp.json['data']['ENFANT'][0]['CONTACT'][0]['LIENPARENTE'] == 'GRP1'
assert resp.json['data']['ENFANT'][0]['CONTACT'][0]['LIENPARENTE_label'] == 'Grands-parents paternels'
assert resp.json['data']['ENFANT'][0]['CONTACT'][1]['LIENPARENTE'] is None
assert resp.json['data']['ENFANT'][0]['CONTACT'][1]['LIENPARENTE_label'] is None
assert resp.json['data']['REVENUS']['TYPEREGIME'] == 'GENE'
assert resp.json['data']['REVENUS']['TYPEREGIME_label'] == 'Régime général'
# a DUI with less data
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/family_info_light.xml')
with open(filepath) as xml:
content = xml.read()
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_management_dates'
) as management_dates:
management_dates.return_value = {'foo': 'bar'}
with mock_getdata(content, 'RefFamilleDui'):
resp = app.get('/toulouse-axel/test/family_info?NameID=yyy')
assert resp.json['err'] == 0
assert set(resp.json['data'].keys()) == {
'ADRESSE',
'CODEMISEAJOUR',
'DEMATFACTURES',
'ENFANT',
'IDDUI',
'NBENFANTACTIF',
'NBRLACTIF',
'REACTUALISATIONENLIGNE',
'REVENUS',
'RL1',
'SITUATIONFAMILIALE',
'SITUATIONFAMILIALE_label',
'TELFIXE',
'management_dates',
'annee_reference',
'annee_reference_short',
'annee_reference_label',
}
assert resp.json['data']['ADRESSE'] is None
def test_children_info_endpoint_axel_error(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with mock.patch('passerelle.contrib.toulouse_axel.schemas.ref_famille_dui') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get('/toulouse-axel/test/children_info?NameID=yyy')
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
def test_children_info_endpoint_no_result(app, resource):
resp = app.get('/toulouse-axel/test/children_info?NameID=yyy')
assert resp.json['err_desc'] == "Person not found"
assert resp.json['err'] == 'not-found'
def test_children_info_endpoint(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/family_info.xml')
with open(filepath) as xml:
content = xml.read()
with mock_getdata(content, 'RefFamilleDui'):
resp = app.get('/toulouse-axel/test/children_info?NameID=yyy')
assert resp.json['err'] == 0
assert len(resp.json['data']) == 2
assert resp.json['data'][0]['id'] == '4242'
assert resp.json['data'][0]['text'] == 'foo foo'
assert resp.json['data'][0]['CONTACT'][0]['id'] == 0
assert resp.json['data'][0]['CONTACT'][0]['text'] == 'foo foo'
assert resp.json['data'][0]['CONTACT'][1]['id'] == 1
assert resp.json['data'][0]['CONTACT'][1]['text'] == 'foo2 foo2'
assert resp.json['data'][0]['CONTACT'][2]['id'] == 2
assert resp.json['data'][0]['CONTACT'][2]['text'] == 'foo3 foo3'
assert resp.json['data'][1]['id'] == '3535'
assert resp.json['data'][1]['text'] == 'foo foo'
def test_child_info_endpoint_axel_error(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with mock.patch('passerelle.contrib.toulouse_axel.schemas.ref_famille_dui') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get('/toulouse-axel/test/child_info?NameID=yyy&idpersonne=zzz')
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
def test_child_info_endpoint_no_result(app, resource):
resp = app.get('/toulouse-axel/test/child_info?NameID=yyy&idpersonne=zzz')
assert resp.json['err_desc'] == "Person not found"
assert resp.json['err'] == 'not-found'
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/family_info.xml')
with open(filepath) as xml:
content = xml.read()
with mock_getdata(content, 'RefFamilleDui'):
resp = app.get('/toulouse-axel/test/child_info?NameID=yyy&idpersonne=zzz')
assert resp.json['err_desc'] == "Child not found"
assert resp.json['err'] == 'not-found'
def test_child_info_endpoint(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/family_info.xml')
with open(filepath) as xml:
content = xml.read()
with mock_getdata(content, 'RefFamilleDui'):
resp = app.get('/toulouse-axel/test/child_info?NameID=yyy&idpersonne=4242')
assert resp.json['err'] == 0
assert set(resp.json['data'].keys()) == {
'id',
'text',
'ASSURANCE',
'CONTACT',
'DATENAISSANCE',
'IDPERSONNE',
'PRENOM',
'PRENOMMERE',
'PRENOMPERE',
'NOM',
'NOMMERE',
'NOMPERE',
'RATTACHEAUTREDUI',
'SANITAIRE',
'SEXE',
'clae_cantine_current',
}
assert resp.json['data']['id'] == '4242'
assert resp.json['data']['text'] == 'foo foo'
assert resp.json['data']['CONTACT'][0]['id'] == 0
assert resp.json['data']['CONTACT'][0]['text'] == 'foo foo'
assert resp.json['data']['CONTACT'][1]['id'] == 1
assert resp.json['data']['CONTACT'][1]['text'] == 'foo2 foo2'
assert resp.json['data']['CONTACT'][2]['id'] == 2
assert resp.json['data']['CONTACT'][2]['text'] == 'foo3 foo3'
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.are_children_registered'
) as registered:
registered.return_value = {'4242': True}
with mock_getdata(content, 'RefFamilleDui'):
resp = app.get('/toulouse-axel/test/child_info?NameID=yyy&idpersonne=4242')
assert resp.json['err'] == 0
assert resp.json['data']['clae_cantine_current'] is True
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.are_children_registered'
) as registered:
registered.return_value = {}
with mock_getdata(content, 'RefFamilleDui'):
resp = app.get('/toulouse-axel/test/child_info?NameID=yyy&idpersonne=4242')
assert resp.json['err'] == 0
assert resp.json['data']['clae_cantine_current'] is None
assert resp.json['data']['CONTACT'][0]['LIENPARENTE'] == 'GRP1'
assert resp.json['data']['CONTACT'][0]['LIENPARENTE_label'] == 'Grands-parents paternels'
assert resp.json['data']['CONTACT'][1]['LIENPARENTE'] is None
assert resp.json['data']['CONTACT'][1]['LIENPARENTE_label'] is None
def test_child_contacts_info_endpoint_axel_error(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with mock.patch('passerelle.contrib.toulouse_axel.schemas.ref_famille_dui') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get('/toulouse-axel/test/child_contacts_info?NameID=yyy&idpersonne=zzz')
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
def test_child_contacts_info_endpoint_no_result(app, resource):
resp = app.get('/toulouse-axel/test/child_contacts_info?NameID=yyy&idpersonne=zzz')
assert resp.json['err_desc'] == "Person not found"
assert resp.json['err'] == 'not-found'
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/family_info.xml')
with open(filepath) as xml:
content = xml.read()
with mock_getdata(content, 'RefFamilleDui'):
resp = app.get('/toulouse-axel/test/child_contacts_info?NameID=yyy&idpersonne=zzz')
assert resp.json['err_desc'] == "Child not found"
assert resp.json['err'] == 'not-found'
def test_child_contacts_info_endpoint(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/family_info.xml')
with open(filepath) as xml:
content = xml.read()
with mock_getdata(content, 'RefFamilleDui'):
resp = app.get('/toulouse-axel/test/child_contacts_info?NameID=yyy&idpersonne=4242')
assert resp.json['err'] == 0
assert len(resp.json['data']) == 3
assert resp.json['data'][0]['id'] == 0
assert resp.json['data'][0]['text'] == 'foo foo'
assert resp.json['data'][1]['id'] == 1
assert resp.json['data'][1]['text'] == 'foo2 foo2'
assert resp.json['data'][2]['id'] == 2
assert resp.json['data'][2]['text'] == 'foo3 foo3'
with mock_getdata(content, 'RefFamilleDui'):
resp = app.get('/toulouse-axel/test/child_contacts_info?NameID=yyy&idpersonne=3535')
assert resp.json['err'] == 0
assert len(resp.json['data']) == 1
assert resp.json['data'][0]['id'] == 0
assert resp.json['data'][0]['text'] == 'foo foo'
def test_children_contacts_info_endpoint(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/family_info.xml')
with open(filepath) as xml:
content = xml.read()
with mock_getdata(content, 'RefFamilleDui'):
resp = app.get('/toulouse-axel/test/children_contacts_info?NameID=yyy')
assert resp.json['err'] == 0
assert len(resp.json['data']) == 3
assert {x['text'] for x in resp.json['data']} == {'foo foo', 'foo2 foo2', 'foo3 foo3'}
assert {x['id'] for x in resp.json['data']} == {0, 1, 2}
def test_update_family_info_endpoint_axel_error(app, resource, update_params, family_data):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with mock.patch('passerelle.contrib.toulouse_axel.schemas.form_maj_famille_dui') as operation:
operation.side_effect = AxelError('FooBar')
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data
):
resp = app.post_json('/toulouse-axel/test/update_family_info?NameID=yyy', params=update_params)
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
assert 'error_post_data' in resp.json['data']
def test_update_family_info_endpoint_no_result(app, resource, update_params):
resp = app.post_json('/toulouse-axel/test/update_family_info?NameID=yyy', params=update_params)
assert resp.json['err_desc'] == "Person not found"
assert resp.json['err'] == 'not-found'
def test_update_family_info_endpoint(app, resource, update_params, family_data):
link = Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
content = "<PORTAIL/>"
with mock_getdata(content, 'FormMajFamilleDui'):
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data
):
resp = app.post_json('/toulouse-axel/test/update_family_info?NameID=yyy', params=update_params)
assert resp.json['err'] == 0
assert resp.json['dui'] == 'XXX'
assert resp.json['updated'] is True
assert 'data' in resp.json
assert 'xml_request' in resp.json['data']
assert 'xml_response' in resp.json['data']
with mock.patch('passerelle.contrib.toulouse_axel.schemas.form_maj_famille_dui') as operation:
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data
):
resp = app.post_json('/toulouse-axel/test/update_family_info?NameID=yyy', params=update_params)
assert operation.call_args_list[0][0][1]['PORTAIL']['DUI']['IDDUI'] == 'XXX'
assert operation.call_args_list[0][0][1]['PORTAIL']['DUI'][
'DATEDEMANDE'
] == datetime.date.today().strftime('%Y-%m-%d')
assert operation.call_args_list[0][0][1]['PORTAIL']['DUI']['QUIACTUALISEDUI'] == '1'
link.person_id = '35'
link.save()
with mock.patch('passerelle.contrib.toulouse_axel.schemas.form_maj_famille_dui') as operation:
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data
):
resp = app.post_json('/toulouse-axel/test/update_family_info?NameID=yyy', params=update_params)
assert operation.call_args_list[0][0][1]['PORTAIL']['DUI']['IDDUI'] == 'XXX'
assert operation.call_args_list[0][0][1]['PORTAIL']['DUI'][
'DATEDEMANDE'
] == datetime.date.today().strftime('%Y-%m-%d')
assert operation.call_args_list[0][0][1]['PORTAIL']['DUI']['QUIACTUALISEDUI'] == '2'
def test_update_family_info_flat_endpoint(app, resource, flat_update_params, family_data):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
content = "<PORTAIL/>"
with mock_getdata(content, 'FormMajFamilleDui'):
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data
):
resp = app.post_json(
'/toulouse-axel/test/update_family_info?NameID=yyy', params=flat_update_params
)
assert resp.json['err'] == 0
assert resp.json['dui'] == 'XXX'
assert resp.json['updated'] is True
assert 'data' in resp.json
assert 'xml_request' in resp.json['data']
assert 'xml_response' in resp.json['data']
def test_sanitize_update_family_data_missing_rl_fields(app, resource, update_params, family_data):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
json_schema = schemas.UPDATE_FAMILY_SCHEMA
full_update_params = copy.deepcopy(update_params)
for key in ['IDPERSONNE', 'NOM', 'PRENOM', 'NOMJEUNEFILLE', 'DATENAISSANCE', 'CIVILITE']:
assert key not in full_update_params['RL1']
assert key not in full_update_params['RL2']
resource.pre_sanitize_update_family_data(post_data=full_update_params)
jsonschema.validate(full_update_params, json_schema)
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data
):
resource.sanitize_update_family_data(dui='XXX', post_data=full_update_params)
for key in ['IDPERSONNE', 'NOM', 'PRENOM', 'NOMJEUNEFILLE', 'DATENAISSANCE', 'CIVILITE']:
assert full_update_params['RL1'][key] == family_data['RL1'][key]
assert full_update_params['RL2'][key] == family_data['RL2'][key]
assert full_update_params['RL1']['INDICATEURRL'] == '1'
assert full_update_params['RL2']['INDICATEURRL'] == '2'
def test_sanitize_update_family_data_missing_revenus_fields(app, resource, update_params, family_data):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
json_schema = schemas.UPDATE_FAMILY_SCHEMA
full_update_params = copy.deepcopy(update_params)
assert 'NBENFANTSACHARGE' not in update_params['REVENUS']
resource.pre_sanitize_update_family_data(post_data=full_update_params)
jsonschema.validate(full_update_params, json_schema)
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data
):
resource.sanitize_update_family_data(dui='XXX', post_data=full_update_params)
assert full_update_params['REVENUS']['NBENFANTSACHARGE'] == family_data['REVENUS']['NBENFANTSACHARGE']
# if revenus are not set in Axel
full_update_params = copy.deepcopy(update_params)
family_data.pop('REVENUS')
resource.pre_sanitize_update_family_data(post_data=full_update_params)
jsonschema.validate(full_update_params, json_schema)
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data
):
resource.sanitize_update_family_data(dui='XXX', post_data=full_update_params)
assert full_update_params['REVENUS']['NBENFANTSACHARGE'] is None
def test_pre_sanitize_update_upperize(app, resource, update_params):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
json_schema = schemas.UPDATE_FAMILY_SCHEMA
def check_upper(data):
if isinstance(data, dict):
for val in data.values():
check_upper(val)
if isinstance(data, list):
for val in data:
check_upper(val)
if isinstance(data, str):
assert data == data.upper()
resource.pre_sanitize_update_family_data(post_data=update_params)
jsonschema.validate(update_params, json_schema)
check_upper(update_params)
assert upperize('something with an accent é') == 'SOMETHING WITH AN ACCENT E'
def test_pre_sanitize_update_family_data_adresse(app, resource, update_params):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
json_schema = schemas.UPDATE_FAMILY_SCHEMA
# test maj:adresse
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:adresse'] = False
for key in partial_update_params['ADRESSE'].keys():
partial_update_params['ADRESSE'][key] = None # reset fields
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
for value in partial_update_params['ADRESSE'].values():
assert value is None
def test_pre_sanitize_update_family_data_revenus(app, resource, update_params):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
json_schema = schemas.UPDATE_FAMILY_SCHEMA
# test maj:revenus
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:revenus'] = False
for key in partial_update_params['REVENUS'].keys():
partial_update_params['REVENUS'][key] = None # reset fields
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert 'REVENUS' not in partial_update_params
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:revenus'] = False
partial_update_params.pop('REVENUS')
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert 'REVENUS' not in partial_update_params
def test_pre_sanitize_update_family_data_rln(app, resource, update_params):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
json_schema = schemas.UPDATE_FAMILY_SCHEMA
# test maj:rln
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:rl1'] = False
for key in partial_update_params['RL1'].keys():
partial_update_params['RL1'][key] = None # reset fields
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert 'RL1' not in partial_update_params
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:rl2'] = False
for key in partial_update_params['RL2'].keys():
partial_update_params['RL2'][key] = None # reset fields
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert 'RL2' not in partial_update_params
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:rl1'] = False
partial_update_params['maj:rl2'] = False
partial_update_params.pop('RL1')
partial_update_params.pop('RL2')
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert 'RL1' not in partial_update_params
assert 'RL2' not in partial_update_params
def test_pre_sanitize_update_family_data_rln_adresse_employeur(app, resource, update_params):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
json_schema = schemas.UPDATE_FAMILY_SCHEMA
# test maj:rln_adresse_employeur
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:rl1_adresse_employeur'] = False
for key in partial_update_params['RL1']['ADREMPLOYEUR'].keys():
partial_update_params['RL1']['ADREMPLOYEUR'][key] = None # reset fields
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert 'ADREMPLOYEUR' not in partial_update_params['RL1']
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:rl2_adresse_employeur'] = False
for key in partial_update_params['RL2']['ADREMPLOYEUR'].keys():
partial_update_params['RL2']['ADREMPLOYEUR'][key] = None # reset fields
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert 'ADREMPLOYEUR' not in partial_update_params['RL2']
# combine with maj:rln
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:rl1'] = False
partial_update_params['maj:rl1_adresse_employeur'] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert 'RL1' not in partial_update_params
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:rl2'] = False
partial_update_params['maj:rl2_adresse_employeur'] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert 'RL2' not in partial_update_params
# test maj:rln_adresse_employeur not set
for val in [None, '']:
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:rl1_adresse_employeur'] = val
partial_update_params['RL1'].pop('ADREMPLOYEUR')
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert 'ADREMPLOYEUR' not in partial_update_params['RL1']
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:rl2_adresse_employeur'] = val
partial_update_params['RL2'].pop('ADREMPLOYEUR')
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert 'ADREMPLOYEUR' not in partial_update_params['RL2']
def test_pre_sanitize_update_family_data_enfant_n(app, resource, update_params):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
json_schema = schemas.UPDATE_FAMILY_SCHEMA
# test maj:enfant_n
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_0'] = False
for key in partial_update_params['ENFANT'][0].keys():
if key == 'IDPERSONNE':
continue
partial_update_params['ENFANT'][0][key] = None # reset fields
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert len(partial_update_params['ENFANT']) == 1
assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "3535"
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_1'] = False
for key in partial_update_params['ENFANT'][1].keys():
if key == 'IDPERSONNE':
continue
partial_update_params['ENFANT'][1][key] = None # reset fields
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert len(partial_update_params['ENFANT']) == 1
assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "4242"
# do not fill IDPERSONNE for the removed child
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_1'] = False
for key in partial_update_params['ENFANT'][1].keys():
partial_update_params['ENFANT'][1][key] = None # reset fields
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert len(partial_update_params['ENFANT']) == 1
assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "4242"
# remove all children
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_0'] = False
partial_update_params['maj:enfant_1'] = False
partial_update_params.pop('ENFANT')
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert 'ENFANT' not in partial_update_params
# unknown child
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_5'] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert len(partial_update_params['ENFANT']) == 2
# missing IDPERSONNE
partial_update_params = copy.deepcopy(update_params)
partial_update_params['ENFANT'][0].pop('IDPERSONNE')
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert len(partial_update_params['ENFANT']) == 1
def test_pre_sanitize_update_family_data_enfant_n_assurance(app, resource, update_params):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
json_schema = schemas.UPDATE_FAMILY_SCHEMA
# test maj:enfant_n_assurance
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_1_assurance'] = False
for key in partial_update_params['ENFANT'][1]['ASSURANCE'].keys():
partial_update_params['ENFANT'][1]['ASSURANCE'][key] = None # reset fields
partial_update_params['maj:enfant_0'] = False # check that ordering is not a problem
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert len(partial_update_params['ENFANT']) == 1
assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "3535"
assert 'ASSURANCE' not in partial_update_params['ENFANT'][0]
# combine with maj:enfant_n
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_1'] = False
partial_update_params['maj:enfant_1_assurance'] = False
partial_update_params['maj:enfant_0'] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert 'ENFANT' not in partial_update_params
# test maj:enfant_n_assurance not set
for val in [None, '']:
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_1_assurance'] = val
partial_update_params['maj:enfant_0'] = False
partial_update_params['ENFANT'][0].pop('ASSURANCE')
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert 'ASSURANCE' not in partial_update_params['ENFANT'][0]
def test_pre_sanitize_update_family_data_enfant_n_contact(app, resource, update_params):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
json_schema = schemas.UPDATE_FAMILY_SCHEMA
# test maj:enfant_n_contact
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_0_contact'] = False
for i, contact in enumerate(partial_update_params['ENFANT'][0]['CONTACT']):
for key in contact.keys():
partial_update_params['ENFANT'][0]['CONTACT'][i][key] = None # reset fields
partial_update_params['maj:enfant_1'] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert len(partial_update_params['ENFANT']) == 1
assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "4242"
assert 'CONTACT' not in partial_update_params['ENFANT'][0]
# combine with maj:enfant_n
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_1'] = False
partial_update_params['maj:enfant_1_contact'] = False
partial_update_params['maj:enfant_0'] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert 'ENFANT' not in partial_update_params
# test maj:enfant_n_contact not set
for val in [None, '']:
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_0_contact'] = val
partial_update_params['ENFANT'][0].pop('CONTACT')
partial_update_params['maj:enfant_1'] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert 'CONTACT' not in partial_update_params['ENFANT'][0]
# third contact of first child is not complete
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_1'] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert 'CONTACT' in partial_update_params['ENFANT'][0]
assert len(partial_update_params['ENFANT'][0]['CONTACT']) == 2
def test_pre_sanitize_update_family_data_enfant_n_sanitaire(app, resource, update_params):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
json_schema = schemas.UPDATE_FAMILY_SCHEMA
# test maj:enfant_n_sanitaire
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_1_sanitaire'] = False
for key in partial_update_params['ENFANT'][1]['SANITAIRE'].keys():
partial_update_params['ENFANT'][1]['SANITAIRE'][key] = None # reset fields
partial_update_params['maj:enfant_0'] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert len(partial_update_params['ENFANT']) == 1
assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "3535"
assert 'SANITAIRE' not in partial_update_params['ENFANT'][0]
# combine with maj:enfant_n
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_1'] = False
partial_update_params['maj:enfant_1_sanitaire'] = False
partial_update_params['maj:enfant_0'] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert 'ENFANT' not in partial_update_params
# test maj:enfant_n_sanitaire not set
for val in [None, '']:
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_0_sanitaire'] = val
partial_update_params['maj:enfant_1_sanitaire'] = val
partial_update_params['ENFANT'][0].pop('SANITAIRE')
partial_update_params['ENFANT'][1].pop('SANITAIRE')
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert 'SANITAIRE' not in partial_update_params['ENFANT'][0]
assert 'SANITAIRE' not in partial_update_params['ENFANT'][1]
def test_sanitize_update_family_data_enfant_n_sanitaire_allergie(app, resource, update_params, family_data):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
json_schema = schemas.UPDATE_FAMILY_SCHEMA
# test maj:enfant_n_sanitaire_allergie
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_0_sanitaire_allergie'] = False
for key in partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE'].keys():
partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE'][key] = None # reset fields
partial_update_params['maj:enfant_1'] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert '_to_reset' in partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data
):
resource.sanitize_update_family_data(dui='XXX', post_data=partial_update_params)
assert len(partial_update_params['ENFANT']) == 1
assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "4242"
assert 'ALLERGIE' in partial_update_params['ENFANT'][0]['SANITAIRE']
# fields were set with origin values found in Axel
new_values = partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']
old_values = family_data['ENFANT'][0]['SANITAIRE']['ALLERGIE']
assert new_values == old_values
# combine with maj:enfant_n_sanitaire
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_1_sanitaire'] = False
partial_update_params['maj:enfant_1_sanitaire_allergie'] = False
partial_update_params['maj:enfant_0'] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data
):
resource.sanitize_update_family_data(dui='XXX', post_data=partial_update_params)
assert len(partial_update_params['ENFANT']) == 1
assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "3535"
assert 'SANITAIRE' not in partial_update_params['ENFANT'][0]
# combine with maj:enfant_n
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_1'] = False
partial_update_params['maj:enfant_1_sanitaire_allergie'] = False
partial_update_params['maj:enfant_0'] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data
):
resource.sanitize_update_family_data(dui='XXX', post_data=partial_update_params)
assert 'ENFANT' not in partial_update_params
# test maj:enfant_n_sanitaire_allergie not set
for val in [None, '']:
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_0_sanitaire_allergie'] = val
partial_update_params['maj:enfant_1'] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data
):
resource.sanitize_update_family_data(dui='XXX', post_data=partial_update_params)
new_values = partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']
old_values = family_data['ENFANT'][0]['SANITAIRE']['ALLERGIE']
assert new_values == old_values
# allergie field is required
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_0_sanitaire_allergie'] = False
partial_update_params['ENFANT'][0]['SANITAIRE'].pop('ALLERGIE')
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
with pytest.raises(jsonschema.exceptions.ValidationError, match="'ALLERGIE' is a required property"):
jsonschema.validate(partial_update_params, json_schema)
def test_sanitize_update_family_data_enfant_n_sanitaire_allergie_values(
app, resource, update_params, family_data
):
json_schema = schemas.UPDATE_FAMILY_SCHEMA
# check values
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_1'] = False
partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['ASTHME'] = 'NON'
partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['MEDICAMENTEUSES'] = '0'
partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['ALIMENTAIRES'] = 'False'
partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['AUTRES'] = ''
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data
):
resource.sanitize_update_family_data(dui='XXX', post_data=partial_update_params)
assert 'ALLERGIE' not in partial_update_params['ENFANT'][0]['SANITAIRE']
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_1'] = False
partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['ASTHME'] = False
partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['MEDICAMENTEUSES'] = ''
partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['ALIMENTAIRES'] = None
partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['AUTRES'] = ''
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data
):
resource.sanitize_update_family_data(dui='XXX', post_data=partial_update_params)
assert 'ALLERGIE' not in partial_update_params['ENFANT'][0]['SANITAIRE']
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_1'] = False
partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['ASTHME'] = 'OUI'
partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['MEDICAMENTEUSES'] = '1'
partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['ALIMENTAIRES'] = 'True'
partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['AUTRES'] = 'accariens'
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data
):
resource.sanitize_update_family_data(dui='XXX', post_data=partial_update_params)
assert partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE'] == [
{'TYPE': 'ASTHME', 'ALLERGIQUE': 'OUI', 'NOMALLERGIE': None},
{'TYPE': 'MEDICAMENTEUSES', 'ALLERGIQUE': 'OUI', 'NOMALLERGIE': None},
{'TYPE': 'ALIMENTAIRES', 'ALLERGIQUE': 'OUI', 'NOMALLERGIE': None},
{'TYPE': 'AUTRES', 'ALLERGIQUE': 'OUI', 'NOMALLERGIE': 'ACCARIENS'},
]
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_1'] = False
partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['ASTHME'] = ''
partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['MEDICAMENTEUSES'] = '1'
partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['ALIMENTAIRES'] = 'True'
partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['AUTRES'] = ''
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data
):
resource.sanitize_update_family_data(dui='XXX', post_data=partial_update_params)
assert partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE'] == [
{'TYPE': 'MEDICAMENTEUSES', 'ALLERGIQUE': 'OUI', 'NOMALLERGIE': None},
{'TYPE': 'ALIMENTAIRES', 'ALLERGIQUE': 'OUI', 'NOMALLERGIE': None},
]
def test_pre_sanitize_update_family_data_enfant_n_sanitaire_medecin(app, resource, update_params):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
json_schema = schemas.UPDATE_FAMILY_SCHEMA
# test maj:enfant_n_sanitaire_medecin
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_1_sanitaire_medecin'] = False
for key in partial_update_params['ENFANT'][1]['SANITAIRE']['MEDECIN'].keys():
partial_update_params['ENFANT'][1]['SANITAIRE']['MEDECIN'][key] = None # reset fields
partial_update_params['maj:enfant_0'] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert len(partial_update_params['ENFANT']) == 1
assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "3535"
assert 'MEDECIN' not in partial_update_params['ENFANT'][0]['SANITAIRE']
# combine with maj:enfant_n_sanitaire
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_1_sanitaire'] = False
partial_update_params['maj:enfant_1_sanitaire_medecin'] = False
partial_update_params['maj:enfant_0'] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert len(partial_update_params['ENFANT']) == 1
assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "3535"
assert 'SANITAIRE' not in partial_update_params['ENFANT'][0]
# combine with maj:enfant_n
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_1'] = False
partial_update_params['maj:enfant_1_sanitaire_medecin'] = False
partial_update_params['maj:enfant_0'] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert 'ENFANT' not in partial_update_params
# test maj:enfant_n_sanitaire_medecin not set
for val in [None, '']:
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_0_sanitaire_medecin'] = val
partial_update_params['maj:enfant_1_sanitaire_medecin'] = val
partial_update_params['ENFANT'][0]['SANITAIRE'].pop('MEDECIN')
partial_update_params['ENFANT'][1]['SANITAIRE'].pop('MEDECIN')
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert 'MEDECIN' not in partial_update_params['ENFANT'][0]['SANITAIRE']
assert 'MEDECIN' not in partial_update_params['ENFANT'][1]['SANITAIRE']
def test_pre_sanitize_update_family_data_enfant_n_sanitaire_vaccin(app, resource, update_params):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
json_schema = schemas.UPDATE_FAMILY_SCHEMA
# test maj:enfant_n_sanitaire_vaccin
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_1_sanitaire_vaccin'] = False
for key in partial_update_params['ENFANT'][1]['SANITAIRE']['VACCIN'].keys():
partial_update_params['ENFANT'][1]['SANITAIRE']['VACCIN'][key] = None # reset fields
partial_update_params['maj:enfant_0'] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert len(partial_update_params['ENFANT']) == 1
assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "3535"
assert 'VACCIN' not in partial_update_params['ENFANT'][0]['SANITAIRE']
# combine with maj:enfant_n_sanitaire
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_1_sanitaire'] = False
partial_update_params['maj:enfant_1_sanitaire_vaccin'] = False
partial_update_params['maj:enfant_0'] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert len(partial_update_params['ENFANT']) == 1
assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "3535"
assert 'SANITAIRE' not in partial_update_params['ENFANT'][0]
# combine with maj:enfant_n
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_1'] = False
partial_update_params['maj:enfant_1_sanitaire_vaccin'] = False
partial_update_params['maj:enfant_0'] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert 'ENFANT' not in partial_update_params
# test maj:enfant_n_sanitaire_vaccin not set
for val in [None, '']:
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_0_sanitaire_vaccin'] = val
partial_update_params['maj:enfant_1_sanitaire_vaccin'] = val
partial_update_params['ENFANT'][0]['SANITAIRE'].pop('VACCIN')
partial_update_params['ENFANT'][1]['SANITAIRE'].pop('VACCIN')
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert 'VACCIN' not in partial_update_params['ENFANT'][0]['SANITAIRE']
assert 'VACCIN' not in partial_update_params['ENFANT'][1]['SANITAIRE']
def test_sanitize_update_family_data_enfant_n_sanitaire_handicap(app, resource, update_params, family_data):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
json_schema = schemas.UPDATE_FAMILY_SCHEMA
# test maj:enfant_n_sanitaire_handicap
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_0_sanitaire_handicap'] = False
# reset fields
handicap_fields = [
'AUTREDIFFICULTE',
'ECOLESPECIALISEE',
'INDICATEURAUXILIAIREVS',
'INDICATEURECOLE',
'INDICATEURHANDICAP',
'INDICATEURNOTIFMDPH',
]
for key in handicap_fields:
partial_update_params['ENFANT'][0]['SANITAIRE']['HANDICAP'][key] = None
partial_update_params['maj:enfant_1'] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
assert '_to_reset' in partial_update_params['ENFANT'][0]['SANITAIRE']['HANDICAP']
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data
):
resource.sanitize_update_family_data(dui='XXX', post_data=partial_update_params)
assert len(partial_update_params['ENFANT']) == 1
assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "4242"
# fields were set with origin values found in Axel
new_values = partial_update_params['ENFANT'][0]['SANITAIRE']
for key in handicap_fields:
assert new_values[key] == family_data['ENFANT'][0]['SANITAIRE'][key]
assert '_to_reset' not in new_values
assert 'HANDICAP' not in new_values
# combine with maj:enfant_n_sanitaire
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_1_sanitaire'] = False
partial_update_params['maj:enfant_1_sanitaire_handicap'] = False
partial_update_params['maj:enfant_0'] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data
):
resource.sanitize_update_family_data(dui='XXX', post_data=partial_update_params)
assert len(partial_update_params['ENFANT']) == 1
assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "3535"
assert 'SANITAIRE' not in partial_update_params['ENFANT'][0]
# combine with maj:enfant_n
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_1'] = False
partial_update_params['maj:enfant_1_sanitaire_handicap'] = False
partial_update_params['maj:enfant_0'] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data
):
resource.sanitize_update_family_data(dui='XXX', post_data=partial_update_params)
assert 'ENFANT' not in partial_update_params
# test maj:enfant_n_sanitaire_handicap not set
for val in [None, '']:
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_0_sanitaire_handicap'] = val
partial_update_params['maj:enfant_1'] = False
# reset fields
for key in handicap_fields:
partial_update_params['ENFANT'][0]['SANITAIRE']['HANDICAP'][key] = None
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data
):
resource.sanitize_update_family_data(dui='XXX', post_data=partial_update_params)
new_values = partial_update_params['ENFANT'][0]['SANITAIRE']
for key in handicap_fields:
assert new_values[key] == family_data['ENFANT'][0]['SANITAIRE'][key]
assert 'HANDICAP' not in new_values
# handicap field is required
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_0_sanitaire_handicap'] = False
partial_update_params['ENFANT'][0]['SANITAIRE'].pop('HANDICAP')
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
with pytest.raises(jsonschema.exceptions.ValidationError, match="'HANDICAP' is a required property"):
jsonschema.validate(partial_update_params, json_schema)
@pytest.mark.parametrize(
'flags',
[
# get family data to fill handicap fields
['maj:enfant_0_sanitaire_handicap', 'maj:revenus', 'maj:rl1', 'maj:rl2'],
# get family data to fill revenus fields
['maj:rl1', 'maj:rl2'],
# get family data to fill rl1 fields
['maj:revenus', 'maj:rl2'],
# get family data to fill rl2 fields
['maj:revenus', 'maj:rl1'],
],
)
def test_sanitize_update_family_data_axel_error(app, resource, update_params, flags):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
json_schema = schemas.UPDATE_FAMILY_SCHEMA
partial_update_params = copy.deepcopy(update_params)
for flag in flags:
partial_update_params[flag] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
jsonschema.validate(partial_update_params, json_schema)
with mock.patch('passerelle.contrib.toulouse_axel.schemas.ref_famille_dui') as operation:
operation.side_effect = AxelError('FooBar')
with pytest.raises(APIError, match='Axel error: FooBar'):
resource.sanitize_update_family_data(dui='XXX', post_data=partial_update_params)
def test_update_family_info_endpoint_sanitize_axel_error(app, resource, update_params):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.sanitize_update_family_data'
) as sanitize:
sanitize.side_effect = APIError('Axel error: FooBar')
resp = app.post_json('/toulouse-axel/test/update_family_info?NameID=yyy', params=update_params)
assert resp.json['err_desc'] == "Axel error: FooBar"
def test_invoices_endpoint_axel_error(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with mock.patch('passerelle.contrib.toulouse_axel.schemas.ref_facture_a_payer') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get('/toulouse-axel/test/regie/MAREGIE/invoices?NameID=yyy')
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
resp = app.get('/toulouse-axel/test/regie/MAREGIE/invoices?NameID=', status=400)
assert 'InvalidParameterValue' in resp.json['err_class']
assert resp.json['err'] == 1
def test_invoices_endpoint_no_result(app, resource):
resp = app.get('/toulouse-axel/test/regie/MAREGIE/invoices?NameID=yyy')
assert resp.json['err_desc'] == "Person not found"
assert resp.json['err'] == 'not-found'
def test_invoices_endpoint_no_invoices(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
content = '''<PORTAIL>
<DUI>
<IDDUI>XXX</IDDUI>
<CHOIXDEMAT>0</CHOIXDEMAT>
<NBFACTURES>0</NBFACTURES>
</DUI>
</PORTAIL>'''
with mock_getdata(content, 'RefFactureAPayer'):
resp = app.get('/toulouse-axel/test/regie/MAREGIE/invoices?NameID=yyy')
assert resp.json['err'] == 0
assert resp.json['data'] == []
def test_invoices_endpoint(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/invoices.xml')
with open(filepath) as xml:
content = xml.read()
with mock_getdata(content, 'RefFactureAPayer'):
resp = app.get('/toulouse-axel/test/regie/MAREGIE/invoices?NameID=yyy')
assert resp.json['err'] == 0
assert resp.json['data'] == [
{
'id': 'XXX-42',
'display_id': '42',
'label': 'PRESTATIONS PERISCOLAIRES SEPTEMBRE-OCTOBRE 2019',
'amount': '4.94',
'total_amount': '44.94',
'amount_paid': '40.00',
'online_payment': True,
'created': '2019-11-12',
'pay_limit_date': '2019-12-04',
'has_pdf': True,
'paid': False,
'vendor': {
'toulouse-axel': {
'IDFACTURATION': '4242-35AA',
'IDFACTURE': 42,
'IDREGIE': 'MAREGIE',
'DATEECHEANCE': '2019-12-04',
'DATEEMISSION': '2019-11-12',
'EXISTEPDF': '1',
'LIBELLE': 'PRESTATIONS PERISCOLAIRES SEPTEMBRE-OCTOBRE 2019',
'MONTANTTOTAL': '44.94',
'NUMFACTURE': 42,
'RESTEAPAYER': '4.94',
}
},
},
{
'id': 'XXX-43',
'display_id': '43',
'label': 'PRESTATIONS PERISCOLAIRES NOVEMBRE 2019',
'amount': '44.94',
'total_amount': '44.94',
'amount_paid': '',
'online_payment': True,
'created': '2019-12-12',
'pay_limit_date': '2020-01-04',
'has_pdf': False,
'paid': False,
'vendor': {
'toulouse-axel': {
'IDFACTURATION': '4243-35AA',
'IDFACTURE': 43,
'DATEECHEANCE': '2020-01-04',
'DATEEMISSION': '2019-12-12',
'EXISTEPDF': '0',
'IDREGIE': 'MAREGIE',
'LIBELLE': 'PRESTATIONS PERISCOLAIRES NOVEMBRE 2019',
'MONTANTTOTAL': '44.94',
'NUMFACTURE': 43,
'RESTEAPAYER': '44.94',
}
},
},
]
with mock_getdata(content, 'RefFactureAPayer'):
resp = app.get('/toulouse-axel/test/regie/AUTREREGIE/invoices?NameID=yyy')
assert resp.json['err'] == 0
assert resp.json['data'] == [
{
'id': 'XXX-44',
'display_id': '44',
'label': 'PRESTATIONS PERISCOLAIRES DECEMBRE 2019',
'amount': '44.94',
'total_amount': '44.94',
'amount_paid': '',
'online_payment': True,
'created': '2020-01-12',
'pay_limit_date': '2020-01-15',
'has_pdf': True,
'paid': False,
'vendor': {
'toulouse-axel': {
'IDFACTURATION': '4244-35AA',
'IDFACTURE': 44,
'IDREGIE': 'AUTREREGIE',
'DATEECHEANCE': '2020-01-15',
'DATEEMISSION': '2020-01-12',
'EXISTEPDF': '1',
'LIBELLE': 'PRESTATIONS PERISCOLAIRES DECEMBRE 2019',
'MONTANTTOTAL': '44.94',
'NUMFACTURE': 44,
'RESTEAPAYER': '44.94',
}
},
}
]
def test_invoices_history_endpoint_empty_nameid_error(app, resource):
resp = app.get('/toulouse-axel/test/regie/MAREGIE/invoices/history?NameID=', status=400)
assert resp.json['err_desc'] == 'invalid value for parameter "NameID"'
assert resp.json['err'] == 1
def test_invoices_history_endpoint_axel_error(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with mock.patch('passerelle.contrib.toulouse_axel.schemas.list_dui_factures') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get('/toulouse-axel/test/regie/MAREGIE/invoices/history?NameID=yyy')
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
def test_invoices_history_endpoint_no_result(app, resource):
resp = app.get('/toulouse-axel/test/regie/MAREGIE/invoices/history?NameID=yyy')
assert resp.json['err_desc'] == "Person not found"
assert resp.json['err'] == 'not-found'
def test_invoices_history_endpoint_no_invoices(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
content = '''<PORTAIL>
<LISTFACTURE>
<NBFACTURERESTANTE>0</NBFACTURERESTANTE>
</LISTFACTURE>
</PORTAIL>'''
with mock_getdata(content, 'ListeDuiFacturesPayeesRecettees'):
resp = app.get('/toulouse-axel/test/regie/MAREGIE/invoices/history?NameID=yyy')
assert resp.json['err'] == 0
assert resp.json['data'] == []
def test_invoices_history_endpoint(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/invoices_history.xml')
with open(filepath) as xml:
content = xml.read()
with mock_getdata(content, 'ListeDuiFacturesPayeesRecettees'):
resp = app.get('/toulouse-axel/test/regie/MAREGIE/invoices/history?NameID=yyy')
assert resp.json['err'] == 0
assert resp.json['data'] == [
{
'amount': 0,
'created': '2017-03-23',
'display_id': '42',
'has_pdf': True,
'id': 'historical-XXX-42',
'label': 'PRESTATIONS SEPTEMBRE 2015',
'online_payment': False,
'paid': False,
'pay_limit_date': '',
'total_amount': '28.98',
'vendor': {
'toulouse-axel': {
'EMISSION': '2017-03-23',
'IDAXEL': 'AXEL',
'IDDIRECTION': 'DIR-A',
'IDFACTURE': 42,
'IDFAMILLE': 'XXX',
'IPDF': 'O',
'LIBDIRECTION': 'DIRECTION A',
'LIBELLE': 'PRESTATIONS SEPTEMBRE 2015',
'MONTANT': '28.98',
'NOFACTURE': 42,
'NUMDIRECTION': 10,
}
},
},
{
'amount': 0,
'created': '2017-03-23',
'display_id': '43',
'has_pdf': False,
'id': 'historical-XXX-43',
'label': 'PRESTATIONS OCTOBRE 2015',
'online_payment': False,
'paid': False,
'pay_limit_date': '',
'total_amount': '28.98',
'vendor': {
'toulouse-axel': {
'EMISSION': '2017-03-23',
'IDAXEL': 'AXEL',
'IDDIRECTION': 'DIR-B',
'IDFACTURE': 43,
'IDFAMILLE': 'XXX',
'IPDF': 'N',
'LIBDIRECTION': 'DIRECTION B',
'LIBELLE': 'PRESTATIONS OCTOBRE 2015',
'MONTANT': '28.98',
'NOFACTURE': 43,
'NUMDIRECTION': 11,
}
},
},
]
def test_invoice_endpoint_axel_error(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with mock.patch('passerelle.contrib.toulouse_axel.schemas.ref_facture_a_payer') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get('/toulouse-axel/test/regie/MAREGIE/invoice/XXX-42?NameID=yyy')
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
def test_invoice_endpoint_no_result(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/invoices.xml')
with open(filepath) as xml:
content = xml.read()
with mock_getdata(content, 'RefFactureAPayer'):
resp = app.get('/toulouse-axel/test/regie/MAREGIE/invoice/XXX-35?NameID=yyy')
assert resp.json['err_desc'] == "Invoice not found"
assert resp.json['err'] == 'not-found'
with mock_getdata(content, 'RefFactureAPayer'):
resp = app.get('/toulouse-axel/test/regie/MAREGIE/invoice/XXX-44?NameID=yyy')
assert resp.json['err_desc'] == "Invoice not found"
assert resp.json['err'] == 'not-found'
@pytest.mark.parametrize('dui', ['XXX', 'S-XXX'])
def test_invoice_endpoint(app, resource, dui):
Link.objects.create(resource=resource, name_id='yyy', dui=dui, person_id='42')
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/invoices.xml')
with open(filepath) as xml:
content = xml.read().replace('XXX', dui)
with mock_getdata(content, 'RefFactureAPayer'):
resp = app.get('/toulouse-axel/test/regie/MAREGIE/invoice/%s-42?NameID=yyy' % dui)
assert resp.json['err'] == 0
assert resp.json['data'] == {
'id': '%s-42' % dui,
'display_id': '42',
'label': 'PRESTATIONS PERISCOLAIRES SEPTEMBRE-OCTOBRE 2019',
'amount': '4.94',
'total_amount': '44.94',
'amount_paid': '40.00',
'online_payment': True,
'created': '2019-11-12',
'pay_limit_date': '2019-12-04',
'has_pdf': True,
'paid': False,
'vendor': {
'toulouse-axel': {
'IDFACTURATION': '4242-35AA',
'IDFACTURE': 42,
'IDREGIE': 'MAREGIE',
'DATEECHEANCE': '2019-12-04',
'DATEEMISSION': '2019-11-12',
'EXISTEPDF': '1',
'LIBELLE': 'PRESTATIONS PERISCOLAIRES SEPTEMBRE-OCTOBRE 2019',
'MONTANTTOTAL': '44.94',
'NUMFACTURE': 42,
'RESTEAPAYER': '4.94',
}
},
}
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/invoices_history.xml')
with open(filepath) as xml:
content = xml.read().replace('XXX', dui)
with mock_getdata(content, 'ListeDuiFacturesPayeesRecettees'):
resp = app.get('/toulouse-axel/test/regie/MAREGIE/invoice/historical-%s-42?NameID=yyy' % dui)
assert resp.json['err'] == 0
assert resp.json['data'] == {
'amount': 0,
'created': '2017-03-23',
'display_id': '42',
'has_pdf': True,
'id': 'historical-%s-42' % dui,
'label': 'PRESTATIONS SEPTEMBRE 2015',
'online_payment': False,
'paid': False,
'pay_limit_date': '',
'total_amount': '28.98',
'vendor': {
'toulouse-axel': {
'EMISSION': '2017-03-23',
'IDAXEL': 'AXEL',
'IDDIRECTION': 'DIR-A',
'IDFACTURE': 42,
'IDFAMILLE': dui,
'IPDF': 'O',
'LIBDIRECTION': 'DIRECTION A',
'LIBELLE': 'PRESTATIONS SEPTEMBRE 2015',
'MONTANT': '28.98',
'NOFACTURE': 42,
'NUMDIRECTION': 10,
}
},
}
@pytest.mark.parametrize('dui', ['XXX', 'S-XXX'])
def test_invoice_endpoint_anonymous(app, resource, dui):
Link.objects.create(resource=resource, name_id='yyy', dui=dui, person_id='42')
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/invoices.xml')
with open(filepath) as xml:
content = xml.read().replace('XXX', dui)
with mock_getdata(content, 'RefFactureAPayer'):
resp = app.get('/toulouse-axel/test/regie/MAREGIE/invoice/%s-42' % dui)
assert resp.json['err'] == 0
assert resp.json['data'] == {
'id': '%s-42' % dui,
'display_id': '42',
'label': 'PRESTATIONS PERISCOLAIRES SEPTEMBRE-OCTOBRE 2019',
'amount': '4.94',
'total_amount': '44.94',
'amount_paid': '40.00',
'online_payment': True,
'created': '2019-11-12',
'pay_limit_date': '2019-12-04',
'has_pdf': True,
'paid': False,
'vendor': {
'toulouse-axel': {
'IDFACTURATION': '4242-35AA',
'IDFACTURE': 42,
'IDREGIE': 'MAREGIE',
'DATEECHEANCE': '2019-12-04',
'DATEEMISSION': '2019-11-12',
'EXISTEPDF': '1',
'LIBELLE': 'PRESTATIONS PERISCOLAIRES SEPTEMBRE-OCTOBRE 2019',
'MONTANTTOTAL': '44.94',
'NUMFACTURE': 42,
'RESTEAPAYER': '4.94',
}
},
}
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/invoices_history.xml')
with open(filepath) as xml:
content = xml.read().replace('XXX', dui)
with mock_getdata(content, 'ListeDuiFacturesPayeesRecettees'):
resp = app.get('/toulouse-axel/test/regie/MAREGIE/invoice/historical-%s-42' % dui)
assert resp.json['err'] == 0
assert resp.json['data'] == {
'amount': 0,
'created': '2017-03-23',
'display_id': '42',
'has_pdf': True,
'id': 'historical-%s-42' % dui,
'label': 'PRESTATIONS SEPTEMBRE 2015',
'online_payment': False,
'paid': False,
'pay_limit_date': '',
'total_amount': '28.98',
'vendor': {
'toulouse-axel': {
'EMISSION': '2017-03-23',
'IDAXEL': 'AXEL',
'IDDIRECTION': 'DIR-A',
'IDFACTURE': 42,
'IDFAMILLE': dui,
'IPDF': 'O',
'LIBDIRECTION': 'DIRECTION A',
'LIBELLE': 'PRESTATIONS SEPTEMBRE 2015',
'MONTANT': '28.98',
'NOFACTURE': 42,
'NUMDIRECTION': 10,
}
},
}
def test_invoice_pdf_endpoint_axel_error(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with mock.patch('passerelle.contrib.toulouse_axel.schemas.ref_facture_a_payer') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get('/toulouse-axel/test/regie/MAREGIE/invoice/XXX-42/pdf?NameID=yyy', status=404)
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/invoices.xml')
with open(filepath) as xml:
content = xml.read()
with mock_getdata(content, 'RefFactureAPayer'):
with mock.patch('passerelle.contrib.toulouse_axel.schemas.ref_facture_pdf') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get('/toulouse-axel/test/regie/MAREGIE/invoice/XXX-42/pdf?NameID=yyy', status=404)
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
def test_invoice_pdf_endpoint_no_result(app, resource):
resp = app.get('/toulouse-axel/test/regie/MAREGIE/invoice/XXX-42/pdf?NameID=yyy', status=404)
assert resp.json['err_desc'] == "Person not found"
assert resp.json['err'] == 'not-found'
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/invoices.xml')
with open(filepath) as xml:
content = xml.read()
with mock_getdata(content, 'RefFactureAPayer'):
resp = app.get('/toulouse-axel/test/regie/MAREGIE/invoice/XXX-35/pdf?NameID=yyy', status=404)
assert resp.json['err_desc'] == "Invoice not found"
assert resp.json['err'] == 'not-found'
with mock_getdata(content, 'RefFactureAPayer'):
resp = app.get('/toulouse-axel/test/regie/MAREGIE/invoice/XXX-44/pdf?NameID=yyy', status=404)
assert resp.json['err_desc'] == "Invoice not found"
assert resp.json['err'] == 'not-found'
with mock_getdata(content, 'RefFactureAPayer'):
resp = app.get('/toulouse-axel/test/regie/MAREGIE/invoice/XXX-43/pdf?NameID=yyy', status=404)
assert resp.json['err_desc'] == "PDF not available"
assert resp.json['err'] == 'not-available'
pdf_content = '''<PORTAIL>
<PDF FILE=''></PDF>
</PORTAIL>'''
with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_invoice') as invoice:
invoice.return_value = {'has_pdf': True, 'display_id': '42'}
with mock_getdata(pdf_content, 'RefFacturePDF'):
resp = app.get('/toulouse-axel/test/regie/MAREGIE/invoice/XXX-42/pdf?NameID=yyy', status=404)
assert resp.json['err_desc'] == "PDF error"
assert resp.json['err'] == 'error'
@pytest.mark.parametrize('dui', ['XXX', 'S-XXX'])
def test_invoice_pdf_endpoint(app, resource, dui):
Link.objects.create(resource=resource, name_id='yyy', dui=dui, person_id='42')
pdf_content = '''<PORTAIL>
<PDF FILE='aGVsbG8gd29ybGQ='></PDF>
</PORTAIL>'''
with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_invoice') as invoice:
invoice.return_value = {'has_pdf': True, 'display_id': '42'}
with mock_getdata(pdf_content, 'RefFacturePDF'):
app.get('/toulouse-axel/test/regie/MAREGIE/invoice/%s-42/pdf?NameID=yyy' % dui)
assert invoice.call_args_list[0][1]['historical'] is False
with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_invoice') as invoice:
invoice.return_value = {'has_pdf': True, 'display_id': '42'}
with mock_getdata(pdf_content, 'RefFacturePDF'):
app.get('/toulouse-axel/test/regie/MAREGIE/invoice/historical-%s-42/pdf?NameID=yyy' % dui)
assert invoice.call_args_list[0][1]['historical'] is True
def test_pay_invoice_endpoint_axel_error(app, resource):
payload = {
'transaction_date': '2020-01-01T12:00:00',
'transaction_id': 'foo',
}
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with mock.patch('passerelle.contrib.toulouse_axel.schemas.ref_facture_a_payer') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.post_json(
'/toulouse-axel/test/regie/MAREGIE/invoice/XXX-42/pay?NameID=yyy', params=payload
)
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/invoices.xml')
with open(filepath) as xml:
content = xml.read()
with mock_getdata(content, 'RefFactureAPayer'):
with mock.patch('passerelle.contrib.toulouse_axel.schemas.form_paiement_dui') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.post_json(
'/toulouse-axel/test/regie/MAREGIE/invoice/XXX-42/pay?NameID=yyy', params=payload
)
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
def test_pay_invoice_endpoint_no_result(app, resource):
payload = {
'transaction_date': '2020-01-01T12:00:00',
'transaction_id': 'foo',
}
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/invoices.xml')
with open(filepath) as xml:
content = xml.read()
with mock_getdata(content, 'RefFactureAPayer'):
resp = app.post_json(
'/toulouse-axel/test/regie/MAREGIE/invoice/XXX-35/pay?NameID=yyy', params=payload
)
assert resp.json['err_desc'] == "Invoice not found"
assert resp.json['err'] == 'not-found'
with mock_getdata(content, 'RefFactureAPayer'):
resp = app.post_json(
'/toulouse-axel/test/regie/MAREGIE/invoice/XXX-44/pay?NameID=yyy', params=payload
)
assert resp.json['err_desc'] == "Invoice not found"
assert resp.json['err'] == 'not-found'
@pytest.mark.parametrize('dui', ['XXX', 'S-XXX'])
def test_pay_invoice_endpoint(app, resource, dui):
payload = {
'transaction_date': '2020-01-01T12:00:00',
'transaction_id': 'foo',
}
Link.objects.create(resource=resource, name_id='yyy', dui=dui, person_id='42')
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/invoices.xml')
with open(filepath) as xml:
content = xml.read().replace('XXX', dui)
with mock_getdata(content, 'RefFactureAPayer'):
with mock.patch('passerelle.contrib.toulouse_axel.schemas.form_paiement_dui') as operation:
resp = app.post_json(
'/toulouse-axel/test/regie/MAREGIE/invoice/%s-42/pay?NameID=yyy' % dui, params=payload
)
assert resp.json['err'] == 0
assert resp.json['data'] is True
assert operation.call_args_list[0][0][1] == {
'PORTAIL': {
'DUI': {
'DATEPAIEMENT': '01/01/2020 13:00:00',
'IDFACTURE': 42,
'IDREGIEENCAISSEMENT': '',
'MONTANTPAYE': decimal.Decimal('4.94'),
'REFERENCE': 'foo',
}
}
}
@freezegun.freeze_time('2020-06-30')
def test_clae_years_endpoint_axel_error(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with mock.patch('passerelle.contrib.toulouse_axel.schemas.enfants_activites') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get('/toulouse-axel/test/clae_years?NameID=yyy&pivot_date=06-15')
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
@pytest.mark.parametrize('value', ['foo', '20/01/2020', '15/06', '06'])
def test_clae_years_endpoint_bad_date_format(app, resource, value):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
resp = app.get('/toulouse-axel/test/clae_years?NameID=yyy&pivot_date=%s' % value, status=400)
assert resp.json['err_desc'] == "bad date format, should be MM-DD"
assert resp.json['err'] == 'bad-request'
def test_clae_years_endpoint_no_result(app, resource):
resp = app.get('/toulouse-axel/test/clae_years?NameID=yyy&pivot_date=06-15')
assert resp.json['err_desc'] == "Person not found"
assert resp.json['err'] == 'not-found'
@pytest.mark.parametrize(
'today,pivot,next_year,next_date',
[
('2019-08-01', '08-01', True, '2020-08-01'),
('2019-08-01', '08-02', False, None),
('2020-07-31', '07-31', True, '2021-07-31'),
('2020-07-30', '07-31', False, None),
('2020-06-14', '06-15', False, None),
('2020-06-15', '06-15', True, '2021-06-15'),
('2020-06-16', '06-15', True, '2021-06-16'),
('2020-02-29', '02-01', True, '2021-03-01'),
],
)
def test_clae_years_endpoint(app, resource, today, pivot, next_year, next_date):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/child_activities.xml')
with open(filepath) as xml:
content = xml.read()
with mock_getdata(content, 'EnfantsActivites'):
with freezegun.freeze_time(today):
resp = app.get('/toulouse-axel/test/clae_years?NameID=yyy&pivot_date=%s' % pivot)
assert resp.json['data'][0] == {'id': '2019', 'text': '2019/2020', 'type': 'encours', 'refdate': today}
if next_year:
assert len(resp.json['data']) == 2
assert resp.json['data'][1] == {
'id': '2020',
'text': '2020/2021',
'type': 'suivante',
'refdate': next_date,
}
else:
assert len(resp.json['data']) == 1
@freezegun.freeze_time('2020-06-30')
def test_clae_years_endpoint_noactivities(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_children_activities', return_value={}
) as mock_activities:
resp = app.get('/toulouse-axel/test/clae_years?NameID=yyy&pivot_date=06-15')
assert mock_activities.call_args_list == [mock.call(dui='XXX', reference_year=2020)]
assert len(resp.json['data']) == 1
def test_clae_children_activities_info_endpoint_axel_error(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with mock.patch('passerelle.contrib.toulouse_axel.schemas.enfants_activites') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get('/toulouse-axel/test/clae_children_activities_info?NameID=yyy&booking_date=2020-01-20')
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
@pytest.mark.parametrize('value', ['foo', '20/01/2020', '2020'])
def test_clae_children_activities_info_endpoint_bad_date_format(app, resource, value):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
resp = app.get(
'/toulouse-axel/test/clae_children_activities_info?NameID=yyy&booking_date=%s' % value, status=400
)
assert resp.json['err_desc'] == "bad date format, should be YYYY-MM-DD"
assert resp.json['err'] == 'bad-request'
def test_clae_children_activities_info_endpoint_no_result(app, resource):
resp = app.get('/toulouse-axel/test/clae_children_activities_info?NameID=yyy&booking_date=2020-01-20')
assert resp.json['err_desc'] == "Person not found"
assert resp.json['err'] == 'not-found'
def test_clae_children_activities_info_endpoint(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/child_activities.xml')
with open(filepath) as xml:
content = xml.read()
with mock_getdata(content, 'EnfantsActivites'):
resp = app.get('/toulouse-axel/test/clae_children_activities_info?NameID=yyy&booking_date=2020-01-20')
assert resp.json['err'] == 0
assert resp.json['data'] == [
{
'ACTIVITE': [
{
'COUTREVIENT': '99999',
'DATEDEBUT': '2019-08-01',
'DATEENTREE': '2019-08-01',
'DATEFIN': '2020-07-31',
'DATESORTIE': '2020-07-31',
'IDACTIVITE': 'A19P1M1',
'ISPAI': False,
'LIBELLEACTIVITE': 'Temps du matin',
'TARIF': '0.42',
'TYPEACTIVITE': 'MAT',
},
{
'COUTREVIENT': '99999',
'DATEDEBUT': '2019-08-01',
'DATEENTREE': '2019-08-01',
'DATEFIN': '2020-07-31',
'DATESORTIE': '2020-07-31',
'IDACTIVITE': 'A19P1M2',
'ISPAI': False,
'LIBELLEACTIVITE': 'Temps du midi',
'TARIF': '0.43',
'TYPEACTIVITE': 'MIDI',
},
{
'COUTREVIENT': '99999',
'DATEDEBUT': '2019-08-01',
'DATEENTREE': '2019-08-01',
'DATEFIN': '2020-07-31',
'DATESORTIE': '2020-07-31',
'IDACTIVITE': 'A19P1M3',
'ISPAI': False,
'LIBELLEACTIVITE': 'Temps du soir',
'TARIF': '0.44',
'TYPEACTIVITE': 'SOIR',
},
{
'COUTREVIENT': '99999',
'DATEDEBUT': '2019-08-01',
'DATEENTREE': '2019-08-01',
'DATEFIN': '2020-07-31',
'DATESORTIE': '2020-07-31',
'IDACTIVITE': 'A19P1M4',
'ISPAI': False,
'LIBELLEACTIVITE': 'Temps mercredi apr\xe8s midi',
'TARIF': '0.45',
'TYPEACTIVITE': 'GARD',
},
],
'DATENAISSANCE': '2019-01-01',
'IDPERSONNE': '3535',
'LIBELLEECOLE': 'MATERNELLE 1',
'NOM': 'foo',
'PRENOM': 'foo',
'REGIME': 'SV',
'REGIME_label': 'Menu sans viande',
'id': '3535',
'text': 'foo foo',
}
]
# again - data are in cache
resp = app.get('/toulouse-axel/test/clae_children_activities_info?NameID=yyy&booking_date=2020-01-20')
assert resp.json['err'] == 0
@pytest.mark.parametrize(
'activities, expected',
[
# all activities except GARD - optional
(['MAT', 'MIDI', 'SOIR'], True),
# all activities
(['MAT', 'MIDI', 'SOIR', 'GARD'], True),
# duplicated activities
(['MAT', 'MAT', 'MIDI', 'SOIR', 'GARD'], False),
(['MAT', 'MIDI', 'MIDI', 'SOIR', 'GARD'], False),
(['MAT', 'MIDI', 'SOIR', 'SOIR', 'GARD'], False),
(['MAT', 'MIDI', 'SOIR', 'GARD', 'GARD'], False),
# missing activity
(['MIDI', 'SOIR'], False),
(['MAT', 'SOIR'], False),
(['MAT', 'MIDI'], False),
],
)
def test_clae_children_activities_info_check(app, resource, activities, expected):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
result = []
for activity in activities:
result.append({'IDACTIVITE': 'foo%s' % activity, 'TYPEACTIVITE': activity})
result = {
'DATA': {
'PORTAIL': {
'DUI': {
'ENFANT': [
{
'IDPERSONNE': '42',
'NOM': '',
'PRENOM': '',
'REGIME': '',
'LIBELLEECOLE': '',
'ACTIVITE': result,
}
]
}
}
}
}
with mock.patch('passerelle.contrib.toulouse_axel.schemas.enfants_activites') as operation:
operation.return_value = OperationResult(json_response=result, xml_request='', xml_response='')
resp = app.get('/toulouse-axel/test/clae_children_activities_info?NameID=yyy&booking_date=2020-01-20')
assert resp.json['err'] == 0
assert len(resp.json['data']) == int(expected)
def test_clae_booking_activities_info_endpoint_axel_error(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with mock.patch('passerelle.contrib.toulouse_axel.schemas.enfants_activites') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get(
'/toulouse-axel/test/clae_booking_activities_info?NameID=yyy&idpersonne=3535&start_date=2020-01-20&end_date=2020-01-24'
)
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/child_activities.xml')
with open(filepath) as xml:
content = xml.read()
with mock_getdata(content, 'EnfantsActivites'):
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_periode') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get(
'/toulouse-axel/test/clae_booking_activities_info?NameID=yyy&idpersonne=3535&start_date=2020-01-20&end_date=2020-01-24'
)
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
@pytest.mark.parametrize('value', ['foo', '20/01/2020', '2020'])
def test_clae_booking_activities_info_endpoint_bad_date_format(app, resource, value):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
resp = app.get(
'/toulouse-axel/test/clae_booking_activities_info?NameID=yyy&idpersonne=3535&start_date=%s&end_date=2020-01-24'
% value,
status=400,
)
assert resp.json['err_desc'] == "bad date format, should be YYYY-MM-DD"
assert resp.json['err'] == 'bad-request'
resp = app.get(
'/toulouse-axel/test/clae_booking_activities_info?NameID=yyy&idpersonne=3535&start_date=2020-01-20&end_date=%s'
% value,
status=400,
)
assert resp.json['err_desc'] == "bad date format, should be YYYY-MM-DD"
assert resp.json['err'] == 'bad-request'
def test_clae_booking_activities_info_endpoint_no_result(app, resource, child_activities_data):
resp = app.get(
'/toulouse-axel/test/clae_booking_activities_info?NameID=yyy&idpersonne=3535&start_date=2020-01-20&end_date=2020-01-24'
)
assert resp.json['err_desc'] == "Person not found"
assert resp.json['err'] == 'not-found'
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/child_activities.xml')
with open(filepath) as xml:
content = xml.read()
with mock_getdata(content, 'EnfantsActivites'):
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_periode') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get(
'/toulouse-axel/test/clae_booking_activities_info?NameID=yyy&idpersonne=4242&start_date=2020-01-20&end_date=2020-01-24'
)
assert resp.json['err_desc'] == "Child not found"
assert resp.json['err'] == 'not-found'
content = """<PORTAIL>
<DUI>
<IDDUI>XXX</IDDUI>
<ENFANT>
<IDPERSONNE>4242</IDPERSONNE>
<ACTIVITE>
<ANNEEREFERENCE>2019</ANNEEREFERENCE>
<IDACTIVITE>A19P1M1</IDACTIVITE>
<JOUR>00000</JOUR>
</ACTIVITE>
</ENFANT>
</DUI>
</PORTAIL>"""
activities = child_activities_data['ENFANT'][0]
with mock_getdata(content, 'ReservationPeriode'):
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities',
return_value=activities,
):
resp = app.get(
'/toulouse-axel/test/clae_booking_activities_info?NameID=yyy&idpersonne=3535&start_date=2020-01-20&end_date=2020-01-24'
)
assert resp.json['err_desc'] == "Child not found"
assert resp.json['err'] == 'not-found'
def test_clae_booking_activities_info_endpoint(app, resource, child_activities_data):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/booking_info.xml')
with open(filepath) as xml:
content = xml.read()
activities = copy.deepcopy(child_activities_data['ENFANT'][0])
with mock_getdata(content, 'ReservationPeriode'):
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities',
return_value=activities,
):
resp = app.get(
'/toulouse-axel/test/clae_booking_activities_info?NameID=yyy&idpersonne=3535&start_date=2020-01-20&end_date=2020-01-24'
)
assert resp.json['err'] == 0
assert resp.json['data'] == [
{
'day': '2020-01-20',
'activity_id': 'A19P1M1',
'activity_type': 'MAT',
'activity_label': 'Temps du matin',
'booked': False,
'bookable': False,
'week': 'week:2020-01-20:2020-01-24',
},
{
'day': '2020-01-20',
'activity_id': 'A19P1M2',
'activity_type': 'MIDI',
'activity_label': 'Temps du midi',
'booked': True,
'bookable': False,
'week': 'week:2020-01-20:2020-01-24',
},
{
'day': '2020-01-20',
'activity_id': 'A19P1M3',
'activity_type': 'SOIR',
'activity_label': 'Temps du soir',
'booked': True,
'bookable': False,
'week': 'week:2020-01-20:2020-01-24',
},
{
'day': '2020-01-21',
'activity_id': 'A19P1M1',
'activity_type': 'MAT',
'activity_label': 'Temps du matin',
'booked': False,
'bookable': False,
'week': 'week:2020-01-20:2020-01-24',
},
{
'day': '2020-01-21',
'activity_id': 'A19P1M2',
'activity_type': 'MIDI',
'activity_label': 'Temps du midi',
'booked': True,
'bookable': False,
'week': 'week:2020-01-20:2020-01-24',
},
{
'day': '2020-01-21',
'activity_id': 'A19P1M3',
'activity_type': 'SOIR',
'activity_label': 'Temps du soir',
'booked': True,
'bookable': False,
'week': 'week:2020-01-20:2020-01-24',
},
{
'day': '2020-01-22',
'activity_id': 'A19P1M1',
'activity_type': 'MAT',
'activity_label': 'Temps du matin',
'booked': False,
'bookable': False,
'week': 'week:2020-01-20:2020-01-24',
},
{
'day': '2020-01-22',
'activity_id': 'A19P1M2',
'activity_type': 'MIDI',
'activity_label': 'Temps du midi',
'booked': True,
'bookable': False,
'week': 'week:2020-01-20:2020-01-24',
},
{
'day': '2020-01-22',
'activity_id': 'A19P1M4',
'activity_type': 'GARD',
'activity_label': 'Temps mercredi après midi',
'booked': True,
'bookable': False,
'week': 'week:2020-01-20:2020-01-24',
},
{
'day': '2020-01-23',
'activity_id': 'A19P1M1',
'activity_type': 'MAT',
'activity_label': 'Temps du matin',
'booked': False,
'bookable': False,
'week': 'week:2020-01-20:2020-01-24',
},
{
'day': '2020-01-23',
'activity_id': 'A19P1M2',
'activity_type': 'MIDI',
'activity_label': 'Temps du midi',
'booked': True,
'bookable': False,
'week': 'week:2020-01-20:2020-01-24',
},
{
'day': '2020-01-23',
'activity_id': 'A19P1M3',
'activity_type': 'SOIR',
'activity_label': 'Temps du soir',
'booked': True,
'bookable': False,
'week': 'week:2020-01-20:2020-01-24',
},
{
'day': '2020-01-24',
'activity_id': 'A19P1M1',
'activity_type': 'MAT',
'activity_label': 'Temps du matin',
'booked': False,
'bookable': False,
'week': 'week:2020-01-20:2020-01-24',
},
{
'day': '2020-01-24',
'activity_id': 'A19P1M2',
'activity_type': 'MIDI',
'activity_label': 'Temps du midi',
'booked': True,
'bookable': False,
'week': 'week:2020-01-20:2020-01-24',
},
{
'day': '2020-01-24',
'activity_id': 'A19P1M3',
'activity_type': 'SOIR',
'activity_label': 'Temps du soir',
'booked': True,
'bookable': False,
'week': 'week:2020-01-20:2020-01-24',
},
]
content = """<PORTAIL>
<DUI>
<IDDUI>XXX</IDDUI>
<ENFANT>
<IDPERSONNE>3535</IDPERSONNE>
<ACTIVITE>
<ANNEEREFERENCE>2019</ANNEEREFERENCE>
<IDACTIVITE>A19P1M1</IDACTIVITE>
<JOUR>10201</JOUR>
</ACTIVITE>
</ENFANT>
</DUI>
</PORTAIL>"""
cache.clear()
activities = copy.deepcopy(child_activities_data['ENFANT'][0])
activities['ACTIVITE'] = activities['ACTIVITE'][:1]
with mock_getdata(content, 'ReservationPeriode'):
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities',
return_value=activities,
):
resp = app.get(
'/toulouse-axel/test/clae_booking_activities_info?NameID=yyy&idpersonne=3535&start_date=2020-01-20&end_date=2020-01-24'
)
assert resp.json['err'] == 0
assert resp.json['data'] == [
{
'day': '2020-01-20',
'activity_id': 'A19P1M1',
'activity_type': 'MAT',
'activity_label': 'Temps du matin',
'booked': True,
'bookable': False,
'week': 'week:2020-01-20:2020-01-24',
},
{
'day': '2020-01-21',
'activity_id': 'A19P1M1',
'activity_type': 'MAT',
'activity_label': 'Temps du matin',
'booked': False,
'bookable': False,
'week': 'week:2020-01-20:2020-01-24',
},
{
'day': '2020-01-23',
'activity_id': 'A19P1M1',
'activity_type': 'MAT',
'activity_label': 'Temps du matin',
'booked': False,
'bookable': False,
'week': 'week:2020-01-20:2020-01-24',
},
{
'day': '2020-01-24',
'activity_id': 'A19P1M1',
'activity_type': 'MAT',
'activity_label': 'Temps du matin',
'booked': True,
'bookable': False,
'week': 'week:2020-01-20:2020-01-24',
},
]
@freezegun.freeze_time('2020-03-26')
@pytest.mark.parametrize(
'start_date, end_date, last_date',
[
# end date is a not a friday
('2020-04-07', '2020-04-13', '2020-04-13'),
# except if end date is saturday or sunday => ends on previous friday
('2020-04-07', '2020-04-18', '2020-04-17'),
('2020-04-07', '2020-04-19', '2020-04-17'),
# start date is after end date, same week => result is empty
('2020-04-16', '2020-04-15', None),
# start date is after end date, not the same week => result is empty
('2020-04-16', '2020-04-12', None),
],
)
def test_clae_booking_activities_info_period(app, resource, start_date, end_date, last_date):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_booking_data'
) as activities_info:
activities_info.return_value = {
'ACTIVITE': [
{
'id': 'TOTO',
'booking': {
'days': {
'monday': True,
'tuesday': True,
'wednesday': True,
'thursday': True,
'friday': True,
}
},
'TYPEACTIVITE': 'MAT',
'LIBELLEACTIVITE': 'Matin',
}
]
}
resp = app.get(
'/toulouse-axel/test/clae_booking_activities_info?NameID=yyy&idpersonne=3535'
'&start_date=%s&end_date=%s' % (start_date, end_date)
)
if last_date is None:
assert resp.json['data'] == []
else:
assert resp.json['data'][0]['day'] == start_date
assert resp.json['data'][-1]['day'] == last_date
@freezegun.freeze_time('2020-04-15')
def test_clae_booking_activities_info_bookable(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_booking_data'
) as activities_info:
activities_info.return_value = {
'ACTIVITE': [
{
'id': 'TOTO',
'booking': {
'days': {
'monday': True,
'tuesday': True,
'wednesday': True,
'thursday': True,
'friday': True,
}
},
'TYPEACTIVITE': 'MAT',
'LIBELLEACTIVITE': 'Matin',
}
]
}
resp = app.get(
'/toulouse-axel/test/clae_booking_activities_info?NameID=yyy&idpersonne=3535'
'&start_date=2020-04-01&end_date=2020-04-30'
)
activities = {a['day']: a['bookable'] for a in resp.json['data']}
assert activities['2020-04-01'] is False
assert activities['2020-04-02'] is False
assert activities['2020-04-03'] is False
assert activities['2020-04-06'] is False
assert activities['2020-04-07'] is False
assert activities['2020-04-08'] is False
assert activities['2020-04-09'] is False
assert activities['2020-04-10'] is False
assert activities['2020-04-13'] is False
assert activities['2020-04-14'] is False
assert activities['2020-04-15'] is False
assert activities['2020-04-16'] is False
assert activities['2020-04-17'] is False
assert activities['2020-04-20'] is False
assert activities['2020-04-21'] is False
assert activities['2020-04-22'] is False
assert activities['2020-04-23'] is True
assert activities['2020-04-24'] is True
assert activities['2020-04-27'] is True
assert activities['2020-04-28'] is True
assert activities['2020-04-29'] is True
assert activities['2020-04-30'] is True
@freezegun.freeze_time('2019-09-01')
def test_clae_booking_activity_possible_days_endpoint_axel_error(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with mock.patch('passerelle.contrib.toulouse_axel.schemas.enfants_activites') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_possible_days?NameID=yyy&idpersonne=3535'
'&start_date=2020-01-20&end_date=2020-01-24&activity_type=MAT'
)
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/child_activities.xml')
with open(filepath) as xml:
content = xml.read()
with mock_getdata(content, 'EnfantsActivites'):
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_periode') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_possible_days?NameID=yyy&idpersonne=3535'
'&start_date=2020-01-20&end_date=2020-01-24&activity_type=MAT'
)
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
@freezegun.freeze_time('2019-09-01')
@pytest.mark.parametrize('value', ['foo', '20/01/2020', '2020'])
def test_clae_booking_activity_possible_days_endpoint_bad_date_format(app, resource, value):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_possible_days?NameID=yyy&idpersonne=3535'
'&start_date=%s&end_date=2020-01-24&activity_type=MAT' % value,
status=400,
)
assert resp.json['err_desc'] == "bad date format, should be YYYY-MM-DD"
assert resp.json['err'] == 'bad-request'
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_possible_days?NameID=yyy&idpersonne=3535'
'&start_date=2020-02-20&end_date=%s&activity_type=MAT' % value,
status=400,
)
assert resp.json['err_desc'] == "bad date format, should be YYYY-MM-DD"
assert resp.json['err'] == 'bad-request'
@freezegun.freeze_time('2019-09-01')
def test_clae_booking_activity_possible_days_endpoint_activity_type(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_possible_days?NameID=yyy&idpersonne=3535'
'&start_date=2020-01-20&end_date=2020-01-24&activity_type=FOO',
status=400,
)
assert resp.json['err_desc'] == "bad activity_type, should be MAT, MIDI, SOIR or GARD"
assert resp.json['err'] == 'bad-request'
@freezegun.freeze_time('2019-09-01')
def test_clae_booking_activity_possible_days_endpoint_no_result(app, resource, child_activities_data):
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_possible_days?NameID=yyy&idpersonne=3535'
'&start_date=2020-01-20&end_date=2020-01-24&activity_type=MAT'
)
assert resp.json['err_desc'] == "Person not found"
assert resp.json['err'] == 'not-found'
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/child_activities.xml')
with open(filepath) as xml:
content = xml.read()
with mock_getdata(content, 'EnfantsActivites'):
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_periode') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_possible_days?NameID=yyy&idpersonne=4242'
'&start_date=2020-01-20&end_date=2020-01-24&activity_type=MAT'
)
assert resp.json['err_desc'] == "Child not found"
assert resp.json['err'] == 'not-found'
content = """<PORTAIL>
<DUI>
<IDDUI>XXX</IDDUI>
<ENFANT>
<IDPERSONNE>4242</IDPERSONNE>
<ACTIVITE>
<ANNEEREFERENCE>2019</ANNEEREFERENCE>
<IDACTIVITE>A19P1M1</IDACTIVITE>
<JOUR>00000</JOUR>
</ACTIVITE>
</ENFANT>
</DUI>
</PORTAIL>"""
activities = child_activities_data['ENFANT'][0]
with mock_getdata(content, 'ReservationPeriode'):
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities',
return_value=activities,
):
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_possible_days?NameID=yyy&idpersonne=3535'
'&start_date=2020-01-20&end_date=2020-01-24&activity_type=MAT'
)
assert resp.json['err_desc'] == "Child not found"
assert resp.json['err'] == 'not-found'
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_booking_data'
) as activities_info:
activities_info.return_value = {'ACTIVITE': []}
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_possible_days?NameID=yyy&idpersonne=3535'
'&start_date=2020-01-20&end_date=2020-01-24&activity_type=MAT'
)
assert resp.json['err'] == 0
assert resp.json['data'] == []
@freezegun.freeze_time('2019-09-01')
def test_clae_booking_activity_possible_days_endpoint(app, resource, child_activities_data):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
content = """<PORTAIL>
<DUI>
<IDDUI>XXX</IDDUI>
<ENFANT>
<IDPERSONNE>3535</IDPERSONNE>
<ACTIVITE>
<ANNEEREFERENCE>2019</ANNEEREFERENCE>
<IDACTIVITE>A19P1M1</IDACTIVITE>
<JOUR>00000</JOUR>
</ACTIVITE>
<ACTIVITE>
<ANNEEREFERENCE>2019</ANNEEREFERENCE>
<IDACTIVITE>A19P1M2</IDACTIVITE>
<JOUR>10201</JOUR>
</ACTIVITE>
</ENFANT>
</DUI>
</PORTAIL>"""
activities = child_activities_data['ENFANT'][0]
with mock_getdata(content, 'ReservationPeriode'):
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities',
return_value=activities,
):
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_possible_days?NameID=yyy&idpersonne=3535'
'&start_date=2020-01-20&end_date=2020-01-24&activity_type=MIDI'
)
assert resp.json['err'] == 0
assert len(resp.json['data']) == 5
assert set(resp.json['data'][0].keys()) == {'id', 'text', 'disabled', 'prefill', 'details'}
assert resp.json['data'][0]['id'] == '3535:MIDI:A19P1M2:2020-01-20'
assert resp.json['data'][1]['id'] == '3535:MIDI:A19P1M2:2020-01-21'
assert resp.json['data'][2]['id'] == '3535:MIDI:A19P1M2:2020-01-22'
assert resp.json['data'][3]['id'] == '3535:MIDI:A19P1M2:2020-01-23'
assert resp.json['data'][4]['id'] == '3535:MIDI:A19P1M2:2020-01-24'
assert resp.json['data'][0]['text'] == 'Monday 20 January 2020'
assert resp.json['data'][1]['text'] == 'Tuesday 21 January 2020'
assert resp.json['data'][2]['text'] == 'Wednesday 22 January 2020'
assert resp.json['data'][3]['text'] == 'Thursday 23 January 2020'
assert resp.json['data'][4]['text'] == 'Friday 24 January 2020'
assert resp.json['data'][0]['disabled'] is False
assert resp.json['data'][1]['disabled'] is False
assert resp.json['data'][2]['disabled'] is True
assert resp.json['data'][3]['disabled'] is False
assert resp.json['data'][4]['disabled'] is False
assert resp.json['data'][0]['prefill'] is True
assert resp.json['data'][1]['prefill'] is False
assert resp.json['data'][2]['prefill'] is None
assert resp.json['data'][3]['prefill'] is False
assert resp.json['data'][4]['prefill'] is True
# again - data are in cache
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities', return_value=activities
):
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_possible_days?NameID=yyy&idpersonne=3535'
'&start_date=2020-01-20&end_date=2020-01-24&activity_type=MAT'
)
assert resp.json['err'] == 0
assert len(resp.json['data']) == 5
@pytest.mark.parametrize(
'today, start_date, first_date, end_date, last_date',
[
# today is start date -> + 8 days
('2020-03-26', '2020-03-26', '2020-04-03', '2020-04-17', '2020-04-17'),
# start date is a friday => starts friday
('2020-03-26', '2020-04-03', '2020-04-03', '2020-04-17', '2020-04-17'),
# start date is a saturday => starts on next monday
('2020-03-26', '2020-04-04', '2020-04-06', '2020-04-17', '2020-04-17'),
# start date is a sunday => starts on next monday
('2020-03-26', '2020-04-05', '2020-04-06', '2020-04-17', '2020-04-17'),
# start date is a monday => starts on monday
('2020-03-26', '2020-04-06', '2020-04-06', '2020-04-17', '2020-04-17'),
# start date is a tuesday => starts on tuesday
('2020-03-26', '2020-04-07', '2020-04-07', '2020-04-17', '2020-04-17'),
# end date is a not a friday
('2020-03-26', '2020-04-07', '2020-04-07', '2020-04-13', '2020-04-13'),
# except if end date is saturday or sunday => ends on previous friday
('2020-03-26', '2020-04-07', '2020-04-07', '2020-04-18', '2020-04-17'),
('2020-03-26', '2020-04-07', '2020-04-07', '2020-04-19', '2020-04-17'),
# start date is after end date, same week => result is empty
('2020-03-26', '2020-04-16', None, '2020-04-15', None),
# start date is after end date, not the same week => result is empty
('2020-03-26', '2020-04-16', None, '2020-04-12', None),
],
)
def test_clae_booking_activity_possible_days_period(
app, resource, today, start_date, first_date, end_date, last_date, child_activities_data
):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
activities = child_activities_data['ENFANT'][0]
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities', return_value=activities
):
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_booking_data'
) as activities_info:
activities_info.return_value = {
'ACTIVITE': [
{
'id': 'TOTO',
'TYPEACTIVITE': 'MAT',
'booking': {
'days': {
'monday': True,
'tuesday': True,
'wednesday': True,
'thursday': True,
'friday': True,
}
},
}
]
}
with freezegun.freeze_time(today):
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_possible_days?NameID=yyy&idpersonne=3535'
'&start_date=%s&end_date=%s&activity_type=MAT' % (start_date, end_date)
)
if first_date is None:
assert resp.json['data'] == []
else:
assert resp.json['data'][0]['id'] == '3535:MAT:TOTO:%s' % first_date
assert resp.json['data'][-1]['id'] == '3535:MAT:TOTO:%s' % last_date
def test_clae_booking_activity_possible_days_next_year(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with freezegun.freeze_time('2020-07-01'):
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities'
) as mock_activities:
mock_activities.return_value = {}
app.get(
'/toulouse-axel/test/clae_booking_activity_possible_days?NameID=yyy&idpersonne=3535'
'&start_date=2020-09-01&end_date=2020-09-30&activity_type=MAT'
)
assert mock_activities.call_args_list == [
mock.call(child_id='3535', dui='XXX', reference_year=2020),
mock.call(child_id='3535', dui='XXX', reference_year=2020),
]
@freezegun.freeze_time('2019-09-01')
def test_clae_booking_activity_possible_days_endpoint_dates(app, resource, child_activities_data):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
activities = child_activities_data['ENFANT'][0]
# second activity starts after 2019-08-01
activities['ACTIVITE'][1]['DATEENTREE'] = '2019-10-01'
# last activity ends before 2020-07-31
activities['ACTIVITE'][3]['DATESORTIE'] = '2020-06-30'
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_booking_data'
) as activities_info:
activities_info.return_value = {
'ACTIVITE': [
{
'id': 'TOTO',
'TYPEACTIVITE': 'MAT',
'booking': {
'days': {
'monday': True,
'tuesday': True,
'wednesday': True,
'thursday': True,
'friday': True,
}
},
}
]
}
# it is not possible to book before 2019-10-01
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities',
return_value=activities,
):
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_possible_days?NameID=yyy&idpersonne=3535'
'&start_date=2019-09-01&end_date=2019-10-11&activity_type=MAT'
)
assert resp.json['err'] == 0
assert len(resp.json['data']) == 9
assert resp.json['data'][0]['id'] == '3535:MAT:TOTO:2019-10-01'
assert resp.json['data'][-1]['id'] == '3535:MAT:TOTO:2019-10-11'
# it is not possible to book after 2020-06-30
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities',
return_value=activities,
):
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_possible_days?NameID=yyy&idpersonne=3535'
'&start_date=2020-06-20&end_date=2020-07-15&activity_type=MAT'
)
assert resp.json['err'] == 0
assert len(resp.json['data']) == 7
assert resp.json['data'][0]['id'] == '3535:MAT:TOTO:2020-06-22'
assert resp.json['data'][-1]['id'] == '3535:MAT:TOTO:2020-06-30'
@freezegun.freeze_time('2019-09-01')
def test_clae_booking_activity_annual_possible_days_endpoint_axel_error(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with mock.patch('passerelle.contrib.toulouse_axel.schemas.enfants_activites') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_annual_possible_days?NameID=yyy&idpersonne=3535'
'&activity_type=MAT&booking_date=2019-09-01'
)
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
@freezegun.freeze_time('2019-09-01')
@pytest.mark.parametrize('value', ['foo', '20/01/2020', '2020'])
def test_clae_booking_activity_annual_possible_days_endpoint_bad_date_format(app, resource, value):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_annual_possible_days?NameID=yyy&idpersonne=3535'
'&activity_type=MAT&booking_date=%s' % value,
status=400,
)
assert resp.json['err_desc'] == "bad date format, should be YYYY-MM-DD"
assert resp.json['err'] == 'bad-request'
@freezegun.freeze_time('2019-09-01')
def test_clae_booking_activity_annual_possible_days_endpoint_activity_type(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_annual_possible_days?NameID=yyy&idpersonne=3535'
'&activity_type=FOO&booking_date=2019-09-01',
status=400,
)
assert resp.json['err_desc'] == "bad activity_type, should be MAT, MIDI, SOIR or GARD"
assert resp.json['err'] == 'bad-request'
@freezegun.freeze_time('2019-09-01')
def test_clae_booking_activity_annual_possible_days_endpoint_no_result(app, resource):
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_annual_possible_days?NameID=yyy&idpersonne=3535'
'&activity_type=MAT&booking_date=2019-09-01'
)
assert resp.json['err_desc'] == "Person not found"
assert resp.json['err'] == 'not-found'
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/child_activities.xml')
with open(filepath) as xml:
content = xml.read()
with mock_getdata(content, 'EnfantsActivites'):
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_annual_possible_days?NameID=yyy&idpersonne=4242'
'&activity_type=MAT&booking_date=2019-09-01'
)
assert resp.json['err_desc'] == "Child not found"
assert resp.json['err'] == 'not-found'
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities',
return_value={'ACTIVITE': []},
):
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_annual_possible_days?NameID=yyy&idpersonne=3535'
'&activity_type=MAT&booking_date=2019-09-01'
)
assert resp.json['err'] == 0
assert resp.json['data'] == []
@freezegun.freeze_time('2019-09-01')
def test_clae_booking_activity_annual_possible_days_endpoint(app, resource, child_activities_data):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
activities = child_activities_data['ENFANT'][0]
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities', return_value=activities
):
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_annual_possible_days?NameID=yyy&idpersonne=3535'
'&activity_type=MAT&booking_date=2019-09-01'
)
assert resp.json['err'] == 0
assert resp.json['data'] == [
{
'id': '3535:MAT:A19P1M1:monday',
'text': 'Monday',
'disabled': False,
},
{
'id': '3535:MAT:A19P1M1:tuesday',
'text': 'Tuesday',
'disabled': False,
},
{
'id': '3535:MAT:A19P1M1:wednesday',
'text': 'Wednesday',
'disabled': False,
},
{
'id': '3535:MAT:A19P1M1:thursday',
'text': 'Thursday',
'disabled': False,
},
{
'id': '3535:MAT:A19P1M1:friday',
'text': 'Friday',
'disabled': False,
},
]
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities', return_value=activities
):
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_annual_possible_days?NameID=yyy&idpersonne=3535'
'&activity_type=MIDI&booking_date=2019-09-01'
)
assert resp.json['err'] == 0
assert resp.json['data'] == [
{
'id': '3535:MIDI:A19P1M2:monday',
'text': 'Monday',
'disabled': False,
},
{
'id': '3535:MIDI:A19P1M2:tuesday',
'text': 'Tuesday',
'disabled': False,
},
{
'id': '3535:MIDI:A19P1M2:wednesday',
'text': 'Wednesday',
'disabled': False,
},
{
'id': '3535:MIDI:A19P1M2:thursday',
'text': 'Thursday',
'disabled': False,
},
{
'id': '3535:MIDI:A19P1M2:friday',
'text': 'Friday',
'disabled': False,
},
]
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities', return_value=activities
):
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_annual_possible_days?NameID=yyy&idpersonne=3535'
'&activity_type=SOIR&booking_date=2019-09-01'
)
assert resp.json['err'] == 0
assert resp.json['data'] == [
{
'id': '3535:SOIR:A19P1M3:monday',
'text': 'Monday',
'disabled': False,
},
{
'id': '3535:SOIR:A19P1M3:tuesday',
'text': 'Tuesday',
'disabled': False,
},
{
'id': '3535:SOIR:A19P1M3:wednesday',
'text': 'Wednesday',
'disabled': True,
},
{
'id': '3535:SOIR:A19P1M3:thursday',
'text': 'Thursday',
'disabled': False,
},
{
'id': '3535:SOIR:A19P1M3:friday',
'text': 'Friday',
'disabled': False,
},
]
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities', return_value=activities
):
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_annual_possible_days?NameID=yyy&idpersonne=3535'
'&activity_type=GARD&booking_date=2019-09-01'
)
assert resp.json['err'] == 0
assert resp.json['data'] == [
{
'id': '3535:GARD:A19P1M4:monday',
'text': 'Monday',
'disabled': True,
},
{
'id': '3535:GARD:A19P1M4:tuesday',
'text': 'Tuesday',
'disabled': True,
},
{
'id': '3535:GARD:A19P1M4:wednesday',
'text': 'Wednesday',
'disabled': False,
},
{
'id': '3535:GARD:A19P1M4:thursday',
'text': 'Thursday',
'disabled': True,
},
{
'id': '3535:GARD:A19P1M4:friday',
'text': 'Friday',
'disabled': True,
},
]
def test_clae_booking_activity_annual_possible_days_next_year(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with freezegun.freeze_time('2020-07-01'):
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities'
) as mock_activities:
mock_activities.return_value = {}
app.get(
'/toulouse-axel/test/clae_booking_activity_annual_possible_days?NameID=yyy&idpersonne=3535'
'&activity_type=GARD&booking_date=2020-09-01'
)
assert mock_activities.call_args_list == [
mock.call(child_id='3535', dui='XXX', reference_year=2020),
]
@freezegun.freeze_time('2019-09-01')
def test_clae_booking_activity_prefill_endpoint_axel_error(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with mock.patch('passerelle.contrib.toulouse_axel.schemas.enfants_activites') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_prefill?NameID=yyy&idpersonne=3535'
'&start_date=2020-01-20&end_date=2020-01-24&activity_type=MAT'
)
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/child_activities.xml')
with open(filepath) as xml:
content = xml.read()
with mock_getdata(content, 'EnfantsActivites'):
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_periode') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_prefill?NameID=yyy&idpersonne=3535'
'&start_date=2020-01-20&end_date=2020-01-24&activity_type=MAT'
)
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
@freezegun.freeze_time('2019-09-01')
@pytest.mark.parametrize('value', ['foo', '20/01/2020', '2020'])
def test_clae_booking_activity_prefill_endpoint_bad_date_format(app, resource, value):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_prefill?NameID=yyy&idpersonne=3535'
'&start_date=%s&end_date=2020-01-24&activity_type=MAT' % value,
status=400,
)
assert resp.json['err_desc'] == "bad date format, should be YYYY-MM-DD"
assert resp.json['err'] == 'bad-request'
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_prefill?NameID=yyy&idpersonne=3535'
'&start_date=2020-01-20&end_date=%s&activity_type=MAT' % value,
status=400,
)
assert resp.json['err_desc'] == "bad date format, should be YYYY-MM-DD"
assert resp.json['err'] == 'bad-request'
@freezegun.freeze_time('2019-09-01')
def test_clae_booking_activity_prefill_endpoint_activity_type(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_prefill?NameID=yyy&idpersonne=3535'
'&start_date=2020-01-20&end_date=2020-01-24&activity_type=FOO',
status=400,
)
assert resp.json['err_desc'] == "bad activity_type, should be MAT, MIDI, SOIR or GARD"
assert resp.json['err'] == 'bad-request'
@freezegun.freeze_time('2019-09-01')
def test_clae_booking_activity_prefill_endpoint_no_result(app, resource, child_activities_data):
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_prefill?NameID=yyy&idpersonne=3535'
'&start_date=2020-01-20&end_date=2020-01-24&activity_type=MAT'
)
assert resp.json['err_desc'] == "Person not found"
assert resp.json['err'] == 'not-found'
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/child_activities.xml')
with open(filepath) as xml:
content = xml.read()
with mock_getdata(content, 'EnfantsActivites'):
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_periode') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_prefill?NameID=yyy&idpersonne=4242'
'&start_date=2020-01-20&end_date=2020-01-24&activity_type=MAT'
)
assert resp.json['err_desc'] == "Child not found"
assert resp.json['err'] == 'not-found'
content = """<PORTAIL>
<DUI>
<IDDUI>XXX</IDDUI>
<ENFANT>
<IDPERSONNE>4242</IDPERSONNE>
<ACTIVITE>
<ANNEEREFERENCE>2019</ANNEEREFERENCE>
<IDACTIVITE>A19P1M1</IDACTIVITE>
<JOUR>00000</JOUR>
</ACTIVITE>
</ENFANT>
</DUI>
</PORTAIL>"""
activities = child_activities_data['ENFANT'][0]
with mock_getdata(content, 'ReservationPeriode'):
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities',
return_value=activities,
):
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_prefill?NameID=yyy&idpersonne=3535'
'&start_date=2020-01-20&end_date=2020-01-24&activity_type=MAT'
)
assert resp.json['err_desc'] == "Child not found"
assert resp.json['err'] == 'not-found'
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.clae_booking_activity_possible_days'
) as possible_days:
possible_days.return_value = {'data': []}
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_prefill?NameID=yyy&idpersonne=3535'
'&start_date=2020-01-20&end_date=2020-01-24&activity_type=MAT'
)
assert resp.json['err'] == 0
assert resp.json['data'] == []
def test_clae_booking_activity_prefill_endpoint(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.clae_booking_activity_possible_days'
) as possible_days:
possible_days.return_value = {
'data': [
{
'id': '3535:MAT:A19P1M1:2020-01-20',
'prefill': True,
},
{
'id': '3535:MAT:A19P1M1:2020-01-21',
'prefill': False,
},
{
'id': '3535:MAT:A19P1M1:2020-01-22',
'prefill': None,
},
{
'id': '3535:MAT:A19P1M1:2020-01-23',
'prefill': False,
},
{
'id': '3535:MAT:A19P1M1:2020-01-24',
'prefill': True,
},
]
}
resp = app.get(
'/toulouse-axel/test/clae_booking_activity_prefill?NameID=yyy&idpersonne=3535'
'&start_date=2020-01-20&end_date=2020-01-24&activity_type=MAT'
)
assert resp.json['err'] == 0
assert resp.json['data'] == ['3535:MAT:A19P1M1:2020-01-20', '3535:MAT:A19P1M1:2020-01-24']
def test_are_children_registered_axel_error(resource):
with mock.patch('passerelle.contrib.toulouse_axel.schemas.enfants_activites') as operation:
operation.side_effect = AxelError('FooBar')
assert resource.are_children_registered(dui='XXX') == {}
@pytest.mark.parametrize(
'date_value, expected',
[
('2019-08-01', {'3535': True}),
('2020-07-31', {'3535': True}),
],
)
def test_are_children_registered_reference_year(resource, date_value, expected):
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_children_activities'
) as get_children_activities:
get_children_activities.return_value = {'3535': {'ACTIVITE': [{}]}}
with freezegun.freeze_time(date_value):
assert resource.are_children_registered(dui='XXX') == expected
@pytest.mark.parametrize(
'activities, expected',
[
({}, {}),
({'3535': {'ACTIVITE': []}}, {'3535': False}),
({'3535': {'ACTIVITE': [{}]}}, {'3535': True}),
({'3535': {'ACTIVITE': [{}]}, '4242': {}}, {'3535': True, '4242': False}),
],
)
def test_are_children_registered(resource, activities, expected):
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_children_activities'
) as get_children_activities:
get_children_activities.return_value = activities
assert resource.are_children_registered(dui='XXX') == expected
@freezegun.freeze_time('2019-09-01')
def test_clae_booking_endpoint_axel_error(app, resource, booking_params):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with mock.patch('passerelle.contrib.toulouse_axel.schemas.enfants_activites') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.post_json('/toulouse-axel/test/clae_booking?NameID=yyy', params=booking_params)
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/child_activities.xml')
with open(filepath) as xml:
content = xml.read()
with mock_getdata(content, 'EnfantsActivites'):
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.post_json('/toulouse-axel/test/clae_booking?NameID=yyy', params=booking_params)
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
def test_clae_booking_endpoint_date_error(app, resource, booking_params):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
# DATEDEBUT must be before DATEDFIN
booking_params['booking_start_date'] = '2020-02-01'
booking_params['booking_end_date'] = '2020-01-01'
with freezegun.freeze_time('2019-09-01'):
resp = app.post_json('/toulouse-axel/test/clae_booking?NameID=yyy', params=booking_params, status=400)
assert resp.json['err_desc'] == "booking_start_date should be before booking_end_date"
assert resp.json['err'] == 'bad-request'
# today + 8j rule
booking_params['booking_start_date'] = '2020-01-01'
booking_params['booking_end_date'] = '2020-07-31'
# date in the past
with freezegun.freeze_time('2020-01-01'):
resp = app.post_json('/toulouse-axel/test/clae_booking?NameID=yyy', params=booking_params, status=400)
assert resp.json['err_desc'] == "booking_start_date min value: 2020-01-09"
assert resp.json['err'] == 'bad-request'
# too soon
with freezegun.freeze_time('2019-12-25'):
resp = app.post_json('/toulouse-axel/test/clae_booking?NameID=yyy', params=booking_params, status=400)
assert resp.json['err_desc'] == "booking_start_date min value: 2020-01-02"
assert resp.json['err'] == 'bad-request'
with freezegun.freeze_time('2019-12-31'):
resp = app.post_json('/toulouse-axel/test/clae_booking?NameID=yyy', params=booking_params, status=400)
assert resp.json['err_desc'] == "booking_start_date min value: 2020-01-08"
assert resp.json['err'] == 'bad-request'
# bad reference year for end_date
booking_params['booking_start_date'] = '2020-01-01'
booking_params['booking_end_date'] = '2020-12-31'
with freezegun.freeze_time('2019-09-01'):
resp = app.post_json('/toulouse-axel/test/clae_booking?NameID=yyy', params=booking_params, status=400)
assert resp.json['err_desc'] == "booking_end_date max value: 2020-07-31"
assert resp.json['err'] == 'bad-request'
booking_params['booking_start_date'] = '2021-01-01'
booking_params['booking_end_date'] = '2021-12-31'
with freezegun.freeze_time('2019-09-01'):
resp = app.post_json('/toulouse-axel/test/clae_booking?NameID=yyy', params=booking_params, status=400)
assert resp.json['err_desc'] == "booking_end_date max value: 2021-07-31"
assert resp.json['err'] == 'bad-request'
def test_clae_booking_endpoint_no_result(app, resource, booking_params):
resp = app.post_json('/toulouse-axel/test/clae_booking?NameID=yyy', params=booking_params)
assert resp.json['err_desc'] == "Person not found"
assert resp.json['err'] == 'not-found'
@freezegun.freeze_time('2019-09-01')
def test_clae_booking_endpoint(app, resource, booking_params, child_activities_data):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
activities = child_activities_data['ENFANT'][0]
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities', return_value=activities
):
content = "<PORTAIL/>"
with mock_getdata(content, 'ReservationAnnuelle'):
with mock.patch('django.core.cache.cache.delete') as mock_cache_delete:
resp = app.post_json('/toulouse-axel/test/clae_booking?NameID=yyy', params=booking_params)
assert mock_cache_delete.call_args_list == [
mock.call('toulouse-axel-%s-children-activities-XXX-2019' % resource.pk),
mock.call('toulouse-axel-%s-booking-data-XXX-3535-2020-04-13' % resource.pk),
]
assert resp.json['err'] == 0
assert resp.json['updated'] is True
assert 'data' in resp.json
assert 'xml_request' in resp.json['data']
assert 'xml_response' in resp.json['data']
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
resp = app.post_json('/toulouse-axel/test/clae_booking?NameID=yyy', params=booking_params)
payload = operation.call_args_list[0][0][1]['PORTAIL']['DUI']
assert payload == {
'DATEDEMANDE': '2019-09-01',
'ENFANT': [
{
'IDPERSONNE': '3535',
'REGIME': 'AV',
'ACTIVITE': [
{
'IDACTIVITE': 'A19P1M1',
'ANNEEREFERENCE': '2019',
'PERIODE': [
{
'DATEDEBUT': '2020-04-13',
'DATEDFIN': '2020-04-17',
'SEMAINETYPE': '11011',
},
],
},
{
'IDACTIVITE': 'A19P1M2',
'ANNEEREFERENCE': '2019',
'PERIODE': [
{
'DATEDEBUT': '2020-04-13',
'DATEDFIN': '2020-04-17',
'SEMAINETYPE': '11011',
},
],
},
{
'IDACTIVITE': 'A19P1M3',
'ANNEEREFERENCE': '2019',
'PERIODE': [
{
'DATEDEBUT': '2020-04-13',
'DATEDFIN': '2020-04-17',
'SEMAINETYPE': '10000',
},
],
},
{
'IDACTIVITE': 'A19P1M4',
'ANNEEREFERENCE': '2019',
'PERIODE': [
{
'DATEDEBUT': '2020-04-13',
'DATEDFIN': '2020-04-17',
'SEMAINETYPE': '00100',
},
],
},
],
}
],
'IDDUI': 'XXX',
}
# empty list
new_booking_params = copy.deepcopy(booking_params)
new_booking_params['booking_list_MAT'] = ['42:MAT:A19P1M1:2020-04-15'] # wrong child, ignored
new_booking_params['booking_list_MIDI'] = []
new_booking_params['booking_list_SOIR'] = []
new_booking_params['booking_list_GARD'] = []
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
resp = app.post_json('/toulouse-axel/test/clae_booking?NameID=yyy', params=new_booking_params)
payload = operation.call_args_list[0][0][1]['PORTAIL']['DUI']
assert len(payload['ENFANT']) == 1
assert payload['ENFANT'][0]['IDPERSONNE'] == '3535'
assert len(payload['ENFANT'][0]['ACTIVITE']) == 4
activity1 = payload['ENFANT'][0]['ACTIVITE'][0]
assert activity1['IDACTIVITE'] == 'A19P1M1'
assert len(activity1['PERIODE']) == 1
assert activity1['PERIODE'][0]['DATEDEBUT'] == '2020-04-13'
assert activity1['PERIODE'][0]['DATEDFIN'] == '2020-04-17'
assert activity1['PERIODE'][0]['SEMAINETYPE'] == '00000'
activity2 = payload['ENFANT'][0]['ACTIVITE'][1]
assert activity2['IDACTIVITE'] == 'A19P1M2'
assert len(activity2['PERIODE']) == 1
assert activity2['PERIODE'][0]['DATEDEBUT'] == '2020-04-13'
assert activity2['PERIODE'][0]['DATEDFIN'] == '2020-04-17'
assert activity2['PERIODE'][0]['SEMAINETYPE'] == '00000'
activity3 = payload['ENFANT'][0]['ACTIVITE'][2]
assert activity3['IDACTIVITE'] == 'A19P1M3'
assert len(activity3['PERIODE']) == 1
assert activity3['PERIODE'][0]['DATEDEBUT'] == '2020-04-13'
assert activity3['PERIODE'][0]['DATEDFIN'] == '2020-04-17'
assert activity3['PERIODE'][0]['SEMAINETYPE'] == '00000'
activity4 = payload['ENFANT'][0]['ACTIVITE'][3]
assert activity4['IDACTIVITE'] == 'A19P1M4'
assert len(activity4['PERIODE']) == 1
assert activity4['PERIODE'][0]['DATEDEBUT'] == '2020-04-13'
assert activity4['PERIODE'][0]['DATEDFIN'] == '2020-04-17'
assert activity4['PERIODE'][0]['SEMAINETYPE'] == '00000'
# null list
new_booking_params = copy.deepcopy(booking_params)
new_booking_params['booking_list_MAT'] = None
new_booking_params['booking_list_MIDI'] = None
new_booking_params['booking_list_SOIR'] = None
new_booking_params['booking_list_GARD'] = None
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
resp = app.post_json('/toulouse-axel/test/clae_booking?NameID=yyy', params=new_booking_params)
payload = operation.call_args_list[0][0][1]['PORTAIL']['DUI']
assert 'ACTIVITE' not in payload['ENFANT'][0]
# many weeks => many periods
new_booking_params = copy.deepcopy(booking_params)
new_booking_params['booking_start_date'] = '2020-04-01'
new_booking_params['booking_end_date'] = '2020-04-30'
new_booking_params['booking_list_MAT'].append('3535:MAT:A19P1M1:2020-04-01')
new_booking_params['booking_list_MAT'].append(
'3535:MAT:A19P1M1:2020-03-31'
) # before the period, ignored
new_booking_params['booking_list_MAT'].append('3535:MAT:A19P1M1:2020-04-30')
new_booking_params['booking_list_MAT'].append(
'3535:MAT:A19P1M1:2020-05-01'
) # after the period, ignored
new_booking_params['booking_list_MAT'].append('4242:MAT:A19P1M1:2020-04-15') # wrong child, ignored
new_booking_params['booking_list_MAT'].append('3535:MAT:FOO:2020-04-15') # wrong activity id, ignored
new_booking_params['booking_list_MIDI'] = None
new_booking_params['booking_list_SOIR'] = None
new_booking_params['booking_list_GARD'] = None
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
with mock.patch('django.core.cache.cache.delete') as mock_cache_delete:
resp = app.post_json('/toulouse-axel/test/clae_booking?NameID=yyy', params=new_booking_params)
assert mock_cache_delete.call_args_list == [
mock.call('toulouse-axel-%s-children-activities-XXX-2019' % resource.pk),
mock.call('toulouse-axel-%s-booking-data-XXX-3535-2020-03-30' % resource.pk),
mock.call('toulouse-axel-%s-booking-data-XXX-3535-2020-04-06' % resource.pk),
mock.call('toulouse-axel-%s-booking-data-XXX-3535-2020-04-13' % resource.pk),
mock.call('toulouse-axel-%s-booking-data-XXX-3535-2020-04-20' % resource.pk),
mock.call('toulouse-axel-%s-booking-data-XXX-3535-2020-04-27' % resource.pk),
]
payload = operation.call_args_list[0][0][1]['PORTAIL']['DUI']
assert len(payload['ENFANT']) == 1
assert payload['ENFANT'][0]['IDPERSONNE'] == '3535'
assert len(payload['ENFANT'][0]['ACTIVITE']) == 1
activity = payload['ENFANT'][0]['ACTIVITE'][0]
assert activity['IDACTIVITE'] == 'A19P1M1'
assert len(activity['PERIODE']) == 5
assert activity['PERIODE'][0]['DATEDEBUT'] == '2020-04-01'
assert activity['PERIODE'][0]['DATEDFIN'] == '2020-04-03'
assert activity['PERIODE'][0]['SEMAINETYPE'] == '00100'
assert activity['PERIODE'][1]['DATEDEBUT'] == '2020-04-06'
assert activity['PERIODE'][1]['DATEDFIN'] == '2020-04-10'
assert activity['PERIODE'][1]['SEMAINETYPE'] == '00000'
assert activity['PERIODE'][2]['DATEDEBUT'] == '2020-04-13'
assert activity['PERIODE'][2]['DATEDFIN'] == '2020-04-17'
assert activity['PERIODE'][2]['SEMAINETYPE'] == '11011'
assert activity['PERIODE'][3]['DATEDEBUT'] == '2020-04-20'
assert activity['PERIODE'][3]['DATEDFIN'] == '2020-04-24'
assert activity['PERIODE'][3]['SEMAINETYPE'] == '00000'
assert activity['PERIODE'][4]['DATEDEBUT'] == '2020-04-27'
assert activity['PERIODE'][4]['DATEDFIN'] == '2020-04-30'
assert activity['PERIODE'][4]['SEMAINETYPE'] == '00010'
@freezegun.freeze_time('2019-09-01')
def test_clae_booking_regime(app, resource, booking_params, child_activities_data):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
activities = child_activities_data['ENFANT'][0]
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities', return_value=activities
):
booking_params['regime'] = None
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
app.post_json('/toulouse-axel/test/clae_booking?NameID=yyy', params=booking_params)
payload = operation.call_args_list[0][0][1]['PORTAIL']['DUI']
assert payload['ENFANT'][0]['REGIME'] == 'SV'
booking_params['regime'] = ''
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
app.post_json('/toulouse-axel/test/clae_booking?NameID=yyy', params=booking_params)
payload = operation.call_args_list[0][0][1]['PORTAIL']['DUI']
assert payload['ENFANT'][0]['REGIME'] == 'SV'
del booking_params['regime']
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
app.post_json('/toulouse-axel/test/clae_booking?NameID=yyy', params=booking_params)
payload = operation.call_args_list[0][0][1]['PORTAIL']['DUI']
assert payload['ENFANT'][0]['REGIME'] == 'SV'
@freezegun.freeze_time('2019-09-01')
def test_clae_booking_endpoint_next_year(app, resource, child_activities_data):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
activities = child_activities_data['ENFANT'][0]
for activity in activities['ACTIVITE']:
activity['DATEDEBUT'] = '2020-08-01'
activity['DATEENTREE'] = '2020-08-01'
activity['DATEFIN'] = '2021-07-31'
activity['DATESORTIE'] = '2021-07-31'
booking_params = {
'booking_start_date': '2020-09-01',
'booking_end_date': '2020-09-04',
'booking_list_MAT': [],
'booking_list_MIDI': None,
'booking_list_SOIR': None,
'booking_list_GARD': None,
'child_id': '3535',
'regime': 'AV',
}
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities'
) as mock_activities:
mock_activities.return_value = activities
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
app.post_json('/toulouse-axel/test/clae_booking?NameID=yyy', params=booking_params)
assert mock_activities.call_args_list == [
mock.call(child_id='3535', dui='XXX', reference_year=2020),
]
payload = operation.call_args_list[0][0][1]['PORTAIL']['DUI']
assert len(payload['ENFANT']) == 1
assert payload['ENFANT'][0]['IDPERSONNE'] == '3535'
assert len(payload['ENFANT'][0]['ACTIVITE']) == 1
activity = payload['ENFANT'][0]['ACTIVITE'][0]
assert len(activity['PERIODE']) == 1
assert activity['PERIODE'][0]['DATEDEBUT'] == '2020-09-01'
assert activity['PERIODE'][0]['DATEDFIN'] == '2020-09-04'
@freezegun.freeze_time('2019-09-01')
def test_clae_booking_annual_endpoint_axel_error(app, resource, annual_booking_params):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with mock.patch('passerelle.contrib.toulouse_axel.schemas.enfants_activites') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.post_json(
'/toulouse-axel/test/clae_booking_annual?NameID=yyy', params=annual_booking_params
)
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/child_activities.xml')
with open(filepath) as xml:
content = xml.read()
with mock_getdata(content, 'EnfantsActivites'):
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.post_json(
'/toulouse-axel/test/clae_booking_annual?NameID=yyy', params=annual_booking_params
)
assert resp.json['err_desc'] == "Axel error: FooBar"
assert resp.json['err'] == 'error'
def test_clae_booking_annual_endpoint_no_result(app, resource, annual_booking_params):
resp = app.post_json('/toulouse-axel/test/clae_booking_annual?NameID=yyy', params=annual_booking_params)
assert resp.json['err_desc'] == "Person not found"
assert resp.json['err'] == 'not-found'
@freezegun.freeze_time('2019-09-01')
def test_clae_booking_annual_endpoint(app, resource, annual_booking_params, child_activities_data):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
activities = child_activities_data['ENFANT'][0]
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities', return_value=activities
):
content = "<PORTAIL/>"
with mock_getdata(content, 'ReservationAnnuelle'):
with mock.patch('django.core.cache.cache.delete') as mock_cache_delete:
resp = app.post_json(
'/toulouse-axel/test/clae_booking_annual?NameID=yyy', params=annual_booking_params
)
assert len(mock_cache_delete.call_args_list) == 48
assert mock_cache_delete.call_args_list[0] == mock.call(
'toulouse-axel-%s-children-activities-XXX-2019' % resource.pk
)
assert mock_cache_delete.call_args_list[1] == mock.call(
'toulouse-axel-%s-booking-data-XXX-3535-2019-09-09' % resource.pk
)
assert mock_cache_delete.call_args_list[-1] == mock.call(
'toulouse-axel-%s-booking-data-XXX-3535-2020-07-27' % resource.pk
)
assert resp.json['err'] == 0
assert resp.json['updated'] is True
assert 'data' in resp.json
assert 'xml_request' in resp.json['data']
assert 'xml_response' in resp.json['data']
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
resp = app.post_json(
'/toulouse-axel/test/clae_booking_annual?NameID=yyy', params=annual_booking_params
)
payload = operation.call_args_list[0][0][1]['PORTAIL']['DUI']
assert payload == {
'DATEDEMANDE': '2019-09-01',
'ENFANT': [
{
'IDPERSONNE': '3535',
'REGIME': 'AV',
'ACTIVITE': [
{
'ANNEEREFERENCE': '2019',
'IDACTIVITE': 'A19P1M1',
'PERIODE': [
{'DATEDEBUT': '2019-09-09', 'DATEDFIN': '2020-07-31', 'SEMAINETYPE': '11011'}
],
},
{
'ANNEEREFERENCE': '2019',
'IDACTIVITE': 'A19P1M2',
'PERIODE': [
{'DATEDEBUT': '2019-09-09', 'DATEDFIN': '2020-07-31', 'SEMAINETYPE': '11011'}
],
},
{
'ANNEEREFERENCE': '2019',
'IDACTIVITE': 'A19P1M3',
'PERIODE': [
{'DATEDEBUT': '2019-09-09', 'DATEDFIN': '2020-07-31', 'SEMAINETYPE': '10000'}
],
},
{
'ANNEEREFERENCE': '2019',
'IDACTIVITE': 'A19P1M4',
'PERIODE': [
{'DATEDEBUT': '2019-09-09', 'DATEDFIN': '2020-07-31', 'SEMAINETYPE': '00100'}
],
},
],
}
],
'IDDUI': 'XXX',
}
# empty list
new_booking_params = copy.deepcopy(annual_booking_params)
new_booking_params['booking_list_MAT'] = ['42:MAT:A19P1M1:monday'] # wrong child, ignored
new_booking_params['booking_list_MIDI'] = []
new_booking_params['booking_list_SOIR'] = []
new_booking_params['booking_list_GARD'] = []
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
resp = app.post_json(
'/toulouse-axel/test/clae_booking_annual?NameID=yyy', params=new_booking_params
)
payload = operation.call_args_list[0][0][1]['PORTAIL']['DUI']
assert len(payload['ENFANT']) == 1
assert payload['ENFANT'][0]['IDPERSONNE'] == '3535'
assert len(payload['ENFANT'][0]['ACTIVITE']) == 4
activity1 = payload['ENFANT'][0]['ACTIVITE'][0]
assert activity1['IDACTIVITE'] == 'A19P1M1'
assert len(activity1['PERIODE']) == 1
assert activity1['PERIODE'][0]['DATEDEBUT'] == '2019-09-09'
assert activity1['PERIODE'][0]['DATEDFIN'] == '2020-07-31'
assert activity1['PERIODE'][0]['SEMAINETYPE'] == '00000'
activity2 = payload['ENFANT'][0]['ACTIVITE'][1]
assert activity2['IDACTIVITE'] == 'A19P1M2'
assert len(activity2['PERIODE']) == 1
assert activity2['PERIODE'][0]['DATEDEBUT'] == '2019-09-09'
assert activity2['PERIODE'][0]['DATEDFIN'] == '2020-07-31'
assert activity2['PERIODE'][0]['SEMAINETYPE'] == '00000'
activity3 = payload['ENFANT'][0]['ACTIVITE'][2]
assert activity3['IDACTIVITE'] == 'A19P1M3'
assert len(activity3['PERIODE']) == 1
assert activity3['PERIODE'][0]['DATEDEBUT'] == '2019-09-09'
assert activity3['PERIODE'][0]['DATEDFIN'] == '2020-07-31'
assert activity3['PERIODE'][0]['SEMAINETYPE'] == '00000'
activity4 = payload['ENFANT'][0]['ACTIVITE'][3]
assert activity4['IDACTIVITE'] == 'A19P1M4'
assert len(activity4['PERIODE']) == 1
assert activity4['PERIODE'][0]['DATEDEBUT'] == '2019-09-09'
assert activity4['PERIODE'][0]['DATEDFIN'] == '2020-07-31'
assert activity4['PERIODE'][0]['SEMAINETYPE'] == '00000'
# null list
new_booking_params = copy.deepcopy(annual_booking_params)
new_booking_params['booking_list_MAT'] = None
new_booking_params['booking_list_MIDI'] = None
new_booking_params['booking_list_SOIR'] = None
new_booking_params['booking_list_GARD'] = None
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
resp = app.post_json(
'/toulouse-axel/test/clae_booking_annual?NameID=yyy', params=new_booking_params
)
payload = operation.call_args_list[0][0][1]['PORTAIL']['DUI']
assert 'ACTIVITE' not in payload['ENFANT'][0]
@freezegun.freeze_time('2019-09-01')
def test_clae_booking_annual_next_year(app, resource, child_activities_data):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
activities = child_activities_data['ENFANT'][0]
for activity in activities['ACTIVITE']:
activity['DATEDEBUT'] = '2020-08-01'
activity['DATEENTREE'] = '2020-08-01'
activity['DATEFIN'] = '2021-07-31'
activity['DATESORTIE'] = '2021-07-31'
annual_booking_params = {
'booking_list_MAT': [],
'booking_list_MIDI': None,
'booking_list_SOIR': None,
'booking_list_GARD': None,
'child_id': '3535',
'regime': 'AV',
'booking_date': '2020-08-01',
}
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities', return_value=activities
):
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
app.post_json('/toulouse-axel/test/clae_booking_annual?NameID=yyy', params=annual_booking_params)
payload = operation.call_args_list[0][0][1]['PORTAIL']['DUI']
assert payload['ENFANT'][0]['ACTIVITE'][0]['PERIODE'][0]['DATEDEBUT'] == '2020-08-01'
assert payload['ENFANT'][0]['ACTIVITE'][0]['PERIODE'][0]['DATEDFIN'] == '2021-07-31'
@freezegun.freeze_time('2019-09-01')
def test_clae_booking_annual_regime(app, resource, annual_booking_params, child_activities_data):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
activities = child_activities_data['ENFANT'][0]
with mock.patch(
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities', return_value=activities
):
annual_booking_params['regime'] = None
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
app.post_json('/toulouse-axel/test/clae_booking_annual?NameID=yyy', params=annual_booking_params)
payload = operation.call_args_list[0][0][1]['PORTAIL']['DUI']
assert payload['ENFANT'][0]['REGIME'] == 'SV'
annual_booking_params['regime'] = ''
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
app.post_json('/toulouse-axel/test/clae_booking_annual?NameID=yyy', params=annual_booking_params)
payload = operation.call_args_list[0][0][1]['PORTAIL']['DUI']
assert payload['ENFANT'][0]['REGIME'] == 'SV'
del annual_booking_params['regime']
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
app.post_json('/toulouse-axel/test/clae_booking_annual?NameID=yyy', params=annual_booking_params)
payload = operation.call_args_list[0][0][1]['PORTAIL']['DUI']
assert payload['ENFANT'][0]['REGIME'] == 'SV'