From 2b02092f50958d49f9c6a44f0f63069869376e93 Mon Sep 17 00:00:00 2001
From: Nicolas ROCHE <nroche@entrouvert.com>
Date: Fri, 16 Dec 2022 01:07:14 +0100
Subject: [PATCH 3/4] toulouse-maelis: return an indicators dict (#72523)

---
 functests/toulouse_maelis/conftest.py         |   4 +
 .../data/test_child_indicators.json           |  66 +++++++++++
 .../data/test_rl_indicators.json              |  34 ++++++
 functests/toulouse_maelis/test_family.py      |  12 +-
 passerelle/contrib/toulouse_maelis/models.py  |  20 ++--
 tests/test_toulouse_maelis.py                 | 108 +++++++++++++++---
 6 files changed, 217 insertions(+), 27 deletions(-)
 create mode 100644 functests/toulouse_maelis/data/test_child_indicators.json
 create mode 100644 functests/toulouse_maelis/data/test_rl_indicators.json

diff --git a/functests/toulouse_maelis/conftest.py b/functests/toulouse_maelis/conftest.py
index 9564ed71..e1a2bd77 100644
--- a/functests/toulouse_maelis/conftest.py
+++ b/functests/toulouse_maelis/conftest.py
@@ -283,22 +283,26 @@ def diff(result, expected_file):
 
 def remove_id_on_child(child):
     child['num'] = 'N/A'
     child['lastname'] = 'N/A'
     child['mother'] = 'N/A'  # dont care yet
     child['father'] = 'N/A'  # dont care yet
     for person in child['authorizedPersonList']:
         person['personInfo']['num'] = 'N/A'
+    child['indicatorList'].sort(key=lambda x: x['code'])
+    del child['indicators']  # order may change
 
 
 def remove_id_on_rlg(rlg):
     if rlg:
         rlg['num'] = 'N/A'
         rlg['lastname'] = 'N/A'
+        rlg['indicatorList'].sort(key=lambda x: x['code'])
+        del rlg['indicators']  # order may change
 
 
 def remove_id_on_family(family):
     family['number'] = 'N/A'
     remove_id_on_rlg(family['RL1'])
     remove_id_on_rlg(family['RL2'])
     for child in family['childList']:
         remove_id_on_child(child)
diff --git a/functests/toulouse_maelis/data/test_child_indicators.json b/functests/toulouse_maelis/data/test_child_indicators.json
new file mode 100644
index 00000000..660449dd
--- /dev/null
+++ b/functests/toulouse_maelis/data/test_child_indicators.json
@@ -0,0 +1,66 @@
+[
+  {
+    "id": "APPDENTAIRE",
+    "code": "APPDENTAIRE",
+    "text": "Port appareil dentaire",
+    "label": "Port appareil dentaire",
+    "typeDesc": "NONE",
+    "isActive": false
+  },
+  {
+    "id": "AUTRE",
+    "code": "AUTRE",
+    "text": "Autre",
+    "label": "Autre",
+    "typeDesc": "NOTE",
+    "isActive": true
+  },
+  {
+    "id": "AVL",
+    "code": "AVL",
+    "text": "Auxiliaire de Vie loisirs",
+    "label": "Auxiliaire de Vie loisirs",
+    "typeDesc": "NONE",
+    "isActive": false
+  },
+  {
+    "id": "AVS",
+    "code": "AVS",
+    "text": "Auxiliaire de Vie scolaire",
+    "label": "Auxiliaire de Vie scolaire ",
+    "typeDesc": "NONE",
+    "isActive": false
+  },
+  {
+    "id": "ETABSPEC",
+    "code": "ETABSPEC",
+    "text": "Etablissement sp\u00e9cialis\u00e9",
+    "label": "Etablissement sp\u00e9cialis\u00e9",
+    "typeDesc": "NOTE",
+    "isActive": false
+  },
+  {
+    "id": "LENTILLE",
+    "code": "LENTILLE",
+    "text": "Port lentilles de contact",
+    "label": "Port lentilles de contact",
+    "typeDesc": "NONE",
+    "isActive": false
+  },
+  {
+    "id": "LUNETTE",
+    "code": "LUNETTE",
+    "text": "Port de lunettes",
+    "label": "Port de lunettes",
+    "typeDesc": "NONE",
+    "isActive": true
+  },
+  {
+    "id": "MDPH",
+    "code": "MDPH",
+    "text": "Notification MDPH",
+    "label": "Notification MDPH",
+    "typeDesc": "NONE",
+    "isActive": false
+  }
+]
diff --git a/functests/toulouse_maelis/data/test_rl_indicators.json b/functests/toulouse_maelis/data/test_rl_indicators.json
new file mode 100644
index 00000000..9f6cdca0
--- /dev/null
+++ b/functests/toulouse_maelis/data/test_rl_indicators.json
@@ -0,0 +1,34 @@
+[
+  {
+    "id": "AVL",
+    "code": "AVL",
+    "text": "Auxiliaire de Vie loisirs",
+    "label": "Auxiliaire de Vie loisirs",
+    "typeDesc": "NONE",
+    "isActive": true
+  },
+  {
+    "id": "AVS",
+    "code": "AVS",
+    "text": "Auxiliaire de Vie scolaire",
+    "label": "Auxiliaire de Vie scolaire ",
+    "typeDesc": "NONE",
+    "isActive": false
+  },
+  {
+    "id": "ETABSPEC",
+    "code": "ETABSPEC",
+    "text": "Etablissement sp\u00e9cialis\u00e9",
+    "label": "Etablissement sp\u00e9cialis\u00e9",
+    "typeDesc": "NOTE",
+    "isActive": true
+  },
+  {
+    "id": "MDPH",
+    "code": "MDPH",
+    "text": "Notification MDPH",
+    "label": "Notification MDPH",
+    "typeDesc": "NONE",
+    "isActive": false
+  }
+]
diff --git a/functests/toulouse_maelis/test_family.py b/functests/toulouse_maelis/test_family.py
index c71e5cc3..17a4dad3 100644
--- a/functests/toulouse_maelis/test_family.py
+++ b/functests/toulouse_maelis/test_family.py
@@ -729,17 +729,21 @@ def test_update_rl_indicator(conn, update_data):
     assert resp.json()['err'] == 0
     assert diff_rlg(conn, update_data['name_id'], 1, 'test_rl_indicator.json', key='indicatorList')
 
     # restore RL indicators
     payload = {'indicatorList': update_data['family_payload']['rl2']['indicatorList']}
     resp = requests.post(url, json=payload)
     resp.raise_for_status()
     assert resp.json()['err'] == 0
-    assert diff_family(conn, update_data['name_id'], 'test_update_family.json')
+    data = diff_family(conn, update_data['name_id'], 'test_update_family.json')
+
+    # check indicator dict
+    indicators = sorted(data['RL2']['indicators'].values(), key=lambda x: x['id'])
+    assert diff(indicators, 'test_rl_indicators.json')
 
 
 def test_update_child_indicator(conn, update_data):
     unlink(conn, update_data['name_id'])
     link(conn, update_data)
     url = conn + '/update-child-indicator?NameID=%s&child_id=%s' % (
         update_data['name_id'],
         update_data['bart_num'],
@@ -752,17 +756,21 @@ def test_update_child_indicator(conn, update_data):
     assert resp.json()['err'] == 0
     assert diff_child(conn, update_data['name_id'], 0, 'test_child_indicator.json', key='indicatorList')
 
     # restore Bart indicators
     payload = {'indicatorList': update_data['family_payload']['childList'][0]['indicatorList']}
     resp = requests.post(url, json=payload)
     resp.raise_for_status()
     assert resp.json()['err'] == 0
-    assert diff_family(conn, update_data['name_id'], 'test_update_family.json')
+    data = diff_family(conn, update_data['name_id'], 'test_update_family.json')
+
+    # check indicator dict
+    indicators = sorted(data['childList'][0]['indicators'].values(), key=lambda x: x['id'])
+    assert diff(indicators, 'test_child_indicators.json')
 
 
 def test_update_quotient(conn, create_data):
     unlink(conn, create_data['name_id'])
     link(conn, create_data)
 
     # add quotient
     url = conn + '/update-quotient?NameID=%s&rl_id=%s' % (create_data['name_id'], create_data['rl1_num'])
diff --git a/passerelle/contrib/toulouse_maelis/models.py b/passerelle/contrib/toulouse_maelis/models.py
index ed470019..9b8bcc5b 100644
--- a/passerelle/contrib/toulouse_maelis/models.py
+++ b/passerelle/contrib/toulouse_maelis/models.py
@@ -231,16 +231,26 @@ class ToulouseMaelis(BaseResource, HTTPResource):
         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_indicators_field(self, referential_name, data):
+        active_indicators = [x['code'] for x in data['indicatorList']]
+        indicators = self.get_referential(referential_name)
+        result = {}
+        for item in indicators:
+            item['isActive'] = item['id'] in active_indicators
+            del item['choiceList']  # no list based indicator on parsifal project
+            result[item['id']] = item
+        data['indicators'] = result
+
     def add_text_value_to_rl_indicator(self, data):
         self.add_text_value('RLIndicator', data, ['code'])
 
     def add_text_value_to_child_indicator(self, data):
         self.add_text_value('ChildIndicator', data, ['code'])
 
     def add_text_value_to_child_person(self, data):
         self.add_text_value('Civility', data, ['personInfo', 'civility'])
@@ -251,20 +261,17 @@ class ToulouseMaelis(BaseResource, HTTPResource):
     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)
         for indicator in data['indicatorList']:
             self.add_text_value_to_child_indicator(indicator)
-
-        # sort indicators
-        if data['indicatorList']:
-            data['indicatorList'].sort(key=lambda x: x['code'])
+        self.add_indicators_field('ChildIndicator', data)
         return data
 
     def add_text_value_to_person(self, data):
         self.add_text_value('Civility', data, ['civility'])
         self.add_text_value('Quality', data, ['quality'])
         self.add_text_value('Sex', data, ['sexe'])
 
     def add_text_value_to_rl(self, data):
@@ -273,20 +280,17 @@ class ToulouseMaelis(BaseResource, HTTPResource):
         self.add_text_value('Complement', data, ['adresse', 'numComp'])
         self.add_text_value('Street', data, ['adresse', 'idStreet'])
         self.add_text_value('CSP', data, ['profession', 'codeCSP'])
         self.add_text_value('Organ', data, ['CAFInfo', 'organ'])
         for indicator in data['indicatorList']:
             self.add_text_value_to_rl_indicator(indicator)
         for quotient in data['quotientList']:
             self.add_text_value('Quotient', quotient, ['cdquo'])
-
-        # sort indicators
-        if data['indicatorList']:
-            data['indicatorList'].sort(key=lambda x: x['code'])
+        self.add_indicators_field('RLIndicator', data)
 
     def add_text_value_to_family(self, data):
         self.add_text_value('Category', data, ['category'])
         self.add_text_value('Situation', data, ['situation'])
         for rlg in 'RL1', 'RL2':
             if data.get(rlg):
                 self.add_text_value_to_rl(data[rlg])
         for child in data['childList']:
diff --git a/tests/test_toulouse_maelis.py b/tests/test_toulouse_maelis.py
index 41a2dbeb..29872a6b 100644
--- a/tests/test_toulouse_maelis.py
+++ b/tests/test_toulouse_maelis.py
@@ -806,16 +806,18 @@ def test_read_family(family_service, xml, con, app):
         'quotientList': [],
         'indicatorList': [],
         'childErrorList': [],
         'category_text': 'BIPARENTALE',
         'situation_text': 'Marié (e)',
     }
     data = resp.json['data']['RL1']
     del data['profession']
