diff --git a/passerelle/contrib/toulouse_maelis/models.py b/passerelle/contrib/toulouse_maelis/models.py
index a984624c..14bf9746 100644
--- a/passerelle/contrib/toulouse_maelis/models.py
+++ b/passerelle/contrib/toulouse_maelis/models.py
@@ -529,6 +529,17 @@ class ToulouseMaelis(BaseResource, HTTPResource):
data = serialize_object(response)
return data
+ def get_basket_raw(self, family_id):
+ response = self.call(
+ 'Activity',
+ 'getFamilyBasket',
+ getFamilyBasketRequestBean={
+ 'numFamily': family_id,
+ },
+ )
+ data = serialize_object(response)
+ return data
+
@endpoint(
display_category='Famille',
description='Liste des catégories',
@@ -2521,6 +2532,125 @@ class ToulouseMaelis(BaseResource, HTTPResource):
raise APIError(response['controlResult']['message'])
return {'data': serialize_object(response)}
+ @endpoint(
+ display_category='Inscriptions',
+ description="Lecture du panier de la famille",
+ name='get-basket',
+ perm='can_access',
+ parameters={
+ 'NameID': {'description': 'Publik NameID'},
+ 'family_id': {'description': 'Numéro de DUI'},
+ },
+ )
+ def get_basket(self, request, NameID=None, family_id=None):
+ family_id = family_id or self.get_link(NameID).family_id
+ return {'data': self.get_basket_raw(family_id)}
+
+ @endpoint(
+ display_category='Inscriptions',
+ description="Prolonge la durée de vie du panier",
+ name='update-basket-time',
+ perm='can_access',
+ parameters={
+ 'NameID': {'description': 'Publik NameID'},
+ 'family_id': {'description': 'Numéro de DUI'},
+ },
+ methods=['post'],
+ )
+ def update_basket_time(self, request, NameID=None, family_id=None):
+ family_id = family_id or self.get_link(NameID).family_id
+ basket = self.get_basket_raw(family_id)
+ if not basket or not basket.get('id'):
+ raise APIError("no basket on '%s' family" % family_id)
+
+ self.call('Activity', 'updateBasketTime', idBasket=basket['id'])
+ return {'data': 'ok'}
+
+ @endpoint(
+ display_category='Inscriptions',
+ description="Suppression d'une ligne du panier",
+ name='delete-basket-line',
+ perm='can_access',
+ parameters={
+ 'NameID': {'description': 'Publik NameID'},
+ 'family_id': {'description': 'Numéro de DUI'},
+ 'line_id': {'description': 'Numéro de ligne du panier'},
+ },
+ methods=['post'],
+ )
+ def delete_basket_line(self, request, line_id, NameID=None, family_id=None):
+ family_id = family_id or self.get_link(NameID).family_id
+ basket = self.get_basket_raw(family_id)
+ if not basket or not basket.get('id'):
+ raise APIError("no basket on '%s' family" % family_id)
+ for line in basket['lignes']:
+ if line['id'] == line_id:
+ break
+ else:
+ raise APIError("no '%s' basket line on '%s' family" % (line_id, family_id))
+
+ response = self.call(
+ 'Activity',
+ 'deletePersonUnitBasket',
+ deletePersonUnitBasketRequestBean={
+ 'idBasketLine': line_id,
+ },
+ )
+ return {'data': serialize_object(response)}
+
+ @endpoint(
+ display_category='Inscriptions',
+ description="Suppression du panier de la famille",
+ name='delete-basket',
+ perm='can_access',
+ parameters={
+ 'NameID': {'description': 'Publik NameID'},
+ 'family_id': {'description': 'Numéro de DUI'},
+ },
+ methods=['post'],
+ )
+ def delete_basket(self, request, NameID=None, family_id=None):
+ family_id = family_id or self.get_link(NameID).family_id
+ basket = self.get_basket_raw(family_id)
+ if not basket or not basket.get('id'):
+ raise APIError("no basket on '%s' family" % family_id)
+
+ self.call(
+ 'Activity',
+ 'deleteBasket',
+ deleteBasketRequestBean={
+ 'idBasket': basket['id'],
+ 'idUtilisat': NameID or 'Middle-office',
+ },
+ )
+ return {'data': 'ok'}
+
+ @endpoint(
+ display_category='Inscriptions',
+ description="Validation du panier de la famille",
+ name='validate-basket',
+ perm='can_access',
+ parameters={
+ 'NameID': {'description': 'Publik NameID'},
+ 'family_id': {'description': 'Numéro de DUI'},
+ },
+ methods=['post'],
+ )
+ def validate_basket(self, request, NameID=None, family_id=None):
+ family_id = family_id or self.get_link(NameID).family_id
+ basket = self.get_basket_raw(family_id)
+ if not basket or not basket.get('id'):
+ raise APIError("no basket on '%s' family" % family_id)
+
+ response = self.call(
+ 'Activity',
+ 'validateBasket',
+ validateBasketRequestBean={
+ 'idBasket': basket['id'],
+ },
+ )
+ return {'data': serialize_object(response)}
+
class Link(models.Model):
resource = models.ForeignKey(ToulouseMaelis, on_delete=models.CASCADE)
diff --git a/tests/data/toulouse_maelis/R_delete_basket.xml b/tests/data/toulouse_maelis/R_delete_basket.xml
new file mode 100644
index 00000000..d4d0fac4
--- /dev/null
+++ b/tests/data/toulouse_maelis/R_delete_basket.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/tests/data/toulouse_maelis/R_delete_person_unit_basket.xml b/tests/data/toulouse_maelis/R_delete_person_unit_basket.xml
new file mode 100644
index 00000000..b8165319
--- /dev/null
+++ b/tests/data/toulouse_maelis/R_delete_person_unit_basket.xml
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+ 2023-01-30T00:42:48+01:00
+ 2023-01-30T00:42:48+01:00
+ 0
+ S10053200723
+ S10053183425
+
+ 2023-01-28T23:50:34+01:00
+ S10053203105
+ S10053203103
+ S10053203104
+ S10053200723
+
+ 2023-02-01T00:00:00+01:00
+ 2023-06-30T00:00:00+02:00
+ A10051141965
+ S10053203103
+ S10053203104
+ A10053179226
+ A10049327675
+ A10051141970
+ Vitrail Fusing 1/2 Je Adultes 2022/2023 - Mardi 14h-17h
+ Centre Culturel ALBAN MINVILLE
+ Inscription 2ème semestre
+
+
+ 2014-04-01T00:00:00+02:00
+ BART
+ NICO
+ 246711
+ M
+
+
+
+ 2023-01-26T17:39:40+01:00
+ S10053200724
+ S10053200721
+ S10053200722
+ S10053200723
+
+ 2022-09-01T00:00:00+02:00
+ 2023-08-31T00:00:00+02:00
+ A10051141965
+ S10053200721
+ S10053200722
+ A10053179226
+ A10049327675
+ A10051141990
+ Vitrail Fusing 1/2 Je Adultes 2022/2023 - Mardi 14h-17h
+ Centre Culturel ALBAN MINVILLE
+ Inscription 1er semestre
+
+
+ 2014-04-01T00:00:00+02:00
+ BART
+ NICO
+ 246711
+ M
+
+
+
+
+
+
+
diff --git a/tests/data/toulouse_maelis/R_get_family_basket.xml b/tests/data/toulouse_maelis/R_get_family_basket.xml
new file mode 100644
index 00000000..1bc9180a
--- /dev/null
+++ b/tests/data/toulouse_maelis/R_get_family_basket.xml
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+ 2023-01-28T23:56:23+01:00
+ 2023-01-28T23:56:23+01:00
+ 0
+ S10053200723
+ S10053183425
+
+ 2023-01-28T23:56:23+01:00
+ S10053203120
+ S10053203118
+ S10053203119
+ S10053200723
+
+ 2023-02-20T00:00:00+01:00
+ 2023-02-24T00:00:00+01:00
+ A10053187065
+ S10053203118
+ S10053203119
+ A10053179604
+ A10049327667
+ A10053187085
+ Vacances Hivers 2023
+ ALEX JANY
+ Semaine 1
+
+
+ 2014-04-01T00:00:00+02:00
+ BART
+ NICO
+ 246711
+ M
+
+
+
+ 2023-01-28T23:50:34+01:00
+ S10053203105
+ S10053203103
+ S10053203104
+ S10053200723
+
+ 2023-02-01T00:00:00+01:00
+ 2023-06-30T00:00:00+02:00
+ A10051141965
+ S10053203103
+ S10053203104
+ A10053179226
+ A10049327675
+ A10051141970
+ Vitrail Fusing 1/2 Je Adultes 2022/2023 - Mardi 14h-17h
+ Centre Culturel ALBAN MINVILLE
+ Inscription 2ème semestre
+
+
+ 2014-04-01T00:00:00+02:00
+ BART
+ NICO
+ 246711
+ M
+
+
+
+ 2023-01-26T17:39:40+01:00
+ S10053200724
+ S10053200721
+ S10053200722
+ S10053200723
+
+ 2022-09-01T00:00:00+02:00
+ 2023-08-31T00:00:00+02:00
+ A10051141965
+ S10053200721
+ S10053200722
+ A10053179226
+ A10049327675
+ A10051141990
+ Vitrail Fusing 1/2 Je Adultes 2022/2023 - Mardi 14h-17h
+ Centre Culturel ALBAN MINVILLE
+ Inscription 1er semestre
+
+
+ 2014-04-01T00:00:00+02:00
+ BART
+ NICO
+ 246711
+ M
+
+
+
+
+
+
+
diff --git a/tests/data/toulouse_maelis/R_get_family_basket_empty.xml b/tests/data/toulouse_maelis/R_get_family_basket_empty.xml
new file mode 100644
index 00000000..85bfc153
--- /dev/null
+++ b/tests/data/toulouse_maelis/R_get_family_basket_empty.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/tests/data/toulouse_maelis/R_update_basket_time.xml b/tests/data/toulouse_maelis/R_update_basket_time.xml
new file mode 100644
index 00000000..282e50ce
--- /dev/null
+++ b/tests/data/toulouse_maelis/R_update_basket_time.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/tests/data/toulouse_maelis/R_validate_basket.xml b/tests/data/toulouse_maelis/R_validate_basket.xml
new file mode 100644
index 00000000..1ae30f1a
--- /dev/null
+++ b/tests/data/toulouse_maelis/R_validate_basket.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ S10053183425
+ S10053203103
+ S10053200721
+
+
+
+
diff --git a/tests/test_toulouse_maelis.py b/tests/test_toulouse_maelis.py
index 04003f5f..ca92f323 100644
--- a/tests/test_toulouse_maelis.py
+++ b/tests/test_toulouse_maelis.py
@@ -5740,3 +5740,205 @@ def test_add_person_basket_subscription_not_linked_error(con, app):
resp = app.post_json(url + '?NameID=local', params=params)
assert resp.json['err'] == 'not-linked'
assert resp.json['err_desc'] == 'User not linked to family'
+
+
+def test_get_basket(activity_service, con, app):
+ activity_service.add_soap_response('getFamilyBasket', get_xml_file('R_get_family_basket.xml'))
+ url = get_endpoint('get-basket')
+
+ resp = app.get(url + '?family_id=311352')
+ assert resp.json['err'] == 0
+ Link.objects.create(resource=con, family_id='311352', name_id='local')
+
+ resp = app.get(url + '?NameID=local')
+ assert resp.json['err'] == 0
+ data = resp.json['data']
+ assert len(data['lignes']) == 3
+ del data['lignes'][2]
+ del data['lignes'][1]
+ assert data == {
+ 'dateAdd': '2023-01-28T23:56:23+01:00',
+ 'dateMaj': '2023-01-28T23:56:23+01:00',
+ 'delai': 0,
+ 'id': 'S10053200723',
+ 'idFam': 'S10053183425',
+ 'lignes': [
+ {
+ 'datEchn': None,
+ 'dateMaj': '2023-01-28T23:56:23+01:00',
+ 'id': 'S10053203120',
+ 'idIns': 'S10053203118',
+ 'idInsLieu': 'S10053203119',
+ 'idPanier': 'S10053200723',
+ 'inscription': {
+ 'dateDeb': '2023-02-20T00:00:00+01:00',
+ 'dateFin': '2023-02-24T00:00:00+01:00',
+ 'idAct': 'A10053187065',
+ 'idInsAct': 'S10053203118',
+ 'idInsLieu': 'S10053203119',
+ 'idLieu': 'A10053179604',
+ 'idRegie': 'A10049327667',
+ 'idUnit': 'A10053187085',
+ 'libAct': 'Vacances Hivers 2023',
+ 'libLieu': 'ALEX JANY',
+ 'libUnit': 'Semaine 1',
+ },
+ 'montant': None,
+ 'personneInfo': {
+ 'dateBirth': '2014-04-01T00:00:00+02:00',
+ 'firstname': 'BART',
+ 'lastname': 'NICO',
+ 'numPerson': 246711,
+ 'sexe': 'M',
+ },
+ 'prixUnit': None,
+ 'qte': None,
+ },
+ ],
+ }
+
+
+def test_get_basket_not_linked_error(con, app):
+ url = get_endpoint('get-basket')
+ resp = app.get(url + '?NameID=local')
+ assert resp.json['err'] == 'not-linked'
+ assert resp.json['err_desc'] == 'User not linked to family'
+
+
+def test_update_basket_time(activity_service, con, app):
+ activity_service.add_soap_response('getFamilyBasket', get_xml_file('R_get_family_basket.xml'))
+ activity_service.add_soap_response('updateBasketTime', get_xml_file('R_update_basket_time.xml'))
+ url = get_endpoint('update-basket-time')
+
+ resp = app.post(url + '?family_id=311352')
+ assert resp.json['err'] == 0
+ Link.objects.create(resource=con, family_id='311352', name_id='local')
+
+ resp = app.post(url + '?NameID=local')
+ assert resp.json['err'] == 0
+ assert resp.json['data'] == 'ok'
+
+
+def test_update_basket_time_not_linked_error(con, app):
+ url = get_endpoint('update-basket-time')
+ resp = app.post(url + '?NameID=local')
+ assert resp.json['err'] == 'not-linked'
+ assert resp.json['err_desc'] == 'User not linked to family'
+
+
+def test_update_basket_time_basket_not_found(activity_service, con, app):
+ activity_service.add_soap_response('getFamilyBasket', get_xml_file('R_get_family_basket_empty.xml'))
+ url = get_endpoint('update-basket-time')
+ resp = app.post(url + '?family_id=311352')
+ assert resp.json['err'] == 1
+ assert resp.json['err_desc'] == "no basket on '311352' family"
+
+
+def test_delete_basket_line(activity_service, con, app):
+ activity_service.add_soap_response('getFamilyBasket', get_xml_file('R_get_family_basket.xml'))
+ activity_service.add_soap_response(
+ 'deletePersonUnitBasket', get_xml_file('R_delete_person_unit_basket.xml')
+ )
+ url = get_endpoint('delete-basket-line')
+
+ resp = app.post(url + '?family_id=311352&line_id=S10053203120')
+ assert resp.json['err'] == 0
+ Link.objects.create(resource=con, family_id='311352', name_id='local')
+
+ resp = app.post(url + '?NameID=local&line_id=S10053203120')
+ assert resp.json['err'] == 0
+ assert len(resp.json['data']['lignes']) == 2
+ assert 'S10053203120' not in [x['id'] for x in resp.json['data']['lignes']]
+
+
+def test_delete_basket_line_not_linked_error(con, app):
+ url = get_endpoint('delete-basket-line')
+ resp = app.post(url + '?NameID=local&line_id=S10053203120')
+ assert resp.json['err'] == 'not-linked'
+ assert resp.json['err_desc'] == 'User not linked to family'
+
+
+def test_update_basket_line_basket_not_found(activity_service, con, app):
+ activity_service.add_soap_response('getFamilyBasket', get_xml_file('R_get_family_basket_empty.xml'))
+ url = get_endpoint('delete-basket-line')
+ resp = app.post(url + '?family_id=311352&line_id=S10053203120')
+ assert resp.json['err'] == 1
+ assert resp.json['err_desc'] == "no basket on '311352' family"
+
+
+def test_delete_basket_line_line_not_found(activity_service, con, app):
+ activity_service.add_soap_response('getFamilyBasket', get_xml_file('R_get_family_basket.xml'))
+ url = get_endpoint('delete-basket-line')
+ resp = app.post(url + '?family_id=311352&line_id=plop')
+ assert resp.json['err'] == 1
+ assert resp.json['err_desc'] == "no 'plop' basket line on '311352' family"
+
+
+def test_delete_basket(activity_service, con, app):
+ def request_check(request):
+ assert request.idUtilisat in ('local', 'Middle-office')
+
+ activity_service.add_soap_response('getFamilyBasket', get_xml_file('R_get_family_basket.xml'))
+ activity_service.add_soap_response(
+ 'deleteBasket',
+ get_xml_file('R_delete_basket.xml'),
+ request_check=request_check,
+ )
+ url = get_endpoint('delete-basket')
+
+ resp = app.post(url + '?family_id=311352')
+ assert resp.json['err'] == 0
+ Link.objects.create(resource=con, family_id='311352', name_id='local')
+
+ resp = app.post(url + '?NameID=local')
+ assert resp.json['err'] == 0
+ assert resp.json['data'] == 'ok'
+
+
+def test_delete_basket_not_linked_error(con, app):
+ url = get_endpoint('delete-basket')
+ resp = app.post(url + '?NameID=local')
+ assert resp.json['err'] == 'not-linked'
+ assert resp.json['err_desc'] == 'User not linked to family'
+
+
+def test_delete_basket_not_found(activity_service, con, app):
+ activity_service.add_soap_response('getFamilyBasket', get_xml_file('R_get_family_basket_empty.xml'))
+ url = get_endpoint('delete-basket')
+ resp = app.post(url + '?family_id=311352')
+ assert resp.json['err'] == 1
+ assert resp.json['err_desc'] == "no basket on '311352' family"
+
+
+def test_validate_basket(activity_service, con, app):
+ activity_service.add_soap_response('getFamilyBasket', get_xml_file('R_get_family_basket.xml'))
+ activity_service.add_soap_response('validateBasket', get_xml_file('R_validate_basket.xml'))
+ url = get_endpoint('validate-basket')
+
+ resp = app.post(url + '?family_id=311352')
+ assert resp.json['err'] == 0
+ Link.objects.create(resource=con, family_id='311352', name_id='local')
+
+ resp = app.post(url + '?NameID=local')
+ assert resp.json['err'] == 0
+ assert resp.json['data'] == {
+ 'idFam': 'S10053183425',
+ 'idFactureLst': [],
+ 'idInsLst': ['S10053203103', 'S10053200721'],
+ 'paramUrlReglement': [],
+ }
+
+
+def test_validate_basket_not_linked_error(con, app):
+ url = get_endpoint('validate-basket')
+ resp = app.post(url + '?NameID=local')
+ assert resp.json['err'] == 'not-linked'
+ assert resp.json['err_desc'] == 'User not linked to family'
+
+
+def test_validate_basket_not_found(activity_service, con, app):
+ activity_service.add_soap_response('getFamilyBasket', get_xml_file('R_get_family_basket_empty.xml'))
+ url = get_endpoint('validate-basket')
+ resp = app.post(url + '?family_id=311352')
+ assert resp.json['err'] == 1
+ assert resp.json['err_desc'] == "no basket on '311352' family"