From 5702c8f50018e96fbc1f49c276e76973c80bc31a Mon Sep 17 00:00:00 2001
From: Nicolas ROCHE <nroche@entrouvert.com>
Date: Mon, 3 Oct 2022 23:52:08 +0200
Subject: [PATCH 2/5] toulouse-maelis: add read family person endpoint (#69891)

---
 passerelle/contrib/toulouse_maelis/models.py | 38 ++++++++++
 tests/data/toulouse_maelis/R_read_family.xml | 19 +++++
 tests/test_toulouse_maelis.py                | 79 +++++++++++++++++++-
 3 files changed, 135 insertions(+), 1 deletion(-)

diff --git a/passerelle/contrib/toulouse_maelis/models.py b/passerelle/contrib/toulouse_maelis/models.py
index 01e8794b..45b29f5f 100644
--- a/passerelle/contrib/toulouse_maelis/models.py
+++ b/passerelle/contrib/toulouse_maelis/models.py
@@ -143,30 +143,47 @@ class ToulouseMaelis(BaseResource, HTTPResource):
 
     def get_child_raw(self, family_id, child_id):
         data = self.get_family_raw(family_id)
         for child in data['childList']:
             if child['num'] == child_id:
                 return child
         raise APIError("no '%s' child on '%s' family" % (child_id, family_id), err_code='not-found')
 
+    def get_child_person_raw(self, family_id, child_id, person_id):
+        data = self.get_child_raw(family_id, child_id)
+        for person in data['authorizedPersonList']:
+            if str(person['personInfo']['num']) == person_id:
+                return person
+        raise APIError(
+            "no '%s' authorized person on '%s' child" % (person_id, child_id), err_code='not-found'
+        )
+
     def add_text_value(self, referential_name, data, keys):
         '''add text from referentials'''
         last_key = keys.pop()
         for key in keys:
             if not isinstance(data, dict) or not key in data:
                 return
             data = data[key]
         if isinstance(data, dict) and last_key in data and data[last_key] is not None:
             data[last_key + '_text'] = self.get_referential_value(referential_name, data[last_key])
 
+    def add_text_value_to_child_person(self, data):
+        self.add_text_value('Civility', data, ['personInfo', 'civility'])
+        self.add_text_value('Quality', data, ['personQuality', 'code'])
+        self.add_text_value('Sex', data, ['personInfo', 'sexe'])
+        return data
+
     def add_text_value_to_child(self, data):
         self.add_text_value('Sex', data, ['sexe'])
         self.add_text_value('DietCode', data, ['dietcode'])
         self.add_text_value('PAI', data, ['paiInfoBean', 'code'])
+        for person in data['authorizedPersonList']:
+            self.add_text_value_to_child_person(person)
 
         # convert O/N string into boolean
         if data.get('fsl'):
             for key in (
                 'allergieAlimentaire',
                 'allergieRespiratoire',
                 'allergieAutre',
                 'allergieMedicament',
@@ -194,16 +211,21 @@ class ToulouseMaelis(BaseResource, HTTPResource):
             if data.get(rlg):
                 self.add_text_value_to_rl(data[rlg])
         for child in data['childList']:
             self.add_text_value_to_child(child)
             for person in data['emergencyPersonList']:
                 self.add_text_value_to_person(person)
         return data
 
+    def get_child_person(self, family_id, child_id, person_id):
+        data = self.get_child_person_raw(family_id, child_id, person_id)
+        self.add_text_value_to_child_person(data)
+        return data
+
     def get_child(self, family_id, child_id):
         data = self.get_child_raw(family_id, child_id)
         self.add_text_value_to_child(data)
         return data
 
     def get_person(self, family_id, person_id):
         data = self.get_person_raw(family_id, person_id)
         self.add_text_value_to_person(data)
@@ -430,16 +452,32 @@ class ToulouseMaelis(BaseResource, HTTPResource):
             'child_id': {'description': "Numéro de l'enfant"},
         },
     )
     def read_child(self, request, NameID, child_id):
         family_id = self.get_link(NameID).family_id
         data = self.get_child(family_id, child_id)
         return {'data': data}
 
+    @endpoint(
+        display_category='Famille',
+        description="Informations sur une personne autorisée à récupérer l'enfant",
+        perm='can_access',
+        name='read-child-person',
+        parameters={
+            'NameID': {'description': 'Publik NameID'},
+            'child_id': {'description': "Numéro de l'enfant"},
+            'person_id': {'description': 'Numéro de la personne'},
+        },
+    )
+    def read_child_person(self, request, NameID, child_id, person_id):
+        family_id = self.get_link(NameID).family_id
+        data = self.get_child_person(family_id, child_id, person_id)
+        return {'data': data}
+
     @endpoint(
         display_category='Famille',
         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.ISEXISTS_SCHEMA}}},
     )
     def is_rl_exists(self, request, post_data):
