From 4ddef8b09cf6e302b0a004a8819e73fbbe6bd40f Mon Sep 17 00:00:00 2001 From: Nicolas ROCHE Date: Fri, 20 Jan 2023 15:41:12 +0100 Subject: [PATCH 1/4] toulouse-maelis: get last wsdls to run tests (#73721) --- .../data/toulouse_maelis/ActivityService.wsdl | 1342 ++++++++--------- tests/data/toulouse_maelis/FamilyService.wsdl | 18 +- 2 files changed, 634 insertions(+), 726 deletions(-) diff --git a/tests/data/toulouse_maelis/ActivityService.wsdl b/tests/data/toulouse_maelis/ActivityService.wsdl index d63f2cc7..7dff3527 100644 --- a/tests/data/toulouse_maelis/ActivityService.wsdl +++ b/tests/data/toulouse_maelis/ActivityService.wsdl @@ -1,9 +1,76 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -106,151 +173,27 @@ - + - - + + + + + - + - - - - - - - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -284,19 +227,12 @@ - + - - - - - - - @@ -398,7 +334,6 @@ - @@ -438,8 +373,7 @@ - - + @@ -449,31 +383,9 @@ - - - - - - - - - - - - - - - - - - - - - - - + @@ -497,11 +409,56 @@ + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -509,10 +466,9 @@ + + - - - @@ -525,28 +481,34 @@ - + + + + + + + + + + + + + + + + + - - - - + + + - - - - - - - - - @@ -555,19 +517,6 @@ - - - - - - - - - - - - - @@ -603,6 +552,21 @@ + + + + + + + + + + + + + + + @@ -615,67 +579,24 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - @@ -688,81 +609,147 @@ + + + + + + + + + - - - - - - + + + + + + + + + - - + + + + - - - - - - - - - - + + - - - - + + - + - + - + + + + - - + - + - + + - + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -775,9 +762,6 @@ - - - @@ -790,43 +774,14 @@ - + - - - - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - + @@ -876,25 +831,6 @@ - - - - - - - - - - - - - - - - - - - @@ -908,6 +844,25 @@ + + + + + + + + + + + + + + + + + + + @@ -936,76 +891,19 @@ - + - - - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -1021,22 +919,34 @@ - + - + - + - + + - - - - + - + + + + + + + + + + + + + + + @@ -1047,16 +957,6 @@ - - - - - - - - - - @@ -1067,37 +967,22 @@ - - - - - - - - - - - + - + - + - + - + - + - - - - - - + @@ -1110,6 +995,22 @@ + + + + + + + + + + + + + + + + @@ -1129,15 +1030,6 @@ - - - - - - - - - @@ -1168,10 +1060,26 @@ + + + + + + + + + + + + + + + + @@ -1184,32 +1092,20 @@ - - - - - - - - - - + + - - + + - - - - - - + + @@ -1220,46 +1116,38 @@ - - + + - - + + - - - - - - - - - - + + - - - - - - + + + + + + @@ -1280,8 +1168,8 @@ - - + + @@ -1292,48 +1180,28 @@ - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + - - + + @@ -1341,11 +1209,71 @@ - -Met à jour la quantité d'une ligne du panier - + +Ajoute au panier une inscription d'un enfant à une activité du catalogue + +-------------------------------------- +Cette méthode doit être appelée lorsque l'usager demande à s'inscrire à une activité/unité/lieu. +Il s'agit de réserver la place tout en gérant un panier qui peut être vider par l'usager ou si le délai de conservation du panier est dépassé + Traitement : + +Lors de la validation de l'inscription, le contrôle d'inscription à des unités incompatibles est effectué à nouveau ainsi que le contrôle d'existence de l'inscription +Génération de + - L'inscription (état « WEB_PANIER »), l'inscription à l'unité standard si elle n'existe pas, est générée à l'état WEB_STANDARD + - Son calendrier, + - Le panier s'il n'en existe pas pour la famille + - La ligne de l'inscription du panier + +--------------------------------------- + Retour : +Le panier avec toutes les inscriptions du panier, avec facturation immédiate ou pas. +Une erreur si plus de place + - + + + + + + +Ajoute au panier une inscription en liste d'attente d'une personne à une activité du catalogue + +------------------------------------------ +Cette méthode peut être utilisée lorsqu'il n'y a plus de place +mais que l'on souhaite quand même ajouter l'inscription en liste d'attente (lorsque le paramétrage de l'activité l'autorise) + + Traitement : + Génération de + - L'inscription (état « WEB_WAIT »), l'inscription à l'unité standard si elle n'existe pas, est générée à l'état WEB_STANDARD + - Son calendrier + - Le panier s'il n'en existe pas pour la famille + - La ligne de l'inscription du panier + + Retour : + L'inscription générée + + + + + + + + +Méthode qui renvoie le nombre de jour de présence pour une activité sur une période + + ------------------------------- + - numPerson : numéro de personne (obligatoire) + - idAct : identifiant de l'activité (obligatoire) + - idUni : identifiant de l'unité (obligatoire) + - dateStart : date de début (obligatoire) + - dateEnd : date de fin (obligatoire) + + ------------------------------- + Retour : + La quantité + + + @@ -1359,51 +1287,47 @@ - -Renvoie le nombre d'inscriptions disponibles autres que PORTAL (en fonction d'une inscription à faire) + +Méthode d'ajout d'une présence prévisionnelle - ---------------------- - idPers la personne (pour quota filles/garçons) - idAct l'activité (obligatoire) - idUni l'unité (obligatoire) - idPlace le lieu - date de début période d'inscription - date de fin période d'inscription + Cette méthode est utilisée dans le cas des activités pour lesquelles le calendrier journalier des présences doit être saisie sur la plage de l'inscription. +Pour chaque jour coché, cette méthode est invoquée pour que la présence soit immédiatement réservée avec contrôle de place en cas d'erreur. - le total trouvé : - -1 si plus de place et l'inscription doit être refusée, - 0 si plus de place et l'inscription doit être mise en attente - NA si pas de controle - NN est le nombre de places disponibles - - - - - - - - -Ferme le calendrier d'une inscription + ------------------------------- + unitPersonDayInfoBean : jour du calendrier (obligatoire) + - numPerson : numéro de personne (obligatoire) + - idAct : identifiant de l'activité (obligatoire) + - idUni : identifiant de l'unité (obligatoire) + - idPlace : identifiant de l'unité (obligatoire) + - date : date du jour dans le calendrier (obligatoire) - ---------------------- - idSubscribe : identifiant de l'inscription (obligatoire) - idActivity : identifiant de l'activité - idPerson : identifiant de la personne - dateEnd : la date de fin d'inscription (obligatoire) - + ------------------------------- + Traitement : + Pour chaque élément de la liste + Si l'enfant est inscrit à l'unité + Si l'enfant est inscrit au lieu + Si action = ajout de présence + Si le calendrier prévisionnel n'existe pas + Création du calendrier + Sinon si la présence prévisionnelle existe déjà + Retour erreur « Il y a déjà un prévisionnel à cette unité pour cet enfant » + Sinon si pas de présence réelle existante + Mise à jour du calendrier Sinon retour erreur « présence réelle déjà existante » + Si action = suppression de présence + Si le calendrier prévisionnel existe + Si présence prévisionnelle existante + Mise à jour calendrier + Sinon retour erreur « pas de présence » + Sinon retour erreur « Il n'y a pas de prévisionnel pour cette unité » + Sinon Retour erreur « non inscrit au lieu » + Sinon Retour erreur « non inscrit à l'unité » + + ------------------------------ + Retour : + UpdateScheduleCalendarsResultBean + - - - - - - -Renvoie les enfants de la famille avec leurs inscriptions - La liste est composée des enfants de la famille (y compris les enfants en garde alternée) - avec, pour chaque enfant, un second niveau composé de la liste de ses inscriptions existantes - - - + @@ -1460,17 +1384,75 @@ - -Ajoute au panier une inscription en liste d'attente d'un enfant à une activité du catalogue - + +Méthode suppression d'une présence prévisionnelle + + Cette méthode est utilisée dans le cas des activités pour lesquelles le calendrier journalier des présences doit être saisie sur la plage de l'inscription. +Pour chaque jour dé-coché, cette méthode est invoquée pour que la présence soit immédiatement supprimé avec en cas d'erreur. + + ------------------------------- + unitPersonDayInfoBean : jour du calendrier (obligatoire) + - numPerson : numéro de personne (obligatoire) + - idAct : identifiant de l'activité (obligatoire) + - idUni : identifiant de l'unité (obligatoire) + - idPlace : identifiant de l'unité (obligatoire) + - date : date du jour dans le calendrier (obligatoire) + + ------------------------------- + Traitement : + Pour chaque élément de la liste + Si l'enfant est inscrit à l'unité + Si l'enfant est inscrit au lieu + Si action = suppression de présence + Si le calendrier prévisionnel existe + Si présence prévisionnelle existante + Mise à jour calendrier + Sinon retour erreur « pas de présence » + Sinon retour erreur « Il n'y a pas de prévisionnel pour cette unité » + Sinon Retour erreur « non inscrit au lieu » + Sinon Retour erreur « non inscrit à l'unité » + + ------------------------------ + Retour : + UnitPersonDayInfoErrorBean + - + -Renvoie les informations d'inscription d'un enfant à une activité du catalogue +Renvoie les informations pour l'inscription d'une personne à l'unité d'une activité du catalogue + +------------------------------------------ + Traitement : +Le traitement contrôle en premier que l'inscription est possible : + - Contrôle qu'il n'existe pas déjà une inscription (inscription effectuée par un agent ou en back office après l'affichage du catalogue). + - Contrôle qu'il n'existe pas une inscription à une unité ennemi + +En cas d'inscription existante, il n'y a pas d'action. Le message de retour indique qu'une inscription existe déjà +S'il n'y a plus de place et que le paramétrage autorise l'inscription en liste d'attente, l'action est « ADD_WAIT », sinon aucune action possible. +Si l'inscription n'existe pas et qu'il y a de la place, l'action est « ADD_SUBSCRIBE » + + + Lecture des informations de l'activité, de l'unité et du lieu +Le prix unitaire est calculé pour la date de début d'inscription, et les années de référence de l'utilisateur PORTAIL + +Le top « mono facture guichet automatique » de l'activité (CT_FLFACT) détermine si la facture doit être générée au moment de l'inscription. +Si l'activité est facturée en batch, l'information concernant le mode de facturation n'est pas remplie. Dans le cas où la facturation est effectuée à l'inscription, une ligne de train pour l'activité doit avoir été paramétrée pour pourvoir déterminer le mode de facturation et la quantité à facturer en fonction du mode de paramétrage de la ligne de train. +Cette quantité n'est renvoyée que si une facture est à générer + + + Lecture Calendriers +Pour les activités pour lesquelles un calendrier hebdomadaire prévisionnel doit être saisi lors de l'inscription, la propriété calendarGeneration est à O ou I, à savoir respectivement, saisie obligatoire ou facultative d'un calendrier hebdomadaire. + +Pour les activités pour lesquelles un calendrier journalier prévisionnel doit être saisi sur la période de l'inscription, le paramétrage suivant sera renvoyé : + - La propriété calendarGeneration à I, à savoir pas de calendrier hebdomadaire. + - La propriété List<DayInfoBean> dayInfoList fournit la liste des jours pour lesquels la saisie doit être proposée (idem que pour le module réservation/annulation) + + Contrôle de capacité +La capacité est contrôle lors de la lecture des information et en fonction du paramétrage et du nombre de place et l'action disponible est retournée @@ -1487,20 +1469,11 @@ - -Renvoie les unités de l'activité indiquée - + +Met à jour la quantité d'une ligne du panier + - - - - - - -Renvoie les natures d'activités pour le profil portail - - - + @@ -1517,15 +1490,6 @@ - -Ajoute au panier une inscription d'un enfant à une activité du catalogue - - - - - - - Mise à jour des présences/absences aux activités auxquelles est inscrite la personne @@ -1545,69 +1509,49 @@ - -Met à jour le calendrier hebdomadaire d'une personne, par rapport à une activité + +Méthode de lecture des natures et des types d'activité + Cette méthode retourne la liste des natures d'activités avec, pour chaque nature, + la liste des types d'activité de cette nature. - ---------------------- - idActivity : identifiant de l'activité - numPerson : Numéro de personne - weeklyPlanningAM : modèle hebdomadaire matin - weeklyPlanningPM : modèle hebdomadaire après-midi - dateStart : date de début d'application - dateEnd : date de fin d'application, facultatif, si non fourni date de fin de l'inscription - - ------------------------------ - Traitement : - La méthode enregistre le nouveau calendrier hebdomadaire et effectue une mise à jour du calendrier annuel calculé à partir du modèle hebdomadaire à partir de la date d'application passée en paramètre jusqu'à la date de fin. - Le modèle hebdomadaire est une chaine sur 7 positions constituée suivant la codification existante dans Maelis : - - 1 = jour fermé pour l'activité, - - 0 = jour ouvert sans présence, - - lettre = présence à l'unité correspondant à cette lettre - +La nature d'activité est un paramètre de la méthode de lecture du catalogue personnalisé qui permet de filtrer les activités par rapport à cette nature pour cibler une catégorie d'activité (loisirs, vacances) et/ou un public (enfant, ado, adulte, sénior) + + - + - + Supprime une ligne du panier - + - - - - - - -Renvoie la liste des familles correspondant aux critères indiqués - Les critères disponibles sont les suivants : - - Numéro de famille - - Nom du RL1 - - Prénom du RL1 - - Numéro de l'enfant - - Nom de l'enfant - - Prénom de l'enfant - - Plage de date de naissance - - Plage de date des activités/inscriptions - - Nature des activités (appel de la méthode getSelectionCriteriaForFamilylList) - - Année scolaire - Il faut fournir obligatoirement un des critères suivants : - - Le numéro de famille - - Le numéro de l'enfant - - Le nom de famille - - Le nom de l'enfant - - La date de naissance de l'enfant - Les autres critères sont facultatifs - - - + -Renvoie le catalogue des activités d'une personne de la famille +Renvoie le catalogue des activités/unités/lieux disponibles pour une personne de la famille + +-------------------------------------- + + Traitement : +- Liste des activités/unités/lieux du catalogue + +La requête récupère toutes les activités du catalogue toutes les activités/unités lieux auxquelles la personne a accès y compris celles pour lesquelles une inscription existe déjà. +Lorsque la personne est déjà inscrite, l'identifiant de l'inscription existante idIns est renvoyé au niveau de l'unité et du lieu afin de disposer de cette information pour ne pas permettre une autre inscription. + +- Liste des indicateurs bloquants (non utilisé pour Toulouse) + +Des indicateurs peuvent être positionnés pour les activités pour interdire l'inscription à certaines personnes en fonction de la présence ou de l'absence de l'indicateur pour la personne + +- Contrôle de capacité + +Lorsque le contrôle de capacité est effectué par rapport au nombre d'inscrits, le contrôle est effectué par rapport au nombre d'inscriptions confirmées déjà présentes +Si la capacité est effectuée par jour, il n'y a pas de contrôle du nombre d'inscrits mais lors de la saisie de l'inscription, pour chaque jour est indiqué s'il reste ou non de la place + @@ -1618,12 +1562,36 @@ - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1642,36 +1610,12 @@ - + - + - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -1726,12 +1670,12 @@ - + - + - + @@ -1762,24 +1706,12 @@ - + - + - - - - - - - - - - - - - + @@ -1798,18 +1730,6 @@ - - - - - - - - - - - - @@ -1822,36 +1742,24 @@ - + - + - + - + - + - - - - - - - - - - - - - + diff --git a/tests/data/toulouse_maelis/FamilyService.wsdl b/tests/data/toulouse_maelis/FamilyService.wsdl index 4777bd6a..03c81655 100644 --- a/tests/data/toulouse_maelis/FamilyService.wsdl +++ b/tests/data/toulouse_maelis/FamilyService.wsdl @@ -800,6 +800,15 @@ + + + + + + + + + @@ -817,15 +826,6 @@ - - - - - - - - - -- 2.39.2 From 3e6dade291c4748adaef4c1ea637105bb3f90954 Mon Sep 17 00:00:00 2001 From: Nicolas ROCHE Date: Sat, 21 Jan 2023 17:08:29 +0100 Subject: [PATCH 2/4] toulouse-maelis: new endpoint to get person activities (#73734) --- passerelle/contrib/toulouse_maelis/models.py | 66 ++++++ .../R_read_person_catalog_activity.xml | 191 ++++++++++++++++++ tests/test_toulouse_maelis.py | 144 +++++++++++++ 3 files changed, 401 insertions(+) create mode 100644 tests/data/toulouse_maelis/R_read_person_catalog_activity.xml diff --git a/passerelle/contrib/toulouse_maelis/models.py b/passerelle/contrib/toulouse_maelis/models.py index e1b72bf0..03fdd869 100644 --- a/passerelle/contrib/toulouse_maelis/models.py +++ b/passerelle/contrib/toulouse_maelis/models.py @@ -496,6 +496,23 @@ class ToulouseMaelis(BaseResource, HTTPResource): 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', @@ -2099,6 +2116,55 @@ class ToulouseMaelis(BaseResource, HTTPResource): 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']}} + class Link(models.Model): resource = models.ForeignKey(ToulouseMaelis, on_delete=models.CASCADE) diff --git a/tests/data/toulouse_maelis/R_read_person_catalog_activity.xml b/tests/data/toulouse_maelis/R_read_person_catalog_activity.xml new file mode 100644 index 00000000..cc5c53a0 --- /dev/null +++ b/tests/data/toulouse_maelis/R_read_person_catalog_activity.xml @@ -0,0 +1,191 @@ + + + + + + 2014-04-01T00:00:00+02:00 + BART + SIMPSON + 246423 + M + + + + A10051141965 + Vitrail Fusing 1/2 Je Adultes 2022/2023 - Mardi 14h-17h + Activité modèle + + LOI_ADU + Loisirs Adultes + + P + Loisirs + + + I + I + + + A10051141970 + Inscription 2ème semestre + 2023-02-01T00:00:00+01:00 + 2023-06-30T00:00:00+02:00 + + + A10053179226 + Centre Culturel ALBAN MINVILLE + H + + + true + + + + + A10051141990 + Inscription 1er semestre + 2022-09-01T00:00:00+02:00 + 2023-01-31T00:00:00+01:00 + + + A10053179226 + Centre Culturel ALBAN MINVILLE + H + + + true + + + + + A10051141968 + Inscription annuelle + 2022-09-01T00:00:00+02:00 + 2023-06-30T00:00:00+02:00 + + + A10053179226 + Centre Culturel ALBAN MINVILLE + N + + + true + + + + false + + + + A10053187087 + Vacances Ete 2023 + + LOI_VAC + Loisirs - Vacances + + V + Vacances Enfants + + + I + I + + + A10053187241 + Juillet + 2023-07-10T00:00:00+02:00 + 2023-07-31T00:00:00+02:00 + + + A10053179604 + ALEX JANY + H + 2.0 + 1.0 + + + true + + + + + A10053187242 + Aout + 2023-08-01T00:00:00+02:00 + 2023-08-31T00:00:00+02:00 + + + A10053179604 + ALEX JANY + M + 2.0 + 1.0 + + + true + + + + false + + + + A10053187065 + Vacances Hivers 2023 + + LOI_VAC + Loisirs - Vacances + + V + Vacances Enfants + + + I + I + + + A10053187086 + Semaine 2 + 2023-02-27T00:00:00+01:00 + 2023-03-03T00:00:00+01:00 + + + A10053179604 + ALEX JANY + 2011-01-01T00:00:00+01:00 + 2018-12-31T00:00:00+01:00 + H + 2.0 + 1.0 + + + true + + + + + A10053187085 + Semaine 1 + 2023-02-20T00:00:00+01:00 + 2023-02-24T00:00:00+01:00 + + + A10053179604 + ALEX JANY + 2011-01-01T00:00:00+01:00 + 2020-12-31T00:00:00+01:00 + H + 2.0 + 1.0 + + + true + + + + false + + + + + diff --git a/tests/test_toulouse_maelis.py b/tests/test_toulouse_maelis.py index 9adb649f..fab11784 100644 --- a/tests/test_toulouse_maelis.py +++ b/tests/test_toulouse_maelis.py @@ -4646,3 +4646,147 @@ def test_create_child_school_pre_registration_with_sibling(family_service, con, assert resp.json['data']['codeWait'] == 'MO_FRATERIE' assert resp.json['data']['derogReason'] == '01PRIO-5' assert resp.json['data']['derogComment'] == 'SERGHEI3 LISA' + + +def test_get_person_activity_list(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-activity-list') + + params = { + 'NameID': '', + 'family_id': '311323', + 'person_id': '246423', + 'nature_id': '', + 'start_date': '2022-09-01', + 'end_date': '2023-08-31', + 'text_template': '', + } + 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 resp.json['err'] == 0 + assert [(x['id'], x['text']) for x in resp.json['data']] == [ + ('A10051141965', 'Activité modèle'), + ('A10053187087', 'Vacances Ete 2023'), + ('A10053187065', 'Vacances Hivers 2023'), + ] + data = resp.json['data'][1] + del data['unitInfoList'][1] + assert data == { + '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', + }, + 'id': 'A10053187087', + 'incompleteFamilyFile': False, + 'indicatorBlockSubscribeList': [], + 'text': 'Vacances Ete 2023', + 'unitInfoList': [ + { + 'dateEnd': '2023-07-31T00:00:00+02:00', + 'dateStart': '2023-07-10T00:00:00+02:00', + 'idIns': None, + 'idUnit': 'A10053187241', + 'libelle': 'Juillet', + 'placeInfoList': [ + { + 'capacityInfo': {'controlOK': True, 'message': None}, + 'idIns': None, + 'place': { + 'ageEnd': None, + 'ageStart': None, + 'ctrlPlaces': 'H', + 'etatIns': None, + 'idIns': None, + 'idPlace': 'A10053179604', + 'latitude': 1, + 'lib1': 'ALEX JANY', + 'lib2': None, + 'listBlocNoteBean': [], + 'longitude': 2, + }, + } + ], + }, + ], + } + assert resp.json['meta']['person']['numPerson'] == 246423 + + params['text_template'] = '{{ unitInfoList.0.libelle }}' + resp = app.get(url, params=params) + assert resp.json['err'] == 0 + assert [(x['id'], x['text']) for x in resp.json['data']] == [ + ('A10051141965', 'Inscription 2ème semestre'), + ('A10053187087', 'Juillet'), + ('A10053187065', 'Semaine 2'), + ] + + +def test_get_person_activity_list_not_linked_error(con, app): + url = get_endpoint('get-person-activity-list') + params = { + 'NameID': 'local', + 'family_id': '', + 'person_id': '246423', + 'nature_id': '', + 'start_date': '2022-09-01', + 'end_date': '2023-08-31', + 'text_template': '', + } + 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_activity_list_date_error(con, app): + url = get_endpoint('get-person-activity-list') + + params = { + 'NameID': '', + 'family_id': '311323', + 'person_id': '246423', + 'nature_id': '', + 'start_date': 'bad', + 'end_date': '2023-08-31', + 'text_template': '', + } + 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 From c024e7eb876f2b296262d2b5f0ee9afb8804724e Mon Sep 17 00:00:00 2001 From: Nicolas ROCHE Date: Sat, 21 Jan 2023 17:09:02 +0100 Subject: [PATCH 3/4] toulouse-maelis: new endpoint to get person units (#73734) --- passerelle/contrib/toulouse_maelis/models.py | 57 ++++++++ tests/test_toulouse_maelis.py | 144 +++++++++++++++++++ 2 files changed, 201 insertions(+) diff --git a/passerelle/contrib/toulouse_maelis/models.py b/passerelle/contrib/toulouse_maelis/models.py index 03fdd869..788c3a7b 100644 --- a/passerelle/contrib/toulouse_maelis/models.py +++ b/passerelle/contrib/toulouse_maelis/models.py @@ -2165,6 +2165,63 @@ class ToulouseMaelis(BaseResource, HTTPResource): 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} + 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 fab11784..37d5ad11 100644 --- a/tests/test_toulouse_maelis.py +++ b/tests/test_toulouse_maelis.py @@ -4790,3 +4790,147 @@ def test_get_person_activity_list_date_error(con, app): 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)' + + +def test_get_person_unit_list(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-unit-list') + + params = { + 'NameID': '', + 'family_id': '311323', + 'person_id': '246423', + 'activity_id': 'A10053187087', + 'start_date': '2022-09-01', + 'end_date': '2023-08-31', + 'text_template': '', + } + 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 resp.json['err'] == 0 + assert [(x['id'], x['text']) for x in resp.json['data']] == [ + ('A10053187241', 'Juillet'), + ('A10053187242', 'Aout'), + ] + assert resp.json['data'][0] == { + 'dateEnd': '2023-07-31T00:00:00+02:00', + 'dateStart': '2023-07-10T00:00:00+02:00', + 'id': 'A10053187241', + 'idIns': None, + 'idUnit': 'A10053187241', + 'libelle': 'Juillet', + 'placeInfoList': [ + { + 'capacityInfo': {'controlOK': True, 'message': None}, + 'idIns': None, + 'place': { + 'ageEnd': None, + 'ageStart': None, + 'ctrlPlaces': 'H', + 'etatIns': None, + 'idIns': None, + 'idPlace': 'A10053179604', + 'latitude': 1, + 'lib1': 'ALEX JANY', + 'lib2': None, + 'listBlocNoteBean': [], + 'longitude': 2, + }, + } + ], + 'text': 'Juillet', + } + assert resp.json['meta']['person']['numPerson'] == 246423 + assert resp.json['meta']['activity']['activity']['idActivity'] == 'A10053187087' + + params['text_template'] = '{{ meta.activity.activity.activityType.natureSpec.libelle }} - {{ libelle }}' + resp = app.get(url, params=params) + assert resp.json['err'] == 0 + assert [(x['id'], x['text']) for x in resp.json['data']] == [ + ('A10053187241', 'Vacances Enfants - Juillet'), + ('A10053187242', 'Vacances Enfants - Aout'), + ] + + +def test_get_person_unit_list_not_linked_error(con, app): + url = get_endpoint('get-person-unit-list') + params = { + 'NameID': 'local', + 'family_id': '', + 'person_id': '246423', + 'activity_id': 'A10053187087', + 'start_date': '2022-09-01', + 'end_date': '2023-08-31', + 'text_template': '', + } + 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_unit_list_date_error(con, app): + url = get_endpoint('get-person-unit-list') + + params = { + 'NameID': '', + 'family_id': '311323', + 'person_id': '246423', + 'activity_id': 'A10053187087', + 'start_date': 'bad', + 'end_date': '2023-08-31', + 'text_template': '', + } + 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)' + + +def test_get_person_unit_list_no_activity_error(activity_service, con, app): + activity_service.add_soap_response( + 'getPersonCatalogueActivity', + get_xml_file('R_read_person_catalog_activity.xml'), + ) + url = get_endpoint('get-person-unit-list') + + params = { + 'NameID': '', + 'family_id': '311323', + 'person_id': '246423', + 'activity_id': 'plop', + 'start_date': '2022-09-01', + 'end_date': '2023-08-31', + 'text_template': '', + } + resp = app.get(url, params=params) + assert resp.json['err'] == 'no-activity' + assert resp.json['err_desc'] == 'No activity plop for person' -- 2.39.2 From da4ec8680a3ebf92d269979d9da8758e97937a8f Mon Sep 17 00:00:00 2001 From: Nicolas ROCHE Date: Sat, 21 Jan 2023 17:49:09 +0100 Subject: [PATCH 4/4] toulouse-maelis: new endpoint to get person places (#73734) --- passerelle/contrib/toulouse_maelis/models.py | 65 +++++++++ tests/test_toulouse_maelis.py | 141 +++++++++++++++++++ 2 files changed, 206 insertions(+) diff --git a/passerelle/contrib/toulouse_maelis/models.py b/passerelle/contrib/toulouse_maelis/models.py index 788c3a7b..b31583d3 100644 --- a/passerelle/contrib/toulouse_maelis/models.py +++ b/passerelle/contrib/toulouse_maelis/models.py @@ -2222,6 +2222,71 @@ class ToulouseMaelis(BaseResource, HTTPResource): 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) diff --git a/tests/test_toulouse_maelis.py b/tests/test_toulouse_maelis.py index 37d5ad11..05b3a31f 100644 --- a/tests/test_toulouse_maelis.py +++ b/tests/test_toulouse_maelis.py @@ -4934,3 +4934,144 @@ def test_get_person_unit_list_no_activity_error(activity_service, con, app): resp = app.get(url, params=params) assert resp.json['err'] == 'no-activity' assert resp.json['err_desc'] == 'No activity plop for person' + + +def test_get_person_place_list(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-place-list') + + params = { + 'NameID': '', + 'family_id': '311323', + 'person_id': '246423', + 'activity_id': 'A10053187087', + 'unit_id': 'A10053187241', + 'start_date': '2022-09-01', + 'end_date': '2023-08-31', + 'text_template': '', + } + 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 resp.json['err'] == 0 + assert [(x['id'], x['text']) for x in resp.json['data']] == [('A10053179604', 'ALEX JANY')] + assert resp.json['data'] == [ + { + 'capacityInfo': {'controlOK': True, 'message': None}, + 'id': 'A10053179604', + '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, + }, + 'text': 'ALEX JANY', + } + ] + assert resp.json['meta']['person']['numPerson'] == 246423 + assert resp.json['meta']['activity']['activity']['idActivity'] == 'A10053187087' + assert resp.json['meta']['unit']['idUnit'] == 'A10053187241' + + params['text_template'] = '{{ meta.unit.libelle }} - {{ place.lib1 }}' + resp = app.get(url, params=params) + assert resp.json['err'] == 0 + assert [(x['id'], x['text']) for x in resp.json['data']] == [('A10053179604', 'Juillet - ALEX JANY')] + + +def test_get_person_place_list_not_linked_error(con, app): + url = get_endpoint('get-person-place-list') + params = { + 'NameID': 'local', + 'family_id': '', + 'person_id': '246423', + 'activity_id': 'A10053187087', + 'unit_id': 'A10053187241', + 'start_date': '2022-09-01', + 'end_date': '2023-08-31', + 'text_template': '', + } + 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_place_list_date_error(con, app): + url = get_endpoint('get-person-place-list') + + params = { + 'NameID': '', + 'family_id': '311323', + 'person_id': '246423', + 'activity_id': 'A10053187087', + 'unit_id': 'A10053187241', + 'start_date': 'bad', + 'end_date': '2023-08-31', + 'text_template': '', + } + 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)' + + +def test_get_person_place_list_no_unit_error(activity_service, con, app): + activity_service.add_soap_response( + 'getPersonCatalogueActivity', + get_xml_file('R_read_person_catalog_activity.xml'), + ) + url = get_endpoint('get-person-place-list') + + params = { + 'NameID': '', + 'family_id': '311323', + 'person_id': '246423', + 'activity_id': 'plop', + 'unit_id': 'plop', + 'start_date': '2022-09-01', + 'end_date': '2023-08-31', + 'text_template': '', + } + resp = app.get(url, params=params) + assert resp.json['err'] == 'no-activity' + assert resp.json['err_desc'] == 'No activity plop for person' + + params['activity_id'] = 'A10053187087' + resp = app.get(url, params=params) + assert resp.json['err'] == 'no-unit' + assert resp.json['err_desc'] == 'No unit plop for person' -- 2.39.2