From 55674c9598ad3d1e32fe73468aaf86115a32573a Mon Sep 17 00:00:00 2001
From: Nicolas ROCHE <nroche@entrouvert.com>
Date: Tue, 4 Oct 2022 00:04:22 +0200
Subject: [PATCH 3/5] toulouse-maelis: add endpoint to add child person
 (#69891)

---
 passerelle/contrib/toulouse_maelis/models.py  |  28 ++++
 passerelle/contrib/toulouse_maelis/schemas.py |  30 +++++
 .../toulouse_maelis/Q_create_child_person.xml |  55 ++++++++
 .../R_update_child_authorization.xml          |   5 +
 tests/test_toulouse_maelis.py                 | 122 ++++++++++++++++++
 5 files changed, 240 insertions(+)
 create mode 100644 tests/data/toulouse_maelis/Q_create_child_person.xml
 create mode 100644 tests/data/toulouse_maelis/R_update_child_authorization.xml

diff --git a/passerelle/contrib/toulouse_maelis/models.py b/passerelle/contrib/toulouse_maelis/models.py
index 51723648..81e34e83 100644
--- a/passerelle/contrib/toulouse_maelis/models.py
+++ b/passerelle/contrib/toulouse_maelis/models.py
@@ -850,16 +850,44 @@ class ToulouseMaelis(BaseResource, HTTPResource):
             'nbChild': family['nbChild'],
             'nbTotalChild': family['nbTotalChild'],
             'nbAES': family['nbAES'],
             kind + 'PersonList': [{'personList': personList}],
         }
         self.call('Family', 'updateFamily', **payload)
         return {'data': 'ok'}
 
