From 94bd1bf246bdd962d91c0c35fb4e3ac270cb7471 Mon Sep 17 00:00:00 2001
From: Nicolas ROCHE <nroche@entrouvert.com>
Date: Tue, 12 Jan 2021 09:33:21 +0100
Subject: [PATCH] maelis: provide dates to subscribe and unsubscribe
 webservices (#50059)

---
 passerelle/apps/maelis/models.py           | 18 ++++----
 passerelle/apps/maelis/utils.py            | 12 ++++--
 passerelle/locale/fr/LC_MESSAGES/django.po |  2 +-
 tests/data/maelis/child_activities.json    | 48 ++++++++++++++++++++++
 tests/test_maelis.py                       |  7 +++-
 5 files changed, 74 insertions(+), 13 deletions(-)

diff --git a/passerelle/apps/maelis/models.py b/passerelle/apps/maelis/models.py
index dfa0547a..83a44d05 100644
--- a/passerelle/apps/maelis/models.py
+++ b/passerelle/apps/maelis/models.py
@@ -419,35 +419,35 @@ class Maelis(BaseResource):
             if subscribingStatus != 'subscribed' and subscribingStatus != 'not-subscribed':
                 raise APIError('wrong value for subscribingStatus: %s' % subscribingStatus)
         if queryDate:
             try:
                 start_date = parse_date(queryDate)
             except ValueError as exc:
                 raise APIError('input is well formatted but not a valid date: %s' % exc)
             if not start_date:
-                raise APIError("input isn't well formatted, YYYY-MM-DD expected")
-        if not queryDate:
+                raise APIError("input isn't well formatted, YYYY-MM-DD expected: %s" % queryDate)
+        else:
             start_date = timezone.now().date()
         if start_date.strftime('%m-%d') >= '05-01':
             # start displaying next year activities on may
             school_year = start_date.year
         else:
             school_year = start_date.year - 1
         end_date = utils.get_datetime('%s-07-31' % (school_year + 1)).date()
 
         child_info = self.get_child_info(NameID, childID)
         r = self.call('ActivityService?wsdl', 'readActivityList',
                       schoolyear=school_year,
                       numPerson=childID,
                       dateStartCalend=start_date,
                       dateEndCalend=end_date)
 
         flatted_activities = utils.flatten_activities(
-            serialize_object(r), [school_year, school_year + 1])
+            serialize_object(r), start_date, end_date)
         utils.mark_subscribed_flatted_activities(flatted_activities, child_info)
         data = utils.flatted_activities_as_list(flatted_activities, subscribingStatus)
         return {'data': data}
 
     @endpoint(
         display_category=_('Activities'),
         perm='can_access',
         display_order=3,
@@ -504,48 +504,52 @@ class Maelis(BaseResource):
         description=_('Subscribe'),
         parameters={
             'NameID': {'description': _('Publik ID')},
             'childID': {'description': _('Child ID')},
             'activityID': {'description': _('Activity ID')},
             'unitID': {'description': _('Unit ID')},
             'placeID': {'description': _('Place ID')},
             'weeklyPlanning': {'description': _('Week planning (7 chars)')},
+            'start_date': {'description': _('Start date of the unit (YYYY-MM-DD)')},
+            'end_date': {'description': _('End date of the unit (YYYY-MM-DD)')},
     })
     def subscribe(self, request, NameID, childID, activityID, unitID, placeID,
-                  weeklyPlanning):
+                  weeklyPlanning, start_date, end_date):
         self.get_child_info(NameID, childID)
         client = self.get_client('FamilyService?wsdl')
         trigram_type = client.get_type('ns1:activityUnitPlaceBean')
         trigram = trigram_type(
             idActivity=activityID,
             idUnit=unitID,
             idPlace=placeID)
         subscription_type = client.get_type('ns1:subscribeActivityRequestBean')
         subpscription = subscription_type(
             personNumber=childID,
             activityUnitPlace=trigram,
-            weeklyPlanning=weeklyPlanning)
+            weeklyPlanning=weeklyPlanning,
+            dateStart=start_date,
+            dateEnd=end_date)
         r = self.call('FamilyService?wsdl', 'subscribeActivity',
                       subscribeActivityRequestBean=subpscription)
         return {'data': serialize_object(r)}
 
 
     @endpoint(
         display_category=_('Family'),
         perm='can_access',
         display_order=11,
         description=_('Unsubscribe'),
         parameters={
             'NameID': {'description': _('Publik ID')},
             'childID': {'description': _('Child ID')},
             'activityID': {'description': _('Activity ID')},
-            'start_date': {'description': _('Start date of the activity (YYYY-MM-DD)')}
+            'start_date': {'description': _('Start date of the unit (YYYY-MM-DD)')},
     })
