From 9f7894291d4531e114d8353f23f53996210c9bf1 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/FamilyService.wsdl | 21 +++++-----
 tests/data/toulouse_maelis/R_read_family.xml  | 19 ++++++++++
 tests/test_toulouse_maelis.py                 | 22 ++++++++++-
 4 files changed, 87 insertions(+), 13 deletions(-)

diff --git a/passerelle/contrib/toulouse_maelis/models.py b/passerelle/contrib/toulouse_maelis/models.py
index 04b41527..51723648 100644
--- a/passerelle/contrib/toulouse_maelis/models.py
+++ b/passerelle/contrib/toulouse_maelis/models.py
@@ -151,30 +151,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',
@@ -203,16 +220,21 @@ class ToulouseMaelis(BaseResource, HTTPResource):
                 self.add_text_value_to_rl(data[rlg])
         for child in data['childList']:
             self.add_text_value_to_child(child)
         for kind in ('authorized', 'emergency'):
             for person in data[kind + 'PersonList']:
                 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, kind='authorized'):
         data = self.get_person_raw(family_id, person_id, kind)
         self.add_text_value_to_person(data)
@@ -440,16 +462,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/FamilyService.wsdl b/tests/data/toulouse_maelis/FamilyService.wsdl
index 1ad4d068..9548a8fd 100644
--- a/tests/data/toulouse_maelis/FamilyService.wsdl
+++ b/tests/data/toulouse_maelis/FamilyService.wsdl
@@ -382,17 +382,16 @@
     <xs:sequence>
       <xs:element name="dossierNumber" type="xs:int"/>
       <xs:element name="personNumber" type="xs:int"/>
       <xs:element name="quotient" type="tns:familyQuotientRedvBean"/>
     </xs:sequence>
   </xs:complexType>
   <xs:complexType name="familyQuotientRedvBean">
     <xs:sequence>
-      <xs:element name="year" type="xs:int"/>
       <xs:element name="yearRev" type="xs:int"/>
       <xs:element name="dateStart" type="xs:dateTime"/>
       <xs:element name="dateEnd" type="xs:dateTime"/>
       <xs:element name="mtt" type="xs:double"/>
       <xs:element name="cdquo" type="xs:string"/>
       <xs:element minOccurs="0" name="codeUti" type="xs:string"/>
     </xs:sequence>
   </xs:complexType>
@@ -749,16 +748,17 @@
     <xs:complexContent>
       <xs:extension base="ns1:abstractSpecBean">
         <xs:sequence>
           <xs:element minOccurs="0" name="numPerson" type="xs:int"/>
           <xs:element minOccurs="0" name="civility" type="xs:string"/>
           <xs:element name="firstname" type="xs:string"/>
           <xs:element name="lastname" type="xs:string"/>
           <xs:element name="dateBirth" type="xs:dateTime"/>
+          <xs:element minOccurs="0" name="sexe" type="xs:string"/>
           <xs:element name="quality" type="xs:string"/>
           <xs:element minOccurs="0" name="contact" type="tns:contactLightBean"/>
         </xs:sequence>
       </xs:extension>
     </xs:complexContent>
   </xs:complexType>
 
   <xs:complexType name="contactLightBean">
@@ -802,32 +802,32 @@
       <xs:element minOccurs="0" name="place" type="xs:string"/>
     </xs:sequence>
   </xs:complexType>
 
   <xs:complexType name="relatedPersonBean">
     <xs:complexContent>
       <xs:extension base="ns1:abstractSpecBean">
         <xs:sequence>
-          <xs:element minOccurs="0" name="person" type="tns:personInfoBean"/>
+          <xs:element minOccurs="0" name="personInfo" type="tns:personInfoBean"/>
           <xs:element minOccurs="0" name="personQuality" type="tns:personQualityBean"/>
         </xs:sequence>
       </xs:extension>
     </xs:complexContent>
   </xs:complexType>
 
   <xs:complexType name="personInfoBean">
     <xs:sequence>
       <xs:element name="num" type="xs:int"/>
       <xs:element minOccurs="0" name="lastname" type="xs:string"/>
       <xs:element minOccurs="0" name="firstname" type="xs:string"/>
+      <xs:element minOccurs="0" name="dateBirth" type="xs:dateTime"/>
       <xs:element minOccurs="0" name="civility" type="xs:string"/>
       <xs:element minOccurs="0" name="sexe" type="xs:string"/>
-      <xs:element minOccurs="0" name="phone" type="xs:string"/>
-      <xs:element minOccurs="0" name="mobile" type="xs:string"/>
+      <xs:element minOccurs="0" name="contact" type="tns:contactLightBean"/>
     </xs:sequence>
   </xs:complexType>
 
   <xs:complexType name="personQualityBean">
     <xs:sequence>
       <xs:element name="code" type="xs:string"/>
       <xs:element minOccurs="0" name="libelle" type="xs:string"/>
     </xs:sequence>
@@ -966,39 +966,38 @@
       </xs:extension>
     </xs:complexContent>
   </xs:complexType>
 
   <xs:complexType name="updateChildAutorizationRequestBean">
     <xs:sequence>
       <xs:element name="numFamily" type="xs:string"/>
       <xs:element name="numPerson" type="xs:int"/>
