passerelle/tests/test_toulouse_axel.py

2175 lines
93 KiB
Python

# -*- coding: utf-8 -*-
# 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/>.
from __future__ import unicode_literals
from contextlib import contextmanager
import copy
import datetime
import decimal
import json
import mock
import os
import xml.etree.ElementTree as ET
import freezegun
import pytest
import xmlschema
from passerelle.contrib.toulouse_axel.models import (
AxelError,
Link,
Lock,
OperationResult,
ToulouseAxel,
enfants_activites,
form_maj_famille_dui,
form_paiement_dui,
list_dui_factures,
ref_date_gestion_dui,
ref_famille_dui,
ref_facture_a_payer,
ref_facture_pdf,
ref_verif_dui,
reservation_periode,
)
from passerelle.contrib.toulouse_axel.utils import (
situation_familiale_mapping,
csp_mapping,
lien_parente_mapping,
type_regime_mapping,
get_reference_year_from_date,
)
from passerelle.utils.jsonresponse import APIError
import utils
@pytest.fixture
def resource(db):
return 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 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 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)
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'):
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):
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):
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):
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):
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):
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):
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):
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):
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):
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):
reservation_periode(resource, {
'PORTAIL': {
'DUI': {
'IDDUI': 'XXX',
}
}
})
def test_management_dates_endpoint_axel_error(app, resource):
with mock.patch('passerelle.contrib.toulouse_axel.models.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()) == set(['err', 'data'])
assert resp.json['err'] == 0
assert set(resp.json['data'].keys()) == set(['REPORT-REVENUS', 'EXTRACTION-FAMILLES', 'EXTRACTION-CAFPRO'])
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.models.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.toulouse_axel.models.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
@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()) == set(['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()) == set(['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_refetential_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),
])
def test_refetential_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 dict(resp.json['data']) == dict(expected)
def test_family_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.models.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'
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'
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_getdata(content, 'RefFamilleDui'):
resp = app.get('/toulouse-axel/test/family_info?NameID=yyy')
assert resp.json['err'] == 0
assert set(resp.json['data'].keys()) == set([
'ADRESSE',
'CODEMISEAJOUR',
'DEMATFACTURES',
'ENFANT',
'IDDUI',
'NBENFANTACTIF',
'NBRLACTIF',
'REACTUALISATIONENLIGNE',
'REVENUS',
'RL1',
'RL2',
'SITUATIONFAMILIALE',
'SITUATIONFAMILIALE_label',
'TELFIXE',
])
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'] == 'foo foo'
assert resp.json['data']['ENFANT'][0]['CONTACT'][2]['id'] == 2
assert resp.json['data']['ENFANT'][0]['CONTACT'][2]['text'] == 'foo foo'
assert resp.json['data']['ENFANT'][1]['id'] == '3535'
assert resp.json['data']['ENFANT'][1]['text'] == 'foo foo'
with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.are_children_registered') as registered:
registered.side_effect = [{'4242': True}, {}]
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'][0]['clae_cantine_next'] is None
assert resp.json['data']['ENFANT'][1]['clae_cantine_current'] is None
assert resp.json['data']['ENFANT'][1]['clae_cantine_next'] is None
with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.are_children_registered') as registered:
registered.side_effect = [{}, {'4242': False, '3535': True}]
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'][0]['clae_cantine_next'] is False
assert resp.json['data']['ENFANT'][1]['clae_cantine_current'] is None
assert resp.json['data']['ENFANT'][1]['clae_cantine_next'] is True
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'
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.models.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'] == 'foo foo'
assert resp.json['data'][0]['CONTACT'][2]['id'] == 2
assert resp.json['data'][0]['CONTACT'][2]['text'] == 'foo foo'
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.models.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()) == set([
'id',
'text',
'ASSURANCE',
'CONTACT',
'DATENAISSANCE',
'IDPERSONNE',
'PRENOM',
'PRENOMMERE',
'PRENOMPERE',
'NOM',
'NOMMERE',
'NOMPERE',
'RATTACHEAUTREDUI',
'SANITAIRE',
'SEXE',
'clae_cantine_current',
'clae_cantine_next',
])
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'] == 'foo foo'
assert resp.json['data']['CONTACT'][2]['id'] == 2
assert resp.json['data']['CONTACT'][2]['text'] == 'foo foo'
with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.are_children_registered') as registered:
registered.side_effect = [{'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
assert resp.json['data']['clae_cantine_next'] is None
with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.are_children_registered') as registered:
registered.side_effect = [{}, {'4242': False}]
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']['clae_cantine_next'] is False
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.models.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'] == 'foo foo'
assert resp.json['data'][2]['id'] == 2
assert resp.json['data'][2]['text'] == 'foo foo'
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']) == 0
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.models.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.models.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.models.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')
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']
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')
full_update_params = copy.deepcopy(update_params)
assert 'NBENFANTSACHARGE' not in update_params['REVENUS']
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')
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_family_data_adresse(app, resource, update_params):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
# 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)
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')
# 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)
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')
# 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)
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)
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')
# 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)
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)
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)
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)
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
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
assert 'ADREMPLOYEUR' not in partial_update_params['RL1']
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:rl2_adresse_employeur'] = val
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
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')
# 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)
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)
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)
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
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
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)
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)
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')
# 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)
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)
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
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
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')
# 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)
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)
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['maj:enfant_1'] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
assert 'CONTACT' not in partial_update_params['ENFANT'][0]
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')
# 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)
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)
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
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
assert 'SANITAIRE' not in partial_update_params['ENFANT'][0]
assert 'SANITAIRE' not in partial_update_params['ENFANT'][1]
def test_pre_sanitize_update_family_data_enfant_n_sanitaire_allergie(app, resource, update_params):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
# test maj:enfant_n_sanitaire_allergie
partial_update_params = copy.deepcopy(update_params)
partial_update_params['maj:enfant_1_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_0'] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
assert len(partial_update_params['ENFANT']) == 1
assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "3535"
assert 'ALLERGIE' 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_allergie'] = False
partial_update_params['maj:enfant_0'] = False
resource.pre_sanitize_update_family_data(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)
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_sanitaire_allergie'] = val
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
assert 'ALLERGIE' not in partial_update_params['ENFANT'][0]['SANITAIRE']
assert 'ALLERGIE' not in partial_update_params['ENFANT'][1]['SANITAIRE']
def test_sanitize_update_family_data_enfant_n_sanitaire_allergie(app, resource, update_params, family_data):
# 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'] = 'NON'
partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['ALIMENTAIRES'] = 'NON'
partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['AUTRES'] = ''
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': 'NON', 'NOMALLERGIE': None},
{'TYPE': 'MEDICAMENTEUSES', 'ALLERGIQUE': 'NON', 'NOMALLERGIE': None},
{'TYPE': 'ALIMENTAIRES', 'ALLERGIQUE': 'NON', 'NOMALLERGIE': None},
]
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'] = 'OUI'
partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['ALIMENTAIRES'] = 'OUI'
partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['AUTRES'] = 'accariens'
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'},
]
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')
# 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)
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)
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)
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
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
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')
# 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)
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)
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)
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
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
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')
# test maj:enfant_n_contact
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)
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
# 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)
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_sanitaire'] = False
partial_update_params['maj:enfant_0'] = False
resource.pre_sanitize_update_family_data(post_data=partial_update_params)
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)
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]
@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')
partial_update_params = copy.deepcopy(update_params)
for flag in flags:
partial_update_params[flag] = False
with mock.patch('passerelle.contrib.toulouse_axel.models.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.models.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'
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': '44.94',
'total_amount': '44.94',
'online_payment': False,
'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': '44.94',
}
}
},
{
'id': 'XXX-43',
'display_id': '43',
'label': 'PRESTATIONS PERISCOLAIRES NOVEMBRE 2019',
'amount': '44.94',
'total_amount': '44.94',
'online_payment': False,
'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',
'online_payment': False,
'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_axel_error(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
with mock.patch('passerelle.contrib.toulouse_axel.models.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': False,
'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': 'O',
'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.models.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):
resp = app.get('/toulouse-axel/test/regie/MAREGIE/invoice/XXX-42?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')
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'
def test_invoice_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/invoice/XXX-42?NameID=yyy')
assert resp.json['err'] == 0
assert resp.json['data'] == {
'id': 'XXX-42',
'display_id': '42',
'label': 'PRESTATIONS PERISCOLAIRES SEPTEMBRE-OCTOBRE 2019',
'amount': '44.94',
'total_amount': '44.94',
'online_payment': False,
'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': '44.94',
}
}
}
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/invoice/historical-XXX-42?NameID=yyy')
assert resp.json['err'] == 0
assert resp.json['data'] == {
'amount': 0,
'created': '2017-03-23',
'display_id': '42',
'has_pdf': False,
'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
}
}
}
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.models.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.models.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'
def test_invoice_pdf_endpoint(app, resource):
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', 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/XXX-42/pdf?NameID=yyy')
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-XXX-42/pdf?NameID=yyy')
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.models.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.models.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'
def test_pay_invoice_endpoint(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')
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.models.form_paiement_dui') as operation:
resp = app.post_json('/toulouse-axel/test/regie/MAREGIE/invoice/XXX-42/pay?NameID=yyy', 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 12:00:00',
'IDFACTURE': 42,
'IDREGIEENCAISSEMENT': '',
'MONTANTPAYE': decimal.Decimal('44.94'),
'REFERENCE': 'foo',
}
}
}
def test_clae_booking_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.models.enfants_activites') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get('/toulouse-axel/test/clae_booking_info?NameID=yyy&idpersonne=3535&booking_date=2020-01-20')
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.models.reservation_periode') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get('/toulouse-axel/test/clae_booking_info?NameID=yyy&idpersonne=3535&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_booking_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_info?NameID=yyy&idpersonne=3535&booking_date=%s' % value, status=400)
assert resp.json['err_desc'] == "bad date format"
assert resp.json['err'] == 'bad-request'
def test_clae_booking_info_endpoint_no_result(app, resource, child_activities_data):
resp = app.get('/toulouse-axel/test/clae_booking_info?NameID=yyy&idpersonne=3535&booking_date=2020-01-20')
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.models.reservation_periode') as operation:
operation.side_effect = AxelError('FooBar')
resp = app.get('/toulouse-axel/test/clae_booking_info?NameID=yyy&idpersonne=4242&booking_date=2020-01-20')
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_info?NameID=yyy&idpersonne=3535&booking_date=2020-01-20')
assert resp.json['err_desc'] == "Child not found"
assert resp.json['err'] == 'not-found'
def test_clae_booking_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 = 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_info?NameID=yyy&idpersonne=3535&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',
'booking': {
'days': {
'friday': False,
'monday': False,
'thursday': False,
'tuesday': False,
'wednesday': False
},
'raw_value': '00000'
}
},
{
'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',
'booking': {
'days': {
'friday': True,
'monday': True,
'thursday': True,
'tuesday': True,
'wednesday': True
},
'raw_value': '11111'
}
},
{
'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',
'booking': {
'days': {
'friday': True,
'monday': True,
'thursday': True,
'tuesday': True,
'wednesday': None
},
'raw_value': '11211'
}
},
{
'COUTREVIENT': '99999',
'DATEDEBUT': '2019-08-01',
'DATEENTREE': '2019-08-01',
'DATEFIN': '2020-07-31',
'DATESORTIE': '2020-07-31',
'IDACTIVITE': 'A19P1M4',
'ISPAI': False,
'LIBELLEACTIVITE': u'Temps mercredi après midi',
'TARIF': '0.45',
'TYPEACTIVITE': 'GARD',
'booking': {
'days': {
'friday': None,
'monday': None,
'thursday': None,
'tuesday': None,
'wednesday': True
},
'raw_value': '22122'
}
}
],
'DATENAISSANCE': '2019-01-01',
'IDPERSONNE': '3535',
'LIBELLEECOLE': 'MATERNELLE 1',
'NOM': 'foo',
'PRENOM': 'foo',
'REGIME': 'SV'
}
# test wrong and missing IDACTIVITE
content = """<PORTAIL>
<DUI>
<IDDUI>XXX</IDDUI>
<ENFANT>
<IDPERSONNE>3535</IDPERSONNE>
<ACTIVITE>
<ANNEEREFERENCE>2019</ANNEEREFERENCE>
<IDACTIVITE>UNKNOWN</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_info?NameID=yyy&idpersonne=3535&booking_date=2020-01-20')
assert resp.json['err'] == 0
assert resp.json['data']['ACTIVITE'][0]['IDACTIVITE'] == 'A19P1M1'
assert resp.json['data']['ACTIVITE'][0]['booking'] == {}
assert resp.json['data']['ACTIVITE'][1]['IDACTIVITE'] == 'A19P1M2'
assert resp.json['data']['ACTIVITE'][1]['booking'] == {}
assert resp.json['data']['ACTIVITE'][2]['IDACTIVITE'] == 'A19P1M3'
assert resp.json['data']['ACTIVITE'][2]['booking'] == {}
assert resp.json['data']['ACTIVITE'][3]['IDACTIVITE'] == 'A19P1M4'
assert resp.json['data']['ACTIVITE'][3]['booking'] == {}
def test_are_children_registered_axel_error(resource):
with mock.patch('passerelle.contrib.toulouse_axel.models.enfants_activites') as operation:
operation.side_effect = AxelError('FooBar')
assert resource.are_children_registered(dui='XXX', reference_year=42) == {}
@pytest.mark.parametrize('date_value, year, expected', [
# neither current year nor next year
('2020-01-01', 2018, {}),
('2020-01-01', 2021, {}),
# current year
('2019-08-01', 2019, {'3535': True}),
('2020-07-31', 2019, {'3535': True}),
# too early for next_year
('2019-08-01', 2020, {}),
('2020-01-01', 2020, {}),
('2020-05-31', 2020, {}),
# good period for next year
('2020-06-01', 2020, {'3535': True}),
('2020-07-31', 2020, {'3535': True}),
])
def test_are_children_registered_reference_year(resource, date_value, year, 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', reference_year=year) == 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):
today = datetime.date.today()
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', reference_year=get_reference_year_from_date(today)) == expected