-    def unsubscribe(self, request, NameID, childID, activityID, start_date=None):
+    def unsubscribe(self, request, NameID, childID, activityID, start_date):
         self.get_child_info(NameID, childID)
         r = self.call('FamilyService?wsdl', 'deletesubscribe',
                       numPerson=childID,
                       idActivite=activityID,
                       dateRefDelete=start_date)
         return {'data': serialize_object(r)}
 
 
diff --git a/passerelle/apps/maelis/utils.py b/passerelle/apps/maelis/utils.py
index 66905eba..51ce5ebf 100644
--- a/passerelle/apps/maelis/utils.py
+++ b/passerelle/apps/maelis/utils.py
@@ -201,17 +201,17 @@ def decompose_event(event):
         new_event['datetime'] = '%s %s' % (date_string, component['time'])
         new_event['slot_id'] = "%s%s" % (composition['virtual_unit'], component_id)
         new_event['id'] = '%s-%s-%s' % (
             date_string, event['category_id'], new_event['slot_id'])
         new_event['text'] = component['text']
         yield new_event
 
 
-def flatten_activities(activities, years):
+def flatten_activities(activities, start_date, end_date):
     data = {}
     for activity in activities:
         if activity.get('openDayList'):
             del activity['openDayList']
         activity_id = activity['activityPortail']['idAct']
         activity_text = activity['activityPortail']['label']
         activity_obj = deepcopy(activity)
         del activity_obj['unitPortailList']
@@ -222,17 +222,17 @@ def flatten_activities(activities, years):
                 "natureSpec" : {
                     "code" : "?",
                     "libelle" : "Inconnu"
                 }
             }
 
         # compute weekly planning mask parameter to use for subscribing
         planning_masks = []
-        for year in years:
+        for year in range(start_date.year, end_date.year+1):
             for item in activity['activityPortail']['weeklyCalendarActivityList']:
                 if item['yearCalendar'] == year:
                     planning_masks.append(item['weeklyCalendarStr'])
                     break
         if planning_masks:
             activity_weekly_planning_mask = ""
             for letters in zip(*planning_masks):
                 if '1' in letters:
@@ -243,17 +243,20 @@ def flatten_activities(activities, years):
             activity_weekly_planning_mask = "0000000"
 
         units = {}
         for unit in activity['unitPortailList']:
             unit_id = unit['idUnit']
             unit_text = unit['label']
             unit_obj = deepcopy(unit)
             del unit_obj['placeList']
-            # compute weekly planning parameter to use for subscribing
+
+            # compute subscribing parameters
+            unit_start_date = unit['dateStart'] or start_date
+            unit_end_date = unit['dateEnd'] or end_date
             unit_calendar_letter = unit['calendarLetter']
             unit_weekly_planning = ""
             for letter in activity_weekly_planning_mask:
                 if letter == '0':
                     unit_weekly_planning += unit_calendar_letter
                 else:
                     unit_weekly_planning += '1'
 
@@ -267,16 +270,18 @@ def flatten_activities(activities, years):
                     'text': '%s / %s / %s' % (activity_text, unit_text, place_text),
                     'activity_id': activity_id,
                     'unit_id': unit_id,
                     'place_id': place_id,
                     'activity_text': activity_text,
                     'unit_text': unit_text,
                     'place_text': place_text,
                     'activity_weekly_planning_mask': activity_weekly_planning_mask,
+                    'subscribe_start_date': unit_start_date,
+                    'subscribe_end_date': unit_end_date,
                     'unit_calendar_letter': unit_calendar_letter,
                     'unit_weekly_planning': unit_weekly_planning,
                     'activity_object': activity_obj,
                     'unit_object': unit_obj,
                     'place_object': place,
                 }
             units[unit_id] = places
         data[activity_id] = units
