toulouse_maelis: parsifal: add webservices to manage RL (#67326)

This commit is contained in:
Nicolas Roche 2022-07-12 18:56:47 +02:00
parent b6b40e501b
commit c238a9f2b0
13 changed files with 919 additions and 1 deletions

View File

@ -138,6 +138,14 @@ class ToulouseMaelis(BaseResource, HTTPResource):
add_text_value('Sex', child, ['sexe'])
return data
def replace_null_values(self, dico):
'''send null fields as empty SOAP tag to tell maelis to empty the value'''
for key, value in dico.items():
if isinstance(value, dict):
self.replace_null_values(value)
if value is None:
dico[key] = ''
@endpoint(
display_category=_('Family'),
description='Liste des catégories',
@ -256,6 +264,100 @@ class ToulouseMaelis(BaseResource, HTTPResource):
data = self.get_family(family_id)
return {'data': data}
@endpoint(
display_category=_('Family'),
description="Informations sur un responsable légal",
perm='can_access',
name='read-rl',
parameters={
'NameID': {'description': _('Publik ID')},
'rl_id': {'description': 'Numéro du représentant légal'},
},
)
def read_rl(self, request, NameID, rl_id):
family_id = self.get_link(NameID).family_id
data = self.get_family(family_id)
if data['RL1']['num'] == rl_id:
data = data['RL1']
elif data['RL2'] and data['RL2']['num'] == rl_id:
data = data['RL2']
else:
raise APIError("no '%s' RL on '%s' family" % (rl_id, family_id), err_code='not-found')
return {'data': data}
@endpoint(
display_category=_('Family'),
description="Vérifier qu'un responsable légal existe en base",
perm='can_access',
name='is-rl-exists',
post={'request_body': {'schema': {'application/json': schemas.ISRLEXISTS_SCHEMA}}},
)
def is_rl_exists(self, request, post_data):
response = self.call('Family', 'isRLExists', **post_data)
return {'data': response}
@endpoint(
display_category=_('Family'),
description='Création de la famille',
name='create-family',
perm='can_access',
parameters={'NameID': {'description': _('Publik ID')}},
post={'request_body': {'schema': {'application/json': schemas.CREATE_FAMILY_SCHEMA}}},
)
def create_family(self, request, NameID, post_data):
if self.link_set.filter(name_id=NameID).exists():
raise APIError('User already linked to family', err_code='already-linked')
response = self.call('Family', 'createFamily', **post_data)
data = serialize_object(response)
family_id = data.get('number')
if not family_id:
errors = data.get('rl1ErrorList') + data.get('childErrorList')
err_codes = [x.split(':')[0][:4] for x in errors]
raise APIError(' ; '.join(errors), err_code=', '.join(err_codes))
Link.objects.create(resource=self, name_id=NameID, family_id=family_id)
return {'data': data}
@endpoint(
display_category=_('Family'),
description='Modification de la famille',
name='update-family',
perm='can_access',
parameters={'NameID': {'description': _('Publik ID')}},
post={'request_body': {'schema': {'application/json': schemas.UPDATE_FAMILY_SCHEMA}}},
)
def update_family(self, request, NameID, post_data):
family_id = self.get_link(NameID).family_id
self.replace_null_values(post_data)
response = self.call('Family', 'updateFamily', dossierNumber=family_id, **post_data)
data = serialize_object(response)
family_id = data.get('number')
if not family_id:
errors = data.get('rl1ErrorList') + data.get('childErrorList')
err_codes = [x.split(':')[0][:4] for x in errors]
raise APIError(' ; '.join(errors), err_code=', '.join(err_codes))
return {'data': data}
@endpoint(
display_category=_('Family'),
description="Mise à jour des coordonnées d'une personne",
name='update-coordinate',
perm='can_access',
parameters={
'NameID': {'description': _('Publik ID')},
'rl_id': {'description': 'Numéro du représentant légal'},
},
post={'request_body': {'schema': {'application/json': schemas.UPDATE_COORDINATE_SCHEMA}}},
)
def update_coordinate(self, request, NameID, rl_id, post_data):
family_id = self.get_link(NameID).family_id
self.replace_null_values(post_data)
self.call('Family', 'updateCoordinate', numDossier=family_id, numPerson=rl_id, **post_data)
return {'data': 'ok'}
class Link(models.Model):
resource = models.ForeignKey(ToulouseMaelis, on_delete=models.CASCADE)

View File

@ -14,6 +14,17 @@
# 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
BOOLEAN_TYPES = [
{'type': 'boolean'},
{
'type': 'string',
'pattern': '^([Oo][Uu][Ii]|[Nn][Oo][Nn]|[Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee]|1|0)$',
'pattern_description': 'Les valeurs "0", "1", "true", "false", "oui" ou "non" sont autorisées (insensibles à la casse).',
},
]
LINK_SCHEMA = {
'$schema': 'http://json-schema.org/draft-04/schema#',
'title': 'Link',
@ -36,7 +47,279 @@ LINK_SCHEMA = {
'dateBirth': {
'description': 'Date de naissance du RL1',
'type': 'string',
'pattern': '[0-9]{4}-[0-9]{2}-[0-9]{2}',
'pattern': '^[0-9]{4}-[0-9]{2}-[0-9]{2}$',
},
},
}
ISRLEXISTS_SCHEMA = {
'$schema': 'http://json-schema.org/draft-04/schema#',
'title': 'Link',
'description': "Appairage d'un usager Publik à une famille dans Maelis",
'type': 'object',
'required': ['firstname', 'lastname', 'datebirth'],
'properties': {
'firstname': {
'description': 'Prénom',
'type': 'string',
},
'lastname': {
'description': 'Nom',
'type': 'string',
},
'datebirth': {
'description': 'Date de naissance',
'type': 'string',
'pattern': '^[0-9]{4}-[0-9]{2}-[0-9]{2}$',
},
},
}
ADDRESS_SCHEMA = {
'$schema': 'http://json-schema.org/draft-04/schema#',
'title': 'Address',
'description': 'Informations sur une adresse',
'type': 'object',
'required': ['street1', 'town', 'zipcode'],
'properties': {
'num': {
'description': 'numéro',
'oneOf': [{'type': 'null'}, {'type': 'string'}],
},
'numComp': {
'description': 'Complément du numéro (B, T ou Q)',
'oneOf': [{'type': 'null'}, {'type': 'string'}],
},
'street1': {
'description': 'Libellé de la voie',
'type': 'string',
},
'street2': {
'description': 'Complément de la voie',
'oneOf': [{'type': 'null'}, {'type': 'string'}],
},
'town': {
'description': 'Ville',
'type': 'string',
},
'zipcode': {
'description': 'Code postal',
'type': 'string',
},
},
}
CONTACT_SCHEMA = {
'$schema': 'http://json-schema.org/draft-04/schema#',
'title': 'Contact',
'description': 'Informations sur le contact',
'oneOf': [
{'type': 'null'},
{
'type': 'object',
'properties': {
'phone': {
'description': 'Téléphone',
'oneOf': [{'type': 'null'}, {'type': 'string'}],
},
'mobile': {
'description': 'Portable',
'oneOf': [{'type': 'null'}, {'type': 'string'}],
},
'mail': {
'description': 'Mail',
'oneOf': [{'type': 'null'}, {'type': 'string'}],
},
'isContactMail': {
'description': 'Accepte de recevoir des mails',
'oneOf': BOOLEAN_TYPES,
},
'isContactSms': {
'description': 'Accepte de recevoir des sms',
'oneOf': BOOLEAN_TYPES,
},
'isInvoicePdf': {
'description': 'Accepte de ne plus recevoir de facture papier',
'oneOf': BOOLEAN_TYPES,
},
},
},
],
}
ADDRESSPROF_SCHEMA = {
'$schema': 'http://json-schema.org/draft-04/schema#',
'title': 'Contact',
'description': "Informations sur l'adresse professionnelle",
'oneOf': [
{'type': 'null'},
{
'type': 'object',
'properties': {
'num': {
'description': "Numéro de l'adresse",
'oneOf': [{'type': 'null'}, {'type': 'string'}],
},
'street': {
'description': 'Nom de la voie',
'oneOf': [{'type': 'null'}, {'type': 'string'}],
},
'town': {
'description': 'Ville',
'oneOf': [{'type': 'null'}, {'type': 'string'}],
},
'zipcode': {
'description': 'Code postal',
'oneOf': [{'type': 'null'}, {'type': 'string'}],
},
},
},
],
}
PROFESSION_SCHEMA = {
'$schema': 'http://json-schema.org/draft-04/schema#',
'title': 'Profession',
'description': 'Informations sur la profession',
'oneOf': [
{'type': 'null'},
{
'type': 'object',
'properties': {
'codeCSP': {
'description': 'Catégorie socio-professionnelle',
'oneOf': [{'type': 'null'}, {'type': 'string'}],
},
'profession': {
'description': 'Profession',
'oneOf': [{'type': 'null'}, {'type': 'string'}],
},
'employerName': {
'description': "Nom de l'employeur",
'oneOf': [{'type': 'null'}, {'type': 'string'}],
},
'phone': {
'description': 'Téléphone',
'oneOf': [{'type': 'null'}, {'type': 'string'}],
},
'addressPro': ADDRESSPROF_SCHEMA,
},
},
],
}
CAFINFO_SCHEMA = {
'$schema': 'http://json-schema.org/draft-04/schema#',
'title': 'Contact',
'description': 'Informations sur la CAF',
'oneOf': [
{'type': 'null'},
{
'type': 'object',
'properties': {
'number': {
'description': "Numéro d'allocataire",
'oneOf': [{'type': 'null'}, {'type': 'string'}],
},
'organ': {
'description': "Nom de l'organisme",
'oneOf': [{'type': 'null'}, {'type': 'string'}],
},
},
},
],
}
RLINFO_SCHEMA = {
'$schema': 'http://json-schema.org/draft-04/schema#',
'title': 'RLInfo',
'description': "Informations sur le responsable légal",
'type': 'object',
'required': ['firstname', 'lastname', 'quality', 'dateBirth', 'adresse'],
'properties': {
'civility': {
'description': 'civilité (depuis référenciel)',
'oneOf': [{'type': 'null'}, {'type': 'string'}],
},
'firstname': {
'description': 'Prénom',
'type': 'string',
},
'lastname': {
'description': 'Nom',
'type': 'string',
},
'quality': {
'description': 'Qualité',
'type': 'string',
},
'dateBirth': {
'description': 'Date de naissance',
'type': 'string',
'pattern': '^[0-9]{4}-[0-9]{2}-[0-9]{2}$',
},
'adresse': ADDRESS_SCHEMA,
'contact': CONTACT_SCHEMA,
'profession': PROFESSION_SCHEMA,
'CAFInfo': CAFINFO_SCHEMA,
},
}
CREATE_FAMILY_SCHEMA = {
'$schema': 'http://json-schema.org/draft-04/schema#',
'title': 'Family',
'description': 'Informations pour créer ou mettre à jour une famille',
'type': 'object',
'required': ['rl1', 'categorie', 'situation'],
'properties': {
'categorie': {
'description': 'Categorie (depuis référenciel)',
'type': 'string',
},
'situation': {
'description': 'Situation familiale (depuis référenciel)',
'type': 'string',
},
'flagCom': {
'description': 'Hors commune',
'oneOf': BOOLEAN_TYPES,
},
'nbChild': {
'description': "Nombre d'enfants à charge",
'oneOf': [{'type': 'null'}, {'type': 'string'}],
},
'nbTotalChild': {
'description': "Nombre total d'enfants",
'oneOf': [{'type': 'null'}, {'type': 'string'}],
},
'nbAES': {
'description': "Nombre d'AES",
'oneOf': [{'type': 'null'}, {'type': 'string'}],
},
'rl1': RLINFO_SCHEMA,
'rl2': RLINFO_SCHEMA,
},
'unflatten': True,
}
UPDATE_FAMILY_SCHEMA = copy.deepcopy(CREATE_FAMILY_SCHEMA)
UPDATE_FAMILY_SCHEMA['required'] = ['categorie', 'situation']
# Schemas below describe parameters of Maelis wrapper around updateFamily endpoint
UPDATE_COORDINATE_SCHEMA = {
'$schema': 'http://json-schema.org/draft-04/schema#',
'title': 'Update coordinate',
'description': "Mise à jour des coordonnées d'un responsable légal",
'type': 'object',
'properties': {
'adresse': ADDRESS_SCHEMA,
'contact': CONTACT_SCHEMA,
'profession': PROFESSION_SCHEMA,
'CAFInfo': CAFINFO_SCHEMA,
},
'unflatten': True,
}

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>maelis-webservice</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">maelis-password</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soap-env:Header>
<soap-env:Body>
<ns0:createFamily xmlns:ns0="family.ws.maelis.sigec.com">
<categorie>ACCEUI</categorie>
<situation>C</situation>
<rl1>
<lastname>Doe</lastname>
<firstname>Jhon</firstname>
<quality>AU</quality>
<dateBirth>1938-07-26</dateBirth>
<adresse>
<street1>Chateau</street1>
<town>Paris</town>
<zipcode>75014</zipcode>
</adresse>
</rl1>
</ns0:createFamily>
</soap-env:Body>
</soap-env:Envelope>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>maelis-webservice</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">maelis-password</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soap-env:Header>
<soap-env:Body>
<ns0:updateCoordinate xmlns:ns0="family.ws.maelis.sigec.com">
<numDossier>1312</numDossier>
<numPerson>613878</numPerson>
<adresse>
<num>169</num>
<numComp/>
<street1>Château</street1>
<street2/>
<town>Paris</town>
<zipcode>75014</zipcode>
</adresse>
</ns0:updateCoordinate>
</soap-env:Body>
</soap-env:Envelope>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>maelis-webservice</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">maelis-password</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soap-env:Header>
<soap-env:Body>
<ns0:updateFamily xmlns:ns0="family.ws.maelis.sigec.com">
<dossierNumber>1312</dossierNumber>
<categorie>BI</categorie>
<situation>C</situation>
<rl1>
<lastname>Doe</lastname>
<firstname>Jhon</firstname>
<quality>AU</quality>
<dateBirth>1938-07-26</dateBirth>
<adresse>
<street1>Chateau</street1>
<town>Paris</town>
<zipcode>75014</zipcode>
</adresse>
</rl1>
</ns0:updateFamily>
</soap-env:Body>
</soap-env:Envelope>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:createFamilyResponse xmlns:ns2="family.ws.maelis.sigec.com">
<familyResult>
<number>196545</number>
<password>394634V2</password>
</familyResult>
</ns2:createFamilyResponse>
</soap:Body>
</soap:Envelope>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:createFamilyResponse xmlns:ns2="family.ws.maelis.sigec.com">
<familyResult>
<number>0</number>
<rl1ErrorList>E54a : Il existe déjà un Responsable Légal correspondant au nom [DOE], prénom [JHON], date de naissance [26/07/1938] - Personne n°[613955] - Famille n°[196544]</rl1ErrorList>
</familyResult>
</ns2:createFamilyResponse>
</soap:Body>
</soap:Envelope>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:isRLExistsResponse xmlns:ns2="family.ws.maelis.sigec.com">
<result>%s</result>
</ns2:isRLExistsResponse>
</soap:Body>
</soap:Envelope>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:updateCoordinateResponse xmlns:ns2="family.ws.maelis.sigec.com"/>
</soap:Body>
</soap:Envelope>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:updateFamilyResponse xmlns:ns2="family.ws.maelis.sigec.com">
<familyResult>
<number>196544</number>
<category>BI</category>
<situation>C</situation>
<RL1>
<num>613955</num>
<lastname>DOE</lastname>
<firstname>JHON</firstname>
<quality>AU</quality>
<civility>MR</civility>
<dateBirth>1938-07-26T00:00:00+01:00</dateBirth>
<adresse>
<idStreet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<num>0</num>
<street1>Chateau</street1>
<town>Paris</town>
<zipcode>75014</zipcode>
</adresse>
<contact>
<isContactMail>false</isContactMail>
<isContactSms>false</isContactSms>
<isInvoicePdf>false</isInvoicePdf>
</contact>
</RL1>
</familyResult>
</ns2:updateFamilyResponse>
</soap:Body>
</soap:Envelope>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:updateFamilyResponse xmlns:ns2="family.ws.maelis.sigec.com">
<familyResult>
<number>0</number>
<RL1>
<adresse>
<idStreet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
</adresse>
</RL1>
<childErrorList>E65a : Il existe déjà un enfant correspondant au nom [ZIMMERMAN], prénom [ROBERT], date de naissance [24/05/1941] - Personne n°[614051] - Famille n°[196544]</childErrorList>
</familyResult>
</ns2:updateFamilyResponse>
</soap:Body>
</soap:Envelope>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>Une erreur est survenue : java.sql.SQLDataException: ORA-01438: valeur incohérente avec la précision indiquée pour cette colonne
</faultstring>
<detail>
<ns1:MaelisFamilyException xmlns:ns1="family.ws.maelis.sigec.com">
<message xmlns:ns2="family.ws.maelis.sigec.com">Une erreur est survenue : java.sql.SQLDataException: ORA-01438: valeur incohérente avec la précision indiquée pour cette colonne
</message>
</ns1:MaelisFamilyException>
</detail>
</soap:Fault>
</soap:Body>
</soap:Envelope>

View File

@ -19,6 +19,7 @@ import os
import mock
import pytest
from lxml import etree
from requests.exceptions import ConnectionError
from passerelle.contrib.toulouse_maelis.models import Link, ToulouseMaelis
@ -46,6 +47,19 @@ READ_CIVILITIES = FakedResponse(content=get_xml_file('R_read_civility_list.xml')
READ_CSP = FakedResponse(content=get_xml_file('R_read_csp_list.xml'), status_code=200)
READ_QUALITIES = FakedResponse(content=get_xml_file('R_read_quality_list.xml'), status_code=200)
READ_SITUATIONS = FakedResponse(content=get_xml_file('R_read_situation_list.xml'), status_code=200)
IS_RL_EXISTS_TRUE = FakedResponse(content=get_xml_file('R_is_rl_exists.xml') % b'true', status_code=200)
IS_RL_EXISTS_FALSE = FakedResponse(content=get_xml_file('R_is_rl_exists.xml') % b'false', status_code=200)
CREATE_FAMILY = FakedResponse(content=get_xml_file('R_create_family.xml'), status_code=200)
CREATE_FAMILY_ERR = FakedResponse(content=get_xml_file('R_create_family_error.xml'), status_code=200)
UPDATE_FAMILY = FakedResponse(content=get_xml_file('R_update_family.xml'), status_code=200)
UPDATE_FAMILY_ERR = FakedResponse(content=get_xml_file('R_update_family_error.xml'), status_code=200)
UPDATE_FAMILY_500 = FakedResponse(content=get_xml_file('R_update_family_soap_error.xml'), status_code=500)
def assert_sent_payload(mocked_post, query_file):
soap_sent = etree.tostring(etree.fromstring(mocked_post.call_args.kwargs['data']), pretty_print=True)
expected = etree.tostring(etree.fromstring(get_xml_file(query_file)), pretty_print=True)
assert soap_sent.decode() == expected.decode()
def get_endpoint(name):
@ -126,6 +140,30 @@ def test_check_status(mocked_post, mocked_get, get_responses, post_responses, ex
con.check_status()
def test_replace_null_values(con):
payload = {
'adresse': {
'num': '169',
'numComp': None,
'street1': 'Chateau',
'street2': None,
'town': 'Paris',
'zipcode': '75014',
}
}
con.replace_null_values(payload)
assert payload == {
'adresse': {
'num': '169',
'numComp': '',
'street1': 'Chateau',
'street2': '',
'town': 'Paris',
'zipcode': '75014',
}
}
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_link(mocked_post, mocked_get, con, app):
@ -420,3 +458,316 @@ def test_read_family_not_linked_error(con, app):
resp = app.get(url + '?NameID=')
assert resp.json['err'] == 'not-linked'
assert resp.json['err_desc'] == 'User not linked to family'
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_read_rl1(mocked_post, mocked_get, con, app):
mocked_get.return_value = FAMILY_SERVICE_WSDL
mocked_post.side_effect = [READ_FAMILY, READ_CATEGORIES, READ_SITUATIONS, READ_CIVILITIES, READ_QUALITIES]
url = get_endpoint('read-rl')
Link.objects.create(resource=con, family_id='1312', name_id='local')
resp = app.get(url + '?NameID=local&rl_id=613878')
assert resp.json['err'] == 0
assert resp.json['data']['firstname'] == 'DAMIEN'
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_read_rl2(mocked_post, mocked_get, con, app):
mocked_get.return_value = FAMILY_SERVICE_WSDL
mocked_post.side_effect = [READ_FAMILY, READ_CATEGORIES, READ_SITUATIONS, READ_CIVILITIES, READ_QUALITIES]
url = get_endpoint('read-rl')
Link.objects.create(resource=con, family_id='1312', name_id='local')
resp = app.get(url + '?NameID=local&rl_id=613879')
assert resp.json['err'] == 0
assert resp.json['data'] == {
'num': '613879',
'lastname': 'COSTANZE',
'firstname': 'JENNIFER',
'quality': 'MERE',
'civility': 'MME',
'dateBirth': '1987-05-21T00:00:00+02:00',
'adresse': {
'idStreet': 'AV0044',
'num': 9,
'numComp': None,
'street1': 'AVENUE VALDILETTA',
'street2': 'LES MANDARINIERS',
'town': 'NICE',
'zipcode': '06100',
},
'contact': {
'phone': None,
'mobile': None,
'mail': None,
'isContactMail': False,
'isContactSms': False,
'isInvoicePdf': False,
},
'profession': None,
'CAFInfo': {'number': '51', 'organ': None},
'civility_text': 'Madame',
'quality_text': 'MERE',
}
def test_read_rl_not_linked_error(con, app):
url = get_endpoint('read-rl')
resp = app.get(url + '?NameID=local&rl_id=613879')
assert resp.json['err'] == 'not-linked'
assert resp.json['err_desc'] == 'User not linked to family'
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_read_rl_not_found(mocked_post, mocked_get, con, app):
mocked_get.return_value = FAMILY_SERVICE_WSDL
mocked_post.side_effect = [READ_FAMILY, READ_CATEGORIES, READ_SITUATIONS, READ_CIVILITIES, READ_QUALITIES]
url = get_endpoint('read-rl')
Link.objects.create(resource=con, family_id='1312', name_id='local')
resp = app.get(url + '?NameID=local&rl_id=000000')
assert resp.json['err'] == 'not-found'
assert resp.json['err_desc'] == "no '000000' RL on '1312' family"
@pytest.mark.parametrize(
'post_response, result',
[
(IS_RL_EXISTS_TRUE, True),
(IS_RL_EXISTS_FALSE, False),
],
)
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_is_rl_exists(mocked_post, mocked_get, post_response, result, con, app):
mocked_get.return_value = FAMILY_SERVICE_WSDL
mocked_post.return_value = post_response
url = get_endpoint('is-rl-exists')
params = {
'firstname': 'Damien',
'lastname': 'Costanze',
'datebirth': '1980-10-07',
}
resp = app.post_json(url, params=params)
assert resp.json['err'] == 0
assert resp.json['data'] == result
def test_is_rl_exists_schema_error(con, app):
url = get_endpoint('is-rl-exists')
params = {
'firstname': 'Damien',
'lastname': 'Costanze',
'datebirth': '1980-10-07 more text',
}
resp = app.post_json(url, params=params, status=400)
assert resp.json['err'] == 1
assert "does not match '^[0-9]{4}-[0-9]{2}-[0-9]{2}$'" in resp.json['err_desc']
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_create_family(mocked_post, mocked_get, con, app):
mocked_get.return_value = FAMILY_SERVICE_WSDL
mocked_post.return_value = CREATE_FAMILY
url = get_endpoint('create-family')
params = {
'categorie': 'ACCEUI',
'situation': 'C',
'rl1/firstname': 'Jhon',
'rl1/lastname': 'Doe',
'rl1/quality': 'AU',
'rl1/dateBirth': '1938-07-26',
'rl1/adresse/street1': 'Chateau',
'rl1/adresse/town': 'Paris',
'rl1/adresse/zipcode': '75014',
}
resp = app.post_json(url + '?NameID=local', params=params)
assert_sent_payload(mocked_post, 'Q_create_family.xml')
assert resp.json['err'] == 0
assert resp.json['data'] == {
'number': 196545,
'password': '394634V2',
'rl1ErrorList': [],
'childErrorList': [],
}
assert Link.objects.get(resource=con, family_id='196545', name_id='local')
def test_create_family_already_linked_error(con, app):
url = get_endpoint('create-family')
params = {
'categorie': 'ACCEUI',
'situation': 'C',
'rl1/firstname': 'Jhon',
'rl1/lastname': 'Doe',
'rl1/quality': 'AU',
'rl1/dateBirth': '1938-07-26',
'rl1/adresse/street1': 'Chateau',
'rl1/adresse/town': 'Paris',
'rl1/adresse/zipcode': '75014',
}
Link.objects.create(resource=con, family_id='1312', name_id='local')
resp = app.post_json(url + '?NameID=local', params=params)
assert resp.json['err'] == 'already-linked'
assert resp.json['err_desc'] == 'User already linked to family'
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_create_family_maelis_error(mocked_post, mocked_get, con, app):
mocked_get.return_value = FAMILY_SERVICE_WSDL
mocked_post.return_value = CREATE_FAMILY_ERR
url = get_endpoint('create-family')
params = {
'categorie': 'ACCEUI',
'situation': 'C',
'rl1/firstname': 'Jhon',
'rl1/lastname': 'Doe',
'rl1/quality': 'AU',
'rl1/dateBirth': '1938-07-26',
'rl1/adresse/street1': 'Chateau',
'rl1/adresse/town': 'Paris',
'rl1/adresse/zipcode': '75014',
}
resp = app.post_json(url + '?NameID=local', params=params)
assert resp.json['err'] == 'E54a'
assert 'Il existe déjà' in resp.json['err_desc']
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_update_family(mocked_post, mocked_get, con, app):
mocked_get.return_value = FAMILY_SERVICE_WSDL
mocked_post.return_value = UPDATE_FAMILY
url = get_endpoint('update-family')
params = {
'categorie': 'BI',
'situation': 'C',
'rl1/firstname': 'Jhon',
'rl1/lastname': 'Doe',
'rl1/quality': 'AU',
'rl1/dateBirth': '1938-07-26',
'rl1/adresse/street1': 'Chateau',
'rl1/adresse/town': 'Paris',
'rl1/adresse/zipcode': '75014',
}
Link.objects.create(resource=con, family_id='1312', name_id='local')
resp = app.post_json(url + '?NameID=local', params=params)
assert_sent_payload(mocked_post, 'Q_update_family.xml')
assert resp.json['err'] == 0
def test_update_family_already_not_linked_error(con, app):
url = get_endpoint('update-family')
params = {
'categorie': 'BI',
'situation': 'C',
'rl1/firstname': 'Jhon',
'rl1/lastname': 'Doe',
'rl1/quality': 'AU',
'rl1/dateBirth': '1938-07-26',
'rl1/adresse/street1': 'Chateau',
'rl1/adresse/town': 'Paris',
'rl1/adresse/zipcode': '75014',
}
resp = app.post_json(url + '?NameID=local', params=params)
assert resp.json['err'] == 'not-linked'
assert resp.json['err_desc'] == 'User not linked to family'
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_update_family_maelis_error(mocked_post, mocked_get, con, app):
mocked_get.return_value = FAMILY_SERVICE_WSDL
mocked_post.return_value = UPDATE_FAMILY_ERR
url = get_endpoint('update-family')
params = {
'categorie': 'ACCEUI',
'situation': 'C',
'childList/0/lastname': 'Zimmerman',
'childList/0/firstname': 'Robert',
'childList/0/sexe': 'M',
'childList/0/birth/dateBirth': '1941-05-24',
'childList/0/birth/place': 'Duluth',
}
Link.objects.create(resource=con, family_id='1312', name_id='local')
# get 500 because error repsonse is wrongly formatted
resp = app.post_json(url + '?NameID=local', params=params, status=500)
assert resp.json == {
'err': 1,
'err_class': 'zeep.exceptions.XMLParseError',
'err_desc': "Unexpected element 'adresse', expected 'lastname'",
'data': None,
}
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_update_family_soap_error(mocked_post, mocked_get, con, app):
mocked_get.return_value = FAMILY_SERVICE_WSDL
mocked_post.return_value = UPDATE_FAMILY_500
url = get_endpoint('update-family')
params = {
'nbChild': '100',
'categorie': 'BI',
'situation': 'C',
'rl1/firstname': 'Jhon',
'rl1/lastname': 'Doe',
'rl1/quality': 'AU',
'rl1/dateBirth': '1938-07-26',
'rl1/adresse/street1': 'Chateau',
'rl1/adresse/town': 'Paris',
'rl1/adresse/zipcode': '75014',
}
Link.objects.create(resource=con, family_id='1312', name_id='local')
resp = app.post_json(url + '?NameID=local', params=params)
assert resp.json['err'] == 'Family-updateFamily-soap:Server'
assert 'Une erreur est survenue' in resp.json['err_desc']
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_update_coordinate(mocked_post, mocked_get, con, app):
mocked_get.return_value = FAMILY_SERVICE_WSDL
mocked_post.return_value = UPDATE_FAMILY
url = get_endpoint('update-coordinate')
params = {
'adresse/num': '169',
'adresse/numComp': None,
'adresse/street1': 'Château',
'adresse/street2': None,
'adresse/town': 'Paris',
'adresse/zipcode': '75014',
}
Link.objects.create(resource=con, family_id='1312', name_id='local')
resp = app.post_json(url + '?NameID=local&rl_id=613878', params=params)
assert_sent_payload(mocked_post, 'Q_update_coordinate.xml')
assert resp.json['err'] == 0
assert resp.json['data'] == 'ok'
def test_update_coordinate_schema_error(con, app):
url = get_endpoint('update-coordinate')
params = {
'contact/isContactMail': 'true more text',
}
resp = app.post_json(url + '?NameID=local&rl_id=613878', params=params, status=400)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == "'true more text' is not of type 'boolean'"