diff --git a/tests/data/toulouse_maelis/R_read_family.xml b/tests/data/toulouse_maelis/R_read_family.xml
index b90823fe..b63e9f65 100644
--- a/tests/data/toulouse_maelis/R_read_family.xml
+++ b/tests/data/toulouse_maelis/R_read_family.xml
@@ -117,16 +117,35 @@
             <obsAssist1>some obsAssist1 text</obsAssist1>
             <obsAssist2>some obsAssist2 text</obsAssist2>
             <obsAssist3>some obsAssist3 text</obsAssist3>
             <cons1Med>some cons1Med text</cons1Med>
             <cons2Med>some cons2Med text</cons2Med>
           </fsl>
           <bPhoto>true</bPhoto>
           <bLeaveAlone>false</bLeaveAlone>
+          <authorizedPersonList>
+            <personInfo>
+              <num>614719</num>
+              <lastname>BENT</lastname>
+              <firstname>AMEL</firstname>
+              <dateBirth>1985-06-21T00:00:00+02:00</dateBirth>
+              <civility>MME</civility>
+              <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>
+          </authorizedPersonList>
           <medicalRecord>
             <familyDoctor>
               <name>DRE</name>
               <phone>0612341234</phone>
               <address>
                 <street1>Alameda</street1>
                 <zipcode>90220</zipcode>
                 <town>Compton</town>
diff --git a/tests/test_toulouse_maelis.py b/tests/test_toulouse_maelis.py
index 94d7438e..597847ae 100644
--- a/tests/test_toulouse_maelis.py
+++ b/tests/test_toulouse_maelis.py
@@ -589,28 +589,28 @@ def test_read_family(mocked_post, mocked_get, con, app):
         },
         'CAFInfo': None,
         'civility_text': 'Monsieur',
         'quality_text': 'PERE',
     }
     data = resp.json['data']['childList'][0]
     del data['fsl']
     del data['medicalRecord']
+    del data['authorizedPersonList']
     assert data == {
         'num': '613880',
         'lastname': 'DOE',
         'firstname': 'JANNIS',
         'sexe': 'F',
         'sexe_text': 'Féminin',
         'birth': {'dateBirth': '1943-01-19T00:00:00+01:00', 'place': None},
         'dietcode': 'RSV',
         'dietcode_text': '3- RÉGIME SANS VIANDE',
         'bPhoto': True,
         'bLeaveAlone': False,
-        'authorizedPersonList': [],
         'indicatorList': [],
         'subscribeSchoolList': [],
         'mother': {'num': 613963, 'civility': 'MME', 'firstname': 'JANE', 'lastname': 'DOE'},
         'father': {'num': 613878, 'civility': 'M.', 'firstname': 'JHON', 'lastname': 'DOE'},
         'rl': None,
         'subscribeActivityList': [],
         'paiInfoBean': {
             'code': 'PAIALI',
@@ -674,16 +674,34 @@ def test_read_family(mocked_post, mocked_get, con, app):
         'quality': 'T',
         'civility': 'MME',
         'sexe': None,
         'contact': {'phone': '0123456789', 'mobile': None, 'mail': 'pueblo@example.org'},
         'numPerson': 614059,
         'civility_text': 'Madame',
         'quality_text': 'TANTE',
     }
+    assert resp.json['data']['childList'][0]['authorizedPersonList'][0] == {
+        'personInfo': {
+            'num': 614719,
+            'lastname': 'BENT',
+            'firstname': 'AMEL',
+            'dateBirth': '1985-06-21T00:00:00+02:00',
+            'civility': 'MME',
+            'civility_text': 'Madame',
+            'sexe': 'F',
+            'sexe_text': 'Féminin',
+            'contact': {'phone': '0123456789', 'mobile': '0623456789', 'mail': 'abent@example.org'},
+        },
+        'personQuality': {
+            'code': 'T',
+            'code_text': 'TANTE',
+            'libelle': 'TANTE',
+        },
+    }
 
 
 def test_read_family_not_linked_error(con, app):
     url = get_endpoint('read-family')
 
     resp = app.get(url + '?NameID=')
     assert resp.json['err'] == 'not-linked'
     assert resp.json['err_desc'] == 'User not linked to family'
@@ -822,16 +840,18 @@ def test_read_person_not_found(mocked_post, mocked_get, con, app):
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
 def test_read_child(mocked_post, mocked_get, con, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
     mocked_post.side_effect = [
         READ_FAMILY,
         READ_DIETCODE,
         READ_PAI,
+        READ_CIVILITIES,
+        READ_QUALITIES,
     ]
     url = get_endpoint('read-child')
     Link.objects.create(resource=con, family_id='1312', name_id='local')
 
     resp = app.get(url + '?NameID=local&child_id=613880')
     assert resp.json['err'] == 0
     assert resp.json['data']['firstname'] == 'JANNIS'
 
@@ -856,16 +876,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')
-- 
2.30.2

