From 440f844f5abeef4c7d615fbc0d57cf1dea2b1b52 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Mon, 13 Jan 2020 15:12:48 +0100
Subject: [PATCH 5/5] toulouse_axel: pre_process the payload, before schema
 validation (#38543)

because w.c.s. always sends all fields, event if all the structure is
empty.
example: all children will always be present in the payload, even if
maj:enfant_n flags are set to False
---
 passerelle/contrib/toulouse_axel/models.py |  90 ++++++++------
 passerelle/views.py                        |   3 +
 tests/test_toulouse_axel.py                | 136 ++++++++-------------
 3 files changed, 108 insertions(+), 121 deletions(-)

diff --git a/passerelle/contrib/toulouse_axel/models.py b/passerelle/contrib/toulouse_axel/models.py
index e6d0d147..915e5648 100644
--- a/passerelle/contrib/toulouse_axel/models.py
+++ b/passerelle/contrib/toulouse_axel/models.py
@@ -508,11 +508,11 @@ class ToulouseAxel(BaseResource):
 
         raise APIError('Child not found', err_code='not-found')
 
-    def sanitize_update_family_data(self, name_id, post_data):
-        family_data = None
+    def pre_sanitize_update_family_data(self, post_data):
+        # before json payload validation, check maj fields and remove empty blocks
 
         # transform ENFANT list to dict, where the key is the field IDPERSONNE
-        # because children in post_date are maybe not in the same order than on Axel side
+        # because children in post_data are maybe not in the same order than on Axel side
         children = {}
         children_by_index = {}
         for i, child in enumerate(post_data.get('ENFANT', [])):
@@ -525,7 +525,7 @@ class ToulouseAxel(BaseResource):
         # sanitize post_data
         flags = sorted(self.UPDATE_FAMILY_FLAGS.keys())
         for flag in flags:
-            flag_value = post_data.pop(flag)
+            flag_value = post_data.get(flag)
             flag_value = encode_bool(flag_value)
 
             # no update for the related block
@@ -567,44 +567,61 @@ class ToulouseAxel(BaseResource):
                 for k in data[element_to_remove].keys():
                     data[element_to_remove][k] = None
             elif element_to_remove == 'HANDICAP':
-                # get the correct child
-                child_data = post_data['ENFANT'][elements[1]]
-                child_id = child_data['IDPERSONNE']
-                # get family info
-                if family_data is None:
-                    family_data = self.get_family_data(name_id)
-                for child in family_data['ENFANT']:
-                    # find the correct child in family info
-                    if child['IDPERSONNE'] != child_id:
-                        continue
-                    # reset handicap related fields
-                    handicap_fields = [
-                        'AUTREDIFFICULTE',
-                        'ECOLESPECIALISEE',
-                        'INDICATEURAUXILIAIREVS',
-                        'INDICATEURECOLE',
-                        'INDICATEURHANDICAP',
-                        'INDICATEURNOTIFMDPH',
-                    ]
-                    for key in handicap_fields:
-                        child_data['SANITAIRE']['HANDICAP'][key] = child['SANITAIRE'][key]
-                    break
+                # will be filled in sanitize_update_family_data
+                data[element_to_remove]['_to_reset'] = True
             elif element_to_remove in data:
                 # remove block
                 data.pop(element_to_remove)
 
-        # transform HANDICAP block
-        for child in post_data['ENFANT'].values():
+        # transform ENFANT dict to a list back
+        post_data['ENFANT'] = post_data['ENFANT'].values()
+
+        # if ENFANT block is empty, remove it
+        if not post_data['ENFANT']:
+            post_data.pop('ENFANT')
+
+    UPDATE_FAMILY_SCHEMA['pre_process'] = pre_sanitize_update_family_data
+
+    def sanitize_update_family_data(self, name_id, post_data):
+        family_data = None
+
+        for i, child_data in enumerate(post_data.get('ENFANT', [])):
+            child_id = child_data['IDPERSONNE']
+            # check if HANDICAP fields are to be filled
+            if 'SANITAIRE' not in child_data:
+                continue
+            if child_data['SANITAIRE']['HANDICAP'].get('_to_reset') is not True:
+                continue
+            # get family info
+            if family_data is None:
+                family_data = self.get_family_data(name_id)
+            for orig_child in family_data['ENFANT']:
+                # find the correct child in family info
+                if orig_child['IDPERSONNE'] != child_id:
+                    continue
+                # reset handicap related fields
+                handicap_fields = [
+                    'AUTREDIFFICULTE',
+                    'ECOLESPECIALISEE',
+                    'INDICATEURAUXILIAIREVS',
+                    'INDICATEURECOLE',
+                    'INDICATEURHANDICAP',
+                    'INDICATEURNOTIFMDPH',
+                ]
+                for key in handicap_fields:
+                    child_data['SANITAIRE']['HANDICAP'][key] = orig_child['SANITAIRE'][key]
+
+        for child in post_data.get('ENFANT', []):
             if 'SANITAIRE' not in child:
                 continue
+
+            # transform HANDICAP block
             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
+
+            # transform ALLERGIE block
             new_allergie = []
             for key in ['ASTHME', 'MEDICAMENTEUSES', 'ALIMENTAIRES']:
                 new_allergie.append({
@@ -637,12 +654,9 @@ class ToulouseAxel(BaseResource):
                 family_data = self.get_family_data(name_id)
             post_data['REVENUS']['NBENFANTSACHARGE'] = family_data.get('REVENUS', {}).get('NBENFANTSACHARGE')
 
-        # transform ENFANT dict to a list back
-        post_data['ENFANT'] = post_data['ENFANT'].values()
-
-        # if ENFANT block is empty, remove it
-        if not post_data['ENFANT']:
-            post_data.pop('ENFANT')
+        # remove flags
+        for flag in self.UPDATE_FAMILY_FLAGS.keys():
+            post_data.pop(flag)
 
     @endpoint(
         description=_("Update information about user's family"),
diff --git a/passerelle/views.py b/passerelle/views.py
index a82f219e..09ef94a9 100644
--- a/passerelle/views.py
+++ b/passerelle/views.py
@@ -348,6 +348,7 @@ class GenericEndpointView(GenericConnectorMixin, SingleObjectMixin, View):
                 json_schema = request_body['schema']['application/json']
                 must_unflatten = hasattr(json_schema, 'items') and json_schema.get('unflatten', False)
                 merge_extra = hasattr(json_schema, 'items') and json_schema.get('merge_extra', False)
+                pre_process = hasattr(json_schema, 'items') and json_schema.get('pre_process')
                 try:
                     data = json.loads(request.body)
                 except ValueError as e:
@@ -356,6 +357,8 @@ class GenericEndpointView(GenericConnectorMixin, SingleObjectMixin, View):
                     data = unflatten(data)
                 if merge_extra and hasattr(data, 'items'):
                     data.update(data.pop('extra', {}))
+                if pre_process is not None:
+                    pre_process(self.endpoint.im_self, data)
                 try:
                     validate(data, json_schema)
                 except ValidationError as e:
diff --git a/tests/test_toulouse_axel.py b/tests/test_toulouse_axel.py
index a263c33c..035eb5c2 100644
--- a/tests/test_toulouse_axel.py
+++ b/tests/test_toulouse_axel.py
@@ -687,7 +687,7 @@ def test_sanitize_update_family_data_missing_revenus_fields(app, resource, updat
     assert full_update_params['REVENUS']['NBENFANTSACHARGE'] is None
 
 
-def test_sanitize_update_family_data_adresse(app, resource, update_params, family_data):
+def test_pre_sanitize_update_family_data_adresse(app, resource, update_params):
     Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
 
     # test maj:adresse
@@ -695,13 +695,12 @@ def test_sanitize_update_family_data_adresse(app, resource, update_params, famil
     partial_update_params['maj:adresse'] = False
     for key in partial_update_params['ADRESSE'].keys():
         partial_update_params['ADRESSE'][key] = None  # reset fields
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     for value in partial_update_params['ADRESSE'].values():
         assert value is None
 
 
-def test_sanitize_update_family_data_revenus(app, resource, update_params, family_data):
+def test_pre_sanitize_update_family_data_revenus(app, resource, update_params):
     Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
 
     # test maj:revenus
@@ -709,12 +708,11 @@ def test_sanitize_update_family_data_revenus(app, resource, update_params, famil
     partial_update_params['maj:revenus'] = False
     for key in partial_update_params['REVENUS'].keys():
         partial_update_params['REVENUS'][key] = None  # reset fields
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert 'REVENUS' not in partial_update_params
 
 
-def test_sanitize_update_family_data_rln(app, resource, update_params, family_data):
+def test_pre_sanitize_update_family_data_rln(app, resource, update_params):
     Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
 
     # test maj:rln
@@ -722,19 +720,17 @@ def test_sanitize_update_family_data_rln(app, resource, update_params, family_da
     partial_update_params['maj:rl1'] = False
     for key in partial_update_params['RL1'].keys():
         partial_update_params['RL1'][key] = None  # reset fields
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert 'RL1' not in partial_update_params
     partial_update_params = copy.deepcopy(update_params)
     partial_update_params['maj:rl2'] = False
     for key in partial_update_params['RL2'].keys():
         partial_update_params['RL2'][key] = None  # reset fields
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert 'RL2' not in partial_update_params
 
 
-def test_sanitize_update_family_data_rln_adresse_employeur(app, resource, update_params, family_data):
+def test_pre_sanitize_update_family_data_rln_adresse_employeur(app, resource, update_params):
     Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
 
     # test maj:rln_adresse_employeur
@@ -742,45 +738,39 @@ def test_sanitize_update_family_data_rln_adresse_employeur(app, resource, update
     partial_update_params['maj:rl1_adresse_employeur'] = False
     for key in partial_update_params['RL1']['ADREMPLOYEUR'].keys():
         partial_update_params['RL1']['ADREMPLOYEUR'][key] = None  # reset fields
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert 'ADREMPLOYEUR' not in partial_update_params['RL1']
     partial_update_params = copy.deepcopy(update_params)
     partial_update_params['maj:rl2_adresse_employeur'] = False
     for key in partial_update_params['RL2']['ADREMPLOYEUR'].keys():
         partial_update_params['RL2']['ADREMPLOYEUR'][key] = None  # reset fields
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert 'ADREMPLOYEUR' not in partial_update_params['RL2']
     # combine with maj:rln
     partial_update_params = copy.deepcopy(update_params)
     partial_update_params['maj:rl1'] = False
     partial_update_params['maj:rl1_adresse_employeur'] = False
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert 'RL1' not in partial_update_params
     partial_update_params = copy.deepcopy(update_params)
     partial_update_params['maj:rl2'] = False
     partial_update_params['maj:rl2_adresse_employeur'] = False
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert 'RL2' not in partial_update_params
 
     # test maj:rln_adresse_employeur not set
     for val in [None, '']:
         partial_update_params = copy.deepcopy(update_params)
         partial_update_params['maj:rl1_adresse_employeur'] = val
-        with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-            resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+        resource.pre_sanitize_update_family_data(post_data=partial_update_params)
         assert 'ADREMPLOYEUR' not in partial_update_params['RL1']
         partial_update_params = copy.deepcopy(update_params)
         partial_update_params['maj:rl2_adresse_employeur'] = val
-        with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-            resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+        resource.pre_sanitize_update_family_data(post_data=partial_update_params)
         assert 'ADREMPLOYEUR' not in partial_update_params['RL2']
 
 
-def test_sanitize_update_family_data_enfant_n(app, resource, update_params, family_data):
+def test_pre_sanitize_update_family_data_enfant_n(app, resource, update_params):
     Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
 
     # test maj:enfant_n
@@ -790,8 +780,7 @@ def test_sanitize_update_family_data_enfant_n(app, resource, update_params, fami
         if key == 'IDPERSONNE':
             continue
         partial_update_params['ENFANT'][0][key] = None  # reset fields
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert len(partial_update_params['ENFANT']) == 1
     assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "3535"
 
@@ -801,8 +790,7 @@ def test_sanitize_update_family_data_enfant_n(app, resource, update_params, fami
         if key == 'IDPERSONNE':
             continue
         partial_update_params['ENFANT'][1][key] = None  # reset fields
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert len(partial_update_params['ENFANT']) == 1
     assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "4242"
 
@@ -811,8 +799,7 @@ def test_sanitize_update_family_data_enfant_n(app, resource, update_params, fami
     partial_update_params['maj:enfant_1'] = False
     for key in partial_update_params['ENFANT'][1].keys():
         partial_update_params['ENFANT'][1][key] = None  # reset fields
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert len(partial_update_params['ENFANT']) == 1
     assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "4242"
 
@@ -820,19 +807,17 @@ def test_sanitize_update_family_data_enfant_n(app, resource, update_params, fami
     partial_update_params = copy.deepcopy(update_params)
     partial_update_params['maj:enfant_0'] = False
     partial_update_params['maj:enfant_1'] = False
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert 'ENFANT' not in partial_update_params
 
     # unknown child
     partial_update_params = copy.deepcopy(update_params)
     partial_update_params['maj:enfant_5'] = False
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert len(partial_update_params['ENFANT']) == 2
 
 
-def test_sanitize_update_family_data_enfant_n_assurance(app, resource, update_params, family_data):
+def test_pre_sanitize_update_family_data_enfant_n_assurance(app, resource, update_params):
     Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
 
     # test maj:enfant_n_assurance
@@ -841,8 +826,7 @@ def test_sanitize_update_family_data_enfant_n_assurance(app, resource, update_pa
     for key in partial_update_params['ENFANT'][1]['ASSURANCE'].keys():
         partial_update_params['ENFANT'][1]['ASSURANCE'][key] = None  # reset fields
     partial_update_params['maj:enfant_0'] = False  # check that ordering is not a problem
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert len(partial_update_params['ENFANT']) == 1
     assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "3535"
     assert 'ASSURANCE' not in partial_update_params['ENFANT'][0]
@@ -851,8 +835,7 @@ def test_sanitize_update_family_data_enfant_n_assurance(app, resource, update_pa
     partial_update_params['maj:enfant_1'] = False
     partial_update_params['maj:enfant_1_assurance'] = False
     partial_update_params['maj:enfant_0'] = False
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert 'ENFANT' not in partial_update_params
 
     # test maj:enfant_n_assurance not set
@@ -860,12 +843,11 @@ def test_sanitize_update_family_data_enfant_n_assurance(app, resource, update_pa
         partial_update_params = copy.deepcopy(update_params)
         partial_update_params['maj:enfant_1_assurance'] = val
         partial_update_params['maj:enfant_0'] = False
-        with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-            resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+        resource.pre_sanitize_update_family_data(post_data=partial_update_params)
         assert 'ASSURANCE' not in partial_update_params['ENFANT'][0]
 
 
-def test_sanitize_update_family_data_enfant_n_contact(app, resource, update_params, family_data):
+def test_pre_sanitize_update_family_data_enfant_n_contact(app, resource, update_params):
     Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
 
     # test maj:enfant_n_contact
@@ -875,8 +857,7 @@ def test_sanitize_update_family_data_enfant_n_contact(app, resource, update_para
         for key in contact.keys():
             partial_update_params['ENFANT'][0]['CONTACT'][i][key] = None  # reset fields
     partial_update_params['maj:enfant_1'] = False
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert len(partial_update_params['ENFANT']) == 1
     assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "4242"
     assert 'CONTACT' not in partial_update_params['ENFANT'][0]
@@ -885,8 +866,7 @@ def test_sanitize_update_family_data_enfant_n_contact(app, resource, update_para
     partial_update_params['maj:enfant_1'] = False
     partial_update_params['maj:enfant_1_contact'] = False
     partial_update_params['maj:enfant_0'] = False
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert 'ENFANT' not in partial_update_params
 
     # test maj:enfant_n_contact not set
@@ -894,12 +874,11 @@ def test_sanitize_update_family_data_enfant_n_contact(app, resource, update_para
         partial_update_params = copy.deepcopy(update_params)
         partial_update_params['maj:enfant_0_contact'] = val
         partial_update_params['maj:enfant_1'] = False
-        with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-            resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+        resource.pre_sanitize_update_family_data(post_data=partial_update_params)
         assert 'CONTACT' not in partial_update_params['ENFANT'][0]
 
 
-def test_sanitize_update_family_data_enfant_n_sanitaire(app, resource, update_params, family_data):
+def test_pre_sanitize_update_family_data_enfant_n_sanitaire(app, resource, update_params):
     Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
 
     # test maj:enfant_n_sanitaire
@@ -908,8 +887,7 @@ def test_sanitize_update_family_data_enfant_n_sanitaire(app, resource, update_pa
     for key in partial_update_params['ENFANT'][1]['SANITAIRE'].keys():
         partial_update_params['ENFANT'][1]['SANITAIRE'][key] = None  # reset fields
     partial_update_params['maj:enfant_0'] = False
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert len(partial_update_params['ENFANT']) == 1
     assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "3535"
     assert 'SANITAIRE' not in partial_update_params['ENFANT'][0]
@@ -918,8 +896,7 @@ def test_sanitize_update_family_data_enfant_n_sanitaire(app, resource, update_pa
     partial_update_params['maj:enfant_1'] = False
     partial_update_params['maj:enfant_1_sanitaire'] = False
     partial_update_params['maj:enfant_0'] = False
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert 'ENFANT' not in partial_update_params
 
     # test maj:enfant_n_sanitaire not set
@@ -927,13 +904,12 @@ def test_sanitize_update_family_data_enfant_n_sanitaire(app, resource, update_pa
         partial_update_params = copy.deepcopy(update_params)
         partial_update_params['maj:enfant_0_sanitaire'] = val
         partial_update_params['maj:enfant_1_sanitaire'] = val
-        with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-            resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+        resource.pre_sanitize_update_family_data(post_data=partial_update_params)
         assert 'SANITAIRE' not in partial_update_params['ENFANT'][0]
         assert 'SANITAIRE' not in partial_update_params['ENFANT'][1]
 
 
-def test_sanitize_update_family_data_enfant_n_sanitaire_allergie(app, resource, update_params, family_data):
+def test_pre_sanitize_update_family_data_enfant_n_sanitaire_allergie(app, resource, update_params):
     Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
 
     # test maj:enfant_n_sanitaire_allergie
@@ -942,8 +918,7 @@ def test_sanitize_update_family_data_enfant_n_sanitaire_allergie(app, resource,
     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
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert len(partial_update_params['ENFANT']) == 1
     assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "3535"
     assert 'ALLERGIE' not in partial_update_params['ENFANT'][0]['SANITAIRE']
@@ -952,8 +927,7 @@ def test_sanitize_update_family_data_enfant_n_sanitaire_allergie(app, resource,
     partial_update_params['maj:enfant_1_sanitaire'] = False
     partial_update_params['maj:enfant_1_sanitaire_allergie'] = False
     partial_update_params['maj:enfant_0'] = False
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert len(partial_update_params['ENFANT']) == 1
     assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "3535"
     assert 'SANITAIRE' not in partial_update_params['ENFANT'][0]
@@ -962,8 +936,7 @@ def test_sanitize_update_family_data_enfant_n_sanitaire_allergie(app, resource,
     partial_update_params['maj:enfant_1'] = False
     partial_update_params['maj:enfant_1_sanitaire_allergie'] = False
     partial_update_params['maj:enfant_0'] = False
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert 'ENFANT' not in partial_update_params
 
     # test maj:enfant_n_sanitaire_allergie not set
@@ -971,11 +944,12 @@ def test_sanitize_update_family_data_enfant_n_sanitaire_allergie(app, resource,
         partial_update_params = copy.deepcopy(update_params)
         partial_update_params['maj:enfant_0_sanitaire_allergie'] = val
         partial_update_params['maj:enfant_1_sanitaire_allergie'] = val
-        with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-            resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+        resource.pre_sanitize_update_family_data(post_data=partial_update_params)
         assert 'ALLERGIE' not in partial_update_params['ENFANT'][0]['SANITAIRE']
         assert 'ALLERGIE' not in partial_update_params['ENFANT'][1]['SANITAIRE']
 
+
+def test_sanitize_update_family_data_enfant_n_sanitaire_allergie(app, resource, update_params, family_data):
     # check values
     partial_update_params = copy.deepcopy(update_params)
     partial_update_params['maj:enfant_1'] = False
@@ -1007,7 +981,7 @@ def test_sanitize_update_family_data_enfant_n_sanitaire_allergie(app, resource,
     ]
 
 
-def test_sanitize_update_family_data_enfant_n_sanitaire_medecin(app, resource, update_params, family_data):
+def test_pre_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')
 
     # test maj:enfant_n_sanitaire_medecin
@@ -1016,8 +990,7 @@ def test_sanitize_update_family_data_enfant_n_sanitaire_medecin(app, resource, u
     for key in partial_update_params['ENFANT'][1]['SANITAIRE']['MEDECIN'].keys():
         partial_update_params['ENFANT'][1]['SANITAIRE']['MEDECIN'][key] = None  # reset fields
     partial_update_params['maj:enfant_0'] = False
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert len(partial_update_params['ENFANT']) == 1
     assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "3535"
     assert 'MEDECIN' not in partial_update_params['ENFANT'][0]['SANITAIRE']
@@ -1026,8 +999,7 @@ def test_sanitize_update_family_data_enfant_n_sanitaire_medecin(app, resource, u
     partial_update_params['maj:enfant_1_sanitaire'] = False
     partial_update_params['maj:enfant_1_sanitaire_medecin'] = False
     partial_update_params['maj:enfant_0'] = False
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert len(partial_update_params['ENFANT']) == 1
     assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "3535"
     assert 'SANITAIRE' not in partial_update_params['ENFANT'][0]
@@ -1036,8 +1008,7 @@ def test_sanitize_update_family_data_enfant_n_sanitaire_medecin(app, resource, u
     partial_update_params['maj:enfant_1'] = False
     partial_update_params['maj:enfant_1_sanitaire_medecin'] = False
     partial_update_params['maj:enfant_0'] = False
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert 'ENFANT' not in partial_update_params
 
     # test maj:enfant_n_sanitaire_medecin not set
@@ -1045,13 +1016,12 @@ def test_sanitize_update_family_data_enfant_n_sanitaire_medecin(app, resource, u
         partial_update_params = copy.deepcopy(update_params)
         partial_update_params['maj:enfant_0_sanitaire_medecin'] = val
         partial_update_params['maj:enfant_1_sanitaire_medecin'] = val
-        with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-            resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+        resource.pre_sanitize_update_family_data(post_data=partial_update_params)
         assert 'MEDECIN' not in partial_update_params['ENFANT'][0]['SANITAIRE']
         assert 'MEDECIN' not in partial_update_params['ENFANT'][1]['SANITAIRE']
 
 
-def test_sanitize_update_family_data_enfant_n_sanitaire_vaccin(app, resource, update_params, family_data):
+def test_pre_sanitize_update_family_data_enfant_n_sanitaire_vaccin(app, resource, update_params):
     Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
 
     # test maj:enfant_n_sanitaire_vaccin
@@ -1060,8 +1030,7 @@ def test_sanitize_update_family_data_enfant_n_sanitaire_vaccin(app, resource, up
     for key in partial_update_params['ENFANT'][1]['SANITAIRE']['VACCIN'].keys():
         partial_update_params['ENFANT'][1]['SANITAIRE']['VACCIN'][key] = None  # reset fields
     partial_update_params['maj:enfant_0'] = False
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert len(partial_update_params['ENFANT']) == 1
     assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "3535"
     assert 'VACCIN' not in partial_update_params['ENFANT'][0]['SANITAIRE']
@@ -1070,8 +1039,7 @@ def test_sanitize_update_family_data_enfant_n_sanitaire_vaccin(app, resource, up
     partial_update_params['maj:enfant_1_sanitaire'] = False
     partial_update_params['maj:enfant_1_sanitaire_vaccin'] = False
     partial_update_params['maj:enfant_0'] = False
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert len(partial_update_params['ENFANT']) == 1
     assert partial_update_params['ENFANT'][0]['IDPERSONNE'] == "3535"
     assert 'SANITAIRE' not in partial_update_params['ENFANT'][0]
@@ -1080,8 +1048,7 @@ def test_sanitize_update_family_data_enfant_n_sanitaire_vaccin(app, resource, up
     partial_update_params['maj:enfant_1'] = False
     partial_update_params['maj:enfant_1_sanitaire_vaccin'] = False
     partial_update_params['maj:enfant_0'] = False
-    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-        resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     assert 'ENFANT' not in partial_update_params
 
     # test maj:enfant_n_sanitaire_vaccin not set
@@ -1089,8 +1056,7 @@ def test_sanitize_update_family_data_enfant_n_sanitaire_vaccin(app, resource, up
         partial_update_params = copy.deepcopy(update_params)
         partial_update_params['maj:enfant_0_sanitaire_vaccin'] = val
         partial_update_params['maj:enfant_1_sanitaire_vaccin'] = val
-        with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
-            resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
+        resource.pre_sanitize_update_family_data(post_data=partial_update_params)
         assert 'VACCIN' not in partial_update_params['ENFANT'][0]['SANITAIRE']
         assert 'VACCIN' not in partial_update_params['ENFANT'][1]['SANITAIRE']
 
@@ -1113,6 +1079,7 @@ def test_sanitize_update_family_data_enfant_n_sanitaire_handicap(app, resource,
     for key in handicap_fields:
         partial_update_params['ENFANT'][0]['SANITAIRE']['HANDICAP'][key] = None
     partial_update_params['maj:enfant_1'] = False
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
         resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
     assert len(partial_update_params['ENFANT']) == 1
@@ -1126,6 +1093,7 @@ def test_sanitize_update_family_data_enfant_n_sanitaire_handicap(app, resource,
     partial_update_params['maj:enfant_1_sanitaire'] = False
     partial_update_params['maj:enfant_1_sanitaire_handicap'] = False
     partial_update_params['maj:enfant_0'] = False
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
         resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
     assert len(partial_update_params['ENFANT']) == 1
@@ -1136,6 +1104,7 @@ def test_sanitize_update_family_data_enfant_n_sanitaire_handicap(app, resource,
     partial_update_params['maj:enfant_1'] = False
     partial_update_params['maj:enfant_1_sanitaire_sanitaire'] = False
     partial_update_params['maj:enfant_0'] = False
+    resource.pre_sanitize_update_family_data(post_data=partial_update_params)
     with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
         resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
     assert 'ENFANT' not in partial_update_params
@@ -1148,6 +1117,7 @@ def test_sanitize_update_family_data_enfant_n_sanitaire_handicap(app, resource,
         # reset fields
         for key in handicap_fields:
             partial_update_params['ENFANT'][0]['SANITAIRE']['HANDICAP'][key] = None
+        resource.pre_sanitize_update_family_data(post_data=partial_update_params)
         with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data):
             resource.sanitize_update_family_data(name_id='yyy', post_data=partial_update_params)
         new_values = partial_update_params['ENFANT'][0]['SANITAIRE']
-- 
2.20.1