+    @endpoint(
+        display_category='Famille',
+        description="Création d'une personne autorisée à récupérer l'enfant",
+        name='create-child-person',
+        perm='can_access',
+        parameters={
+            'NameID': {'description': 'Publik NameID'},
+            'child_id': {'description': "Numéro de l'enfant"},
+        },
+        post={'request_body': {'schema': {'application/json': schemas.CHILDPERSON2_SCHEMA}}},
+    )
+    def create_child_person(self, request, NameID, child_id, post_data):
+        family_id = self.get_link(NameID).family_id
+        child = self.get_child_raw(family_id, child_id)
+        self.replace_null_values(post_data)
+
+        personList = child['authorizedPersonList']
+        personList.append(post_data)
+        req = {
+            'numFamily': family_id,
+            'numPerson': child_id,
+            'bLeaveAlone': child['bLeaveAlone'],
+            'bPhoto': child['bPhoto'],
+            'personList': personList,
+        }
+        self.call('Family', 'updateChildAutorization', updateChildAutorizationRequest=req)
+        return {'data': 'ok'}
+
     @endpoint(
         display_category='Famille',
         description="Créer ou mettre à jour le régime alimentaire d'un enfant",
         name='update-child-dietcode',
         perm='can_access',
         parameters={
             'NameID': {'description': 'Publik NameID'},
             'child_id': {'description': "Numéro de l'enfant"},
diff --git a/passerelle/contrib/toulouse_maelis/schemas.py b/passerelle/contrib/toulouse_maelis/schemas.py
index 6a48df50..9ce7d9a3 100644
--- a/passerelle/contrib/toulouse_maelis/schemas.py
+++ b/passerelle/contrib/toulouse_maelis/schemas.py
@@ -694,8 +694,38 @@ UPDATE_COORDINATE_SCHEMA = {
     'properties': {
         'adresse': ADDRESS_SCHEMA,
         'contact': CONTACT_SCHEMA,
         'profession': PROFESSION_SCHEMA,
         'CAFInfo': CAFINFO_SCHEMA,
     },
     'unflatten': True,
 }
+
+CHILDPERSON_SCHEMA = FAMILYPERSON_SCHEMA
+del CHILDPERSON_SCHEMA['properties']['quality']
+
+PERSONQUALITY_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-04/schema#',
+    'title': 'Child person quality',
+    'description': "Informations sur la qualité des personnes autorisées à venir chercher l'enfant",
+    'type': 'object',
+    'required': ['code'],
+    'properties': {
+        'code': {
+            'description': 'Le code',
+            'type': 'string',
+        },
+    },
+}
+
+CHILDPERSON2_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-04/schema#',
+    'title': 'Family persons',
+    'description': "Informations sur les personnes autorisées à venir chercher l'enfant avec leur qualité",
+    'type': 'object',
+    'required': ['personInfo', 'personQuality'],
+    'properties': {
+        'personInfo': CHILDPERSON_SCHEMA,
+        'personQuality': PERSONQUALITY_SCHEMA,
+    },
+    'unflatten': True,
+}
diff --git a/tests/data/toulouse_maelis/Q_create_child_person.xml b/tests/data/toulouse_maelis/Q_create_child_person.xml
new file mode 100644
index 00000000..7ac29068
--- /dev/null
+++ b/tests/data/toulouse_maelis/Q_create_child_person.xml
@@ -0,0 +1,55 @@
+<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:updateChildAutorization xmlns:ns0="family.ws.maelis.sigec.com">
+      <updateChildAutorizationRequest>
+        <numFamily>1312</numFamily>
+        <numPerson>613880</numPerson>
+        <personList>
+          <personInfo>
+            <num>614719</num>
+            <civility>MME</civility>
+            <lastname>BENT</lastname>
+            <firstname>AMEL</firstname>
+            <dateBirth>1985-06-21T00:00:00+02:00</dateBirth>
+            <sexe>F</sexe>
+            <contact>
+              <phone>0123456789</phone>
+              <mobile>0623456789</mobile>
+              <mail>abent@example.org</mail>
+            </contact>
+          </personInfo>
+          <personQuality>
+            <code>T</code>
+            <libelle>TANTE</libelle>
+          </personQuality>
+        </personList>
+        <personList>
+          <personInfo>
+            <civility>MME</civility>
+            <lastname>Ross</lastname>
+            <firstname>Diana</firstname>
+            <dateBirth>1944-03-26</dateBirth>
+            <contact>
+              <phone>0199999999</phone>
+              <mobile>0723456789</mobile>
+              <mail>dross@example.org</mail>
+            </contact>
+          </personInfo>
+          <personQuality>
+            <code>TUTEUR</code>
+          </personQuality>
+        </personList>
+        <bLeaveAlone>false</bLeaveAlone>
+        <bPhoto>true</bPhoto>
+      </updateChildAutorizationRequest>
+    </ns0:updateChildAutorization>
+  </soap-env:Body>
+</soap-env:Envelope>
diff --git a/tests/data/toulouse_maelis/R_update_child_authorization.xml b/tests/data/toulouse_maelis/R_update_child_authorization.xml
new file mode 100644
index 00000000..2d7c87fe
--- /dev/null
+++ b/tests/data/toulouse_maelis/R_update_child_authorization.xml
@@ -0,0 +1,5 @@
+<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
+  <soap:Body>
+    <ns2:updateChildAutorizationResponse xmlns:ns2="family.ws.maelis.sigec.com"/>
+  </soap:Body>
+</soap:Envelope>
diff --git a/tests/test_toulouse_maelis.py b/tests/test_toulouse_maelis.py
index ebb87769..bc681902 100644
--- a/tests/test_toulouse_maelis.py
+++ b/tests/test_toulouse_maelis.py
@@ -70,16 +70,17 @@ UPDATE_DIETCODE = FakedResponse(content=get_xml_file('R_update_child_dietcode.xm
 UPDATE_PAI = FakedResponse(content=get_xml_file('R_update_child_pai.xml'), status_code=200)
 UPDATE_PAI_500 = FakedResponse(content=get_xml_file('R_update_child_pai_soap_error.xml'), status_code=500)
 UPDATE_FSL = FakedResponse(content=get_xml_file('R_update_child_fsl.xml'), status_code=200)
 UPDATE_FSL_500 = FakedResponse(content=get_xml_file('R_update_child_fsl_soap_error.xml'), status_code=500)
 UPDATE_MEDICAL = FakedResponse(content=get_xml_file('R_update_child_fsl.xml'), status_code=200)
 UPDATE_MEDICAL_500 = FakedResponse(
     content=get_xml_file('R_update_child_medical_record_soap_error.xml'), status_code=500
 )
+UPDATE_CHILD_AUTO = FakedResponse(content=get_xml_file('R_update_child_authorization.xml'), status_code=200)
 
 
 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()
 
 
@@ -884,16 +885,73 @@ def test_read_child_not_found(mocked_post, mocked_get, con, app):
     url = get_endpoint('read-child')
     Link.objects.create(resource=con, family_id='1312', name_id='local')
 
     resp = app.get(url + '?NameID=local&child_id=000000')
     assert resp.json['err'] == 'not-found'
     assert resp.json['err_desc'] == "no '000000' child on '1312' family"
 
 
+@mock.patch('passerelle.utils.Request.get')
+@mock.patch('passerelle.utils.Request.post')
+def test_read_child_person(mocked_post, mocked_get, con, app):
+    mocked_get.return_value = FAMILY_SERVICE_WSDL
+    mocked_post.side_effect = [
+        READ_FAMILY,
+        READ_CIVILITIES,
+        READ_QUALITIES,
+    ]
+    url = get_endpoint('read-child-person')
+    Link.objects.create(resource=con, family_id='1312', name_id='local')
+
+    resp = app.get(url + '?NameID=local&child_id=613880&person_id=614719')
+    assert resp.json['err'] == 0
+    assert resp.json['data']['personInfo']['firstname'] == 'AMEL'
+
+
+def test_read_child_person_not_linked_error(con, app):
+    url = get_endpoint('read-child-person')
+
+    resp = app.get(url + '?NameID=local&child_id=613880&person_id=614719')
+    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_child_person_no_child_error(mocked_post, mocked_get, con, app):
+    mocked_get.return_value = FAMILY_SERVICE_WSDL
+    mocked_post.side_effect = [
+        READ_FAMILY,
+    ]
+    url = get_endpoint('read-child-person')
+    Link.objects.create(resource=con, family_id='1312', name_id='local')
+
+    resp = app.get(url + '?NameID=local&child_id=42&person_id=614719')
+    assert resp.json['err'] == 'not-found'
+    assert resp.json['err_desc'] == "no '42' child on '1312' family"
+
+
+@mock.patch('passerelle.utils.Request.get')
+@mock.patch('passerelle.utils.Request.post')
+def test_read_child_person_no_person_error(mocked_post, mocked_get, con, app):
+    mocked_get.return_value = FAMILY_SERVICE_WSDL
+    mocked_post.side_effect = [
+        READ_FAMILY,
+        READ_CIVILITIES,
+        READ_QUALITIES,
+    ]
+    url = get_endpoint('read-child-person')
+    Link.objects.create(resource=con, family_id='1312', name_id='local')
+
+    resp = app.get(url + '?NameID=local&child_id=613880&person_id=000000')
+    assert resp.json['err'] == 'not-found'
+    assert resp.json['err_desc'] == "no '000000' authorized person on '613880' child"
+
+
 @pytest.mark.parametrize(
     'post_response, result',
     [
         (IS_RL_EXISTS_TRUE, True),
         (IS_RL_EXISTS_FALSE, False),
     ],
 )
 @mock.patch('passerelle.utils.Request.get')
@@ -1775,16 +1833,80 @@ def test_delete_person_not_found(mocked_post, mocked_get, con, app):
     url = get_endpoint('delete-person')
 
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local&person_id=000000&kind=emergency')
     assert resp.json['err'] == 'not-found'
     assert resp.json['err_desc'] == "no '000000' authorized person on '1312' family"
 
 
+@mock.patch('passerelle.utils.Request.get')
+@mock.patch('passerelle.utils.Request.post')
+def test_create_child_person(mocked_post, mocked_get, con, app):
+    mocked_get.return_value = FAMILY_SERVICE_WSDL
+    mocked_post.side_effect = [READ_FAMILY, UPDATE_CHILD_AUTO]
+    url = get_endpoint('create-child-person')
+    params = {
+        'personInfo/civility': 'MME',
+        'personInfo/firstname': 'Diana',
+        'personInfo/lastname': 'Ross',
+        'personInfo/dateBirth': '1944-03-26',
+        'personInfo/contact/phone': '0199999999',
+        'personInfo/contact/mobile': '0723456789',
+        'personInfo/contact/mail': 'dross@example.org',
+        'personQuality/code': 'TUTEUR',
+    }
+
+    Link.objects.create(resource=con, family_id='1312', name_id='local')
+    resp = app.post_json(url + '?NameID=local&child_id=613880', params=params)
+    assert_sent_payload(mocked_post, 'Q_create_child_person.xml')
+    assert resp.json['err'] == 0
+
+
+def test_create_child_person_not_linked_error(con, app):
+    url = get_endpoint('create-child-person')
+    params = {
+        'personInfo/civility': 'MME',
+        'personInfo/firstname': 'Diana',
+        'personInfo/lastname': 'Ross',
+        'personInfo/dateBirth': '1944-03-26',
+        'personInfo/contact/phone': '01999999999',
+        'personInfo/contact/mobile': '0723456789',
+        'personInfo/contact/mail': 'dross@example.org',
+        'personQuality/code': 'TUTEUR',
+    }
+
+    resp = app.post_json(url + '?NameID=local&child_id=613880', 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_create_child_person_no_child_error(mocked_post, mocked_get, con, app):
+    mocked_get.return_value = FAMILY_SERVICE_WSDL
+    mocked_post.side_effect = [READ_FAMILY]
+    url = get_endpoint('create-child-person')
+    params = {
+        'personInfo/civility': 'MME',
+        'personInfo/firstname': 'Diana',
+        'personInfo/lastname': 'Ross',
+        'personInfo/dateBirth': '1944-03-26',
+        'personInfo/contact/phone': '01999999999',
+        'personInfo/contact/mobile': '0723456789',
+        'personInfo/contact/mail': 'dross@example.org',
+        'personQuality/code': 'TUTEUR',
+    }
+
+    Link.objects.create(resource=con, family_id='1312', name_id='local')
+    resp = app.post_json(url + '?NameID=local&child_id=42', params=params)
+    assert resp.json['err'] == 'not-found'
+    assert resp.json['err_desc'] == "no '42' child on '1312' family"
+
+
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
 def test_update_child_dietcode(mocked_post, mocked_get, con, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
     mocked_post.return_value = UPDATE_DIETCODE
     url = get_endpoint('update-child-dietcode')
 
     Link.objects.create(resource=con, family_id='1312', name_id='local')
-- 
2.30.2