@@ -285,16 +290,17 @@ def flatten_activities(activities, years):
 
 def mark_subscribed_flatted_activities(flatted_activities, child_info):
     for child_activity in child_info['subscribeActivityList']:
         activity = flatted_activities[child_activity['idActivity']]
         for child_unit in child_activity['subscribesUnit']:
             unit = activity[child_unit['idUnit']]
             place = unit[child_activity['place']]
             place['user_subscribing_status'] = 'subscribed'
+            place['unsubscribe_start_date'] = child_unit['dateStart']
 
 
 def flatted_activities_as_list(flatted_activities, filtering_status):
     data = []
     for activity in [a[1] for a in sorted(flatted_activities.items())]:
         for unit in [u[1] for u in sorted(activity.items())]:
             is_unit_subscribable = True
             is_unit_subscribed = False
diff --git a/passerelle/locale/fr/LC_MESSAGES/django.po b/passerelle/locale/fr/LC_MESSAGES/django.po
index 3bfc86a7..ff7ced99 100644
--- a/passerelle/locale/fr/LC_MESSAGES/django.po
+++ b/passerelle/locale/fr/LC_MESSAGES/django.po
@@ -2153,17 +2153,17 @@ msgstr ""
 "Décompose les événements reliés à des parties de journées si positionné"
 
 #: apps/maelis/models.py:504
 msgid "Subscribe"
 msgstr "Inscription"
 
 #: apps/maelis/models.py:508 apps/maelis/models.py:540
 msgid "Activity ID"
-msgstr "Identifiant de l'activités"
+msgstr "Identifiant de l'activité"
 
 #: apps/maelis/models.py:509
 msgid "Unit ID"
 msgstr "Identifiant de l'unité"
 
 #: apps/maelis/models.py:510
 msgid "Place ID"
 msgstr "Identifiant du lieu"
diff --git a/tests/data/maelis/child_activities.json b/tests/data/maelis/child_activities.json
index 0fa62928..c103e064 100644
--- a/tests/data/maelis/child_activities.json
+++ b/tests/data/maelis/child_activities.json
@@ -56,16 +56,18 @@
                 "lib2": null,
                 "nbPlace": 0,
                 "nbPlaceBoy": 0,
                 "nbPlaceGirl": 0,
                 "schoolInfoList": [],
                 "typeCtrlPlace": "N"
             },
             "place_text": "3 JEAN GIONO",
