From 8535200811fc6eadc0ca6e446328519342a9a528 Mon Sep 17 00:00:00 2001
From: Nicolas ROCHE <nroche@entrouvert.com>
Date: Tue, 13 Dec 2022 16:40:27 +0100
Subject: [PATCH 1/3] toulouse-maelis: move family schemas (#72288)

---
 .../contrib/toulouse_maelis/family_schemas.py | 719 ++++++++++++++++++
 passerelle/contrib/toulouse_maelis/models.py  |  42 +-
 passerelle/contrib/toulouse_maelis/schemas.py | 702 -----------------
 3 files changed, 740 insertions(+), 723 deletions(-)
 create mode 100644 passerelle/contrib/toulouse_maelis/family_schemas.py

diff --git a/passerelle/contrib/toulouse_maelis/family_schemas.py b/passerelle/contrib/toulouse_maelis/family_schemas.py
new file mode 100644
index 00000000..a43ff695
--- /dev/null
+++ b/passerelle/contrib/toulouse_maelis/family_schemas.py
@@ -0,0 +1,719 @@
+# Copyright (C) 2022 Entr'ouvert
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# 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/>.
+
+import copy
+
+from . import schemas
+
+ISEXISTS_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-04/schema#',
+    'title': 'Exist',
+    'description': "Recherche d'un responsable légal ou d'un enfant dans Maelis",
+    'type': 'object',
+    'required': ['firstname', 'lastname', 'dateBirth'],
+    'properties': schemas.BASIC_ID_PROPERTIES,
+    'additionalProperties': False,
+}
+
+
+CONTACTLIGHT_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-04/schema#',
+    'title': 'Contact light',
+    'description': "Informations de contact pour les personnes autorisées à récupérer les enfants ou à prévenir en cas d'urgence",
+    'type': 'object',
+    'properties': {
+        'phone': {
+            'description': 'Téléphone',
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'mobile': {
+            'description': 'Portable',
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'mail': {
+            'description': 'Mail',
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+    },
+}
+
+
+PERSON_PROPERTIES = {
+    'civility': {
+        'description': 'civilité (depuis référentiel)',
+        'oneOf': [{'type': 'string'}, {'type': 'null'}],
+    },
+    'sexe': {
+        'description': 'Sexe (depuis référentiel)',
+        'oneOf': [{'type': 'string'}, {'type': 'null'}],
+    },
+    'contact': {'oneOf': [CONTACTLIGHT_SCHEMA, {'type': 'null'}]},
+}
+PERSON_PROPERTIES.update(schemas.BASIC_ID_PROPERTIES)
+
+
+EMERGENCY_PERSON_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-04/schema#',
+    'title': 'Emergency person',
+    'description': "Personnes à prévenir en cas d'urgence",
+    'type': 'object',
+    'required': ['firstname', 'lastname', 'dateBirth', 'quality'],
+    'properties': {
+        'quality': {
+            'description': 'Qualité',
+            'type': 'string',
+            'pattern': '.+',
+        },
+    },
+    'unflatten': True,
+    'additionalProperties': False,
+}
+EMERGENCY_PERSON_SCHEMA['properties'].update(PERSON_PROPERTIES)
+
+
+AUTHORIZED_PERSON_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-04/schema#',
+    'title': 'Family persons',
+    'description': "Personnes autorisées à venir chercher l'enfant",
+    'type': 'object',
+    'required': ['personInfo', 'personQuality'],
+    'properties': {
+        'personInfo': {
+            'type': 'object',
+            'required': ['firstname', 'lastname', 'dateBirth'],
+            'properties': PERSON_PROPERTIES,
+        },
+        'personQuality': {
+            'type': 'object',
+            'required': ['code'],
+            'properties': {
+                'code': {
+                    'description': 'Le code (depuis référentiel)',
+                    'type': 'string',
+                    'pattern': '.+',
+                },
+            },
+        },
+    },
+    'additionalProperties': False,
+    'unflatten': True,
+}
+
+
+BIRTH_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-04/schema#',
+    'title': 'Birth info',
+    'description': "Informations relatives à la naissance",
+    'type': 'object',
+    'required': ['dateBirth'],
+    'properties': {
+        'dateBirth': {
+            'description': 'Date de naissance',
+            'type': 'string',
+            'pattern': '^[0-9]{4}-[0-9]{2}-[0-9]{2}$',
+        },
+        'place': {
+            'description': 'Lieu de naissance',
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'communeCode': {
+            'description': 'Commune de naissance (depuis référentiel)',
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'countryCode': {
+            'description': 'Pays de naissance (depuis référentiel)',
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+    },
+}
+
+INDICATOR_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-04/schema#',
+    'title': 'Address',
+    'description': 'Indicateurs',
+    'type': 'object',
+    'required': ['code', 'isActive'],
+    'properties': {
+        'code': {
+            'description': "Code de l'indicateur (depuis référentiel)",
+            'type': 'string',
+            'pattern': '.+',
+        },
+        'note': {
+            'description': "Commentaire pour les indicateurs de type NOTE",
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'isActive': {
+            'description': "True pour ajouter/modifier l'indicateur (défault) ou False pour le retirer",
+            'oneOf': schemas.BOOLEAN_TYPES,
+        },
+    },
+}
+
+ID_PROPERTIES = {
+    'firstname': {
+        'description': 'Prénom',
+        'type': 'string',
+    },
+    'lastname': {
+        'description': 'Nom',
+        'type': 'string',
+    },
+    'maidenName': {
+        'description': "Nom de jeune fille ",
+        'oneOf': [{'type': 'string'}, {'type': 'null'}],
+    },
+    'birth': BIRTH_SCHEMA,
+}
+
+ADDRESS_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-04/schema#',
+    'title': 'Address',
+    'description': 'Informations sur une adresse',
+    'type': 'object',
+    'required': ['street1', 'town', 'zipcode'],
+    'properties': {
+        'num': {
+            'description': "Numéro de l'adresse",
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'numComp': {
+            'description': 'Complément du numéro (depuis référentiel)',
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'idStreet': {
+            'description': 'Identifiant de la voie (depuis référentiel)',
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'street1': {
+            'description': 'Libellé de la voie',
+            'type': 'string',
+        },
+        'street2': {
+            'description': 'Complément de la voie',
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'town': {
+            'description': 'Ville',
+            'type': 'string',
+        },
+        'zipcode': {
+            'description': 'Code postal',
+            'type': 'string',
+        },
+    },
+}
+
+CONTACT_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-04/schema#',
+    'title': 'Contact',
+    'description': 'Informations sur le contact',
+    'type': 'object',
+    'properties': {
+        'phone': {
+            'description': 'Téléphone',
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'mobile': {
+            'description': 'Portable',
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'mail': {
+            'description': 'Mail',
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'isContactMail': {
+            'description': 'Accepte de recevoir des mails',
+            'oneOf': schemas.BOOLEAN_TYPES,
+        },
+        'isContactSms': {
+            'description': 'Accepte de recevoir des sms',
+            'oneOf': schemas.BOOLEAN_TYPES,
+        },
+        'isInvoicePdf': {
+            'description': 'Accepte de ne plus recevoir de facture papier',
+            'oneOf': schemas.BOOLEAN_TYPES,
+        },
+    },
+}
+
+ADDRESSPROF_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-04/schema#',
+    'title': 'Adresse pro',
+    'description': "Informations sur l'adresse professionnelle",
+    'type': 'object',
+    'properties': {
+        'num': {
+            'description': "Numéro de l'adresse",
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'street': {
+            'description': 'Nom de la voie',
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'town': {
+            'description': 'Ville',
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'zipcode': {
+            'description': 'Code postal',
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+    },
+}
+
+PROFESSION_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-04/schema#',
+    'title': 'Profession',
+    'description': 'Informations sur la profession',
+    'type': 'object',
+    'properties': {
+        'codeCSP': {
+            'description': 'Catégorie socio-professionnelle (depuis référentiel)',
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'profession': {
+            'description': 'Profession',
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'employerName': {
+            'description': "Nom de l'employeur",
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'phone': {
+            'description': 'Téléphone',
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'addressPro': ADDRESSPROF_SCHEMA,
+    },
+}
+
+CAFINFO_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-04/schema#',
+    'title': 'CAF',
+    'description': 'Informations sur la CAF',
+    'type': 'object',
+    'properties': {
+        'number': {
+            'description': "Numéro d'allocataire",
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'organ': {
+            'description': "Nom de l'organisme (depuis référentiel)",
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+    },
+}
+
+RLINFO_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-04/schema#',
+    'title': 'RL',
+    'description': "Informations sur le responsable légal",
+    'type': 'object',
+    'required': ['firstname', 'lastname', 'civility', 'quality', 'birth', 'adresse'],
+    'properties': {
+        'civility': {
+            'description': 'civilité (depuis référentiel)',
+            'type': 'string',
+            'pattern': '.+',
+        },
+        'quality': {
+            'description': 'Qualité (depuis référentiel)',
+            'type': 'string',
+            'pattern': '.+',
+        },
+        'adresse': ADDRESS_SCHEMA,
+        'contact': {'oneOf': [CONTACT_SCHEMA, {'type': 'null'}]},
+        'profession': {'oneOf': [PROFESSION_SCHEMA, {'type': 'null'}]},
+        'CAFInfo': {'oneOf': [CAFINFO_SCHEMA, {'type': 'null'}]},
+        'indicatorList': {
+            'oneOf': [
+                {
+                    'type': 'array',
+                    'items': INDICATOR_SCHEMA,
+                },
+                {'type': 'null'},
+            ],
+        },
+    },
+    'unflatten': True,
+    'additionalProperties': False,
+}
+RLINFO_SCHEMA['properties'].update(ID_PROPERTIES)
+
+DOCTORADDRESS_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-04/schema#',
+    'title': 'Doctor address',
+    'description': "Informations sur l'adresse du docteur",
+    'type': 'object',
+    'properties': {
+        'street1': {
+            'description': 'Libellé de la voie',
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'town': {
+            'description': 'Ville',
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'zipcode': {
+            'description': 'Code postal',
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+    },
+}
+
+FAMILYDOCTOR_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-04/schema#',
+    'title': 'Family doctor',
+    'description': "Informations sur le docteur",
+    'type': 'object',
+    'properties': {
+        'name': {
+            'description': 'Nom',
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'phone': {
+            'description': 'Téléphone',
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'address': DOCTORADDRESS_SCHEMA,
+    },
+}
+
+VACCIN_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-04/schema#',
+    'title': 'Vaccin',
+    'description': "Informations sur le vaccin",
+    'type': 'object',
+    'required': ['code', 'vaccinationDate'],
+    'properties': {
+        'code': {
+            'description': 'Code du vaccin (depuis référentiel)',
+            'type': 'string',
+        },
+        'vaccinationDate': {
+            'description': 'Date du vaccin',
+            'type': 'string',
+            'pattern': '^[0-9]{4}-[0-9]{2}-[0-9]{2}$',
+        },
+    },
+}
+
+MEDICALRECORD_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-04/schema#',
+    'title': 'Medical record',
+    'description': "Informations médicales",
+    'oneOf': [
+        {
+            'type': 'object',
+            'properties': {
+                'familyDoctor': FAMILYDOCTOR_SCHEMA,
+                'allergy1': {
+                    'description': 'Allergie 1',
+                    'oneOf': [{'type': 'string'}, {'type': 'null'}],
+                },
+                'allergy2': {
+                    'description': 'Allergie 2',
+                    'oneOf': [{'type': 'string'}, {'type': 'null'}],
+                },
+                'comment1': {
+                    'description': 'Commentaire 1',
+                    'oneOf': [{'type': 'string'}, {'type': 'null'}],
+                },
+                'comment2': {
+                    'description': 'Commentaire 2',
+                    'oneOf': [{'type': 'string'}, {'type': 'null'}],
+                },
+                'observ1': {
+                    'description': 'Observation 1',
+                    'oneOf': [{'type': 'string'}, {'type': 'null'}],
+                },
+                'observ2': {
+                    'description': 'Observation 2',
+                    'oneOf': [{'type': 'string'}, {'type': 'null'}],
+                },
+                'isAuthHospital': {
+                    'description': "Autorisation d'hospitalisation",
+                    'oneOf': schemas.BOOLEAN_TYPES,
+                },
+                'hospital': {
+                    'description': 'Hopital',
+                    'oneOf': [{'type': 'string'}, {'type': 'null'}],
+                },
+                'vaccinList': {
+                    'oneOf': [
+                        {
+                            'type': 'array',
+                            'items': VACCIN_SCHEMA,
+                        },
+                        {'type': 'null'},
+                    ],
+                },
+            },
+            'additionalProperties': False,
+        },
+        {'type': 'null'},
+    ],
+    'unflatten': True,
+}
+
+PAIINFO_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-04/schema#',
+    'title': 'PAI',
+    'description': "Informations médicales",
+    'type': 'object',
+    'required': ['code'],
+    'properties': {
+        'code': {
+            'description': 'Code (depuis référentiel)',
+            'type': 'string',
+            'pattern': '.+',
+        },
+        'dateDeb': {
+            'description': 'Date de début',
+            'type': 'string',
+            'pattern': '^([0-9]{4}-[0-9]{2}-[0-9]{2}){0,1}$',
+        },
+        'dateFin': {
+            'description': 'Date de fin',
+            'type': 'string',
+            'pattern': '^([0-9]{4}-[0-9]{2}-[0-9]{2}){0,1}$',
+        },
+        'description': {
+            'description': 'Texte libre de description (max 500 caractères)',
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+    },
+    'additionalProperties': False,
+}
+
+CHILD_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-04/schema#',
+    'title': 'Child',
+    'description': "Informations sur la création d'un enfant",
+    'type': 'object',
+    'required': ['sexe', 'firstname', 'lastname', 'birth'],
+    'properties': {
+        'num': {
+            'description': "Numéro de l'enfant",
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'sexe': {
+            'description': 'Sexe (depuis référentiel)',
+            'type': 'string',
+            'pattern': '.+',
+        },
+        'birth': BIRTH_SCHEMA,
+        'dietcode': {
+            'description': 'Code de régime alimentaire (depuis référentiel)',
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'bPhoto': {
+            'description': 'Autorisation photo',
+            'oneOf': schemas.BOOLEAN_TYPES,
+        },
+        'bLeaveAlone': {
+            'description': 'Autorisation à partir seul',
+            'oneOf': schemas.BOOLEAN_TYPES,
+        },
+        'medicalRecord': {'oneOf': [MEDICALRECORD_SCHEMA, {'type': 'null'}]},
+        'paiInfoBean': {'oneOf': [PAIINFO_SCHEMA, {'type': 'null'}]},
+        'authorizedPersonList': {
+            'oneOf': [
+                {
+                    'type': 'array',
+                    'items': AUTHORIZED_PERSON_SCHEMA,
+                },
+                {'type': 'null'},
+            ],
+        },
+        'indicatorList': {
+            'oneOf': [
+                {
+                    'type': 'array',
+                    'items': INDICATOR_SCHEMA,
+                },
+                {'type': 'null'},
+            ],
+        },
+    },
+    'additionalProperties': False,
+}
+CHILD_SCHEMA['properties'].update(ID_PROPERTIES)
+
+UPDATE_FAMILY_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-04/schema#',
+    'title': 'Family',
+    'description': 'Informations pour créer ou mettre à jour une famille',
+    'type': 'object',
+    'required': ['category', 'situation'],
+    'properties': {
+        'category': {
+            'description': 'Catégorie (depuis référentiel)',
+            'type': 'string',
+            'pattern': '.+',
+        },
+        'situation': {
+            'description': 'Situation familiale (depuis référentiel)',
+            'type': 'string',
+            'pattern': '.+',
+        },
+        'flagCom': {
+            'description': 'Hors commune',
+            'oneOf': schemas.BOOLEAN_TYPES,
+        },
+        'nbChild': {
+            'description': "Nombre d'enfants à charge",
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'nbTotalChild': {
+            'description': "Nombre total d'enfants",
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'nbAES': {
+            'description': "Nombre d'AES",
+            'oneOf': [{'type': 'string'}, {'type': 'null'}],
+        },
+        'rl1': RLINFO_SCHEMA,
+        'rl2': RLINFO_SCHEMA,
+        'emergencyPersonList': {
+            'oneOf': [
+                {
+                    'type': 'array',
+                    'items': EMERGENCY_PERSON_SCHEMA,
+                },
+                {'type': 'null'},
+            ],
+        },
+        'childList': {
+            'oneOf': [
+                {
+                    'type': 'array',
+                    'items': CHILD_SCHEMA,
+                },
+                {'type': 'null'},
+            ],
+        },
+    },
+    'unflatten': True,
+    'additionalProperties': False,
+}
+
+CREATE_FAMILY_SCHEMA = copy.deepcopy(UPDATE_FAMILY_SCHEMA)
+CREATE_FAMILY_SCHEMA['required'] = ['rl1', 'category', 'situation']
+
+CREATE_RL1_SCHEMA = copy.deepcopy(CREATE_FAMILY_SCHEMA)
+del CREATE_RL1_SCHEMA['properties']['rl2']
+del CREATE_RL1_SCHEMA['properties']['emergencyPersonList']
+del CREATE_RL1_SCHEMA['properties']['childList']
+del CREATE_RL1_SCHEMA['properties']['rl1']['properties']['contact']
+del CREATE_RL1_SCHEMA['properties']['rl1']['properties']['profession']
+del CREATE_RL1_SCHEMA['properties']['rl1']['properties']['CAFInfo']
+
+UPDATE_RL1_SCHEMA = copy.deepcopy(RLINFO_SCHEMA)
+UPDATE_RL1_SCHEMA['required'] = ['firstname', 'lastname', 'civility', 'quality', 'birth']
+del UPDATE_RL1_SCHEMA['properties']['adresse']
+del UPDATE_RL1_SCHEMA['properties']['contact']
+del UPDATE_RL1_SCHEMA['properties']['profession']
+del UPDATE_RL1_SCHEMA['properties']['CAFInfo']
+del UPDATE_RL1_SCHEMA['properties']['indicatorList']
+
+CREATE_RL2_SCHEMA = copy.deepcopy(RLINFO_SCHEMA)
+CREATE_RL2_SCHEMA['unflatten'] = True
+del CREATE_RL2_SCHEMA['properties']['contact']
+del CREATE_RL2_SCHEMA['properties']['profession']
+del CREATE_RL2_SCHEMA['properties']['CAFInfo']
+del CREATE_RL2_SCHEMA['properties']['indicatorList']
+
+UPDATE_RL2_SCHEMA = copy.deepcopy(UPDATE_RL1_SCHEMA)
+
+CREATE_CHILD_SCHEMA = copy.deepcopy(CHILD_SCHEMA)
+CREATE_CHILD_SCHEMA['unflatten'] = True
+del CREATE_CHILD_SCHEMA['properties']['dietcode']
+del CREATE_CHILD_SCHEMA['properties']['medicalRecord']
+del CREATE_CHILD_SCHEMA['properties']['paiInfoBean']
+del CREATE_CHILD_SCHEMA['properties']['authorizedPersonList']
+del CREATE_CHILD_SCHEMA['properties']['indicatorList']
+
+UPDATE_CHILD_SCHEMA = copy.deepcopy(CREATE_CHILD_SCHEMA)
+
+UPDATE_COORDINATE_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-04/schema#',
+    'title': 'Update coordinate',
+    'description': "Mise à jour des coordonnées d'un responsable légal",
+    'type': 'object',
+    'required': ['adresse'],
+    'properties': {
+        'adresse': ADDRESS_SCHEMA,
+        'contact': {'oneOf': [CONTACT_SCHEMA, {'type': 'null'}]},
+        'profession': {'oneOf': [PROFESSION_SCHEMA, {'type': 'null'}]},
+        'CAFInfo': {'oneOf': [CAFINFO_SCHEMA, {'type': 'null'}]},
+    },
+    'unflatten': True,
+    'additionalProperties': False,
+}
+
+UPDATE_INDICATOR_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-04/schema#',
+    'title': 'Update indicators',
+    'description': 'Mise à jour des indicateurs',
+    'type': 'object',
+    'required': ['indicatorList'],
+    'properties': {
+        'indicatorList': {
+            'type': 'array',
+            'items': INDICATOR_SCHEMA,
+            'minItems': 1,
+        }
+    },
+    'additionalProperties': False,
+    'unflatten': True,
+}
+
+UPDATE_QUOTIENT_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-04/schema#',
+    'title': 'Family persons',
+    'description': "Mise à jours des quotients sur les responsables légaux",
+    'type': 'object',
+    'required': ['yearRev', 'dateStart', 'dateEnd', 'mtt', 'cdquo'],
+    'properties': {
+        'yearRev': {
+            'description': 'Année de revenu',
+            'type': 'string',
+            'pattern': '^[0-9]{4}$',
+        },
+        'dateStart': {
+            'description': 'Date de début',
+            'type': 'string',
+            'pattern': '^[0-9]{4}-[0-9]{2}-[0-9]{2}$',
+        },
+        'dateEnd': {
+            'description': 'Date de fin',
+            'type': 'string',
+            'pattern': '^[0-9]{4}-[0-9]{2}-[0-9]{2}$',
+        },
+        'mtt': {
+            'description': 'Montant',
+            'type': 'string',
+            'pattern': r'^[0-9]+\.?[0-9]*$',
+        },
+        'cdquo': {
+            'description': 'Code du quotient (depuis référentiel)',
+            'type': 'string',
+            'pattern': '.+',
+        },
+    },
+    'additionalProperties': False,
+}
diff --git a/passerelle/contrib/toulouse_maelis/models.py b/passerelle/contrib/toulouse_maelis/models.py
index 862035aa..2b9430ce 100644
--- a/passerelle/contrib/toulouse_maelis/models.py
+++ b/passerelle/contrib/toulouse_maelis/models.py
@@ -22,17 +22,17 @@ from django.utils.timezone import now
 from zeep.helpers import serialize_object
 from zeep.wsse.username import UsernameToken
 
 from passerelle.base.models import BaseResource, HTTPResource
 from passerelle.utils.api import endpoint
 from passerelle.utils.conversion import simplify
 from passerelle.utils.jsonresponse import APIError
 
-from . import schemas
+from . import family_schemas, schemas
 
 
 class UpdateError(Exception):
     pass
 
 
 class ToulouseMaelis(BaseResource, HTTPResource):
     # noqa pylint: disable=too-many-public-methods
@@ -801,40 +801,40 @@ class ToulouseMaelis(BaseResource, HTTPResource):
         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}}},
+        post={'request_body': {'schema': {'application/json': family_schemas.ISEXISTS_SCHEMA}}},
     )
     def is_rl_exists(self, request, post_data):
         response = self.call('Family', 'isRLExists', **post_data)
         return {'data': response}
 
     @endpoint(
         display_category='Famille',
         description="Vérifier qu'un responsable légal existe en base",
         perm='can_access',
         name='is-child-exists',
-        post={'request_body': {'schema': {'application/json': schemas.ISEXISTS_SCHEMA}}},
+        post={'request_body': {'schema': {'application/json': family_schemas.ISEXISTS_SCHEMA}}},
     )
     def is_child_exists(self, request, post_data):
         response = self.call('Family', 'isChildExists', **post_data)
         return {'data': response}
 
     @endpoint(
         display_category='Famille',
         description='Création de la famille',
         name='create-family',
         perm='can_access',
         parameters={'NameID': {'description': 'Publik NameID'}},
-        post={'request_body': {'schema': {'application/json': schemas.CREATE_FAMILY_SCHEMA}}},
+        post={'request_body': {'schema': {'application/json': family_schemas.CREATE_FAMILY_SCHEMA}}},
     )
     def create_family(self, request, NameID, post_data):
         if self.link_set.filter(name_id=NameID).exists():
             raise APIError('User already linked to family', err_code='already-linked')
         self.assert_family_payload_in_referential(post_data)
 
         response = self.call('Family', 'createFamily', **post_data)
         data = serialize_object(response)
@@ -848,17 +848,17 @@ class ToulouseMaelis(BaseResource, HTTPResource):
         return {'data': data}
 
     @endpoint(
         display_category='Famille',
         description='Modification de la famille',
         name='update-family',
         perm='can_access',
         parameters={'NameID': {'description': 'Publik NameID'}},
-        post={'request_body': {'schema': {'application/json': schemas.UPDATE_FAMILY_SCHEMA}}},
+        post={'request_body': {'schema': {'application/json': family_schemas.UPDATE_FAMILY_SCHEMA}}},
     )
     def update_family(self, request, NameID, post_data):
         family_id = self.get_link(NameID).family_id
         self.assert_family_payload_in_referential(post_data)
         self.replace_null_values(post_data)
 
         # adapt payload to use same input as create_family
         if len(post_data.get('emergencyPersonList', [])):
@@ -875,17 +875,17 @@ class ToulouseMaelis(BaseResource, HTTPResource):
         return {'data': data}
 
     @endpoint(
         display_category='Famille',
         description='Création du RL1',
         name='create-rl1',
         perm='can_access',
         parameters={'NameID': {'description': 'Publik NameID'}},
-        post={'request_body': {'schema': {'application/json': schemas.CREATE_RL1_SCHEMA}}},
+        post={'request_body': {'schema': {'application/json': family_schemas.CREATE_RL1_SCHEMA}}},
     )
     def create_rl1(self, request, NameID, post_data):
         if self.link_set.filter(name_id=NameID).exists():
             raise APIError('User already linked to family', err_code='already-linked')
         self.assert_create_rl1_payload_in_referential(post_data)
 
         response = self.call('Family', 'createFamily', **post_data)
         data = serialize_object(response)
@@ -898,17 +898,17 @@ class ToulouseMaelis(BaseResource, HTTPResource):
         return {'data': {'family_id': family_id}}
 
     @endpoint(
         display_category='Famille',
         description='Modification du RL1',
         name='update-rl1',
         perm='can_access',
         parameters={'NameID': {'description': 'Publik NameID'}},
-        post={'request_body': {'schema': {'application/json': schemas.UPDATE_RL1_SCHEMA}}},
+        post={'request_body': {'schema': {'application/json': family_schemas.UPDATE_RL1_SCHEMA}}},
     )
     def update_rl1(self, request, NameID, post_data):
         family_id = self.get_link(NameID).family_id
         self.assert_rl_payload_in_referential(post_data)
         self.replace_null_values(post_data)
         family = self.get_family_raw(family_id)
 
         rl1 = post_data
@@ -927,17 +927,17 @@ class ToulouseMaelis(BaseResource, HTTPResource):
         return {'data': 'ok'}
 
     @endpoint(
         display_category='Famille',
         description='Création du RL2',
         name='create-rl2',
         perm='can_access',
         parameters={'NameID': {'description': 'Publik NameID'}},
-        post={'request_body': {'schema': {'application/json': schemas.CREATE_RL2_SCHEMA}}},
+        post={'request_body': {'schema': {'application/json': family_schemas.CREATE_RL2_SCHEMA}}},
     )
     def create_rl2(self, request, NameID, post_data):
         family_id = self.get_link(NameID).family_id
         self.assert_rl_payload_in_referential(post_data)
         family = self.get_family_raw(family_id)
         if family['RL2']:
             raise APIError('RL2 already defined on family', err_code='already-rl2')
 
@@ -955,17 +955,17 @@ class ToulouseMaelis(BaseResource, HTTPResource):
         return {'data': {'id': response['RL2']['num']}}
 
     @endpoint(
         display_category='Famille',
         description='Modification du RL2',
         name='update-rl2',
         perm='can_access',
         parameters={'NameID': {'description': 'Publik NameID'}},
-        post={'request_body': {'schema': {'application/json': schemas.UPDATE_RL2_SCHEMA}}},
+        post={'request_body': {'schema': {'application/json': family_schemas.UPDATE_RL2_SCHEMA}}},
     )
     def update_rl2(self, request, NameID, post_data):
         family_id = self.get_link(NameID).family_id
         self.assert_rl_payload_in_referential(post_data)
         self.replace_null_values(post_data)
         family = self.get_family_raw(family_id)
         if not family['RL2']:
             raise APIError('No RL2 to update on family', err_code='no-rl2')
@@ -993,17 +993,17 @@ class ToulouseMaelis(BaseResource, HTTPResource):
         parameters={
             'NameID': {'description': 'Publik NameID'},
             'force': {
                 'description': 'boolean to bypass doublon error',
                 'type': 'bool',
                 'example_value': 'false',
             },
         },
-        post={'request_body': {'schema': {'application/json': schemas.CREATE_CHILD_SCHEMA}}},
+        post={'request_body': {'schema': {'application/json': family_schemas.CREATE_CHILD_SCHEMA}}},
     )
     def create_child(self, request, NameID, post_data, force=False):
         family_id = self.get_link(NameID).family_id
         self.assert_child_payload_in_referential(post_data)
 
         payload = {
             'numDossier': family_id,
             'isForceCreateChild': force,
@@ -1021,17 +1021,17 @@ class ToulouseMaelis(BaseResource, HTTPResource):
         display_category='Famille',
         description="Modification d'un enfant",
         name='update-child',
         perm='can_access',
         parameters={
             'NameID': {'description': 'Publik NameID'},
             'child_id': {'description': "Numéro de l'enfant"},
         },
-        post={'request_body': {'schema': {'application/json': schemas.UPDATE_CHILD_SCHEMA}}},
+        post={'request_body': {'schema': {'application/json': family_schemas.UPDATE_CHILD_SCHEMA}}},
     )
     def update_child(self, request, NameID, child_id, post_data):
         family_id = self.get_link(NameID).family_id
         self.assert_child_payload_in_referential(post_data)
         self.replace_null_values(post_data)
         family = self.get_family_raw(family_id)
 
         child = post_data
@@ -1059,17 +1059,17 @@ class ToulouseMaelis(BaseResource, HTTPResource):
         display_category='Famille',
         description="Mise à jour des coordonnées d'un responsable légal",
         name='update-coordinate',
         perm='can_access',
         parameters={
             'NameID': {'description': 'Publik NameID'},
             'rl_id': {'description': 'Numéro du représentant légal'},
         },
-        post={'request_body': {'schema': {'application/json': schemas.UPDATE_COORDINATE_SCHEMA}}},
+        post={'request_body': {'schema': {'application/json': family_schemas.UPDATE_COORDINATE_SCHEMA}}},
     )
     def update_coordinate(self, request, NameID, rl_id, post_data):
         family_id = self.get_link(NameID).family_id
         self.assert_update_coordinate_payload_in_referential(post_data)
         self.replace_null_values(post_data)
 
         self.call('Family', 'updateCoordinate', numDossier=family_id, numPerson=rl_id, **post_data)
         return {'data': 'ok'}
@@ -1078,17 +1078,17 @@ class ToulouseMaelis(BaseResource, HTTPResource):
         display_category='Famille',
         description="Mise à jour des indicateurs d'un responsable légal",
         name='update-rl-indicator',
         perm='can_access',
         parameters={
             'NameID': {'description': 'Publik NameID'},
             'rl_id': {'description': 'Numéro du représentant légal'},
         },
-        post={'request_body': {'schema': {'application/json': schemas.UPDATE_INDICATOR_SCHEMA}}},
+        post={'request_body': {'schema': {'application/json': family_schemas.UPDATE_INDICATOR_SCHEMA}}},
     )
     def update_rl_indicator(self, request, NameID, rl_id, post_data):
         self.get_link(NameID)
         self.assert_update_indicator_payload_in_referential('RLIndicator', post_data)
 
         self.call('Family', 'updatePersonIndicatorList', numPerson=rl_id, **post_data)
         return {'data': 'ok'}
 
@@ -1096,17 +1096,17 @@ class ToulouseMaelis(BaseResource, HTTPResource):
         display_category='Famille',
         description="Créer ou mettre à jour un quotient d'un responsable légal",
         name='update-quotient',
         perm='can_access',
         parameters={
             'NameID': {'description': 'Publik NameID'},
             'rl_id': {'description': "Numéro du responsable légal"},
         },
-        post={'request_body': {'schema': {'application/json': schemas.UPDATE_QUOTIENT_SCHEMA}}},
+        post={'request_body': {'schema': {'application/json': family_schemas.UPDATE_QUOTIENT_SCHEMA}}},
     )
     def update_quotient(self, request, NameID, rl_id, post_data):
         family_id = self.get_link(NameID).family_id
         self.assert_post_data_in_referential('Quotient', post_data, ['cdquo'])
 
         payload = {
             'dossierNumber': family_id,
             'personNumber': rl_id,
@@ -1118,17 +1118,17 @@ class ToulouseMaelis(BaseResource, HTTPResource):
     @endpoint(
         display_category='Famille',
         description="Création d'une personne à prévenir en cas d'urgence",
         name='create-person',
         perm='can_access',
         parameters={
             'NameID': {'description': 'Publik NameID'},
         },
-        post={'request_body': {'schema': {'application/json': schemas.EMERGENCY_PERSON_SCHEMA}}},
+        post={'request_body': {'schema': {'application/json': family_schemas.EMERGENCY_PERSON_SCHEMA}}},
     )
     def create_person(self, request, NameID, post_data):
         family_id = self.get_link(NameID).family_id
         self.assert_person_payload_in_referential(post_data)
         family = self.get_family_raw(family_id)
 
         personList = family['emergencyPersonList']
         personList.append(post_data)
@@ -1149,17 +1149,17 @@ class ToulouseMaelis(BaseResource, HTTPResource):
         display_category='Famille',
         description="Mise à jour d'une personne à prévenir en cas d'urgence",
         name='update-person',
         perm='can_access',
         parameters={
             'NameID': {'description': 'Publik NameID'},
             'person_id': {'description': 'Numéro de la personne'},
         },
-        post={'request_body': {'schema': {'application/json': schemas.EMERGENCY_PERSON_SCHEMA}}},
+        post={'request_body': {'schema': {'application/json': family_schemas.EMERGENCY_PERSON_SCHEMA}}},
     )
     def update_person(self, request, NameID, person_id, post_data):
         family_id = self.get_link(NameID).family_id
         self.assert_person_payload_in_referential(post_data)
         family = self.get_family_raw(family_id)
 
         personList = family['emergencyPersonList']
         for i, person in enumerate(personList):
@@ -1225,17 +1225,17 @@ class ToulouseMaelis(BaseResource, HTTPResource):
         display_category='Famille',
         description="Création d'une personne autorisée à récupérer l'enfant",
         name='create-child-person',
         perm='can_access',
         parameters={
             'NameID': {'description': 'Publik NameID'},
             'child_id': {'description': "Numéro de l'enfant"},
         },
-        post={'request_body': {'schema': {'application/json': schemas.AUTHORIZED_PERSON_SCHEMA}}},
+        post={'request_body': {'schema': {'application/json': family_schemas.AUTHORIZED_PERSON_SCHEMA}}},
     )
     def create_child_person(self, request, NameID, child_id, post_data):
         family_id = self.get_link(NameID).family_id
         self.assert_child_person_payload_in_referential(post_data)
         child = self.get_child_raw(family_id, child_id)
 
         personList = child['authorizedPersonList']
         personList.append(post_data)
@@ -1254,17 +1254,17 @@ class ToulouseMaelis(BaseResource, HTTPResource):
         description="Mise à jour d'une personne autorisée à récupérer l'enfant",
         name='update-child-person',
         perm='can_access',
         parameters={
             'NameID': {'description': 'Publik NameID'},
             'child_id': {'description': "Numéro de l'enfant"},
             'person_id': {'description': 'Numéro de la personne'},
         },
-        post={'request_body': {'schema': {'application/json': schemas.AUTHORIZED_PERSON_SCHEMA}}},
+        post={'request_body': {'schema': {'application/json': family_schemas.AUTHORIZED_PERSON_SCHEMA}}},
     )
     def update_child_person(self, request, NameID, child_id, person_id, post_data):
         family_id = self.get_link(NameID).family_id
         self.assert_child_person_payload_in_referential(post_data)
         child = self.get_child_raw(family_id, child_id)
 
         personList = child['authorizedPersonList']
         for i, person in enumerate(personList):
@@ -1344,17 +1344,17 @@ class ToulouseMaelis(BaseResource, HTTPResource):
         display_category='Famille',
         description="Créer ou mettre à jour les informations relatives au PAI d'un enfant",
         name='update-child-pai',
         perm='can_access',
         parameters={
             'NameID': {'description': 'Publik NameID'},
             'child_id': {'description': "Numéro de l'enfant"},
         },
-        post={'request_body': {'schema': {'application/json': schemas.PAIINFO_SCHEMA}}},
+        post={'request_body': {'schema': {'application/json': family_schemas.PAIINFO_SCHEMA}}},
     )
     def update_child_pai(self, request, NameID, child_id, post_data):
         self.get_link(NameID)
         self.assert_child_pai_payoad_in_referential(post_data)
 
         # use None to empty date passed as an empty string by date filter
         for key in 'dateDeb', 'dateFin':
             if post_data[key] == '':
@@ -1367,17 +1367,17 @@ class ToulouseMaelis(BaseResource, HTTPResource):
         display_category='Famille',
         description="Créer ou mettre à jour les données médicales d'un enfant",
         name='update-child-medical-record',
         perm='can_access',
         parameters={
             'NameID': {'description': 'Publik NameID'},
             'child_id': {'description': "Numéro de l'enfant"},
         },
-        post={'request_body': {'schema': {'application/json': schemas.MEDICALRECORD_SCHEMA}}},
+        post={'request_body': {'schema': {'application/json': family_schemas.MEDICALRECORD_SCHEMA}}},
     )
     def update_child_medical_record(self, request, NameID, child_id, post_data):
         self.get_link(NameID)
         self.assert_child_medical_record_payload_in_referential(post_data)
         self.replace_null_values(post_data)
 
         payload = {
             'numPerson': child_id,
@@ -1390,17 +1390,17 @@ class ToulouseMaelis(BaseResource, HTTPResource):
         display_category='Famille',
         description="Mise à jour des indicateurs d'un enfant",
         name='update-child-indicator',
         perm='can_access',
         parameters={
             'NameID': {'description': 'Publik NameID'},
             'child_id': {'description': "Numéro de l'enfant"},
         },
-        post={'request_body': {'schema': {'application/json': schemas.UPDATE_INDICATOR_SCHEMA}}},
+        post={'request_body': {'schema': {'application/json': family_schemas.UPDATE_INDICATOR_SCHEMA}}},
     )
     def update_child_indicator(self, request, NameID, child_id, post_data):
         self.get_link(NameID)
         self.assert_update_indicator_payload_in_referential('ChildIndicator', post_data)
 
         self.call('Family', 'updatePersonIndicatorList', numPerson=child_id, **post_data)
         return {'data': 'ok'}
 
diff --git a/passerelle/contrib/toulouse_maelis/schemas.py b/passerelle/contrib/toulouse_maelis/schemas.py
index 03854375..452c5366 100644
--- a/passerelle/contrib/toulouse_maelis/schemas.py
+++ b/passerelle/contrib/toulouse_maelis/schemas.py
@@ -8,17 +8,16 @@
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU Affero General Public License for more details.
 #
 # 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/>.
 
-import copy
 
 BOOLEAN_TYPES = [
     {'type': 'boolean'},
     {
         'type': 'string',
         'pattern': '^([Oo][Uu][Ii]|[Nn][Oo][Nn]|[Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee]|1|0)$',
         'pattern_description': 'Les valeurs "0", "1", "true", "false", "oui" ou "non" sont autorisées (insensibles à la casse).',
     },
@@ -50,709 +49,8 @@ LINK_SCHEMA = {
         'family_id': {
             'description': 'Numéro DUI',
             'type': 'string',
         },
     },
     'additionalProperties': False,
 }
 LINK_SCHEMA['properties'].update(BASIC_ID_PROPERTIES)
-
-ISEXISTS_SCHEMA = {
-    '$schema': 'http://json-schema.org/draft-04/schema#',
-    'title': 'Exist',
-    'description': "Recherche d'un responsable légal ou d'un enfant dans Maelis",
-    'type': 'object',
-    'required': ['firstname', 'lastname', 'dateBirth'],
-    'properties': BASIC_ID_PROPERTIES,
-    'additionalProperties': False,
-}
-
-
-CONTACTLIGHT_SCHEMA = {
-    '$schema': 'http://json-schema.org/draft-04/schema#',
-    'title': 'Contact light',
-    'description': "Informations de contact pour les personnes autorisées à récupérer les enfants ou à prévenir en cas d'urgence",
-    'type': 'object',
-    'properties': {
-        'phone': {
-            'description': 'Téléphone',
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'mobile': {
-            'description': 'Portable',
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'mail': {
-            'description': 'Mail',
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-    },
-}
-
-
-PERSON_PROPERTIES = {
-    'civility': {
-        'description': 'civilité (depuis référentiel)',
-        'oneOf': [{'type': 'string'}, {'type': 'null'}],
-    },
-    'sexe': {
-        'description': 'Sexe (depuis référentiel)',
-        'oneOf': [{'type': 'string'}, {'type': 'null'}],
-    },
-    'contact': {'oneOf': [CONTACTLIGHT_SCHEMA, {'type': 'null'}]},
-}
-PERSON_PROPERTIES.update(BASIC_ID_PROPERTIES)
-
-
-EMERGENCY_PERSON_SCHEMA = {
-    '$schema': 'http://json-schema.org/draft-04/schema#',
-    'title': 'Emergency person',
-    'description': "Personnes à prévenir en cas d'urgence",
-    'type': 'object',
-    'required': ['firstname', 'lastname', 'dateBirth', 'quality'],
-    'properties': {
-        'quality': {
-            'description': 'Qualité',
-            'type': 'string',
-            'pattern': '.+',
-        },
-    },
-    'unflatten': True,
-    'additionalProperties': False,
-}
-EMERGENCY_PERSON_SCHEMA['properties'].update(PERSON_PROPERTIES)
-
-
-AUTHORIZED_PERSON_SCHEMA = {
-    '$schema': 'http://json-schema.org/draft-04/schema#',
-    'title': 'Family persons',
-    'description': "Personnes autorisées à venir chercher l'enfant",
-    'type': 'object',
-    'required': ['personInfo', 'personQuality'],
-    'properties': {
-        'personInfo': {
-            'type': 'object',
-            'required': ['firstname', 'lastname', 'dateBirth'],
-            'properties': PERSON_PROPERTIES,
-        },
-        'personQuality': {
-            'type': 'object',
-            'required': ['code'],
-            'properties': {
-                'code': {
-                    'description': 'Le code (depuis référentiel)',
-                    'type': 'string',
-                    'pattern': '.+',
-                },
-            },
-        },
-    },
-    'additionalProperties': False,
-    'unflatten': True,
-}
-
-
-BIRTH_SCHEMA = {
-    '$schema': 'http://json-schema.org/draft-04/schema#',
-    'title': 'Birth info',
-    'description': "Informations relatives à la naissance",
-    'type': 'object',
-    'required': ['dateBirth'],
-    'properties': {
-        'dateBirth': {
-            'description': 'Date de naissance',
-            'type': 'string',
-            'pattern': '^[0-9]{4}-[0-9]{2}-[0-9]{2}$',
-        },
-        'place': {
-            'description': 'Lieu de naissance',
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'communeCode': {
-            'description': 'Commune de naissance (depuis référentiel)',
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'countryCode': {
-            'description': 'Pays de naissance (depuis référentiel)',
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-    },
-}
-
-INDICATOR_SCHEMA = {
-    '$schema': 'http://json-schema.org/draft-04/schema#',
-    'title': 'Address',
-    'description': 'Indicateurs',
-    'type': 'object',
-    'required': ['code', 'isActive'],
-    'properties': {
-        'code': {
-            'description': "Code de l'indicateur (depuis référentiel)",
-            'type': 'string',
-            'pattern': '.+',
-        },
-        'note': {
-            'description': "Commentaire pour les indicateurs de type NOTE",
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'isActive': {
-            'description': "True pour ajouter/modifier l'indicateur (défault) ou False pour le retirer",
-            'oneOf': BOOLEAN_TYPES,
-        },
-    },
-}
-
-ID_PROPERTIES = {
-    'firstname': {
-        'description': 'Prénom',
-        'type': 'string',
-    },
-    'lastname': {
-        'description': 'Nom',
-        'type': 'string',
-    },
-    'maidenName': {
-        'description': "Nom de jeune fille ",
-        'oneOf': [{'type': 'string'}, {'type': 'null'}],
-    },
-    'birth': BIRTH_SCHEMA,
-}
-
-ADDRESS_SCHEMA = {
-    '$schema': 'http://json-schema.org/draft-04/schema#',
-    'title': 'Address',
-    'description': 'Informations sur une adresse',
-    'type': 'object',
-    'required': ['street1', 'town', 'zipcode'],
-    'properties': {
-        'num': {
-            'description': "Numéro de l'adresse",
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'numComp': {
-            'description': 'Complément du numéro (depuis référentiel)',
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'idStreet': {
-            'description': 'Identifiant de la voie (depuis référentiel)',
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'street1': {
-            'description': 'Libellé de la voie',
-            'type': 'string',
-        },
-        'street2': {
-            'description': 'Complément de la voie',
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'town': {
-            'description': 'Ville',
-            'type': 'string',
-        },
-        'zipcode': {
-            'description': 'Code postal',
-            'type': 'string',
-        },
-    },
-}
-
-CONTACT_SCHEMA = {
-    '$schema': 'http://json-schema.org/draft-04/schema#',
-    'title': 'Contact',
-    'description': 'Informations sur le contact',
-    'type': 'object',
-    'properties': {
-        'phone': {
-            'description': 'Téléphone',
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'mobile': {
-            'description': 'Portable',
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'mail': {
-            'description': 'Mail',
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'isContactMail': {
-            'description': 'Accepte de recevoir des mails',
-            'oneOf': BOOLEAN_TYPES,
-        },
-        'isContactSms': {
-            'description': 'Accepte de recevoir des sms',
-            'oneOf': BOOLEAN_TYPES,
-        },
-        'isInvoicePdf': {
-            'description': 'Accepte de ne plus recevoir de facture papier',
-            'oneOf': BOOLEAN_TYPES,
-        },
-    },
-}
-
-ADDRESSPROF_SCHEMA = {
-    '$schema': 'http://json-schema.org/draft-04/schema#',
-    'title': 'Adresse pro',
-    'description': "Informations sur l'adresse professionnelle",
-    'type': 'object',
-    'properties': {
-        'num': {
-            'description': "Numéro de l'adresse",
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'street': {
-            'description': 'Nom de la voie',
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'town': {
-            'description': 'Ville',
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'zipcode': {
-            'description': 'Code postal',
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-    },
-}
-
-PROFESSION_SCHEMA = {
-    '$schema': 'http://json-schema.org/draft-04/schema#',
-    'title': 'Profession',
-    'description': 'Informations sur la profession',
-    'type': 'object',
-    'properties': {
-        'codeCSP': {
-            'description': 'Catégorie socio-professionnelle (depuis référentiel)',
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'profession': {
-            'description': 'Profession',
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'employerName': {
-            'description': "Nom de l'employeur",
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'phone': {
-            'description': 'Téléphone',
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'addressPro': ADDRESSPROF_SCHEMA,
-    },
-}
-
-CAFINFO_SCHEMA = {
-    '$schema': 'http://json-schema.org/draft-04/schema#',
-    'title': 'CAF',
-    'description': 'Informations sur la CAF',
-    'type': 'object',
-    'properties': {
-        'number': {
-            'description': "Numéro d'allocataire",
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'organ': {
-            'description': "Nom de l'organisme (depuis référentiel)",
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-    },
-}
-
-RLINFO_SCHEMA = {
-    '$schema': 'http://json-schema.org/draft-04/schema#',
-    'title': 'RL',
-    'description': "Informations sur le responsable légal",
-    'type': 'object',
-    'required': ['firstname', 'lastname', 'civility', 'quality', 'birth', 'adresse'],
-    'properties': {
-        'civility': {
-            'description': 'civilité (depuis référentiel)',
-            'type': 'string',
-            'pattern': '.+',
-        },
-        'quality': {
-            'description': 'Qualité (depuis référentiel)',
-            'type': 'string',
-            'pattern': '.+',
-        },
-        'adresse': ADDRESS_SCHEMA,
-        'contact': {'oneOf': [CONTACT_SCHEMA, {'type': 'null'}]},
-        'profession': {'oneOf': [PROFESSION_SCHEMA, {'type': 'null'}]},
-        'CAFInfo': {'oneOf': [CAFINFO_SCHEMA, {'type': 'null'}]},
-        'indicatorList': {
-            'oneOf': [
-                {
-                    'type': 'array',
-                    'items': INDICATOR_SCHEMA,
-                },
-                {'type': 'null'},
-            ],
-        },
-    },
-    'unflatten': True,
-    'additionalProperties': False,
-}
-RLINFO_SCHEMA['properties'].update(ID_PROPERTIES)
-
-DOCTORADDRESS_SCHEMA = {
-    '$schema': 'http://json-schema.org/draft-04/schema#',
-    'title': 'Doctor address',
-    'description': "Informations sur l'adresse du docteur",
-    'type': 'object',
-    'properties': {
-        'street1': {
-            'description': 'Libellé de la voie',
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'town': {
-            'description': 'Ville',
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'zipcode': {
-            'description': 'Code postal',
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-    },
-}
-
-FAMILYDOCTOR_SCHEMA = {
-    '$schema': 'http://json-schema.org/draft-04/schema#',
-    'title': 'Family doctor',
-    'description': "Informations sur le docteur",
-    'type': 'object',
-    'properties': {
-        'name': {
-            'description': 'Nom',
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'phone': {
-            'description': 'Téléphone',
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'address': DOCTORADDRESS_SCHEMA,
-    },
-}
-
-VACCIN_SCHEMA = {
-    '$schema': 'http://json-schema.org/draft-04/schema#',
-    'title': 'Vaccin',
-    'description': "Informations sur le vaccin",
-    'type': 'object',
-    'required': ['code', 'vaccinationDate'],
-    'properties': {
-        'code': {
-            'description': 'Code du vaccin (depuis référentiel)',
-            'type': 'string',
-        },
-        'vaccinationDate': {
-            'description': 'Date du vaccin',
-            'type': 'string',
-            'pattern': '^[0-9]{4}-[0-9]{2}-[0-9]{2}$',
-        },
-    },
-}
-
-MEDICALRECORD_SCHEMA = {
-    '$schema': 'http://json-schema.org/draft-04/schema#',
-    'title': 'Medical record',
-    'description': "Informations médicales",
-    'oneOf': [
-        {
-            'type': 'object',
-            'properties': {
-                'familyDoctor': FAMILYDOCTOR_SCHEMA,
-                'allergy1': {
-                    'description': 'Allergie 1',
-                    'oneOf': [{'type': 'string'}, {'type': 'null'}],
-                },
-                'allergy2': {
-                    'description': 'Allergie 2',
-                    'oneOf': [{'type': 'string'}, {'type': 'null'}],
-                },
-                'comment1': {
-                    'description': 'Commentaire 1',
-                    'oneOf': [{'type': 'string'}, {'type': 'null'}],
-                },
-                'comment2': {
-                    'description': 'Commentaire 2',
-                    'oneOf': [{'type': 'string'}, {'type': 'null'}],
-                },
-                'observ1': {
-                    'description': 'Observation 1',
-                    'oneOf': [{'type': 'string'}, {'type': 'null'}],
-                },
-                'observ2': {
-                    'description': 'Observation 2',
-                    'oneOf': [{'type': 'string'}, {'type': 'null'}],
-                },
-                'isAuthHospital': {
-                    'description': "Autorisation d'hospitalisation",
-                    'oneOf': BOOLEAN_TYPES,
-                },
-                'hospital': {
-                    'description': 'Hopital',
-                    'oneOf': [{'type': 'string'}, {'type': 'null'}],
-                },
-                'vaccinList': {
-                    'oneOf': [
-                        {
-                            'type': 'array',
-                            'items': VACCIN_SCHEMA,
-                        },
-                        {'type': 'null'},
-                    ],
-                },
-            },
-            'additionalProperties': False,
-        },
-        {'type': 'null'},
-    ],
-    'unflatten': True,
-}
-
-PAIINFO_SCHEMA = {
-    '$schema': 'http://json-schema.org/draft-04/schema#',
-    'title': 'PAI',
-    'description': "Informations médicales",
-    'type': 'object',
-    'required': ['code'],
-    'properties': {
-        'code': {
-            'description': 'Code (depuis référentiel)',
-            'type': 'string',
-            'pattern': '.+',
-        },
-        'dateDeb': {
-            'description': 'Date de début',
-            'type': 'string',
-            'pattern': '^([0-9]{4}-[0-9]{2}-[0-9]{2}){0,1}$',
-        },
-        'dateFin': {
-            'description': 'Date de fin',
-            'type': 'string',
-            'pattern': '^([0-9]{4}-[0-9]{2}-[0-9]{2}){0,1}$',
-        },
-        'description': {
-            'description': 'Texte libre de description (max 500 caractères)',
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-    },
-    'additionalProperties': False,
-}
-
-CHILD_SCHEMA = {
-    '$schema': 'http://json-schema.org/draft-04/schema#',
-    'title': 'Child',
-    'description': "Informations sur la création d'un enfant",
-    'type': 'object',
-    'required': ['sexe', 'firstname', 'lastname', 'birth'],
-    'properties': {
-        'num': {
-            'description': "Numéro de l'enfant",
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'sexe': {
-            'description': 'Sexe (depuis référentiel)',
-            'type': 'string',
-            'pattern': '.+',
-        },
-        'birth': BIRTH_SCHEMA,
-        'dietcode': {
-            'description': 'Code de régime alimentaire (depuis référentiel)',
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'bPhoto': {
-            'description': 'Autorisation photo',
-            'oneOf': BOOLEAN_TYPES,
-        },
-        'bLeaveAlone': {
-            'description': 'Autorisation à partir seul',
-            'oneOf': BOOLEAN_TYPES,
-        },
-        'medicalRecord': {'oneOf': [MEDICALRECORD_SCHEMA, {'type': 'null'}]},
-        'paiInfoBean': {'oneOf': [PAIINFO_SCHEMA, {'type': 'null'}]},
-        'authorizedPersonList': {
-            'oneOf': [
-                {
-                    'type': 'array',
-                    'items': AUTHORIZED_PERSON_SCHEMA,
-                },
-                {'type': 'null'},
-            ],
-        },
-        'indicatorList': {
-            'oneOf': [
-                {
-                    'type': 'array',
-                    'items': INDICATOR_SCHEMA,
-                },
-                {'type': 'null'},
-            ],
-        },
-    },
-    'additionalProperties': False,
-}
-CHILD_SCHEMA['properties'].update(ID_PROPERTIES)
-
-UPDATE_FAMILY_SCHEMA = {
-    '$schema': 'http://json-schema.org/draft-04/schema#',
-    'title': 'Family',
-    'description': 'Informations pour créer ou mettre à jour une famille',
-    'type': 'object',
-    'required': ['category', 'situation'],
-    'properties': {
-        'category': {
-            'description': 'Catégorie (depuis référentiel)',
-            'type': 'string',
-            'pattern': '.+',
-        },
-        'situation': {
-            'description': 'Situation familiale (depuis référentiel)',
-            'type': 'string',
-            'pattern': '.+',
-        },
-        'flagCom': {
-            'description': 'Hors commune',
-            'oneOf': BOOLEAN_TYPES,
-        },
-        'nbChild': {
-            'description': "Nombre d'enfants à charge",
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'nbTotalChild': {
-            'description': "Nombre total d'enfants",
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'nbAES': {
-            'description': "Nombre d'AES",
-            'oneOf': [{'type': 'string'}, {'type': 'null'}],
-        },
-        'rl1': RLINFO_SCHEMA,
-        'rl2': RLINFO_SCHEMA,
-        'emergencyPersonList': {
-            'oneOf': [
-                {
-                    'type': 'array',
-                    'items': EMERGENCY_PERSON_SCHEMA,
-                },
-                {'type': 'null'},
-            ],
-        },
-        'childList': {
-            'oneOf': [
-                {
-                    'type': 'array',
-                    'items': CHILD_SCHEMA,
-                },
-                {'type': 'null'},
-            ],
-        },
-    },
-    'unflatten': True,
-    'additionalProperties': False,
-}
-
-CREATE_FAMILY_SCHEMA = copy.deepcopy(UPDATE_FAMILY_SCHEMA)
-CREATE_FAMILY_SCHEMA['required'] = ['rl1', 'category', 'situation']
-
-CREATE_RL1_SCHEMA = copy.deepcopy(CREATE_FAMILY_SCHEMA)
-del CREATE_RL1_SCHEMA['properties']['rl2']
-del CREATE_RL1_SCHEMA['properties']['emergencyPersonList']
-del CREATE_RL1_SCHEMA['properties']['childList']
-del CREATE_RL1_SCHEMA['properties']['rl1']['properties']['contact']
-del CREATE_RL1_SCHEMA['properties']['rl1']['properties']['profession']
-del CREATE_RL1_SCHEMA['properties']['rl1']['properties']['CAFInfo']
-
-UPDATE_RL1_SCHEMA = copy.deepcopy(RLINFO_SCHEMA)
-UPDATE_RL1_SCHEMA['required'] = ['firstname', 'lastname', 'civility', 'quality', 'birth']
-del UPDATE_RL1_SCHEMA['properties']['adresse']
-del UPDATE_RL1_SCHEMA['properties']['contact']
-del UPDATE_RL1_SCHEMA['properties']['profession']
-del UPDATE_RL1_SCHEMA['properties']['CAFInfo']
-del UPDATE_RL1_SCHEMA['properties']['indicatorList']
-
-CREATE_RL2_SCHEMA = copy.deepcopy(RLINFO_SCHEMA)
-CREATE_RL2_SCHEMA['unflatten'] = True
-del CREATE_RL2_SCHEMA['properties']['contact']
-del CREATE_RL2_SCHEMA['properties']['profession']
-del CREATE_RL2_SCHEMA['properties']['CAFInfo']
-del CREATE_RL2_SCHEMA['properties']['indicatorList']
-
-UPDATE_RL2_SCHEMA = copy.deepcopy(UPDATE_RL1_SCHEMA)
-
-CREATE_CHILD_SCHEMA = copy.deepcopy(CHILD_SCHEMA)
-CREATE_CHILD_SCHEMA['unflatten'] = True
-del CREATE_CHILD_SCHEMA['properties']['dietcode']
-del CREATE_CHILD_SCHEMA['properties']['medicalRecord']
-del CREATE_CHILD_SCHEMA['properties']['paiInfoBean']
-del CREATE_CHILD_SCHEMA['properties']['authorizedPersonList']
-del CREATE_CHILD_SCHEMA['properties']['indicatorList']
-
-UPDATE_CHILD_SCHEMA = copy.deepcopy(CREATE_CHILD_SCHEMA)
-
-UPDATE_COORDINATE_SCHEMA = {
-    '$schema': 'http://json-schema.org/draft-04/schema#',
-    'title': 'Update coordinate',
-    'description': "Mise à jour des coordonnées d'un responsable légal",
-    'type': 'object',
-    'required': ['adresse'],
-    'properties': {
-        'adresse': ADDRESS_SCHEMA,
-        'contact': {'oneOf': [CONTACT_SCHEMA, {'type': 'null'}]},
-        'profession': {'oneOf': [PROFESSION_SCHEMA, {'type': 'null'}]},
-        'CAFInfo': {'oneOf': [CAFINFO_SCHEMA, {'type': 'null'}]},
-    },
-    'unflatten': True,
-    'additionalProperties': False,
-}
-
-UPDATE_INDICATOR_SCHEMA = {
-    '$schema': 'http://json-schema.org/draft-04/schema#',
-    'title': 'Update indicators',
-    'description': 'Mise à jour des indicateurs',
-    'type': 'object',
-    'required': ['indicatorList'],
-    'properties': {
-        'indicatorList': {
-            'type': 'array',
-            'items': INDICATOR_SCHEMA,
-            'minItems': 1,
-        }
-    },
-    'additionalProperties': False,
-    'unflatten': True,
-}
-
-UPDATE_QUOTIENT_SCHEMA = {
-    '$schema': 'http://json-schema.org/draft-04/schema#',
-    'title': 'Family persons',
-    'description': "Mise à jours des quotients sur les responsables légaux",
-    'type': 'object',
-    'required': ['yearRev', 'dateStart', 'dateEnd', 'mtt', 'cdquo'],
-    'properties': {
-        'yearRev': {
-            'description': 'Année de revenu',
-            'type': 'string',
-            'pattern': '^[0-9]{4}$',
-        },
-        'dateStart': {
-            'description': 'Date de début',
-            'type': 'string',
-            'pattern': '^[0-9]{4}-[0-9]{2}-[0-9]{2}$',
-        },
-        'dateEnd': {
-            'description': 'Date de fin',
-            'type': 'string',
-            'pattern': '^[0-9]{4}-[0-9]{2}-[0-9]{2}$',
-        },
-        'mtt': {
-            'description': 'Montant',
-            'type': 'string',
-            'pattern': r'^[0-9]+\.?[0-9]*$',
-        },
-        'cdquo': {
-            'description': 'Code du quotient (depuis référentiel)',
-            'type': 'string',
-            'pattern': '.+',
-        },
-    },
-    'additionalProperties': False,
-}
-- 
2.30.2