-      <xs:element maxOccurs="unbounded" name="personList" type="tns:relatedPerson2Bean"/>
+      <xs:element maxOccurs="unbounded" minOccurs="0" name="personList" nillable="true" type="tns:relatedPerson2Bean"/>
       <xs:element name="bLeaveAlone" type="xs:boolean"/>
       <xs:element name="bPhoto" type="xs:boolean"/>
     </xs:sequence>
   </xs:complexType>
 
   <xs:complexType name="relatedPerson2Bean">
     <xs:sequence>
-      <xs:element name="personInfo" type="tns:person2Bean"/>
+      <xs:element name="personInfo" type="tns:person3Bean"/>
       <xs:element name="personQuality" type="tns:personQualityBean"/>
     </xs:sequence>
   </xs:complexType>
 
-  <xs:complexType name="person2Bean">
+  <xs:complexType name="person3Bean">
     <xs:sequence>
       <xs:element minOccurs="0" name="num" type="xs:int"/>
       <xs:element minOccurs="0" name="civility" type="xs:string"/>
       <xs:element name="lastname" type="xs:string"/>
       <xs:element name="firstname" type="xs:string"/>
       <xs:element name="dateBirth" type="xs:dateTime"/>
       <xs:element minOccurs="0" name="sexe" type="xs:string"/>
-      <xs:element minOccurs="0" name="mail" type="xs:string"/>
-      <xs:element minOccurs="0" name="address" type="tns:addressBean"/>
+      <xs:element minOccurs="0" name="contact" type="tns:contactLightBean"/>
     </xs:sequence>
   </xs:complexType>
 
   <xs:complexType name="subscribeSchoolRequestBean">
     <xs:sequence>
       <xs:element name="personNumber" type="xs:int"/>
       <xs:element minOccurs="0" name="schoolYear" type="xs:int"/>
       <xs:element minOccurs="0" name="dateSubscribe" type="xs:dateTime"/>
@@ -1815,28 +1814,26 @@ Cette méthode permet de mettre à jour les informations relatives au FSL pour u
     </wsdl:operation>
     <wsdl:operation name="createUpdateQuotient">
 <wsdl:documentation> Méthode de création/mise à jour d'un quotient
 
  -------------------------
  dossierNumber: numéro de la famille (obligatoire)
  personNumber: numéro de la personne (obligatoire)
  Quotient : (obligatoire) 
- 	- year : année de référence (obligatoire)
 	- yearRev : année de revenue (obligatoire)
 	- dateStart : date de début (format DD/MM/YYYY) (obligatoire)
 	- dateFin : date de fin (format DD/MM/YYYY) (obligatoire)
 	- mtt : montant (obligatoire)
 	- cdQuo : code du quotient (obligatoire)
 	- codeUti : code de l'utilisateur
 
  -------------------------
  Traitement :
 	Récupère l'identifiant de quotient
-	Récupère les quotients existant de cette personne/année/code quotient (table H_QUOREDV)
 	Clôture les anciens quotients (si la date de fin du quotient est supérieure à la date de début du quotient à insérer)
 	Insère le nouveau quotient
 	Renvoie l'identifiant du quotient créé</wsdl:documentation>
       <wsdl:input message="tns:createUpdateQuotient" name="createUpdateQuotient">
     </wsdl:input>
       <wsdl:output message="tns:createUpdateQuotientResponse" name="createUpdateQuotientResponse">
     </wsdl:output>
       <wsdl:fault message="tns:MaelisFamilyException" name="MaelisFamilyException">
@@ -2202,17 +2199,17 @@ Cette méthode permet de mettre à jour les informations relatives au PAI pour u
     </wsdl:output>
       <wsdl:fault message="tns:MaelisFamilyException" name="MaelisFamilyException">
     </wsdl:fault>
     </wsdl:operation>
     <wsdl:operation name="updateFamilyAuthorizedPersonList">
 <wsdl:documentation>Méthode de mise à jour de la liste des personnes autorisées sur la famille
  La liste comporte toutes les personnes autorisées. 
  Les personnes non présentes dans cette liste sont supprimées en tant que personne autorisée.
- Dépressié : il faut utiliser la méthode updateChildAutorization car nouvelle gestion par enfant (famille recomposée)  
+ Déprécié : il faut utiliser la méthode updateChildAutorization car nouvelle gestion par enfant (famille recomposée)  
 
  ------------------------------
  numDossier : numéro de dossier famille  (obligatoire)
  authorizedPersonList : liste des personnes autorisées
 
  -----------------------------</wsdl:documentation>
       <wsdl:input message="tns:updateFamilyAuthorizedPersonList" name="updateFamilyAuthorizedPersonList">
     </wsdl:input>
diff --git a/tests/data/toulouse_maelis/R_read_family.xml b/tests/data/toulouse_maelis/R_read_family.xml
index 627b3084..03464bc9 100644
--- a/tests/data/toulouse_maelis/R_read_family.xml
+++ b/tests/data/toulouse_maelis/R_read_family.xml
@@ -118,16 +118,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 ecd3f5d5..ebb87769 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',
@@ -673,16 +673,34 @@ def test_read_family(mocked_post, mocked_get, con, app):
         'dateBirth': '1982-12-20T00:00:00+01:00',
         'quality': 'T',
         'civility': 'MME',
         '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'
@@ -830,16 +848,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'
 
-- 
2.30.2