+    del data['indicatorList']
+    del data['indicators']
     assert data == {
         'num': '613878',
         'lastname': 'DOE',
         'firstname': 'JHON',
         'maidenName': None,
         'quality': 'PERE',
         'civility': 'M.',
         'birth': {
@@ -840,32 +842,16 @@ def test_read_family(family_service, xml, con, app):
             'mail': 'djhon@example.org',
             'isContactMail': True,
             'isContactSms': True,
             'isInvoicePdf': True,
         },
         'CAFInfo': None,
         'civility_text': 'Monsieur',
         'quality_text': 'PERE',
-        'indicatorList': [
-            {
-                'choice': None,
-                'code': 'AVL',
-                'code_text': 'Auxiliaire de Vie loisirs',
-                'label': 'Auxiliaire de Vie loisirs',
-                'note': None,
-            },
-            {
-                'choice': None,
-                'code': 'ETABSPEC',
-                'code_text': 'Etablissement spécialisé',
-                'label': 'Etablissement spécialisé',
-                'note': 'SNPP',
-            },
-        ],
         'quotientList': [
             {
                 'cdquo': 'QS',
                 'cdquo_text': 'QUOTIENT SCOLAIRE',
                 'codeUti': None,
                 'dateEnd': '2021-12-31T00:00:00+01:00',
                 'dateStart': '2021-01-01T00:00:00+01:00',
                 'mtt': 1500.33,
@@ -878,21 +864,72 @@ def test_read_family(family_service, xml, con, app):
                 'dateEnd': '2022-12-31T00:00:00+01:00',
                 'dateStart': '2022-01-01T00:00:00+01:00',
                 'mtt': 1500.44,
                 'yearRev': 2021,
             },
         ],
         'subscribeActivityList': [],
     }
