passerelle/passerelle/contrib/toulouse_maelis/models.py

2323 lines
95 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 base64
import datetime
from operator import itemgetter
from urllib.parse import urljoin
import zeep
from dateutil import rrule
from django.contrib.postgres.fields import JSONField
from django.core.serializers.json import DjangoJSONEncoder
from django.db import models
from django.utils import dateformat
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 passerelle.utils.templates import render_to_string
from . import activity_schemas, family_schemas, invoice_schemas, schemas, utils
class UpdateError(Exception):
pass
class ToulouseMaelis(BaseResource, HTTPResource):
# noqa pylint: disable=too-many-public-methods
base_wsdl_url = models.CharField(
max_length=128,
blank=False,
verbose_name='URL de base des WSDL',
default='https://demo-toulouse.sigec.fr/maelisws-toulouse/services/',
)
zeep_wsse_username = models.CharField(
max_length=64, blank=True, default='', verbose_name='Identifiant utilisateur WSSE'
)
zeep_wsse_password = models.CharField(
max_length=64, blank=True, default='', verbose_name='Mot de passe WSSE'
)
category = 'Connecteurs métiers'
_category_ordering = ['Famille', 'Activités']
class Meta:
verbose_name = 'Toulouse Maelis'
def get_client(self, wsdl_short_name):
wsse = UsernameToken(self.zeep_wsse_username, self.zeep_wsse_password)
wsdl_name = wsdl_short_name + 'Service?wsdl'
wsdl_url = urljoin(self.base_wsdl_url, wsdl_name)
settings = zeep.Settings(strict=False, xsd_ignore_sequence_order=True)
return self.soap_client(wsdl_url=wsdl_url, wsse=wsse, settings=settings)
def call(self, wsdl_short_name, service, **kwargs):
client = self.get_client(wsdl_short_name)
method = getattr(client.service, service)
try:
return method(**kwargs)
except zeep.exceptions.Fault as e:
raise APIError(e.message, err_code='%s-%s-%s' % (wsdl_short_name, service, e.code))
def check_status(self):
assert self.call('Family', 'isWSRunning')
assert self.call('Activity', 'isWSRunning')
assert self.call('Invoice', 'isWSRunning')
assert self.call('Site', 'isWSRunning')
def update_referential(self, referential_name, data, id_key, text_key):
last_update = now()
for item in data:
text = item[text_key] or ''
if isinstance(text, int):
text = str(text)
text = text.strip()
self.referential.update_or_create(
resource_id=self.id,
referential_name=referential_name,
item_id=item[id_key],
defaults={
'item_text': text,
'item_unaccent_text': simplify(text),
'item_data': dict({'id': item[id_key], 'text': text}, **item),
'updated': last_update,
},
)
self.referential.filter(referential_name=referential_name, updated__lt=last_update).delete()
def get_referential_data(self, service_name, referential_name):
try:
response = self.call(service_name, 'read' + referential_name + 'List')
return serialize_object(response)
except Exception as e:
raise UpdateError('Service indisponible : %s' % str(e))
def update_family_referentials(self):
# local referentials
complement_data = [
{'id': 'B', 'text': 'bis'},
{'id': 'Q', 'text': 'quater'},
{'id': 'T', 'text': 'ter'},
]
sex_data = [
{'id': 'F', 'text': 'Féminin'},
{'id': 'M', 'text': 'Masculin'},
]
self.update_referential('Complement', complement_data, 'id', 'text')
self.update_referential('Sex', sex_data, 'id', 'text')
# remote referentials
for referential_name in (
'Category',
'ChildIndicator',
'Civility',
'Country',
'CSP',
'DietCode',
'Document',
'Organ',
'PAI',
'Quality',
'Quotient',
'RLIndicator',
'Situation',
'Street',
'Vaccin',
):
id_key, text_key = 'code', 'libelle'
data = self.get_referential_data('Family', referential_name)
if referential_name == 'Organ':
id_key, text_key = 'id', 'code'
elif referential_name == 'Street':
id_key, text_key = 'idStreet', 'libelleStreet'
self.update_referential(referential_name, data, id_key, text_key)
def update_site_referentials(self):
for referential_name in ('YearSchool', 'Level', 'DerogReason'):
id_key, text_key = 'code', 'libelle'
data = self.get_referential_data('Site', referential_name)
if referential_name == 'YearSchool':
id_key, text_key = 'schoolYear', 'schoolYear'
self.update_referential(referential_name, data, id_key, text_key)
def daily(self):
try:
self.update_family_referentials()
self.update_site_referentials()
except UpdateError as e:
self.logger.warning('Erreur sur la mise à jour: %s' % e)
else:
self.logger.info('Réferentiels mis à jour.')
def get_referential(self, referential_name, id=None, q=None, limit=None, distinct=True):
if id is not None:
queryset = self.referential.filter(referential_name=referential_name, item_id=id)
else:
queryset = self.referential.filter(referential_name=referential_name).all()
if q:
queryset = queryset.filter(item_unaccent_text__icontains=simplify(q))
if distinct:
queryset = queryset.distinct('resource', 'referential_name', 'item_text')
if limit:
try:
limit = int(limit)
except ValueError:
pass
else:
queryset = queryset[:limit]
return [x.item_data for x in queryset]
def get_referential_value(self, referential_name, key):
try:
return self.referential.get(referential_name=referential_name, item_id=key).item_text
except Referential.DoesNotExist:
self.logger.warning("No '%s' key into Maelis '%s' referential", key, referential_name)
return key
def get_link(self, NameID):
try:
return self.link_set.get(name_id=NameID)
except Link.DoesNotExist:
raise APIError('User not linked to family', err_code='not-linked')
def get_family_raw(self, family_id, **kwargs):
response = self.call('Family', 'readFamily', dossierNumber=family_id, **kwargs)
data = serialize_object(response)
return data
def get_rl_raw(self, family_id, rl_id, **kwargs):
data = self.get_family_raw(family_id, **kwargs)
if data['RL1']['num'] == rl_id:
return data['RL1']
elif data['RL2'] and data['RL2']['num'] == rl_id:
return data['RL2']
raise APIError("no '%s' RL on '%s' family" % (rl_id, family_id), err_code='not-found')
def get_person_raw(self, family_id, person_id):
data = self.get_family_raw(family_id)
for person in data['emergencyPersonList']:
if str(person['numPerson']) == person_id:
return person
raise APIError(
"no '%s' emergency person on '%s' family" % (person_id, family_id), err_code='not-found'
)
def get_child_raw(self, family_id, child_id):
data = self.get_family_raw(family_id)
for child in data['childList']:
if child['num'] == child_id:
return child
raise APIError("no '%s' child on '%s' family" % (child_id, family_id), err_code='not-found')
def get_child_person_raw(self, family_id, child_id, person_id):
data = self.get_child_raw(family_id, child_id)
for person in data['authorizedPersonList']:
if str(person['personInfo']['num']) == person_id:
return person
raise APIError(
"no '%s' authorized person on '%s' child" % (person_id, child_id), err_code='not-found'
)
def add_text_value(self, referential_name, data, keys):
'''add text from referentials'''
last_key = keys.pop()
for key in keys:
if not isinstance(data, dict) or not key in data:
return
data = data[key]
if isinstance(data, dict) and last_key in data and data[last_key] is not None:
data[last_key + '_text'] = self.get_referential_value(referential_name, data[last_key])
def add_indicators_field(self, referential_name, data):
active_indicators = {x['code']: x for x in data['indicatorList']}
indicators = self.get_referential(referential_name)
result = {}
for item in indicators:
active_indicator = active_indicators.get(item['id']) or {}
item['isActive'] = bool(active_indicator)
if item['typeDesc'] == 'NOTE':
item['note'] = active_indicator.get('note')
del item['choiceList'] # no list based indicator on parsifal project
result[item['id']] = item
data['indicators'] = result
def add_text_value_to_rl_indicator(self, data):
self.add_text_value('RLIndicator', data, ['code'])
def add_text_value_to_child_indicator(self, data):
self.add_text_value('ChildIndicator', data, ['code'])
def add_text_value_to_child_person(self, data):
self.add_text_value('Civility', data, ['personInfo', 'civility'])
self.add_text_value('Quality', data, ['personQuality', 'code'])
self.add_text_value('Sex', data, ['personInfo', 'sexe'])
def add_text_value_to_child(self, data):
self.add_text_value('Sex', data, ['sexe'])
self.add_text_value('DietCode', data, ['dietcode'])
self.add_text_value('PAI', data, ['paiInfoBean', 'code'])
for person in data['authorizedPersonList']:
self.add_text_value_to_child_person(person)
for indicator in data['indicatorList']:
self.add_text_value_to_child_indicator(indicator)
self.add_indicators_field('ChildIndicator', data)
def add_text_value_to_person(self, data):
self.add_text_value('Civility', data, ['civility'])
self.add_text_value('Quality', data, ['quality'])
self.add_text_value('Sex', data, ['sexe'])
def add_text_value_to_rl(self, data):
self.add_text_value('Civility', data, ['civility'])
self.add_text_value('Quality', data, ['quality'])
self.add_text_value('Complement', data, ['adresse', 'numComp'])
self.add_text_value('Street', data, ['adresse', 'idStreet'])
self.add_text_value('CSP', data, ['profession', 'codeCSP'])
self.add_text_value('Organ', data, ['CAFInfo', 'organ'])
for indicator in data['indicatorList']:
self.add_text_value_to_rl_indicator(indicator)
for quotient in data['quotientList']:
self.add_text_value('Quotient', quotient, ['cdquo'])
self.add_indicators_field('RLIndicator', data)
def add_text_value_to_family(self, data):
self.add_text_value('Category', data, ['category'])
self.add_text_value('Situation', data, ['situation'])
for rlg in 'RL1', 'RL2':
if data.get(rlg):
self.add_text_value_to_rl(data[rlg])
for child in data['childList']:
self.add_text_value_to_child(child)
for person in data['emergencyPersonList']:
self.add_text_value_to_person(person)
def get_child_person(self, family_id, child_id, person_id):
data = self.get_child_person_raw(family_id, child_id, person_id)
self.add_text_value_to_child_person(data)
return data
def get_child(self, family_id, child_id):
data = self.get_child_raw(family_id, child_id)
self.add_text_value_to_child(data)
return data
def get_person(self, family_id, person_id):
data = self.get_person_raw(family_id, person_id)
self.add_text_value_to_person(data)
return data
def get_rl(self, family_id, rl_id, **kwargs):
data = self.get_rl_raw(family_id, rl_id, **kwargs)
self.add_text_value_to_rl(data)
return data
def get_family(self, family_id, **kwargs):
data = self.get_family_raw(family_id, **kwargs)
self.add_text_value_to_family(data)
return data
def assert_key_in_referential(self, referential_name, key_value, keys_text, required=True):
if not key_value:
if required:
raise APIError("%s is required and could not be None" % keys_text, err_code='field-required')
return
try:
self.referential.get(referential_name=referential_name, item_id=key_value)
except Referential.DoesNotExist:
ref_text = "required " if required else ""
ref_text = ref_text + "referential"
raise APIError(
"%s key value '%s' do not belong to '%s' %s"
% (keys_text, key_value, referential_name, ref_text),
err_code='wrong-key',
)
def assert_post_data_in_referential(self, referential_name, data, keys, required=True):
key_value = None
for key in keys:
if not (isinstance(data, list) and isinstance(key, int)) and not (
isinstance(data, dict) and key in data
):
break
data = data[key]
else:
key_value = data
self.assert_key_in_referential(referential_name, key_value, '/'.join(str(x) for x in keys), required)
def encode_bool(self, obj):
if obj is True or str(obj).lower() in ['true', 'oui', '1']:
return True
if obj is False or str(obj).lower() in ['false', 'non', '0']:
return False
def assert_update_indicator_payload_in_referential(self, referential, post_data, parent_keys=None):
keys = parent_keys or []
data = post_data
for key in keys:
data = data[key]
for i, item in enumerate(data.get('indicatorList', [])):
self.assert_post_data_in_referential(
referential, post_data, keys + ['indicatorList', i, 'code'], required=True
)
item['isActive'] = self.encode_bool(item['isActive'])
def assert_child_medical_record_payload_in_referential(self, post_data, parent_keys=None):
keys = parent_keys or []
data = post_data
for key in keys:
data = data[key]
if 'isAuthHospital' in data:
data['isAuthHospital'] = self.encode_bool(data['isAuthHospital'])
for i in range(0, len(data.get('vaccinList', []))):
self.assert_post_data_in_referential(
'Vaccin', post_data, keys + ['vaccinList', i, 'code'], required=False
)
def assert_child_pai_payoad_in_referential(self, post_data, parent_keys=None):
keys = parent_keys or []
self.assert_post_data_in_referential('PAI', post_data, keys + ['code'])
def assert_child_person_payload_in_referential(self, post_data, parent_keys=None):
keys = parent_keys or []
self.assert_post_data_in_referential(
'Civility', post_data, keys + ['personInfo', 'civility'], required=False
)
self.assert_post_data_in_referential('Sex', post_data, keys + ['personInfo', 'sexe'], required=False)
self.assert_post_data_in_referential('Quality', post_data, keys + ['personQuality', 'code'])
def assert_child_payload_in_referential(self, post_data, parent_keys=None):
keys = parent_keys or []
self.assert_post_data_in_referential('Sex', post_data, keys + ['sexe'])
data = post_data
for key in keys:
data = data[key]
for key in ('bPhoto', 'bLeaveAlone'):
if key in data:
data[key] = self.encode_bool(data[key])
if 'dietcode' in data:
self.assert_post_data_in_referential('DietCode', post_data, keys + ['dietcode'], required=False)
if 'paiInfoBean' in data:
self.assert_child_pai_payoad_in_referential(post_data, keys + ['paiInfoBean'])
if 'medicalRecord' in data:
# dead code as updateFamily seems not to modify medicalRecord
self.assert_child_medical_record_payload_in_referential(post_data, keys + ['medicalRecord'])
self.assert_update_indicator_payload_in_referential('ChildIndicator', post_data, keys)
def assert_person_payload_in_referential(self, post_data, parent_keys=None):
keys = parent_keys or []
self.assert_post_data_in_referential('Civility', post_data, keys + ['civility'], required=False)
self.assert_post_data_in_referential('Sex', post_data, keys + ['sexe'], required=False)
self.assert_post_data_in_referential('Quality', post_data, keys + ['quality'])
def assert_update_coordinate_payload_in_referential(self, post_data, parent_keys=None):
keys = parent_keys or []
self.assert_post_data_in_referential(
'Street', post_data, keys + ['adresse', 'idStreet'], required=False
)
self.assert_post_data_in_referential(
'Complement', post_data, keys + ['adresse', 'numComp'], required=False
)
self.assert_post_data_in_referential(
'CSP', post_data, keys + ['profession', 'codeCSP'], required=False
)
self.assert_post_data_in_referential('Organ', post_data, keys + ['CAFInfo', 'organ'], required=False)
data = post_data
for key in keys:
data = data[key]
if 'contact' in data:
data = data['contact']
for key in ('isContactMail', 'isContactSms', 'isInvoicePdf'):
if key in data:
data[key] = self.encode_bool(data[key])
def assert_rl_payload_in_referential(self, post_data, parent_keys=None):
keys = parent_keys or []
self.assert_post_data_in_referential('Civility', post_data, keys + ['civility'])
self.assert_post_data_in_referential('Quality', post_data, keys + ['quality'])
self.assert_update_coordinate_payload_in_referential(post_data, keys)
self.assert_update_indicator_payload_in_referential('RLIndicator', post_data, keys)
def assert_create_rl1_payload_in_referential(self, post_data):
self.assert_post_data_in_referential('Category', post_data, ['category'])
self.assert_post_data_in_referential('Situation', post_data, ['situation'])
self.assert_rl_payload_in_referential(post_data, ['rl1'])
def assert_family_payload_in_referential(self, post_data):
self.assert_post_data_in_referential('Category', post_data, ['category'])
self.assert_post_data_in_referential('Situation', post_data, ['situation'])
for rlg in 'rl1', 'rl2':
if rlg in post_data:
self.assert_rl_payload_in_referential(post_data, [rlg])
for i, person in enumerate(post_data.get('emergencyPersonList') or []):
for j in range(0, len(person.get('personList') or [])):
self.assert_person_payload_in_referential(
post_data, ['emergencyPersonList', i, 'personList', j]
)
for i in range(0, len(post_data.get('childList') or [])):
self.assert_child_payload_in_referential(post_data, ['childList', i])
if 'flagCom' in post_data:
post_data['flagCom'] = self.encode_bool(post_data['flagCom'])
def replace_null_values(self, dico):
'''send null fields as empty SOAP tag to tell maelis to empty the value'''
for key, value in dico.items():
if isinstance(value, dict):
self.replace_null_values(value)
if value is None:
dico[key] = ''
def get_person_activity_list_raw(
self, family_id, person_id, nature_id=None, reference_year=None, start_date=None, end_date=None
):
params = {
'numDossier': family_id,
'numPerson': person_id,
'codeNatureActivity': nature_id,
'yearSchool': reference_year,
'dateStartActivity': start_date,
'dateEndActivity': end_date,
}
response = self.call(
'Activity', 'getPersonCatalogueActivity', getPersonCatalogueActivityRequestBean=params
)
data = serialize_object(response)
return data
@endpoint(
display_category='Famille',
description='Liste des catégories',
name='read-category-list',
perm='can_access',
parameters={
'id': {'description': 'Identifiant de lenregistrement'},
'q': {'description': 'Recherche en texte intégral'},
'limit': {'description': 'Nombre maximal de résultats; doit être inférieur à 20.'},
'distinct': {'description': 'Supression des doublons'},
},
)
def read_category_list(self, request, id=None, q=None, limit=None, distinct=True):
return {'data': self.get_referential('Category', id, q, limit, distinct)}
@endpoint(
display_category='Famille',
description='Liste des indicateurs sur le enfants',
name='read-child-indicator-list',
perm='can_access',
parameters={
'id': {'description': 'Identifiant de lenregistrement'},
'q': {'description': 'Recherche en texte intégral'},
'limit': {'description': 'Nombre maximal de résultats; doit être inférieur à 20.'},
'distinct': {'description': 'Supression des doublons'},
},
)
def read_child_indicator_list(self, request, id=None, q=None, limit=None, distinct=True):
return {'data': self.get_referential('ChildIndicator', id, q, limit, distinct)}
@endpoint(
display_category='Famille',
description='Liste des civilités',
name='read-civility-list',
perm='can_access',
parameters={
'id': {'description': 'Identifiant de lenregistrement'},
'q': {'description': 'Recherche en texte intégral'},
'limit': {'description': 'Nombre maximal de résultats; doit être inférieur à 20.'},
'distinct': {'description': 'Supression des doublons'},
},
)
def read_civility_list(self, request, id=None, q=None, limit=None, distinct=True):
return {'data': self.get_referential('Civility', id, q, limit, distinct)}
@endpoint(
display_category='Famille',
description='Liste des compléments du numéro de voie',
name='read-complement-list',
perm='can_access',
parameters={
'id': {'description': 'Identifiant de lenregistrement'},
'q': {'description': 'Recherche en texte intégral'},
'limit': {'description': 'Nombre maximal de résultats; doit être inférieur à 20.'},
'distinct': {'description': 'Supression des doublons'},
},
)
def read_complement_list(self, request, id=None, q=None, limit=None, distinct=True):
return {'data': self.get_referential('Complement', id, q, limit, distinct)}
@endpoint(
display_category='Famille',
description='Liste des pays',
name='read-country-list',
perm='can_access',
parameters={
'id': {'description': 'Identifiant de lenregistrement'},
'q': {'description': 'Recherche en texte intégral'},
'limit': {'description': 'Nombre maximal de résultats; doit être inférieur à 20.'},
'distinct': {'description': 'Supression des doublons'},
},
)
def read_country_list(self, request, id=None, q=None, limit=None, distinct=True):
return {'data': self.get_referential('Country', id, q, limit, distinct)}
@endpoint(
display_category='Famille',
description='liste des catégories socio-professionnelles',
name='read-csp-list',
perm='can_access',
parameters={
'id': {'description': 'Identifiant de lenregistrement'},
'q': {'description': 'Recherche en texte intégral'},
'limit': {'description': 'Nombre maximal de résultats'},
'distinct': {'description': 'Supression des doublons'},
},
)
def read_csp_list(self, request, id=None, q=None, limit=None, distinct=True):
return {'data': self.get_referential('CSP', id, q, limit, distinct)}
@endpoint(
display_category='Famille',
description='Liste des régimes alimentaires',
name='read-dietcode-list',
perm='can_access',
parameters={
'id': {'description': 'Identifiant de lenregistrement'},
'q': {'description': 'Recherche en texte intégral'},
'limit': {'description': 'Nombre maximal de résultats; doit être inférieur à 20.'},
'distinct': {'description': 'Supression des doublons'},
},
)
def read_dietcode_list(self, request, id=None, q=None, limit=None, distinct=True):
return {'data': self.get_referential('DietCode', id, q, limit, distinct)}
@endpoint(
display_category='Famille',
description='Liste des pièces jointes',
name='read-document-list',
perm='can_access',
parameters={
'id': {'description': 'Identifiant de lenregistrement'},
'q': {'description': 'Recherche en texte intégral'},
'limit': {'description': 'Nombre maximal de résultats; doit être inférieur à 20.'},
'distinct': {'description': 'Supression des doublons'},
},
)
def read_document_list(self, request, id=None, q=None, limit=None, distinct=True):
return {'data': self.get_referential('Document', id, q, limit, distinct)}
@endpoint(
display_category='Famille',
description='Liste des organismes (CAF)',
name='read-organ-list',
perm='can_access',
parameters={
'id': {'description': 'Identifiant de lenregistrement'},
'q': {'description': 'Recherche en texte intégral'},
'limit': {'description': 'Nombre maximal de résultats; doit être inférieur à 20.'},
'distinct': {'description': 'Supression des doublons'},
},
)
def read_organ_list(self, request, id=None, q=None, limit=None, distinct=True):
return {'data': self.get_referential('Organ')}
@endpoint(
display_category='Famille',
description="Liste des projet d'accueil individualisés",
name='read-pai-list',
perm='can_access',
parameters={
'id': {'description': 'Identifiant de lenregistrement'},
'q': {'description': 'Recherche en texte intégral'},
'limit': {'description': 'Nombre maximal de résultats; doit être inférieur à 20.'},
'distinct': {'description': 'Supression des doublons'},
},
)
def read_pai_list(self, request, id=None, q=None, limit=None, distinct=True):
return {'data': self.get_referential('PAI', id, q, limit, distinct)}
@endpoint(
display_category='Famille',
description='liste des qualités du référenciel',
name='read-quality-list',
perm='can_access',
parameters={
'id': {'description': 'Identifiant de lenregistrement'},
'q': {'description': 'Recherche en texte intégral'},
'limit': {'description': 'Nombre maximal de résultats; doit être inférieur à 20.'},
'distinct': {'description': 'Supression des doublons'},
},
)
def read_quality_list(self, request, id=None, q=None, limit=None, distinct=True):
return {'data': self.get_referential('Quality', id, q, limit, distinct)}
@endpoint(
display_category='Famille',
description='Liste des quotients',
name='read-quotient-list',
perm='can_access',
parameters={
'id': {'description': 'Identifiant de lenregistrement'},
'q': {'description': 'Recherche en texte intégral'},
'limit': {'description': 'Nombre maximal de résultats; doit être inférieur à 20.'},
'distinct': {'description': 'Supression des doublons'},
},
)
def read_quotient_list(self, request, id=None, q=None, limit=None, distinct=True):
return {'data': self.get_referential('Quotient', id, q, limit, distinct)}
@endpoint(
display_category='Famille',
description='Liste des indicateurs sur les responsables légaux',
name='read-rl-indicator-list',
perm='can_access',
parameters={
'id': {'description': 'Identifiant de lenregistrement'},
'q': {'description': 'Recherche en texte intégral'},
'limit': {'description': 'Nombre maximal de résultats; doit être inférieur à 20.'},
'distinct': {'description': 'Supression des doublons'},
},
)
def read_rl_indicator_list(self, request, id=None, q=None, limit=None, distinct=True):
return {'data': self.get_referential('RLIndicator')}
@endpoint(
display_category='Famille',
description='Liste des sexes',
name='read-sex-list',
perm='can_access',
parameters={
'id': {'description': 'Identifiant de lenregistrement'},
'q': {'description': 'Recherche en texte intégral'},
'limit': {'description': 'Nombre maximal de résultats; doit être inférieur à 20.'},
'distinct': {'description': 'Supression des doublons'},
},
)
def read_sex_list(self, request, id=None, q=None, limit=None, distinct=True):
return {'data': self.get_referential('Sex', id, q, limit, distinct)}
@endpoint(
display_category='Famille',
description='liste des situations',
name='read-situation-list',
perm='can_access',
parameters={
'id': {'description': 'Identifiant de lenregistrement'},
'q': {'description': 'Recherche en texte intégral'},
'limit': {'description': 'Nombre maximal de résultats'},
'distinct': {'description': 'Supression des doublons'},
},
)
def read_situation_list(self, request, id=None, q=None, limit=None, distinct=True):
return {'data': self.get_referential('Situation', id, q, limit, distinct)}
@endpoint(
display_category='Famille',
description='liste des voies',
name='read-street-list',
perm='can_access',
parameters={
'id': {'description': 'Identifiant de lenregistrement'},
'q': {'description': 'Recherche en texte intégral'},
'limit': {'description': 'Nombre maximal de résultats; doit être inférieur à 20.'},
'distinct': {'description': 'Supression des doublons'},
},
)
def read_street_list(self, request, id=None, q=None, limit=None, distinct=True):
return {'data': self.get_referential('Street', id, q, limit, distinct)}
@endpoint(
display_category='Famille',
description='Liste des vaccins',
name='read-vaccin-list',
perm='can_access',
parameters={
'id': {'description': 'Identifiant de lenregistrement'},
'q': {'description': 'Recherche en texte intégral'},
'limit': {'description': 'Nombre maximal de résultats; doit être inférieur à 20.'},
'distinct': {'description': 'Supression des doublons'},
},
)
def read_vaccin_list(self, request, id=None, q=None, limit=None, distinct=True):
return {'data': self.get_referential('Vaccin', id, q, limit, distinct)}
@endpoint(
display_category='Famille',
description='Lier un compte usager à une famille',
perm='can_access',
parameters={'NameID': {'description': 'Publik NameID'}},
post={'request_body': {'schema': {'application/json': schemas.LINK_SCHEMA}}},
)
def link(self, request, NameID, post_data):
family_id = post_data['family_id']
response = self.call('Family', 'readFamily', dossierNumber=family_id)
if not (
response['RL1']['firstname'] == post_data['firstname'].upper()
and response['RL1']['lastname'] == post_data['lastname'].upper()
and response['RL1']['birth']['dateBirth'].strftime('%Y-%m-%d') == post_data['dateBirth']
):
raise APIError("RL1 does not match '%s' family" % family_id, err_code='not-found')
Link.objects.update_or_create(resource=self, name_id=NameID, defaults={'family_id': family_id})
return {'data': 'ok'}
@endpoint(
display_category='Famille',
description='Supprimer une liaison entre un compte usager et une famille',
methods=['post'],
perm='can_access',
parameters={
'NameID': {'description': 'Publik NameID'},
},
)
def unlink(self, request, NameID):
link = self.get_link(NameID)
link.delete()
return {'data': 'ok'}
@endpoint(
display_category='Famille',
description='Informations sur la famille',
perm='can_access',
name='read-family',
parameters={
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
'income_year': {'description': 'Année de revenu pour filtrer les quotients'},
},
)
def read_family(self, request, NameID=None, family_id=None, income_year=None):
family_id = family_id or self.get_link(NameID).family_id
data = self.get_family(family_id, incomeYear=income_year)
data['family_id'] = family_id
return {'data': data}
@endpoint(
display_category='Famille',
description="Liste des responsables légaux",
perm='can_access',
name='read-rl-list',
parameters={
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
'text_template': {
'description': 'template utilisée pour la valeur text',
'example_value': '{{ lastname }} {{ firstname }}',
},
'income_year': {'description': 'Année de revenu pour filtrer les quotients'},
},
)
def read_rl_list(self, request, NameID=None, family_id=None, text_template=None, income_year=None):
family_id = family_id or self.get_link(NameID).family_id
result = self.get_family_raw(family_id, incomeYear=income_year)
if not text_template:
text_template = '{{ lastname }} {{ firstname }}'
data = []
for rlg in 'RL1', 'RL2':
item = result.get(rlg)
self.add_text_value_to_rl(item)
if not item:
break
item['id'] = item['num']
item['text'] = render_to_string(text_template, item).strip()
item['family_id'] = family_id
data.append(item)
return {'data': data}
@endpoint(
display_category='Famille',
description="Liste des personnes à prévenir en cas d'urgence",
perm='can_access',
name='read-person-list',
parameters={
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
'text_template': {
'description': 'template utilisée pour la valeur text',
'example_value': '{{ lastname }} {{ firstname }}',
},
},
)
def read_person_list(self, request, NameID=None, family_id=None, text_template=None):
family_id = family_id or self.get_link(NameID).family_id
result = self.get_family_raw(family_id)
if not text_template:
text_template = '{{ lastname }} {{ firstname }}'
data = []
for item in result['emergencyPersonList']:
self.add_text_value_to_person(item)
item['id'] = item['numPerson']
item['text'] = render_to_string(text_template, item).strip()
item['family_id'] = family_id
data.append(item)
return {'data': data}
@endpoint(
display_category='Famille',
description="Liste des enfants",
perm='can_access',
name='read-child-list',
parameters={
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
'text_template': {
'description': 'template utilisée pour la valeur text',
'example_value': '{{ lastname }} {{ firstname }}',
},
},
)
def read_child_list(self, request, NameID=None, family_id=None, text_template=None):
family_id = family_id or self.get_link(NameID).family_id
result = self.get_family_raw(family_id)
if not text_template:
text_template = '{{ lastname }} {{ firstname }}'
data = []
for item in result['childList']:
self.add_text_value_to_child(item)
item['id'] = item['num']
item['text'] = render_to_string(text_template, item).strip()
item['family_id'] = family_id
data.append(item)
return {'data': data}
@endpoint(
display_category='Famille',
description="Liste des personnes autorisées à récupérer l'enfant",
perm='can_access',
name='read-child-person-list',
parameters={
'child_id': {'description': "Numéro de l'enfant"},
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
'text_template': {
'description': 'template utilisée pour la valeur text',
'example_value': '{{ personInfo.lastname }} {{ personInfo.firstname }}',
},
},
)
def read_child_person_list(self, request, child_id, NameID=None, family_id=None, text_template=None):
family_id = family_id or self.get_link(NameID).family_id
result = self.get_child_raw(family_id, child_id)
if not text_template:
text_template = '{{ personInfo.lastname }} {{ personInfo.firstname }}'
data = []
for item in result['authorizedPersonList']:
self.add_text_value_to_child_person(item)
item['id'] = item['personInfo']['num']
item['text'] = render_to_string(text_template, item).strip()
item['family_id'] = family_id
data.append(item)
return {'data': data}
@endpoint(
display_category='Famille',
description="Informations sur un responsable légal",
perm='can_access',
name='read-rl',
parameters={
'rl_id': {'description': 'Numéro du représentant légal'},
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
'income_year': {'description': 'Année de revenu pour filtrer les quotients'},
},
)
def read_rl(
self,
request,
rl_id,
NameID=None,
family_id=None,
income_year=None,
):
family_id = family_id or self.get_link(NameID).family_id
data = self.get_rl(family_id, rl_id, incomeYear=income_year)
data['family_id'] = family_id
return {'data': data}
@endpoint(
display_category='Famille',
description="Informations sur une personne autorisée à récupérer les enfants",
perm='can_access',
name='read-person',
parameters={
'person_id': {'description': 'Numéro de la personne'},
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
},
)
def read_person(self, request, person_id, NameID=None, family_id=None):
family_id = family_id or self.get_link(NameID).family_id
data = self.get_person(family_id, person_id)
data['family_id'] = family_id
return {'data': data}
@endpoint(
display_category='Famille',
description="Informations sur un enfant",
perm='can_access',
name='read-child',
parameters={
'child_id': {'description': "Numéro de l'enfant"},
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
},
)
def read_child(self, request, child_id, NameID=None, family_id=None):
family_id = family_id or self.get_link(NameID).family_id
data = self.get_child(family_id, child_id)
data['family_id'] = family_id
return {'data': data}
@endpoint(
display_category='Famille',
description="Informations sur une personne autorisée à récupérer l'enfant",
perm='can_access',
name='read-child-person',
parameters={
'child_id': {'description': "Numéro de l'enfant"},
'person_id': {'description': 'Numéro de la personne'},
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
},
)
def read_child_person(self, request, child_id, person_id, NameID=None, family_id=None):
family_id = family_id or self.get_link(NameID).family_id
data = self.get_child_person(family_id, child_id, person_id)
data['family_id'] = family_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': 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': 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': family_schemas.CREATE_FAMILY_SCHEMA}}},
)
def create_family(self, request, post_data, NameID=None):
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)
family_id = data.get('number')
if not family_id:
errors = data.get('rl1ErrorList') + data.get('childErrorList')
err_codes = [x.split(':')[0][:4] for x in errors]
raise APIError(' ; '.join(errors), err_code=', '.join(err_codes))
if NameID:
Link.objects.create(resource=self, name_id=NameID, family_id=family_id)
return {'data': data}
@endpoint(
display_category='Famille',
description='Modification de la famille',
name='update-family',
perm='can_access',
parameters={
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
},
post={'request_body': {'schema': {'application/json': family_schemas.UPDATE_FAMILY_SCHEMA}}},
)
def update_family(self, request, post_data, NameID=None, family_id=None):
family_id = family_id or 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', [])):
persons = post_data.pop('emergencyPersonList')
post_data['emergencyPersonList'] = [{'personList': persons}]
response = self.call('Family', 'updateFamily', dossierNumber=family_id, **post_data)
data = serialize_object(response)
family_id = data.get('number')
errors = data.get('childErrorList')
if errors:
err_codes = [x.split(':')[0][:4] for x in errors]
raise APIError(' ; '.join(errors), err_code=', '.join(err_codes))
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': family_schemas.CREATE_RL1_SCHEMA}}},
)
def create_rl1(self, request, post_data, NameID=None):
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)
family_id = data.get('number')
if not family_id:
errors = data.get('rl1ErrorList') or []
raise APIError(' ; '.join(errors), err_code='already-rl1')
if NameID:
Link.objects.create(resource=self, name_id=NameID, family_id=family_id)
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'},
'family_id': {'description': 'Numéro de DUI'},
},
post={'request_body': {'schema': {'application/json': family_schemas.UPDATE_RL1_SCHEMA}}},
)
def update_rl1(self, request, post_data, NameID=None, family_id=None):
family_id = family_id or 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
rl1['adresse'] = family['RL1']['adresse']
payload = {
'dossierNumber': family_id,
'category': family['category'],
'situation': family['situation'],
'flagCom': family['flagCom'],
'nbChild': family['nbChild'],
'nbTotalChild': family['nbTotalChild'],
'nbAES': family['nbAES'],
'rl1': rl1,
}
self.call('Family', 'updateFamily', **payload)
return {'data': 'ok'}
@endpoint(
display_category='Famille',
description='Création du RL2',
name='create-rl2',
perm='can_access',
parameters={
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
},
post={'request_body': {'schema': {'application/json': family_schemas.CREATE_RL2_SCHEMA}}},
)
def create_rl2(self, request, post_data, NameID=None, family_id=None):
family_id = family_id or 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')
payload = {
'dossierNumber': family_id,
'category': family['category'],
'situation': family['situation'],
'flagCom': family['flagCom'],
'nbChild': family['nbChild'],
'nbTotalChild': family['nbTotalChild'],
'nbAES': family['nbAES'],
'rl2': post_data,
}
response = self.call('Family', 'updateFamily', **payload)
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'},
'family_id': {'description': 'Numéro de DUI'},
},
post={'request_body': {'schema': {'application/json': family_schemas.UPDATE_RL2_SCHEMA}}},
)
def update_rl2(self, request, post_data, NameID=None, family_id=None):
family_id = family_id or 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')
rl2 = post_data
rl2['adresse'] = family['RL2']['adresse']
payload = {
'dossierNumber': family_id,
'category': family['category'],
'situation': family['situation'],
'flagCom': family['flagCom'],
'nbChild': family['nbChild'],
'nbTotalChild': family['nbTotalChild'],
'nbAES': family['nbAES'],
'rl2': rl2,
}
self.call('Family', 'updateFamily', **payload)
return {'data': 'ok'}
@endpoint(
display_category='Famille',
description="Ajout d'un enfant",
name='create-child',
perm='can_access',
parameters={
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
'force': {
'description': 'boolean to bypass doublon error',
'type': 'bool',
'example_value': 'false',
},
},
post={'request_body': {'schema': {'application/json': family_schemas.CREATE_CHILD_SCHEMA}}},
)
def create_child(self, request, post_data, NameID=None, family_id=None, force=False):
family_id = family_id or self.get_link(NameID).family_id
self.assert_child_payload_in_referential(post_data)
payload = {
'numDossier': family_id,
'isForceCreateChild': force,
'child': post_data,
}
response = self.call('Family', 'createChild', **payload)
data = serialize_object(response)
child_id = data.get('number')
if not child_id:
errors = data.get('childErrorList') or []
raise APIError(' ; '.join(errors), err_code='already-child')
return {'data': {'child_id': child_id}}
@endpoint(
display_category='Famille',
description="Modification d'un enfant",
name='update-child',
perm='can_access',
parameters={
'child_id': {'description': "Numéro de l'enfant"},
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
},
post={'request_body': {'schema': {'application/json': family_schemas.UPDATE_CHILD_SCHEMA}}},
)
def update_child(self, request, post_data, child_id, NameID=None, family_id=None):
family_id = family_id or 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
child['num'] = child_id
for known_child in family['childList']:
if str(known_child['num']) == child_id:
child['authorizedPersonList'] = known_child['authorizedPersonList']
break
else:
raise APIError('No child %s to update on family' % child_id, err_code='no-child')
payload = {
'dossierNumber': family_id,
'category': family['category'],
'situation': family['situation'],
'flagCom': family['flagCom'],
'nbChild': family['nbChild'],
'nbTotalChild': family['nbTotalChild'],
'nbAES': family['nbAES'],
'childList': [child],
}
self.call('Family', 'updateFamily', **payload)
return {'data': 'ok'}
@endpoint(
display_category='Famille',
description="Mise à jour des coordonnées d'un responsable légal",
name='update-coordinate',
perm='can_access',
parameters={
'rl_id': {'description': 'Numéro du représentant légal'},
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
},
post={'request_body': {'schema': {'application/json': family_schemas.UPDATE_COORDINATE_SCHEMA}}},
)
def update_coordinate(self, request, post_data, rl_id, NameID=None, family_id=None):
family_id = family_id or 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'}
@endpoint(
display_category='Famille',
description="Mise à jour des indicateurs d'un responsable légal",
name='update-rl-indicator',
perm='can_access',
parameters={
'rl_id': {'description': 'Numéro du représentant légal'},
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
},
post={'request_body': {'schema': {'application/json': family_schemas.UPDATE_INDICATOR_SCHEMA}}},
)
def update_rl_indicator(self, request, post_data, rl_id, NameID=None, family_id=None):
assert family_id or 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'}
@endpoint(
display_category='Famille',
description="Créer ou mettre à jour un quotient d'un responsable légal",
name='update-quotient',
perm='can_access',
parameters={
'rl_id': {'description': "Numéro du responsable légal"},
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
},
post={'request_body': {'schema': {'application/json': family_schemas.UPDATE_QUOTIENT_SCHEMA}}},
)
def update_quotient(self, request, post_data, rl_id, NameID=None, family_id=None):
family_id = family_id or self.get_link(NameID).family_id
self.assert_post_data_in_referential('Quotient', post_data, ['cdquo'])
payload = {
'dossierNumber': family_id,
'personNumber': rl_id,
'quotient': post_data,
}
self.call('Family', 'createUpdateQuotient', **payload)
return {'data': 'ok'}
@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'},
'family_id': {'description': 'Numéro de DUI'},
},
post={'request_body': {'schema': {'application/json': family_schemas.EMERGENCY_PERSON_SCHEMA}}},
)
def create_person(self, request, post_data, NameID=None, family_id=None):
family_id = family_id or 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)
payload = {
'dossierNumber': family_id,
'category': family['category'],
'situation': family['situation'],
'flagCom': family['flagCom'],
'nbChild': family['nbChild'],
'nbTotalChild': family['nbTotalChild'],
'nbAES': family['nbAES'],
'emergencyPersonList': [{'personList': personList}],
}
self.call('Family', 'updateFamily', **payload)
return {'data': 'ok'}
@endpoint(
display_category='Famille',
description="Mise à jour d'une personne à prévenir en cas d'urgence",
name='update-person',
perm='can_access',
parameters={
'person_id': {'description': 'Numéro de la personne'},
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
},
post={'request_body': {'schema': {'application/json': family_schemas.EMERGENCY_PERSON_SCHEMA}}},
)
def update_person(self, request, post_data, person_id, NameID=None, family_id=None):
family_id = family_id or 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):
if str(person['numPerson']) == person_id:
personList[i] = post_data
personList[i]['numPerson'] = person_id
break
else:
raise APIError(
"no '%s' authorized person on '%s' family" % (person_id, family_id), err_code='not-found'
)
payload = {
'dossierNumber': family_id,
'category': family['category'],
'situation': family['situation'],
'flagCom': family['flagCom'],
'nbChild': family['nbChild'],
'nbTotalChild': family['nbTotalChild'],
'nbAES': family['nbAES'],
'emergencyPersonList': [{'personList': personList}],
}
self.call('Family', 'updateFamily', **payload)
return {'data': 'ok'}
@endpoint(
display_category='Famille',
description="Suppression d'une personne à prévenir en cas d'urgence",
name='delete-person',
perm='can_access',
parameters={
'person_id': {'description': 'Numéro de la personne'},
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
},
methods=['post'],
)
def delete_person(self, request, person_id, NameID=None, family_id=None):
family_id = family_id or self.get_link(NameID).family_id
family = self.get_family_raw(family_id)
personList = family['emergencyPersonList']
for i, person in enumerate(personList):
if str(person['numPerson']) == person_id:
del personList[i]
break
else:
raise APIError(
"no '%s' authorized person on '%s' family" % (person_id, family_id), err_code='not-found'
)
payload = {
'dossierNumber': family_id,
'category': family['category'],
'situation': family['situation'],
'flagCom': family['flagCom'],
'nbChild': family['nbChild'],
'nbTotalChild': family['nbTotalChild'],
'nbAES': family['nbAES'],
'emergencyPersonList': [{'personList': personList}],
}
self.call('Family', 'updateFamily', **payload)
return {'data': 'ok'}
@endpoint(
display_category='Famille',
description="Création d'une personne autorisée à récupérer l'enfant",
name='create-child-person',
perm='can_access',
parameters={
'child_id': {'description': "Numéro de l'enfant"},
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
},
post={'request_body': {'schema': {'application/json': family_schemas.AUTHORIZED_PERSON_SCHEMA}}},
)
def create_child_person(self, request, post_data, child_id, NameID=None, family_id=None):
family_id = family_id or 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)
req = {
'numFamily': family_id,
'numPerson': child_id,
'bLeaveAlone': child['bLeaveAlone'],
'bPhoto': child['bPhoto'],
'personList': personList,
}
self.call('Family', 'updateChildAutorization', updateChildAutorizationRequest=req)
return {'data': 'ok'}
@endpoint(
display_category='Famille',
description="Mise à jour d'une personne autorisée à récupérer l'enfant",
name='update-child-person',
perm='can_access',
parameters={
'child_id': {'description': "Numéro de l'enfant"},
'person_id': {'description': 'Numéro de la personne'},
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
},
post={'request_body': {'schema': {'application/json': family_schemas.AUTHORIZED_PERSON_SCHEMA}}},
)
def update_child_person(self, request, post_data, child_id, person_id, NameID=None, family_id=None):
family_id = family_id or 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):
if str(person['personInfo']['num']) == person_id:
personList[i] = post_data
personList[i]['personInfo']['num'] = person_id
break
else:
raise APIError(
"No '%s' authorized person on '%s' child" % (person_id, child_id), err_code='not-found'
)
req = {
'numFamily': family_id,
'numPerson': child_id,
'bLeaveAlone': child['bLeaveAlone'],
'bPhoto': child['bPhoto'],
'personList': personList,
}
self.call('Family', 'updateChildAutorization', updateChildAutorizationRequest=req)
return {'data': 'ok'}
@endpoint(
display_category='Famille',
description="Suppression d'une personne autorisée à récupérer l'enfant",
name='delete-child-person',
perm='can_access',
parameters={
'child_id': {'description': "Numéro de l'enfant"},
'person_id': {'description': 'Numéro de la personne'},
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
},
methods=['post'],
)
def delete_child_person(self, request, child_id, person_id, NameID=None, family_id=None):
family_id = family_id or self.get_link(NameID).family_id
child = self.get_child_raw(family_id, child_id)
personList = child['authorizedPersonList']
for i, person in enumerate(personList):
if str(person['personInfo']['num']) == person_id:
del personList[i]
break
else:
raise APIError(
"No '%s' authorized person on '%s' child" % (person_id, child_id), err_code='not-found'
)
req = {
'numFamily': family_id,
'numPerson': child_id,
'bLeaveAlone': child['bLeaveAlone'],
'bPhoto': child['bPhoto'],
'personList': personList,
}
self.call('Family', 'updateChildAutorization', updateChildAutorizationRequest=req)
return {'data': 'ok'}
@endpoint(
display_category='Famille',
description="Créer ou mettre à jour le régime alimentaire d'un enfant",
name='update-child-dietcode',
perm='can_access',
parameters={
'child_id': {'description': "Numéro de l'enfant"},
'dietcode': {'description': 'code du régime alimentaire'},
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
},
methods=['post'],
)
def update_child_dietcode(self, request, child_id, dietcode, NameID=None, family_id=None):
assert family_id or self.get_link(NameID)
self.assert_key_in_referential('DietCode', dietcode, 'dietcode parameter', required=False)
self.call('Family', 'createOrUpdateChildDiet', personNumber=child_id, code=dietcode)
return {'data': 'ok'}
@endpoint(
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={
'child_id': {'description': "Numéro de l'enfant"},
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
},
post={'request_body': {'schema': {'application/json': family_schemas.PAIINFO_SCHEMA}}},
)
def update_child_pai(self, request, post_data, child_id, NameID=None, family_id=None):
assert family_id or 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] == '':
post_data[key] = None
self.call('Family', 'updateChildPAI', personNumber=child_id, **post_data)
return {'data': 'ok'}
@endpoint(
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={
'child_id': {'description': "Numéro de l'enfant"},
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
},
post={'request_body': {'schema': {'application/json': family_schemas.MEDICALRECORD_SCHEMA}}},
)
def update_child_medical_record(self, request, post_data, child_id, NameID=None, family_id=None):
assert family_id or self.get_link(NameID)
self.assert_child_medical_record_payload_in_referential(post_data)
self.replace_null_values(post_data)
payload = {
'numPerson': child_id,
'medicalRecord': post_data,
}
self.call('Family', 'updateChildMedicalRecord', updateChildMedicalRecordRequest=payload)
return {'data': 'ok'}
@endpoint(
display_category='Famille',
description="Mise à jour des indicateurs d'un enfant",
name='update-child-indicator',
perm='can_access',
parameters={
'child_id': {'description': "Numéro de l'enfant"},
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
},
post={'request_body': {'schema': {'application/json': family_schemas.UPDATE_INDICATOR_SCHEMA}}},
)
def update_child_indicator(self, request, post_data, child_id, NameID=None, family_id=None):
assert family_id or 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'}
@endpoint(
display_category='Famille',
description='Ajoute un document pour une famille, un responsable légal ou un enfant',
name='add-supplied-document',
perm='can_access',
parameters={
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
},
post={'request_body': {'schema': {'application/json': family_schemas.SUPPLIED_DOCUMENTS_SCHEMA}}},
)
def add_supplied_document(self, request, post_data, NameID=None, family_id=None):
family_id = family_id or self.get_link(NameID).family_id
for i in range(0, len(post_data.get('documentList', []))):
self.assert_post_data_in_referential('Document', post_data, ['documentList', i, 'code'])
for item in post_data['documentList']:
file = item.pop('file')
item['filename'] = file['filename']
item['fileSupplied'] = {
'dataHandler': base64.b64decode(file['content']),
'fileType': file['content_type'],
'name': file['filename'],
}
payload = {'addSuppliedDocumentRequestBean': post_data}
payload['addSuppliedDocumentRequestBean']['numDossier'] = family_id
response = self.call('Family', 'addSuppliedDocument', **payload)
data = serialize_object(response)
if data != 'OK':
raise APIError('maelis fails to add the supplied document')
return {'data': 'ok'}
def get_start_and_end_dates(self, start_date, end_date):
try:
start_date = datetime.datetime.strptime(start_date, utils.json_date_format).date()
end_date = datetime.datetime.strptime(end_date, utils.json_date_format).date()
except ValueError:
raise APIError('bad date format, should be YYYY-MM-DD', err_code='bad-request', http_status=400)
if start_date > end_date:
raise APIError(
'start_date should be before end_date',
err_code='bad-request',
http_status=400,
)
reference_year = utils.get_reference_year_from_date(start_date)
end_reference_year = utils.get_reference_year_from_date(end_date)
if reference_year != end_reference_year:
raise APIError(
'start_date and end_date are in different reference year (%s != %s)'
% (reference_year, end_reference_year),
err_code='bad-request',
http_status=400,
)
return start_date, end_date, reference_year
def get_bookings(self, family_id, child_id, start_date, end_date):
bookings = []
for booking_date in rrule.rrule(rrule.MONTHLY, dtstart=start_date.replace(day=1), until=end_date):
payload = {
'requestBean': {
'numDossier': family_id,
'numPerson': child_id,
'year': booking_date.year,
'month': booking_date.month,
}
}
response = self.call('Activity', 'getPersonScheduleList', **payload)
result = serialize_object(response)
for result_data in result or []:
for schedule in result_data['activityScheduleList']:
activity = schedule['activity']
if not activity['activityType']['natureSpec']:
continue
if activity['activityType']['natureSpec']['code'] not in ['A', 'R']:
continue
activity_id = activity['idAct']
many_units = len(schedule['unitScheduleList']) > 1
for unit in schedule['unitScheduleList']:
days = unit['dayInfoList']
for day in days:
if day['status'] in ['NO_READ', 'NO_CUSTODY']:
continue
booking = {
'id': '%s:%s:%s'
% (child_id, activity_id, day['day'].strftime(utils.json_date_format)),
'text': dateformat.format(day['day'], 'l j F Y'),
'prefill': day['scheduledPresence'] > 0 or day['realPresence'] > 1,
'disabled': day['status'] != 'WRITABLE',
'details': day,
}
color = 'white'
if booking['prefill']:
color = 'green'
booking['details']['status_color'] = color
booking['details']['activity_id'] = activity_id
booking['details']['activity_type'] = activity['activityType']['code']
booking['details']['activity_label'] = activity['activityType']['libelle']
if many_units:
booking['details']['activity_label'] += ' (%s)' % unit['unit']['libelle']
booking['details']['child_id'] = child_id
booking['details']['day_str'] = day['day'].strftime(utils.json_date_format)
booking['details']['unit_id'] = unit['unit']['idUnit']
bookings.append(booking)
# sort bookings
activity_types = ['ACCMAT', 'RESTSCOL', 'ACCPERI', 'ACCSOIR']
bookings = [
(
b['details']['day'],
activity_types.index(b['details']['activity_type'])
if b['details']['activity_type'] in activity_types
else 0,
b['details']['activity_label'],
b,
)
for b in bookings
]
bookings = sorted(bookings, key=itemgetter(0, 1, 2))
bookings = [b for d, a, l, b in bookings]
return bookings
@endpoint(
display_category='Réservation',
description="Agenda d'un enfant",
name='read-child-agenda',
perm='can_access',
parameters={
'child_id': {'description': "Numéro de l'enfant"},
'start_date': {'description': 'Début de la période'},
'end_date': {'description': 'Fin de la période'},
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
},
)
def read_child_agenda(self, request, child_id, start_date, end_date, NameID=None, family_id=None):
family_id = family_id or self.get_link(NameID).family_id
start_date, end_date, reference_year = self.get_start_and_end_dates(start_date, end_date)
bookings = self.get_bookings(family_id, child_id, start_date, end_date)
return {
'data': bookings,
'extra_data': {
'start_date': start_date,
'end_date': end_date,
'school_year': '%s/%s' % (reference_year, reference_year + 1),
},
}
@endpoint(
display_category='Réservation',
description="Modifier l'agenda d'un enfant",
name='update-child-agenda',
perm='can_access',
parameters={
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
},
post={
'request_body': {
'schema': {
'application/json': activity_schemas.BOOKING_SCHEMA,
}
}
},
)
def update_child_agenda(self, request, post_data, NameID=None, family_id=None):
family_id = family_id or self.get_link(NameID).family_id
child_id = post_data['child_id']
start_date, end_date, dummy = self.get_start_and_end_dates(
post_data['start_date'], post_data['end_date']
)
requested_bookings = post_data['booking_list']
# build list of existing booked days
bookings = self.get_bookings(family_id, child_id, start_date, end_date)
legacy_bookings = [b['id'] for b in bookings if b['prefill'] is True]
available_bookings = [b['id'] for b in bookings if b['disabled'] is False]
bookings_to_update = []
updated = []
for booking_info in bookings:
day_id = booking_info['id']
booked = None
action = booking_info['details']['action']
if day_id not in available_bookings:
# disabled or not available: not bookable
booked = None
elif (
day_id not in legacy_bookings
and day_id in requested_bookings
and action in ['ADD_PRES_PREVI', 'ADD_PRES_REAL', 'DEL_ABSENCE']
):
booked = action
elif (
day_id in legacy_bookings
and day_id not in requested_bookings
and action in ['DEL_PRES_PREVI', 'DEL_PRES_REAL', 'ADD_ABSENCE']
):
booked = action
if booked is not None:
# no changes, don't send the day
bookings_to_update.append(
{
'numPerson': child_id,
'idAct': booking_info['details']['activity_id'],
'idUni': booking_info['details']['unit_id'],
'date': booking_info['details']['day_str'],
'action': booked,
}
)
updated.append(
{
'activity_id': booking_info['details']['activity_id'],
'activity_type': booking_info['details']['activity_type'],
'activity_label': booking_info['details']['activity_label'],
'day': booking_info['details']['day_str'],
'booked': booked in ['ADD_PRES_PREVI', 'ADD_PRES_REAL', 'DEL_ABSENCE'],
}
)
if not bookings_to_update:
# don't call maelis if no changes
return updated
payload = {
'requestBean': {
'numDossier': family_id,
'unitPersonDayInfoList': bookings_to_update,
}
}
response = self.call('Activity', 'updatePersonSchedule', **payload)
errors = serialize_object(response)
if errors:
raise APIError(' ; '.join(errors), err_code='agenda-child-error')
# sort changes
activity_types = ['ACCMAT', 'RESTSCOL']
updated = [
(
not u['booked'],
activity_types.index(u['activity_type']) if u['activity_type'] in activity_types else 0,
u['activity_label'],
u['day'],
u,
)
for u in updated
]
updated = sorted(updated, key=itemgetter(0, 1, 2, 3))
updated = [u for b, a, l, d, u in updated]
updated = [
{
'booked': u['booked'],
'activity_id': u['activity_id'],
'activity_label': u['activity_label'],
'day': u['day'],
}
for u in updated
]
return {
'updated': True,
'count': len(updated),
'changes': updated,
}
@endpoint(
display_category='Facture',
description="Ajout d'autorisation de prélèvement",
name='add-rl1-direct-debit-order',
perm='can_access',
parameters={
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
},
post={
'request_body': {'schema': {'application/json': invoice_schemas.ADD_DIRECT_DEBIT_ORDER_SCHEMA}}
},
)
def add_rl1_direct_debit_order(self, request, post_data, NameID=None, family_id=None):
family_id = family_id or self.get_link(NameID).family_id
family = self.get_family_raw(family_id)
post_data['numPerson'] = family['RL1']['num']
self.call('Invoice', 'addDirectDebitOrder', numDossier=family_id, **post_data)
return {'data': 'ok'}
@endpoint(
display_category='Facture',
description="Lecture des informations relatives à l'autorisation de prélèvement en cours à la date de référence",
name='get-rl1-direct-debit-order',
perm='can_access',
parameters={
'codeRegie': {'description': 'Code de la régie'},
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
'dateRef': {
'description': 'Date de référence',
'type': 'date',
},
},
)
def get_rl1_direct_debit_order(self, request, codeRegie, dateRef, NameID=None, family_id=None):
family_id = family_id or self.get_link(NameID).family_id
family = self.get_family_raw(family_id)
payload = {
'numDossier': family_id,
'numPerson': family['RL1']['num'],
'codeRegie': codeRegie,
'dateRef': dateRef,
}
response = self.call('Invoice', 'getDirectDebitOrder', **payload)
data = serialize_object(response)
return {'data': data}
@endpoint(
display_category='Inscriptions',
description="Liste des années scolaires",
name='read-school-years-list',
perm='can_access',
)
def read_school_years_list(self, request):
return {'data': self.get_referential('YearSchool')}
@endpoint(
display_category='Inscriptions',
description="Liste des niveaux scolaires",
name='read-school-levels-list',
perm='can_access',
parameters={
'age': {'description': 'Age de l\'enfant', 'example_value': '6'},
},
)
def read_school_levels_list(self, request, age=None):
data = self.get_referential('Level')
if age and age.isnumeric():
return {'data': [item for item in data if item.get('age') == int(age)]}
return {'data': data}
@endpoint(
display_category='Inscriptions',
description="Liste des motifs de dérogation",
name='read-exemption-reasons-list',
perm='can_access',
)
def read_exemption_reasons_list(self, request):
return {'data': self.get_referential('DerogReason')}
@endpoint(
display_category='Inscriptions',
description="Liste les écoles pour une adresse et niveau scolaire",
name='read-schools-for-address-and-level',
perm='can_access',
parameters={
'year': {'description': 'Année', 'example_value': '2022'},
'id_street': {'description': 'Identifiant de la voie', 'example_value': '2317'},
'num': {'description': 'Numero dans la voie', 'example_value': '4'},
'comp': {'description': 'Complément d\'adresse (bis, ...)'},
'level': {'description': 'Niveau scolaire'},
},
)
def read_schools_for_address_and_level(self, request, id_street, year, num, comp=None, level=None):
data = {'schoolYear': year, 'adresse': {'idStreet': id_street, 'num': num}}
if level:
data['levelCode'] = level
if comp:
data['adresse']['numComp'] = comp
response = self.call(
'Site', 'readSchoolForAdressAndLevel', readSchoolForAdressAndLevelRequestBean=data
)
data = []
for item in serialize_object(response):
item['id'] = item['idSchool']
item['text'] = item['schoolName']
data.append(item)
return {'data': serialize_object(data)}
@endpoint(
display_category='Inscriptions',
description="Liste les écoles pour un enfant et niveau scolaire",
name='read-schools-for-child-and-level',
perm='can_access',
parameters={
'year': {'description': 'Année', 'example_value': '2023'},
'child_id': {'description': 'Identifiant de l\'enfant', 'example_value': '190115'},
'level': {'description': 'Niveau scolaire'},
},
)
def read_schools_for_child_and_level(self, request, child_id, year, level=None):
data = {
'numPerson': child_id,
'schoolYear': year,
}
if level:
data['levelCode'] = level
response = self.call('Family', 'readSchoolForChildAndLevel', **data)
data = []
for item in serialize_object(response):
item['id'] = item['idSchool']
item['text'] = item['schoolName']
data.append(item)
return {'data': serialize_object(data)}
@endpoint(
display_category='Inscriptions',
description="Remontée des informations scolaires d'un enfant",
name='read-child-school-informations',
perm='can_access',
parameters={
'child_id': {'description': 'Identifiant de l\'enfant', 'example_value': '190115'},
'level': {'description': 'Niveau scolaire', 'example_value': 'CP'},
'year': {'description': 'Année scolaire', 'example_value': '2023'},
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
},
)
def read_child_school_informations(self, request, child_id, level, year, NameID=None, family_id=None):
family_id = family_id or self.get_link(NameID).family_id
data = {'numDossier': family_id, 'numPerson': child_id, 'schoolYear': year, 'level': level}
response = self.call(
'Family', 'getChildSubscribeSchoolInformation', getFamilySubscribeSchoolInfoRequestBean=data
)
return {'data': serialize_object(response)}
@endpoint(
display_category='Inscriptions',
description="Création d'une pré-inscription scolaire pour un enfant",
name='create-child-school-pre-registration',
perm='can_access',
post={
'request_body': {'schema': {'application/json': family_schemas.SCHOOL_PRE_REGISTRATION_SCHEMA}}
},
)
def create_child_school_pre_registration(self, request, post_data):
response = self.call('Family', 'preSubscribeSchoolPerim', **post_data)
return {'data': serialize_object(response)}
@endpoint(
display_category='Inscriptions',
description="Création d'une pré-inscription scolaire avec demande de dérogation",
name='create-child-school-pre-registration-with-exemption',
perm='can_access',
post={
'request_body': {
'schema': {'application/json': family_schemas.SCHOOL_PRE_REGISTRATION_WITH_EXEMPTION_SCHEMA}
}
},
)
def create_child_school_pre_registration_with_exemption(self, request, post_data):
response = self.call('Family', 'presubscribeSchoolDerog', **post_data)
return {'data': serialize_object(response)}
@endpoint(
display_category='Inscriptions',
description="Création d'une pré-inscription scolaire avec rapprochement de fratrie",
name='create-child-school-pre-registration-with-sibling',
perm='can_access',
post={
'request_body': {
'schema': {'application/json': family_schemas.SCHOOL_PRE_REGISTRATION_WITH_SIBLING_SCHEMA}
}
},
)
def create_child_school_pre_registration_with_sibling(self, request, post_data):
response = self.call('Family', 'presubscribeSchoolSibling', **post_data)
return {'data': serialize_object(response)}
@endpoint(
display_category='Inscriptions',
description="Catalogue des activités d'une personne",
name='get-person-activity-list',
perm='can_access',
parameters={
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
'person_id': {'description': "Numéro du responsale légal ou de l'enfant"},
'nature_id': {'description': "Numéro de la nature des activités"},
'start_date': {'description': 'Début de la période'},
'end_date': {'description': 'Fin de la période'},
'text_template': {
'description': "template utilisé pour la valeur text (URL encoding)",
'example_value': '{{ activity.libelle2 }}',
},
},
)
def get_person_activity_list(
self,
request,
person_id,
NameID=None,
family_id=None,
nature_id=None,
start_date=None,
end_date=None,
text_template=None,
):
family_id = family_id or self.get_link(NameID).family_id
reference_year = None
if start_date and end_date:
start_date, end_date, reference_year = self.get_start_and_end_dates(start_date, end_date)
if not text_template:
text_template = '{{ activity.libelle2|default:activity.libelle1 }}'
response = self.get_person_activity_list_raw(
family_id,
person_id,
nature_id=nature_id,
reference_year=reference_year,
start_date=start_date and start_date.strftime(utils.json_date_format),
end_date=start_date and end_date.strftime(utils.json_date_format),
)
for item in response['catalogueActivityList']:
item['id'] = item['activity']['idActivity']
item['text'] = render_to_string(text_template, item).strip()
return {'data': response['catalogueActivityList'], 'meta': {'person': response['person']}}
@endpoint(
display_category='Inscriptions',
description="Liste des unités d'une activité pour une personne",
name='get-person-unit-list',
perm='can_access',
parameters={
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
'person_id': {'description': "Numéro du responsale légal ou de l'enfant"},
'activity_id': {'description': "Numéro de l'activités"},
'start_date': {'description': 'Début de la période'},
'end_date': {'description': 'Fin de la période'},
'text_template': {
'description': 'template utilisée pour la valeur text (URL encoding)',
'example_value': '{{ libelle }}',
},
},
)
def get_person_unit_list(
self,
request,
person_id,
activity_id,
NameID=None,
family_id=None,
start_date=None,
end_date=None,
text_template=None,
):
family_id = family_id or self.get_link(NameID).family_id
reference_year = None
if start_date and end_date:
start_date, end_date, reference_year = self.get_start_and_end_dates(start_date, end_date)
if not text_template:
text_template = '{{ libelle }}'
response = self.get_person_activity_list_raw(
family_id,
person_id,
reference_year=reference_year,
start_date=start_date and start_date.strftime(utils.json_date_format),
end_date=start_date and end_date.strftime(utils.json_date_format),
)
for activity in response['catalogueActivityList']:
if activity['activity']['idActivity'] == activity_id:
break
else:
raise APIError('No activity %s for person' % activity_id, err_code='no-activity')
data = activity.pop('unitInfoList')
meta = {'person': response['person'], 'activity': activity}
for item in data:
item['id'] = item['idUnit']
context = dict(item)
context['meta'] = meta
item['text'] = render_to_string(text_template, context).strip()
return {'data': data, 'meta': meta}
@endpoint(
display_category='Inscriptions',
description="Liste des lieux d'une unité pour une personne",
name='get-person-place-list',
perm='can_access',
parameters={
'NameID': {'description': 'Publik NameID'},
'family_id': {'description': 'Numéro de DUI'},
'person_id': {'description': "Numéro du responsale légal ou de l'enfant"},
'activity_id': {'description': "Numéro de l'activités"},
'unit_id': {'description': "Numéro de l'unité"},
'start_date': {'description': 'Début de la période'},
'end_date': {'description': 'Fin de la période'},
'text_template': {
'description': 'template utilisée pour la valeur text (URL encoding)',
'example_value': '{{ libelle }}',
},
},
)
def get_person_place_list(
self,
request,
person_id,
activity_id,
unit_id,
NameID=None,
family_id=None,
start_date=None,
end_date=None,
text_template=None,
):
family_id = family_id or self.get_link(NameID).family_id
reference_year = None
if start_date and end_date:
start_date, end_date, reference_year = self.get_start_and_end_dates(start_date, end_date)
if not text_template:
text_template = '{{ place.lib2|default:place.lib1 }}'
response = self.get_person_activity_list_raw(
family_id,
person_id,
reference_year=reference_year,
start_date=start_date and start_date.strftime(utils.json_date_format),
end_date=start_date and end_date.strftime(utils.json_date_format),
)
for activity in response['catalogueActivityList']:
if activity['activity']['idActivity'] == activity_id:
break
else:
raise APIError('No activity %s for person' % activity_id, err_code='no-activity')
for unit in activity['unitInfoList']:
if unit['idUnit'] == unit_id:
break
else:
raise APIError('No unit %s for person' % unit_id, err_code='no-unit')
data = unit.pop('placeInfoList')
del activity['unitInfoList']
meta = {'person': response['person'], 'activity': activity, 'unit': unit}
for item in data:
item['id'] = item['place']['idPlace']
context = dict(item)
context['meta'] = meta
item['text'] = render_to_string(text_template, context).strip()
return {'data': data, 'meta': meta}
class Link(models.Model):
resource = models.ForeignKey(ToulouseMaelis, on_delete=models.CASCADE)
name_id = models.CharField(blank=False, max_length=256)
family_id = models.CharField(blank=False, max_length=128)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Meta:
unique_together = ('resource', 'name_id')
class Referential(models.Model):
resource = models.ForeignKey(
verbose_name='Resource',
to=ToulouseMaelis,
on_delete=models.CASCADE,
related_name='referential',
)
referential_name = models.TextField('Name')
item_id = models.TextField('Key')
item_text = models.TextField('Text')
item_unaccent_text = models.TextField('Text', null=True)
item_data = JSONField('Data', encoder=DjangoJSONEncoder)
created = models.DateTimeField('Created', auto_now_add=True)
updated = models.DateTimeField('Updated', auto_now=True)
def __repr__(self):
return '<Referential "%s/%s">' % (self.referential_name, self.item_id)
class Meta:
ordering = ('resource', 'referential_name', 'item_text', 'item_id')
unique_together = [['resource', 'referential_name', 'item_id']]