From a174bc24ebc29456d4ba44f015ecfb49477728fe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Mon, 27 Jan 2020 15:39:31 +0100
Subject: [PATCH] toulouse_axel: add labels to explain some values (#39291)

---
 functests/toulouse_axel/test_toulouse_axel.py |  7 +--
 passerelle/contrib/toulouse_axel/models.py    | 28 +++++++++++
 passerelle/contrib/toulouse_axel/utils.py     | 50 +++++++++++++++++++
 tests/data/toulouse_axel/family_info.xml      |  4 +-
 tests/test_toulouse_axel.py                   | 47 ++++++++++++++++-
 5 files changed, 130 insertions(+), 6 deletions(-)

diff --git a/functests/toulouse_axel/test_toulouse_axel.py b/functests/toulouse_axel/test_toulouse_axel.py
index 7142bbe3..744ca7ad 100644
--- a/functests/toulouse_axel/test_toulouse_axel.py
+++ b/functests/toulouse_axel/test_toulouse_axel.py
@@ -45,14 +45,14 @@ def test_link(conn, user):
     payload['DROITALIMAGE'] = 'NON'
     payload['REVENUS']['CHOIXREVENU'] = ''
     # remove non editable fields
-    for key in ['SITUATIONFAMILIALE', 'NBENFANTACTIF', 'NBRLACTIF', 'IDDUI', 'CODEMISEAJOUR']:
+    for key in ['SITUATIONFAMILIALE', 'SITUATIONFAMILIALE_label', 'NBENFANTACTIF', 'NBRLACTIF', 'IDDUI', 'CODEMISEAJOUR']:
         payload.pop(key)
-    for key in ['IDPERSONNE', 'NOM', 'PRENOM', 'NOMJEUNEFILLE', 'DATENAISSANCE', 'CIVILITE', 'INDICATEURRL']:
+    for key in ['IDPERSONNE', 'NOM', 'PRENOM', 'NOMJEUNEFILLE', 'DATENAISSANCE', 'CIVILITE', 'INDICATEURRL', 'CSP_label']:
         if 'RL1' in payload:
             payload['RL1'].pop(key)
         if 'RL2' in payload:
             payload['RL2'].pop(key)
-    for key in ['MONTANTTOTAL', 'DATEVALIDITE', 'SFI', 'IREVENUS', 'RNF', 'NBENFANTSACHARGE']:
+    for key in ['MONTANTTOTAL', 'DATEVALIDITE', 'SFI', 'IREVENUS', 'RNF', 'NBENFANTSACHARGE', 'TYPEREGIME_label']:
         payload['REVENUS'].pop(key, None)
     for enfant in payload['ENFANT']:
         for key in ['id', 'text', 'NOM', 'DATENAISSANCE', 'SEXE', 'PRENOMPERE', 'PRENOMMERE', 'NOMPERE', 'NOMMERE', 'RATTACHEAUTREDUI', 'PRENOM',
@@ -63,6 +63,7 @@ def test_link(conn, user):
         for contact in enfant.get('CONTACT', []):
             contact.pop('id')
             contact.pop('text')
+            contact.pop('LIENPARENTE_label')
         if 'SANITAIRE' not in enfant:
             continue
         # manage handicap data (not the same schema)
diff --git a/passerelle/contrib/toulouse_axel/models.py b/passerelle/contrib/toulouse_axel/models.py
index 94d9e083..78c20417 100644
--- a/passerelle/contrib/toulouse_axel/models.py
+++ b/passerelle/contrib/toulouse_axel/models.py
@@ -452,6 +452,22 @@ class ToulouseAxel(BaseResource):
         link.delete()
         return {'link': link_id, 'deleted': True, 'dui': link.dui}
 
+    @endpoint(
+        description=_("Get a referential"),
+        perm='can_access',
+        pattern=r'^(?P<code>[\w-]+)/?$',
+        example_pattern='csp',
+        parameters={
+            'code': {'description': _('Referential code. Possible values: situation_familiale, csp, lien_parente, type_regime')},
+        })
+    def referential(self, request, code):
+        if code not in ['situation_familiale', 'csp', 'lien_parente', 'type_regime']:
+            raise APIError('Referential not found', err_code='not-found')
+        references = getattr(utils, '{}_mapping'.format(code))
+        if references is None:
+            raise APIError('Referential not found', err_code='not-found', http_status=404)
+        return {'data': [{'id': key, 'text': val} for key, val in references.items()]}
+
     def get_family_data(self, dui, check_registrations=False):
         try:
             result = ref_famille_dui(self, {'PORTAIL': {'DUI': {'IDDUI': dui}}})
@@ -480,12 +496,24 @@ class ToulouseAxel(BaseResource):
                 child['clae_cantine_current'] = children_registred_for_current_year.get(child['IDPERSONNE'])
                 child['clae_cantine_next'] = children_registred_for_next_year.get(child['IDPERSONNE'])
 
+        family_data['SITUATIONFAMILIALE_label'] = utils.get_label(utils.situation_familiale_mapping, family_data['SITUATIONFAMILIALE'])
+        for key in ['RL1', 'RL2']:
+            if key not in family_data:
+                continue
+            rl = family_data[key]
+            rl['CSP_label'] = utils.get_label(utils.csp_mapping, rl['CSP'])
+
         for child in family_data.get('ENFANT', []):
             child['id'] = child['IDPERSONNE']
             child['text'] = '{} {}'.format(child['PRENOM'], child['NOM']).strip()
             for i, contact in enumerate(child.get('CONTACT', [])):
                 contact['id'] = i
                 contact['text'] = '{} {}'.format(contact['PRENOM'], contact['NOM']).strip()
+                contact['LIENPARENTE_label'] = utils.get_label(utils.lien_parente_mapping, contact['LIENPARENTE'])
+
+        if 'REVENUS' in family_data:
+            family_data['REVENUS']['TYPEREGIME_label'] = utils.get_label(utils.type_regime_mapping, family_data['REVENUS']['TYPEREGIME'])
+
         return family_data
 
     @endpoint(
diff --git a/passerelle/contrib/toulouse_axel/utils.py b/passerelle/contrib/toulouse_axel/utils.py
index 0b1dd4d5..2c5d64b2 100644
--- a/passerelle/contrib/toulouse_axel/utils.py
+++ b/passerelle/contrib/toulouse_axel/utils.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 # passerelle - uniform access to multiple data sources and services
 # Copyright (C) 2020  Entr'ouvert
 #
@@ -14,6 +15,9 @@
 # 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 collections import OrderedDict
 import datetime
 import xml.etree.ElementTree as ET
 
@@ -37,6 +41,52 @@ xml_date_format = '%d/%m/%Y'
 xml_datetime_format = '%d/%m/%Y %H:%M:%S'
 
 
+situation_familiale_mapping = OrderedDict([
+    ('C', 'Célibataire'),
+    ('D', 'Divorcé (e)'),
+    ('M', 'Marié (e)'),
+    ('S', 'Séparé (e)'),
+    ('V', 'Veuf (ve)'),
+    ('VM', 'Vie Maritale'),
+    ('P', 'Pacs'),
+])
+
+csp_mapping = OrderedDict([
+    ('OUV', 'Ouvriers'),
+    ('EMP', 'Employés'),
+    ('ETU', 'Etudiants'),
+    ('RET', 'Retraités'),
+    ('STA', 'Personnes en stage'),
+    ('AGEX', 'Agriculteurs exploitants'),
+    ('ARCO', 'Artisans commercants chefs entreprise'),
+    ('CADP', 'Cadres professions intellectuelles supérieures'),
+    ('PRIN', 'Professions intermediaires'),
+    ('SACT', 'Autres personnes sans activité professionnelle'),
+    ('REC', 'Recherche emploi'),
+])
+
+lien_parente_mapping = OrderedDict([
+    ('GRP1', 'Grands-parents paternels'),
+    ('GRP2', 'Grands-parents maternels'),
+    ('VOI', 'Voisin'),
+    ('FRE', "Frère de l'enfant"),
+    ('SOE', "Soeur de l'enfant"),
+    ('AMI', 'Ami (e)'),
+    ('FAMI', 'Membre de la famille'),
+    ('BABY', 'Baby sitter'),
+])
+
+type_regime_mapping = OrderedDict([
+    ('GENE', 'Régime général'),
+    ('ZAU', 'Autre'),
+    ('MSA', 'MSA'),
+])
+
+
+def get_label(mapping, code):
+    return mapping.get(code, code)
+
+
 def indent(tree, space="  ", level=0):
     # backport from Lib/xml/etree/ElementTree.py python 3.9
     if isinstance(tree, ET.ElementTree):
diff --git a/tests/data/toulouse_axel/family_info.xml b/tests/data/toulouse_axel/family_info.xml
index 2e42f007..efbe4c07 100644
--- a/tests/data/toulouse_axel/family_info.xml
+++ b/tests/data/toulouse_axel/family_info.xml
@@ -4,7 +4,7 @@
     <CODEMISEAJOUR>19</CODEMISEAJOUR>
     <NBRLACTIF>2</NBRLACTIF>
     <NBENFANTACTIF>2</NBENFANTACTIF>
-    <SITUATIONFAMILIALE>P</SITUATIONFAMILIALE>
+    <SITUATIONFAMILIALE>S</SITUATIONFAMILIALE>
     <REACTUALISATIONENLIGNE>NON</REACTUALISATIONENLIGNE>
     <DEMATFACTURES>NON</DEMATFACTURES>
     <ADRESSE>
@@ -131,7 +131,7 @@
       <CONTACT>
         <NOM>foo</NOM>
         <PRENOM>foo</PRENOM>
-        <LIENPARENTE/>
+        <LIENPARENTE>GRP1</LIENPARENTE>
         <ENCASURGENCE>OUI</ENCASURGENCE>
         <CHERCHERLENFANT>OUI</CHERCHERLENFANT>
         <TELFIXE>0505050505</TELFIXE>
diff --git a/tests/test_toulouse_axel.py b/tests/test_toulouse_axel.py
index a27c1ab4..54410d24 100644
--- a/tests/test_toulouse_axel.py
+++ b/tests/test_toulouse_axel.py
@@ -15,6 +15,8 @@
 # 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
@@ -45,7 +47,13 @@ from passerelle.contrib.toulouse_axel.models import (
     ref_verif_dui,
     reservation_periode,
 )
-from passerelle.contrib.toulouse_axel.utils import get_reference_year_from_date
+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
 
@@ -625,6 +633,24 @@ def test_unlink_endpoint(app, resource):
     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:
@@ -661,6 +687,7 @@ def test_family_info_endpoint(app, resource):
         'RL1',
         'RL2',
         'SITUATIONFAMILIALE',
+        'SITUATIONFAMILIALE_label',
         'TELFIXE',
     ])
     assert resp.json['data']['ENFANT'][0]['id'] == '4242'
@@ -694,6 +721,19 @@ def test_family_info_endpoint(app, resource):
     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')
@@ -807,6 +847,11 @@ def test_child_info_endpoint(app, resource):
     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')
-- 
2.20.1