+    assert sorted(resp.json['data']['RL1']['indicatorList'], key=lambda x: x['code']) == [
+        {
+            'choice': None,
+            'code': 'AVL',
+            'code_text': 'Auxiliaire de Vie loisirs',
+            'label': 'Auxiliaire de Vie loisirs',
+            'note': None,
+        },
+        {
+            'choice': None,
+            'code': 'ETABSPEC',
+            'code_text': 'Etablissement spécialisé',
+            'label': 'Etablissement spécialisé',
+            'note': 'SNPP',
+        },
+    ]
+    assert resp.json['data']['RL1']['indicators'] == {
+        'AVL': {
+            'code': 'AVL',
+            'id': 'AVL',
+            'isActive': True,
+            'label': 'Auxiliaire de Vie loisirs',
+            'text': 'Auxiliaire de Vie loisirs',
+            'typeDesc': 'NONE',
+        },
+        'AVS': {
+            'code': 'AVS',
+            'id': 'AVS',
+            'isActive': False,
+            'label': 'Auxiliaire de Vie scolaire ',
+            'text': 'Auxiliaire de Vie scolaire',
+            'typeDesc': 'NONE',
+        },
+        'ETABSPEC': {
+            'code': 'ETABSPEC',
+            'id': 'ETABSPEC',
+            'isActive': True,
+            'label': 'Etablissement spécialisé',
+            'text': 'Etablissement spécialisé',
+            'typeDesc': 'NOTE',
+        },
+        'MDPH': {
+            'code': 'MDPH',
+            'id': 'MDPH',
+            'isActive': False,
+            'label': 'Notification MDPH',
+            'text': 'Notification MDPH',
+            'typeDesc': 'NONE',
+        },
+    }
     data = resp.json['data']['childList'][0]
     del data['medicalRecord']
     del data['authorizedPersonList']
     del data['paiInfoBean']
     del data['indicatorList']
