From a9af448b5a259ac975540b0fd663f8f41569ba65 Mon Sep 17 00:00:00 2001 From: Nicolas ROCHE Date: Sat, 21 Jan 2023 23:19:58 +0100 Subject: [PATCH] toulouse-maelis: new endpoint for geojson person catalog (#73759) --- passerelle/contrib/toulouse_maelis/models.py | 113 +++++++++++++ tests/test_toulouse_maelis.py | 165 +++++++++++++++++++ 2 files changed, 278 insertions(+) diff --git a/passerelle/contrib/toulouse_maelis/models.py b/passerelle/contrib/toulouse_maelis/models.py index b31583d3..1949c4d8 100644 --- a/passerelle/contrib/toulouse_maelis/models.py +++ b/passerelle/contrib/toulouse_maelis/models.py @@ -2287,6 +2287,119 @@ class ToulouseMaelis(BaseResource, HTTPResource): item['text'] = render_to_string(text_template, context).strip() return {'data': data, 'meta': meta} + @endpoint( + display_category='Inscriptions', + description="Catalog geojson pour une personne", + name='get-person-catalog-geojson', + 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'}, + 'activity_id': {'description': "Numéro de l'activités"}, + 'unit_id': {'description': "Numéro de l'unité"}, + 'place_id': {'description': "Numéro du lieu"}, + }, + ) + def get_person_catalog_geojson( + self, + request, + person_id, + NameID=None, + family_id=None, + start_date=None, + end_date=None, + nature_id=None, + activity_id=None, + unit_id=None, + place_id=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) + + 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), + ) + + def places(properties, place_list, place_id=None): + for place in place_list: + properties['place'] = place + properties['place_id'] = place['place']['idPlace'] + if not place['place']['longitude'] or not place['place']['latitude']: + continue + if place_id: + if properties['place_id'] == place_id: + yield properties + break + else: + yield properties + + def units(properties, unit_list, unit_id=None, place_id=None): + for unit in unit_list: + place_list = unit.pop('placeInfoList') + properties['unit'] = unit + properties['unit_id'] = unit['idUnit'] + if unit_id: + if properties['unit_id'] == unit_id: + yield from places(properties, place_list, place_id) + break + else: + yield from places(properties, place_list, place_id) + + def activities(activity_id=None, unit_id=None, place_id=None): + for activity in response['catalogueActivityList']: + unit_list = activity.pop('unitInfoList') + properties = { + 'person': response['person'], + 'activity_id': activity['activity']['idActivity'], + 'activity': activity, + } + if activity_id: + if properties['activity_id'] == activity_id: + yield from units(properties, unit_list, unit_id, place_id) + break + else: + yield from units(properties, unit_list, unit_id, place_id) + + geojson = { + 'type': 'FeatureCollection', + 'features': [], + } + for item in activities(activity_id, unit_id, place_id): + geojson['features'].append( + { + 'type': 'Feature', + 'geometry': { + 'coordinates': [ + float(item['place']['place']['longitude']), + float(item['place']['place']['latitude']), + ], + 'type': 'Point', + }, + 'properties': { + 'id': '%s:%s:%s' % (item['activity_id'], item['unit_id'], item['place_id']), + 'text': '%s / %s / %s' + % ( + item['activity']['activity']['libelle1'], + item['unit']['libelle'], + item['place']['place']['lib1'], + ), + **item, + }, + } + ) + return geojson + class Link(models.Model): resource = models.ForeignKey(ToulouseMaelis, on_delete=models.CASCADE) diff --git a/tests/test_toulouse_maelis.py b/tests/test_toulouse_maelis.py index 05b3a31f..91496a36 100644 --- a/tests/test_toulouse_maelis.py +++ b/tests/test_toulouse_maelis.py @@ -5075,3 +5075,168 @@ def test_get_person_place_list_no_unit_error(activity_service, con, app): resp = app.get(url, params=params) assert resp.json['err'] == 'no-unit' assert resp.json['err_desc'] == 'No unit plop for person' + + +def test_get_person_catalog_geojson(activity_service, con, app): + def request_check(request): + assert request.yearSchool == 2022 + + activity_service.add_soap_response( + 'getPersonCatalogueActivity', + get_xml_file('R_read_person_catalog_activity.xml'), + request_check=request_check, + ) + url = get_endpoint('get-person-catalog-geojson') + + params = { + 'NameID': '', + 'family_id': '311323', + 'person_id': '246423', + 'nature_id': '', + 'start_date': '2022-09-01', + 'end_date': '2023-08-31', + 'activity_id': 'A10053187087', + 'unit_id': 'A10053187241', + 'place_id': 'A10053179604', + } + resp = app.get(url, params=params) + assert resp.json['err'] == 0 + Link.objects.create(resource=con, family_id='311323', name_id='local') + + params['NameID'] = 'local' + params['family_id'] = '' + resp = app.get(url, params=params) + assert len(resp.json['features']) == 1 + assert resp.json == { + 'err': 0, + 'features': [ + { + 'geometry': {'coordinates': [2.0, 1.0], 'type': 'Point'}, + 'properties': { + 'id': 'A10053187087:A10053187241:A10053179604', + 'text': 'Vacances Ete 2023 / Juillet / ALEX JANY', + 'activity_id': 'A10053187087', + 'unit_id': 'A10053187241', + 'place_id': 'A10053179604', + 'person': { + 'dateBirth': '2014-04-01T00:00:00+02:00', + 'firstname': 'BART', + 'lastname': 'SIMPSON', + 'numPerson': 246423, + 'sexe': 'M', + }, + 'activity': { + 'activity': { + 'activityType': { + 'code': 'LOI_VAC', + 'libelle': 'Loisirs - Vacances', + 'natureSpec': {'code': 'V', 'libelle': 'Vacances ' 'Enfants'}, + }, + 'idActivity': 'A10053187087', + 'libelle1': 'Vacances ' 'Ete 2023', + 'libelle2': None, + 'paiementPortal': 'I', + 'typInsPortal': 'I', + }, + 'incompleteFamilyFile': False, + 'indicatorBlockSubscribeList': [], + }, + 'unit': { + 'dateEnd': '2023-07-31T00:00:00+02:00', + 'dateStart': '2023-07-10T00:00:00+02:00', + 'idIns': None, + 'idUnit': 'A10053187241', + 'libelle': 'Juillet', + }, + 'place': { + 'capacityInfo': {'controlOK': True, 'message': None}, + 'idIns': None, + 'place': { + 'ageEnd': None, + 'ageStart': None, + 'ctrlPlaces': 'H', + 'etatIns': None, + 'idIns': None, + 'idPlace': 'A10053179604', + 'latitude': 1.0, + 'lib1': 'ALEX JANY', + 'lib2': None, + 'listBlocNoteBean': [], + 'longitude': 2.0, + }, + }, + }, + 'type': 'Feature', + }, + ], + 'type': 'FeatureCollection', + } + + params['place_id'] = 'plop' + resp = app.get(url, params=params) + assert len(resp.json['features']) == 0 + + del params['place_id'] + resp = app.get(url, params=params) + assert len(resp.json['features']) == 1 + + params['unit_id'] = 'plop' + resp = app.get(url, params=params) + assert len(resp.json['features']) == 0 + + del params['unit_id'] + resp = app.get(url, params=params) + assert len(resp.json['features']) == 2 + + params['activity_id'] = 'plop' + resp = app.get(url, params=params) + assert len(resp.json['features']) == 0 + + del params['activity_id'] + resp = app.get(url, params=params) + assert len(resp.json['features']) == 4 + + +def test_get_person_catalog_geojson_not_linked_error(con, app): + url = get_endpoint('get-person-catalog-geojson') + params = { + 'NameID': '', + 'family_id': '', + 'person_id': '246423', + } + resp = app.get(url, params=params) + assert resp.json['err'] == 'not-linked' + assert resp.json['err_desc'] == 'User not linked to family' + + +def test_get_person_catalog_geojson_date_error(con, app): + url = get_endpoint('get-person-catalog-geojson') + + params = { + 'NameID': '', + 'family_id': '311323', + 'person_id': '246423', + 'start_date': 'bad', + 'end_date': '2023-08-31', + } + resp = app.get(url, params=params, status=400) + assert resp.json['err'] == 'bad-request' + assert resp.json['err_desc'] == 'bad date format, should be YYYY-MM-DD' + + params['start_date'] = '2022-09-01' + params['end_date'] = 'bad' + resp = app.get(url, params=params, status=400) + assert resp.json['err'] == 'bad-request' + assert resp.json['err_desc'] == 'bad date format, should be YYYY-MM-DD' + + params['start_date'] = '2023-09-01' + params['end_date'] = '2023-08-31' + resp = app.get(url, params=params, status=400) + assert resp.json['err'] == 'bad-request' + assert resp.json['err_desc'] == 'start_date should be before end_date' + + params['start_date'] = '2022-09-01' + params['end_date'] = '2024-08-31' + resp = app.get(url, params=params, status=400) + assert resp.json['err'] == 'bad-request' + assert resp.json['err_desc'] == 'start_date and end_date are in different reference year (2022 != 2023)' -- 2.39.2