+            "subscribe_end_date": "2021-07-06T00:00:00+02:00",
+            "subscribe_start_date": "2020-09-01T00:00:00+02:00",
             "text": "1 2020-2021 GARDERIE MATIN / 1 2020-2021 GARDERIE MATIN / 3 JEAN GIONO",
             "unit_calendar_letter": "X",
             "unit_id": "A10003121694",
             "unit_object": {
                 "birthDateEnd": null,
                 "birthDateStart": null,
                 "calendarLetter": "X",
                 "consoTarifList": [
@@ -156,16 +158,18 @@
                 "lib2": null,
                 "nbPlace": 0,
                 "nbPlaceBoy": 0,
                 "nbPlaceGirl": 0,
                 "schoolInfoList": [],
                 "typeCtrlPlace": "N"
             },
             "place_text": "2 FRANCOIS FABIE",
+            "subscribe_end_date": "2021-07-06T00:00:00+02:00",
+            "subscribe_start_date": "2020-09-01T00:00:00+02:00",
             "text": "1 2020-2021 GARDERIE MATIN / 1 2020-2021 GARDERIE MATIN / 2 FRANCOIS FABIE",
             "unit_calendar_letter": "X",
             "unit_id": "A10003121694",
             "unit_object": {
                 "birthDateEnd": null,
                 "birthDateStart": null,
                 "calendarLetter": "X",
                 "consoTarifList": [
@@ -193,16 +197,17 @@
                 "nbPlaceGirl": 0,
                 "numOrder": 1,
                 "subscribePublication": "E",
                 "topCESU": "O",
                 "typeCtrlPlace": "N"
             },
             "unit_text": "1 2020-2021 GARDERIE MATIN",
             "unit_weekly_planning": "XX1XX11",
+            "unsubscribe_start_date": "2020-09-01T00:00:00+02:00",
             "user_subscribing_status": "subscribed"
         },
         {
             "activity_id": "A10003123490",
             "activity_object": {
                 "activityPortail": {
                     "activityType": {
                         "code": "RESTSCOL",
@@ -271,16 +276,18 @@
                         "idSchool": "A10000003597",
                         "phone": null,
                         "schoolName": "2  FRANCOIS FABIE"
                     }
                 ],
                 "typeCtrlPlace": "N"
             },
             "place_text": "2 FRANCOIS FABIE",
+            "subscribe_end_date": "2021-07-03T00:00:00+02:00",
+            "subscribe_start_date": "2020-09-02T00:00:00+02:00",
             "text": "2 2020-2021  RESTAURATION SCOLAIRE / 2 2020-2021  RESTAURATION SCOLAIRE / 2 FRANCOIS FABIE",
             "unit_calendar_letter": "X",
             "unit_id": "A10003123492",
             "unit_object": {
                 "birthDateEnd": null,
                 "birthDateStart": null,
                 "calendarLetter": "X",
                 "consoTarifList": [
@@ -330,16 +337,17 @@
                 "nbPlaceGirl": 0,
                 "numOrder": 2,
                 "subscribePublication": "E",
                 "topCESU": "N",
                 "typeCtrlPlace": "N"
             },
             "unit_text": "2 2020-2021  RESTAURATION SCOLAIRE",
             "unit_weekly_planning": "XX1XX11",
+            "unsubscribe_start_date": "2020-09-02T00:00:00+02:00",
             "user_subscribing_status": "subscribed"
         },
         {
             "activity_id": "A10003123507",
             "activity_object": {
                 "activityPortail": {
                     "activityType": {
                         "code": "ACCSOIR",
@@ -389,16 +397,18 @@
                 "lib2": null,
                 "nbPlace": 0,
                 "nbPlaceBoy": 0,
                 "nbPlaceGirl": 0,
                 "schoolInfoList": [],
                 "typeCtrlPlace": "N"
             },
             "place_text": "3 JEAN GIONO",
+            "subscribe_end_date": "2021-07-03T00:00:00+02:00",
+            "subscribe_start_date": "2020-09-02T00:00:00+02:00",
             "text": "3 2020-2021 GARDERIE SOIR / 3 2020-2021 GARDERIE SOIR / 3 JEAN GIONO",
             "unit_calendar_letter": "X",
             "unit_id": "A10003123509",
             "unit_object": {
                 "birthDateEnd": null,
                 "birthDateStart": null,
                 "calendarLetter": "X",
                 "consoTarifList": [
@@ -485,16 +495,18 @@
                 "lib2": null,
                 "nbPlace": 0,
                 "nbPlaceBoy": 0,
                 "nbPlaceGirl": 0,
                 "schoolInfoList": [],
                 "typeCtrlPlace": "N"
             },
             "place_text": "2 FRANCOIS FABIE",
+            "subscribe_end_date": "2021-07-03T00:00:00+02:00",
+            "subscribe_start_date": "2020-09-02T00:00:00+02:00",
             "text": "3 2020-2021 GARDERIE SOIR / 3 2020-2021 GARDERIE SOIR / 2 FRANCOIS FABIE",
             "unit_calendar_letter": "X",
             "unit_id": "A10003123509",
             "unit_object": {
                 "birthDateEnd": null,
                 "birthDateStart": null,
                 "calendarLetter": "X",
                 "consoTarifList": [
@@ -585,16 +597,18 @@
                 "lib2": null,
                 "nbPlace": 0,
                 "nbPlaceBoy": 0,
                 "nbPlaceGirl": 0,
                 "schoolInfoList": [],
                 "typeCtrlPlace": "N"
             },
             "place_text": "ALSH PAGNOL",
+            "subscribe_end_date": "2021-03-05T00:00:00+02:00",
+            "subscribe_start_date": "2021-02-28T00:00:00+02:00",
             "text": "2020-2021 ALSH VACANCES PAGNOL (CAPA) / HIVER 2EME SEMAINE / ALSH PAGNOL",
             "unit_calendar_letter": "c",
             "unit_id": "A10003131861",
             "unit_object": {
                 "birthDateEnd": null,
                 "birthDateStart": null,
                 "calendarLetter": "c",
                 "consoTarifList": [
@@ -696,16 +710,18 @@
                 "lib2": null,
                 "nbPlace": 0,
                 "nbPlaceBoy": 0,
                 "nbPlaceGirl": 0,
                 "schoolInfoList": [],
                 "typeCtrlPlace": "N"
             },
             "place_text": "ALSH MISTRAL",
+            "subscribe_end_date": "2021-03-05T00:00:00+02:00",
+            "subscribe_start_date": "2021-02-28T00:00:00+02:00",
             "text": "2020-2021 ALSH VACANCES PAGNOL (CAPA) / HIVER 2EME SEMAINE / ALSH MISTRAL",
             "unit_calendar_letter": "c",
             "unit_id": "A10003131861",
             "unit_object": {
                 "birthDateEnd": null,
                 "birthDateStart": null,
                 "calendarLetter": "c",
                 "consoTarifList": [
@@ -807,16 +823,18 @@
                 "lib2": null,
                 "nbPlace": 0,
                 "nbPlaceBoy": 0,
                 "nbPlaceGirl": 0,
                 "schoolInfoList": [],
                 "typeCtrlPlace": "N"
             },
             "place_text": "ALSH PAGNOL",
+            "subscribe_end_date": "2020-10-30T00:00:00+02:00",
+            "subscribe_start_date": "2020-10-26T00:00:00+02:00",
             "text": "2020-2021 ALSH VACANCES PAGNOL (CAPA) / TOUSSAINT 2EME SEMAINE / ALSH PAGNOL",
             "unit_calendar_letter": "D",
             "unit_id": "A10003131879",
             "unit_object": {
                 "birthDateEnd": null,
                 "birthDateStart": null,
                 "calendarLetter": "D",
                 "consoTarifList": [
@@ -918,16 +936,18 @@
                 "lib2": null,
                 "nbPlace": 0,
                 "nbPlaceBoy": 0,
                 "nbPlaceGirl": 0,
                 "schoolInfoList": [],
                 "typeCtrlPlace": "N"
             },
             "place_text": "ALSH MISTRAL",
+            "subscribe_end_date": "2020-10-30T00:00:00+02:00",
+            "subscribe_start_date": "2020-10-26T00:00:00+02:00",
             "text": "2020-2021 ALSH VACANCES PAGNOL (CAPA) / TOUSSAINT 2EME SEMAINE / ALSH MISTRAL",
             "unit_calendar_letter": "D",
             "unit_id": "A10003131879",
             "unit_object": {
                 "birthDateEnd": null,
                 "birthDateStart": null,
                 "calendarLetter": "D",
                 "consoTarifList": [
@@ -1029,16 +1049,18 @@
                 "lib2": null,
                 "nbPlace": 0,
                 "nbPlaceBoy": 0,
                 "nbPlaceGirl": 0,
                 "schoolInfoList": [],
                 "typeCtrlPlace": "N"
             },
             "place_text": "ALSH PAGNOL",
+            "subscribe_end_date": "2020-10-23T00:00:00+02:00",
+            "subscribe_start_date": "2020-10-19T00:00:00+02:00",
             "text": "2020-2021 ALSH VACANCES PAGNOL (CAPA) / TOUSSAINT 1 ERE SEMAINE / ALSH PAGNOL",
             "unit_calendar_letter": "C",
             "unit_id": "A10003131882",
             "unit_object": {
                 "birthDateEnd": null,
                 "birthDateStart": null,
                 "calendarLetter": "C",
                 "consoTarifList": [
@@ -1140,16 +1162,18 @@
                 "lib2": null,
                 "nbPlace": 0,
                 "nbPlaceBoy": 0,
                 "nbPlaceGirl": 0,
                 "schoolInfoList": [],
                 "typeCtrlPlace": "N"
             },
             "place_text": "ALSH MISTRAL",
+            "subscribe_end_date": "2020-10-23T00:00:00+02:00",
+            "subscribe_start_date": "2020-10-19T00:00:00+02:00",
             "text": "2020-2021 ALSH VACANCES PAGNOL (CAPA) / TOUSSAINT 1 ERE SEMAINE / ALSH MISTRAL",
             "unit_calendar_letter": "C",
             "unit_id": "A10003131882",
             "unit_object": {
                 "birthDateEnd": null,
                 "birthDateStart": null,
                 "calendarLetter": "C",
                 "consoTarifList": [
@@ -1251,16 +1275,18 @@
                 "lib2": null,
                 "nbPlace": 0,
                 "nbPlaceBoy": 0,
                 "nbPlaceGirl": 0,
                 "schoolInfoList": [],
                 "typeCtrlPlace": "N"
             },
             "place_text": "ALSH PAGNOL",
+            "subscribe_end_date": "2020-12-31T00:00:00+02:00",
+            "subscribe_start_date": "2020-12-28T00:00:00+02:00",
             "text": "2020-2021 ALSH VACANCES PAGNOL (CAPA) / NOEL 2EME SEMAINE / ALSH PAGNOL",
             "unit_calendar_letter": "B",
             "unit_id": "A10003131903",
             "unit_object": {
                 "birthDateEnd": null,
                 "birthDateStart": null,
                 "calendarLetter": "B",
                 "consoTarifList": [
@@ -1362,16 +1388,18 @@
                 "lib2": null,
                 "nbPlace": 0,
                 "nbPlaceBoy": 0,
                 "nbPlaceGirl": 0,
                 "schoolInfoList": [],
                 "typeCtrlPlace": "N"
             },
             "place_text": "ALSH MISTRAL",
+            "subscribe_end_date": "2020-12-31T00:00:00+02:00",
+            "subscribe_start_date": "2020-12-28T00:00:00+02:00",
             "text": "2020-2021 ALSH VACANCES PAGNOL (CAPA) / NOEL 2EME SEMAINE / ALSH MISTRAL",
             "unit_calendar_letter": "B",
             "unit_id": "A10003131903",
             "unit_object": {
                 "birthDateEnd": null,
                 "birthDateStart": null,
                 "calendarLetter": "B",
                 "consoTarifList": [
@@ -1473,16 +1501,18 @@
                 "lib2": null,
                 "nbPlace": 0,
                 "nbPlaceBoy": 0,
                 "nbPlaceGirl": 0,
                 "schoolInfoList": [],
                 "typeCtrlPlace": "N"
             },
             "place_text": "ALSH PAGNOL",
+            "subscribe_end_date": "2020-12-24T00:00:00+02:00",
+            "subscribe_start_date": "2020-12-21T00:00:00+02:00",
             "text": "2020-2021 ALSH VACANCES PAGNOL (CAPA) / NOEL 1ERE SEMAINE / ALSH PAGNOL",
             "unit_calendar_letter": "J",
             "unit_id": "A10003131909",
             "unit_object": {
                 "birthDateEnd": null,
                 "birthDateStart": null,
                 "calendarLetter": "J",
                 "consoTarifList": [
@@ -1584,16 +1614,18 @@
                 "lib2": null,
                 "nbPlace": 0,
                 "nbPlaceBoy": 0,
                 "nbPlaceGirl": 0,
                 "schoolInfoList": [],
                 "typeCtrlPlace": "N"
             },
             "place_text": "ALSH MISTRAL",
+            "subscribe_end_date": "2020-12-24T00:00:00+02:00",
+            "subscribe_start_date": "2020-12-21T00:00:00+02:00",
             "text": "2020-2021 ALSH VACANCES PAGNOL (CAPA) / NOEL 1ERE SEMAINE / ALSH MISTRAL",
             "unit_calendar_letter": "J",
             "unit_id": "A10003131909",
             "unit_object": {
                 "birthDateEnd": null,
                 "birthDateStart": null,
                 "calendarLetter": "J",
                 "consoTarifList": [
@@ -1695,16 +1727,18 @@
                 "lib2": null,
                 "nbPlace": 0,
                 "nbPlaceBoy": 0,
                 "nbPlaceGirl": 0,
                 "schoolInfoList": [],
                 "typeCtrlPlace": "N"
             },
             "place_text": "ALSH PAGNOL",
+            "subscribe_end_date": "2021-07-03T00:00:00+02:00",
+            "subscribe_start_date": "2020-09-02T00:00:00+02:00",
             "text": "2020-2021 CENTRE DE LOISIRS MERCREDI / JOURNEE / ALSH PAGNOL",
             "unit_calendar_letter": "A",
             "unit_id": "A10003132034",
             "unit_object": {
                 "birthDateEnd": null,
                 "birthDateStart": null,
                 "calendarLetter": "A",
                 "consoTarifList": [
@@ -1795,16 +1829,18 @@
                 "lib2": null,
                 "nbPlace": 0,
                 "nbPlaceBoy": 0,
                 "nbPlaceGirl": 0,
                 "schoolInfoList": [],
                 "typeCtrlPlace": "N"
             },
             "place_text": "ALSH PAGNOL",
+            "subscribe_end_date": "2021-07-03T00:00:00+02:00",
+            "subscribe_start_date": "2020-09-02T00:00:00+02:00",
             "text": "2020-2021 CENTRE DE LOISIRS MERCREDI / MATIN / ALSH PAGNOL",
             "unit_calendar_letter": "B",
             "unit_id": "A10003132036",
             "unit_object": {
                 "birthDateEnd": null,
                 "birthDateStart": null,
                 "calendarLetter": "B",
                 "consoTarifList": [
@@ -1895,16 +1931,18 @@
                 "lib2": null,
                 "nbPlace": 0,
                 "nbPlaceBoy": 0,
                 "nbPlaceGirl": 0,
                 "schoolInfoList": [],
                 "typeCtrlPlace": "N"
             },
             "place_text": "ALSH PAGNOL",
+            "subscribe_end_date": "2021-07-03T00:00:00+02:00",
+            "subscribe_start_date": "2020-09-02T00:00:00+02:00",
             "text": "2020-2021 CENTRE DE LOISIRS MERCREDI / MATIN ET REPAS / ALSH PAGNOL",
             "unit_calendar_letter": "C",
             "unit_id": "A10003132038",
             "unit_object": {
                 "birthDateEnd": null,
                 "birthDateStart": null,
                 "calendarLetter": "C",
                 "consoTarifList": [
@@ -1995,16 +2033,18 @@
                 "lib2": null,
                 "nbPlace": 0,
                 "nbPlaceBoy": 0,
                 "nbPlaceGirl": 0,
                 "schoolInfoList": [],
                 "typeCtrlPlace": "N"
             },
             "place_text": "ALSH PAGNOL",
+            "subscribe_end_date": "2021-07-03T00:00:00+02:00",
+            "subscribe_start_date": "2020-09-02T00:00:00+02:00",
             "text": "2020-2021 CENTRE DE LOISIRS MERCREDI / APRES MIDI / ALSH PAGNOL",
             "unit_calendar_letter": "D",
             "unit_id": "A10003132040",
             "unit_object": {
                 "birthDateEnd": null,
                 "birthDateStart": null,
                 "calendarLetter": "D",
                 "consoTarifList": [
@@ -2095,16 +2135,18 @@
                 "lib2": null,
                 "nbPlace": 0,
                 "nbPlaceBoy": 0,
                 "nbPlaceGirl": 0,
                 "schoolInfoList": [],
                 "typeCtrlPlace": "N"
             },
             "place_text": "ALSH PAGNOL",
+            "subscribe_end_date": "2021-07-31",
+            "subscribe_start_date": "2020-01-01T00:00:00+02:00",
             "text": "COURS DE DANSE / COURS DE DANSE / ALSH PAGNOL",
             "unit_calendar_letter": "X",
             "unit_id": "A10003132091",
             "unit_object": {
                 "birthDateEnd": null,
                 "birthDateStart": null,
                 "calendarLetter": "X",
                 "consoTarifList": [],
@@ -2179,16 +2221,18 @@
                 "lib2": null,
                 "nbPlace": 0,
                 "nbPlaceBoy": 0,
                 "nbPlaceGirl": 0,
                 "schoolInfoList": [],
                 "typeCtrlPlace": "N"
             },
             "place_text": "ALSH PAGNOL",
+            "subscribe_end_date": "2021-07-31",
+            "subscribe_start_date": "2020-01-01T00:00:00+02:00",
             "text": "LASERQUEST / LASERQUEST / ALSH PAGNOL",
             "unit_calendar_letter": "X",
             "unit_id": "A10003132152",
             "unit_object": {
                 "birthDateEnd": null,
                 "birthDateStart": null,
                 "calendarLetter": "X",
                 "consoTarifList": [],
@@ -2263,16 +2307,18 @@
                 "lib2": null,
                 "nbPlace": 0,
                 "nbPlaceBoy": 0,
                 "nbPlaceGirl": 0,
                 "schoolInfoList": [],
                 "typeCtrlPlace": "N"
             },
             "place_text": "ALSH PAGNOL",
+            "subscribe_end_date": "2021-07-31",
+            "subscribe_start_date": "2020-09-02T00:00:00+02:00",
             "text": "EQUITATION / EQUITATION / ALSH PAGNOL",
             "unit_calendar_letter": "X",
             "unit_id": "A10003132273",
             "unit_object": {
                 "birthDateEnd": "2014-12-31T00:00:00+02:00",
                 "birthDateStart": "1970-01-01T00:00:00+02:00",
                 "calendarLetter": "X",
                 "consoTarifList": [],
@@ -2347,16 +2393,18 @@
                 "lib2": null,
                 "nbPlace": 0,
                 "nbPlaceBoy": 0,
                 "nbPlaceGirl": 0,
                 "schoolInfoList": [],
                 "typeCtrlPlace": "N"
             },
             "place_text": "ALSH PAGNOL",
+            "subscribe_end_date": "2021-07-31",
+            "subscribe_start_date": "2020-01-01T00:00:00+02:00",
             "text": "SORTIE MUSEE / SORTIE MUSEE / ALSH PAGNOL",
             "unit_calendar_letter": "X",
             "unit_id": "A10003132295",
             "unit_object": {
                 "birthDateEnd": null,
                 "birthDateStart": null,
                 "calendarLetter": "X",
                 "consoTarifList": [],
diff --git a/tests/test_maelis.py b/tests/test_maelis.py
index f203b4ac..41cfac4e 100644
--- a/tests/test_maelis.py
+++ b/tests/test_maelis.py
@@ -391,17 +391,19 @@ def test_subscribe(mocked_post, mocked_get, family_service_wsdl,
             status_code=200,
             headers={'Content-Type': 'text/xml'}),
         utils.FakedResponse(
             content=get_xml_file('subscribeActivityResult.xml'),
             status_code=200,
             headers={'Content-Type': 'text/xml'})
     )
     Link.objects.create(resource=connector, family_id='3264', name_id='local')
-    resp = app.get('/maelis/test/subscribe/?NameID=local&childID=21293&activityID=A10003123507&unitID=A10003123507&placeID=A10000000211&weeklyPlanning=XX1XX11')
+    resp = app.get('/maelis/test/subscribe/?NameID=local&childID=21293'
+                   + '&activityID=A10003123507&unitID=A10003123507&placeID=A10000000211'
+                   + '&weeklyPlanning=XX1XX11&start_date=2020-08-01&end_date=2021-07-31')
     assert not resp.json['err']
     assert resp.json['data']['state'] == {
         "idState" : "1",
         "isWaitState" : False,
         "libelle" : "Confirmé"
     }
 
 
@@ -416,11 +418,12 @@ def test_unsubscribe(mocked_post, mocked_get, family_service_wsdl,
             status_code=200,
             headers={'Content-Type': 'text/xml'}),
         utils.FakedResponse(
             content=get_xml_file('deletesubscribe.xml'),
             status_code=200,
             headers={'Content-Type': 'text/xml'})
     )
     Link.objects.create(resource=connector, family_id='3264', name_id='local')
-    resp = app.get('/maelis/test/unsubscribe/?NameID=local&childID=21293&activityID=A10003121692&start_date=2020-09-01')
+    resp = app.get('/maelis/test/unsubscribe/?NameID=local&childID=21293'
+                   + '&activityID=A10003121692&start_date=2020-08-01')
     assert not resp.json['err']
     assert resp.json['data'] is None
-- 
2.29.2