+    del data['indicators']
     assert data == {
         'num': '613880',
         'lastname': 'DOE',
         'firstname': 'JANNIS',
         'sexe': 'F',
         'sexe_text': 'Féminin',
         'birth': {
             'dateBirth': '1943-01-19T00:00:00+01:00',
@@ -983,26 +1020,29 @@ def test_read_family(family_service, xml, con, app):
             'contact': {'phone': '0123456789', 'mobile': '0623456789', 'mail': 'abent@example.org'},
         },
         'personQuality': {
             'code': 'T',
             'code_text': 'TANTE',
             'libelle': 'TANTE',
         },
     }
-    assert resp.json['data']['childList'][0]['indicatorList'] == [
+    assert sorted(resp.json['data']['childList'][0]['indicatorList'], key=lambda x: x['code']) == [
         {'choice': None, 'code': 'AUTRE', 'code_text': 'Autre', 'label': 'Autre', 'note': 'rebellious'},
         {
             'choice': None,
             'code': 'LUNETTE',
             'code_text': 'Port de lunettes',
             'label': 'Port de lunettes',
             'note': None,
         },
     ]
+    indicators = resp.json['data']['childList'][0]['indicators']
+    assert len(indicators) == 8
+    assert len([x for x in indicators.values() if x['isActive']]) == 2
 
 
 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'
@@ -1087,16 +1127,50 @@ def test_read_rl2(family_service, con, app):
             'number': '789',
             'organ': 'A10007752822',
             'organ_text': 'LA COLLE SUR LOUP',
         },
         'civility_text': 'Madame',
         'quality_text': 'MERE',
         'quotientList': [],
         'indicatorList': [],
+        'indicators': {
+            'AVL': {
+                'code': 'AVL',
+                'id': 'AVL',
+                'isActive': False,
+                'label': 'Auxiliaire de Vie loisirs',
+                'text': 'Auxiliaire de Vie loisirs',
+                'typeDesc': 'NONE',
+            },
+            'AVS': {
+                'code': 'AVS',
+                'id': 'AVS',
+                'isActive': False,
+                'label': 'Auxiliaire de Vie scolaire ',
+                'text': 'Auxiliaire de Vie scolaire',
+                'typeDesc': 'NONE',
+            },
+            'ETABSPEC': {
+                'code': 'ETABSPEC',
+                'id': 'ETABSPEC',
+                'isActive': False,
+                'label': 'Etablissement spécialisé',
+                'text': 'Etablissement spécialisé',
+                'typeDesc': 'NOTE',
+            },
+            'MDPH': {
+                'code': 'MDPH',
+                'id': 'MDPH',
+                'isActive': False,
+                'label': 'Notification MDPH',
+                'text': 'Notification MDPH',
+                'typeDesc': 'NONE',
+            },
+        },
         'subscribeActivityList': [],
     }
 
 
 def test_read_rl_not_linked_error(con, app):
     url = get_endpoint('read-rl')
 
     resp = app.get(url + '?NameID=local&rl_id=613879')
-- 
2.30.2

