From c2a5477829f0e49ea380d6f48c14dddd3aeb6066 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Mon, 6 Jan 2020 11:52:40 +0100
Subject: [PATCH 3/5] toulouse_axel: handle allergie fields (#38543)

---
 functests/toulouse_axel/test_toulouse_axel.py | 25 ++++++-
 passerelle/contrib/toulouse_axel/models.py    | 71 ++++++++++++++-----
 .../flat_update_family_info.json              | 26 +++----
 .../toulouse_axel/update_family_info.json     | 46 ++++--------
 tests/test_toulouse_axel.py                   | 33 ++++++++-
 5 files changed, 125 insertions(+), 76 deletions(-)

diff --git a/functests/toulouse_axel/test_toulouse_axel.py b/functests/toulouse_axel/test_toulouse_axel.py
index fa3c1e8b..7a416da3 100644
--- a/functests/toulouse_axel/test_toulouse_axel.py
+++ b/functests/toulouse_axel/test_toulouse_axel.py
@@ -29,14 +29,17 @@ def test_link(conn, user):
     pprint.pprint(data)
     print('\n')
 
+    # take family info and transform them into updatable data
     payload = data['data']
-    for key in ['SITUATIONFAMILIALE', 'NBENFANTACTIF', 'NBRLACTIF', 'IDDUI', 'CODEMISEAJOUR']:
-        payload.pop(key)
+    # complete required fields
     payload['N0TELEDOSSIER'] = '42'
     payload['DROITALIMAGE'] = 'NON'
+    payload['REVENUS']['CHOIXREVENU'] = ''
+    # remove non editable fields
+    for key in ['SITUATIONFAMILIALE', 'NBENFANTACTIF', 'NBRLACTIF', 'IDDUI', 'CODEMISEAJOUR']:
+        payload.pop(key)
     for key in ['MONTANTTOTAL', 'DATEVALIDITE', 'SFI', 'IREVENUS', 'RNF']:
         payload['REVENUS'].pop(key, None)
-    payload['REVENUS']['CHOIXREVENU'] = ''
     for enfant in payload['ENFANT']:
         for key in ['NOM', 'DATENAISSANCE', 'SEXE', 'PRENOMPERE', 'PRENOMMERE', 'NOMPERE', 'NOMMERE', 'RATTACHEAUTREDUI', 'PRENOM']:
             enfant.pop(key)
@@ -55,6 +58,22 @@ def test_link(conn, user):
         enfant['SANITAIRE']['HANDICAP'] = {}
         for key in handicap_fields:
             enfant['SANITAIRE']['HANDICAP'][key] = enfant['SANITAIRE'].pop(key)
+        # manage allergie data (not the same schema)
+        if 'ALLERGIE' not in enfant['SANITAIRE']:
+            continue
+        new_allergie = {
+            'ASTHME': False,
+            'MEDICAMENTEUSES': False,
+            'ALIMENTAIRES': False,
+            'AUTRES': None,
+        }
+        for allergie in enfant['SANITAIRE']['ALLERGIE']:
+            if allergie['TYPE'] == 'AUTRES':
+                if allergie['ALLERGIQUE'] == 'OUI':
+                    new_allergie['AUTRES'] = allergie['NOMALLERGIE']
+                continue
+            new_allergie[allergie['TYPE']] = allergie['ALLERGIQUE']
+        enfant['SANITAIRE']['ALLERGIE'] = new_allergie
     # add partial update flags
     flags = [
         'maj:adresse',
diff --git a/passerelle/contrib/toulouse_axel/models.py b/passerelle/contrib/toulouse_axel/models.py
index 09deed23..f6f3137d 100644
--- a/passerelle/contrib/toulouse_axel/models.py
+++ b/passerelle/contrib/toulouse_axel/models.py
@@ -41,6 +41,17 @@ logger = logging.getLogger('passerelle.contrib.toulouse_axel')
 BASE_XSD_PATH = os.path.join(os.path.dirname(__file__), 'xsd')
 
 
+boolean_type = {
+    'oneOf': [
+        {'type': 'boolean'},
+        {
+            'type': 'string',
+            'pattern': '[Oo][Uu][Ii]|[Nn][Oo][Nn]|[Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee]|1|0',
+        }
+    ]
+}
+
+
 def indent(tree, space="  ", level=0):
     # backport from Lib/xml/etree/ElementTree.py python 3.9
     if isinstance(tree, ET.ElementTree):
@@ -123,15 +134,7 @@ class AxelSchema(JSONSchemaFromXMLSchema):
 
     @classmethod
     def schema_bool(cls):
-        return {
-            'oneOf': [
-                {'type': 'boolean'},
-                {
-                    'type': 'string',
-                    'pattern': '[Oo][Uu][Ii]|[Nn][Oo][Nn]|[Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee]|1|0',
-                }
-            ]
-        }
+        return copy.deepcopy(boolean_type)
 
     def encode_bool(self, obj):
         return encode_bool(obj)
@@ -296,15 +299,7 @@ class ToulouseAxel(BaseResource):
         form_maj_famille_dui.request_schema['properties']['PORTAIL']['properties']['DUI'])
 
     for flag in sorted(UPDATE_FAMILY_FLAGS.keys()):
-        flag_type = {
-            'oneOf': [
-                {'type': 'boolean'},
-                {
-                    'type': 'string',
-                    'pattern': '[Oo][Uu][Ii]|[Nn][Oo][Nn]|[Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee]|1|0',
-                }
-            ]
-        }
+        flag_type = copy.deepcopy(boolean_type)
         if flag not in UPDATE_FAMILY_REQUIRED_FLAGS:
             flag_type['oneOf'].append({'type': 'null'})
             flag_type['oneOf'].append({'type': 'string', 'enum': ['']})
@@ -338,6 +333,25 @@ class ToulouseAxel(BaseResource):
         sanitaire_properties['HANDICAP']['properties'][key] = field
         sanitaire_required.remove(key)
 
+    sanitaire_properties.pop('ALLERGIE')
+    sanitaire_properties['ALLERGIE'] = {
+        'type': 'object',
+        'properties': {},
+        'required': ['ASTHME', 'MEDICAMENTEUSES', 'ALIMENTAIRES', 'AUTRES'],
+    }
+    for key in ['ASTHME', 'MEDICAMENTEUSES', 'ALIMENTAIRES']:
+        sanitaire_properties['ALLERGIE']['properties'][key] = copy.deepcopy(boolean_type)
+    sanitaire_properties['ALLERGIE']['properties']['AUTRES'] = {
+        'oneOf': [
+            {'type': 'null'},
+            {
+                'type': 'string',
+                'minLength': 0,
+                'maxLength': 50,
+            }
+        ]
+    }
+
     UPDATE_FAMILY_SCHEMA['unflatten'] = True
 
     @endpoint(
@@ -577,6 +591,27 @@ class ToulouseAxel(BaseResource):
                 continue
             child['SANITAIRE'].update(child['SANITAIRE'].pop('HANDICAP'))
 
+        # transform ALLERGIE block
+        for child in post_data['ENFANT'].values():
+            if 'SANITAIRE' not in child:
+                continue
+            if 'ALLERGIE' not in child['SANITAIRE']:
+                continue
+            new_allergie = []
+            for key in ['ASTHME', 'MEDICAMENTEUSES', 'ALIMENTAIRES']:
+                new_allergie.append({
+                    'TYPE': key,
+                    'ALLERGIQUE': child['SANITAIRE']['ALLERGIE'][key],
+                    'NOMALLERGIE': None,
+                })
+            if child['SANITAIRE']['ALLERGIE']['AUTRES']:
+                new_allergie.append({
+                    'TYPE': 'AUTRES',
+                    'ALLERGIQUE': 'OUI',
+                    'NOMALLERGIE': child['SANITAIRE']['ALLERGIE']['AUTRES'],
+                })
+            child['SANITAIRE']['ALLERGIE'] = new_allergie
+
         # transform ENFANT dict to a list back
         post_data['ENFANT'] = post_data['ENFANT'].values()
 
diff --git a/tests/data/toulouse_axel/flat_update_family_info.json b/tests/data/toulouse_axel/flat_update_family_info.json
index 8d10f35a..5db4296c 100644
--- a/tests/data/toulouse_axel/flat_update_family_info.json
+++ b/tests/data/toulouse_axel/flat_update_family_info.json
@@ -36,15 +36,10 @@
   "ENFANT/0/CONTACT/2/TELFIXE": "0505050505",
   "ENFANT/0/CONTACT/2/TELPORTABLE": "0606060606",
   "ENFANT/0/IDPERSONNE": "4242",
-  "ENFANT/0/SANITAIRE/ALLERGIE/0/ALLERGIQUE": "OUI",
-  "ENFANT/0/SANITAIRE/ALLERGIE/0/NOMALLERGIE": "",
-  "ENFANT/0/SANITAIRE/ALLERGIE/0/TYPE": "ASTHME",
-  "ENFANT/0/SANITAIRE/ALLERGIE/1/ALLERGIQUE": "OUI",
-  "ENFANT/0/SANITAIRE/ALLERGIE/1/NOMALLERGIE": "",
-  "ENFANT/0/SANITAIRE/ALLERGIE/1/TYPE": "MEDICAMENTEUSES",
-  "ENFANT/0/SANITAIRE/ALLERGIE/2/ALLERGIQUE": "OUI",
-  "ENFANT/0/SANITAIRE/ALLERGIE/2/NOMALLERGIE": "",
-  "ENFANT/0/SANITAIRE/ALLERGIE/2/TYPE": "ALIMENTAIRES",
+  "ENFANT/0/SANITAIRE/ALLERGIE/ASTHME": "OUI",
+  "ENFANT/0/SANITAIRE/ALLERGIE/MEDICAMENTEUSES": "OUI",
+  "ENFANT/0/SANITAIRE/ALLERGIE/ALIMENTAIRES": "OUI",
+  "ENFANT/0/SANITAIRE/ALLERGIE/AUTRES": "",
   "ENFANT/0/SANITAIRE/DATEFINVALIDITE": "2020-12-31",
   "ENFANT/0/SANITAIRE/HANDICAP/AUTREDIFFICULTE": "",
   "ENFANT/0/SANITAIRE/HANDICAP/ECOLESPECIALISEE": "",
@@ -72,15 +67,10 @@
   "ENFANT/1/ASSURANCE/NUMERO": "1234",
   "ENFANT/1/AUTORISATIONURGENCEMEDICALE": "OUI",
   "ENFANT/1/IDPERSONNE": "3535",
-  "ENFANT/1/SANITAIRE/ALLERGIE/0/ALLERGIQUE": "OUI",
-  "ENFANT/1/SANITAIRE/ALLERGIE/0/NOMALLERGIE": "",
-  "ENFANT/1/SANITAIRE/ALLERGIE/0/TYPE": "ASTHME",
-  "ENFANT/1/SANITAIRE/ALLERGIE/1/ALLERGIQUE": "OUI",
-  "ENFANT/1/SANITAIRE/ALLERGIE/1/NOMALLERGIE": "",
-  "ENFANT/1/SANITAIRE/ALLERGIE/1/TYPE": "MEDICAMENTEUSES",
-  "ENFANT/1/SANITAIRE/ALLERGIE/2/ALLERGIQUE": "OUI",
-  "ENFANT/1/SANITAIRE/ALLERGIE/2/NOMALLERGIE": "",
-  "ENFANT/1/SANITAIRE/ALLERGIE/2/TYPE": "ALIMENTAIRES",
+  "ENFANT/1/SANITAIRE/ALLERGIE/ASTHME": "OUI",
+  "ENFANT/1/SANITAIRE/ALLERGIE/MEDICAMENTEUSES": "OUI",
+  "ENFANT/1/SANITAIRE/ALLERGIE/ALIMENTAIRES": "OUI",
+  "ENFANT/1/SANITAIRE/ALLERGIE/AUTRES": "",
   "ENFANT/1/SANITAIRE/DATEFINVALIDITE": "2020-12-31",
   "ENFANT/1/SANITAIRE/HANDICAP/AUTREDIFFICULTE": "",
   "ENFANT/1/SANITAIRE/HANDICAP/ECOLESPECIALISEE": "",
diff --git a/tests/data/toulouse_axel/update_family_info.json b/tests/data/toulouse_axel/update_family_info.json
index bac9df26..f02c57e2 100644
--- a/tests/data/toulouse_axel/update_family_info.json
+++ b/tests/data/toulouse_axel/update_family_info.json
@@ -51,23 +51,12 @@
             ],
             "IDPERSONNE": "4242",
             "SANITAIRE": {
-                "ALLERGIE": [
-                    {
-                        "ALLERGIQUE": "OUI",
-                        "NOMALLERGIE": null,
-                        "TYPE": "ASTHME"
-                    },
-                    {
-                        "ALLERGIQUE": "OUI",
-                        "NOMALLERGIE": null,
-                        "TYPE": "MEDICAMENTEUSES"
-                    },
-                    {
-                        "ALLERGIQUE": "OUI",
-                        "NOMALLERGIE": null,
-                        "TYPE": "ALIMENTAIRES"
-                    }
-                ],
+                "ALLERGIE": {
+                    "ASTHME": "OUI",
+                    "MEDICAMENTEUSES": "OUI",
+                    "ALIMENTAIRES": "OUI",
+                    "AUTRES": null
+                },
                 "DATEFINVALIDITE": "2020-12-31",
                 "HANDICAP": {
                     "AUTREDIFFICULTE": null,
@@ -107,23 +96,12 @@
             "AUTORISATIONURGENCEMEDICALE": "OUI",
             "IDPERSONNE": "3535",
             "SANITAIRE": {
-                "ALLERGIE": [
-                    {
-                        "ALLERGIQUE": "OUI",
-                        "NOMALLERGIE": null,
-                        "TYPE": "ASTHME"
-                    },
-                    {
-                        "ALLERGIQUE": "OUI",
-                        "NOMALLERGIE": null,
-                        "TYPE": "MEDICAMENTEUSES"
-                    },
-                    {
-                        "ALLERGIQUE": "OUI",
-                        "NOMALLERGIE": null,
-                        "TYPE": "ALIMENTAIRES"
-                    }
-                ],
+                "ALLERGIE": {
+                    "ASTHME": "OUI",
+                    "MEDICAMENTEUSES": "OUI",
+                    "ALIMENTAIRES": "OUI",
+                    "AUTRES": null
+                },
                 "DATEFINVALIDITE": "2020-12-31",
                 "HANDICAP": {
                     "AUTREDIFFICULTE": null,
diff --git a/tests/test_toulouse_axel.py b/tests/test_toulouse_axel.py
index 73707a9b..efe528f5 100644
--- a/tests/test_toulouse_axel.py
+++ b/tests/test_toulouse_axel.py
@@ -850,9 +850,8 @@ def test_sanitize_update_family_data_enfant_n_sanitaire_allergie(app, resource,
     # test maj:enfant_n_sanitaire_allergie
     partial_update_params = copy.deepcopy(update_params)
     partial_update_params['maj:enfant_1_sanitaire_allergie'] = False
-    for i, allergie in enumerate(partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']):
-        for key in allergie.keys():
-            partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE'][i][key] = None  # reset fields
+    for key in partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE'].keys():
+        partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE'][key] = None  # reset fields
     partial_update_params['maj:enfant_0'] = False
     resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
     assert len(partial_update_params['ENFANT']) == 1
@@ -884,6 +883,34 @@ def test_sanitize_update_family_data_enfant_n_sanitaire_allergie(app, resource,
         assert 'ALLERGIE' not in partial_update_params['ENFANT'][0]['SANITAIRE']
         assert 'ALLERGIE' not in partial_update_params['ENFANT'][1]['SANITAIRE']
 
+    # check values
+    partial_update_params = copy.deepcopy(update_params)
+    partial_update_params['maj:enfant_1'] = False
+    partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['ASTHME'] = 'NON'
+    partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['MEDICAMENTEUSES'] = 'NON'
+    partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['ALIMENTAIRES'] = 'NON'
+    partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['AUTRES'] = ''
+    resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    assert partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE'] == [
+        {'TYPE': 'ASTHME', 'ALLERGIQUE': 'NON', 'NOMALLERGIE': None},
+        {'TYPE': 'MEDICAMENTEUSES', 'ALLERGIQUE': 'NON', 'NOMALLERGIE': None},
+        {'TYPE': 'ALIMENTAIRES', 'ALLERGIQUE': 'NON', 'NOMALLERGIE': None},
+    ]
+
+    partial_update_params = copy.deepcopy(update_params)
+    partial_update_params['maj:enfant_1'] = False
+    partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['ASTHME'] = 'OUI'
+    partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['MEDICAMENTEUSES'] = 'OUI'
+    partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['ALIMENTAIRES'] = 'OUI'
+    partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE']['AUTRES'] = 'accariens'
+    resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    assert partial_update_params['ENFANT'][0]['SANITAIRE']['ALLERGIE'] == [
+        {'TYPE': 'ASTHME', 'ALLERGIQUE': 'OUI', 'NOMALLERGIE': None},
+        {'TYPE': 'MEDICAMENTEUSES', 'ALLERGIQUE': 'OUI', 'NOMALLERGIE': None},
+        {'TYPE': 'ALIMENTAIRES', 'ALLERGIQUE': 'OUI', 'NOMALLERGIE': None},
+        {'TYPE': 'AUTRES', 'ALLERGIQUE': 'OUI', 'NOMALLERGIE': 'accariens'},
+    ]
+
 
 def test_sanitize_update_family_data_enfant_n_sanitaire_medecin(app, resource, update_params):
     Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
-- 
2.20.1

