From f5d7076ea907accdbfe6818cb3bea6012a647ad7 Mon Sep 17 00:00:00 2001
From: Nicolas ROCHE <nroche@entrouvert.com>
Date: Sun, 20 Dec 2020 02:23:06 +0100
Subject: [PATCH] maelis: add child month planning listing (#48480)

---
 passerelle/apps/maelis/models.py              |   52 +
 passerelle/apps/maelis/utils.py               |  152 +-
 .../child_planning_after_decomposition.json   |  383 +++++
 .../child_planning_before_decomposition.json  |  392 +++++
 ...hild_planning_readActivityListResponse.xml | 1355 +++++++++++++++++
 ...lanning_readChildMonthPlanningResponse.xml |  209 +++
 tests/test_maelis.py                          |  134 +-
 7 files changed, 2667 insertions(+), 10 deletions(-)
 create mode 100644 tests/data/maelis/child_planning_after_decomposition.json
 create mode 100644 tests/data/maelis/child_planning_before_decomposition.json
 create mode 100644 tests/data/maelis/child_planning_readActivityListResponse.xml
 create mode 100644 tests/data/maelis/child_planning_readChildMonthPlanningResponse.xml

diff --git a/passerelle/apps/maelis/models.py b/passerelle/apps/maelis/models.py
index 617f69ed..5a27e583 100644
--- a/passerelle/apps/maelis/models.py
+++ b/passerelle/apps/maelis/models.py
@@ -392,16 +392,68 @@ class Maelis(BaseResource):
             end_datetime = start_datetime + timezone.timedelta(days=62)
         r = self.call('ActivityService?wsdl', 'readActivityList',
                       schoolyear=school_year, numPerson=personID,
                       dateStartCalend=start_datetime,
                       dateEndCalend=end_datetime)
         activities = serialize_object(r)
         return {'data': [utils.normalize_activity(a) for a in activities]}
 
+    @endpoint(
+        display_category=_('Activities'),
+        perm='can_access',
+        display_order=3,
+        description=_('Read child planning'),
+        name='child-planning',
+        parameters={
+            'NameID': {'description': _('Publik ID')},
+            'personID': {'description': _('Person ID')},
+            'start_date': {'description': _('Start date (YYYY-MM-DD format)')},
+            'end_date': {'description': _('End date (YYYY-MM-DD format)')},
+    })
+    def child_planning(self, request, NameID, personID, start_date=None, end_date=None):
+        link = self.get_link(NameID)
+        family_data = self.get_family_data(link.family_id)
+        if personID not in [c['id'] for c in family_data['childInfoList']]:
+            raise APIError('Child not found', err_code='not-found')
+        if start_date and end_date:
+            start = utils.parse_datetime(start_date)
+            end = utils.parse_datetime(end_date)
+        else:
+            # get week that includes start_date
+            start, end = utils.get_week_boundaries(start_date)
+        school_year = utils.get_default_school_year(start)
+
+        # get all events
+        r = self.call('ActivityService?wsdl', 'readActivityList',
+                      schoolyear=school_year, numPerson=personID,
+                      dateStartCalend=start,
+                      dateEndCalend=end)
+        activities = serialize_object(r)
+        events = {key: value
+                       for a in activities
+                       for (key, value) in utils.get_events(a, start, end)}
+
+        # book events matching the child planning
+        for date in utils.get_months(start, end):
+            r = self.call('ActivityService?wsdl', 'readChildMonthPlanning',
+                          year=date.year,
+                          numMonth=date.month,
+                          numPerson=personID)
+            planning = serialize_object(r['calendList'])
+            utils.book_events(events, planning, start, end)
+
+        # decompose units (and use a dict to remove dupplicated components)
+        events = {x['id']: x
+                       for e in events.values()
+                       for x in utils.decompose_event(e)}
+
+        # sort by id
+        return {'data': [s[1] for s in sorted(events.items())]}
+
 
 class Link(models.Model):
     resource = models.ForeignKey(Maelis, on_delete=models.CASCADE)
     name_id = models.CharField(blank=False, max_length=256)
     family_id = models.CharField(blank=False, max_length=128)
     created = models.DateTimeField(auto_now_add=True)
     updated = models.DateTimeField(auto_now=True)
 
diff --git a/passerelle/apps/maelis/utils.py b/passerelle/apps/maelis/utils.py
index 60444cb4..fff4f0c2 100644
--- a/passerelle/apps/maelis/utils.py
+++ b/passerelle/apps/maelis/utils.py
@@ -12,31 +12,71 @@
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU Affero General Public License for more details.
 #
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 from __future__ import unicode_literals
 
+from copy import copy
+from datetime import datetime
+from dateutil.relativedelta import relativedelta
+
 from django.utils import timezone
 
-datetime_format = '%d/%m/%Y %H:%M:%S'
+from passerelle.utils.jsonresponse import APIError
+
+DATETIME_FORMAT = '%Y-%m-%d %H:%M'
+
+COMPONENTS = {
+    'PART01': {
+        'text': 'Matinée',
+        'time': '08:00',
+    },
+    'PART02': {
+        'text': 'Repas',
+        'time': '12:00',
+    },
+    'PART03': {
+        'text': 'Après-midi',
+        'time': '14:00',
+    }
+}
+
+COMPOSED_UNITS = {
+    'A10003132034': {  # JOURNEE
+        'virtual_unit': 'EO0001',
+        'components': ['PART01', 'PART02', 'PART03'],
+    },
+    'A10003132036': {  # MATIN
+        'virtual_unit': 'EO0001',
+        'components': ['PART01'],
+    },
+    'A10003132038': {  # MATIN ET REPAS
+        'virtual_unit': 'EO0001',
+        'components': ['PART01', 'PART02'],
+    },
+    'A10003132040': {  # APRES MIDI
+        'virtual_unit': 'EO0001',
+        'components': ['PART03'],
+    },
+}
 
 
 def normalize_invoice(invoice):
     data = {
         'id': '%s-%s' % (invoice.numFamily, invoice.numInvoice),
         'display_id': str(invoice.numInvoice),
         'label': invoice.TTFInfo.libelle,
-        'created': invoice.dateInvoice.strftime(datetime_format),
+        'created': invoice.dateInvoice.strftime(DATETIME_FORMAT),
         'amount': invoice.amountInvoice - invoice.amountPaid,
         'paid': invoice.amountInvoice == invoice.amountPaid,
         'total_amount': invoice.amountInvoice,
-        'pay_limit_date': invoice.dateDeadline.strftime(datetime_format),
+        'pay_limit_date': invoice.dateDeadline.strftime(DATETIME_FORMAT),
         'has_pdf': bool(invoice.pdfName),
         'amount_paid': invoice.amountPaid
     }
     if invoice.amountInvoice == invoice.amountPaid:
         data.update({
             'amount': 0,
             'pay_limit_date': '',
             'online_payment': False
@@ -52,14 +92,110 @@ def normalize_activity(activity):
 
 def normalize_person(person):
     person['id'] = person['num']
     person['text'] = '{} {}'.format(
                 person['firstname'], person['lastname']).strip()
     return person
 
 
-def get_default_school_year():
-    now = timezone.now()
-    if now.strftime('%m-%d') >= '07-31':
-        return now.year
+def get_default_school_year(date=None):
+    if not date:
+        date = timezone.now()
+    if date.strftime('%m-%d') >= '07-31':
+        return date.year
     else:
-        return now.year - 1
+        return date.year - 1
+
+
+def parse_datetime(date_string):
+    date = timezone.make_aware(datetime.strptime(date_string, '%Y-%m-%d'))
+    return date
+
+
+def get_week_boundaries(date_string=None):
+    if date_string:
+        date = parse_datetime(date_string)
+    else:
+        date = timezone.now()
+    date_string = date.strftime('%Y-W%W')
+    monday = timezone.make_aware(datetime.strptime(date_string + '-1', "%Y-W%W-%w"))
+    sunday = timezone.make_aware(datetime.strptime(date_string + '-0', "%Y-W%W-%w"))
+    return monday, sunday
+
+
+def get_months(start_date, end_date):
+    if end_date < start_date:
+        return
+    date = start_date.replace(day=1)
+    while date.strftime('%Y-%m') <= end_date.strftime('%Y-%m'):
+        yield date
+        date = date + relativedelta(months=1)
+
+
+def get_events(activity, start_date, end_date):
+    activity_id = activity['activityPortail']['idAct']
+    for unit in activity['unitPortailList']:
+        unit_id = unit['idUnit']
+        for day in activity['openDayList']:
+
+            # readActivityList may return more days than requested
+            if not start_date <= day <= end_date:
+                continue
+
+            date_string = day.strftime(DATETIME_FORMAT)
+            event_id = '%s-%s-%s' % (date_string, activity_id, unit_id)
+            yield event_id, {
+                'id': event_id,
+                'category_id': activity_id,
+                'slot_id': unit_id,
+                'datetime': date_string,
+                'category': activity['activityPortail']['label'],
+                'text': unit['label'],
+                'user_booking_status': 'not-booked',
+            }
+
+
+def book_events(events, planning, start_date, end_date):
+    for item in planning:
+        activity_id = item['unit']['idActivity']
+        unit_id = item['unit']['id']
+        for day in item['listDays']:
+            if not start_date <= day['datePlanning'] <= end_date:
+                continue
+
+            # the planning give the current time (I guess this is a bug)
+            # hopefully the hour is still never set from activities
+            date_string = day['datePlanning'].strftime('%Y-%m-%d') + ' 00:00'
+
+            event_id = '%s-%s-%s' % (date_string, activity_id, unit_id)
+
+            # database may be corrupted by using updateScheduleCalendars
+            try:
+                event = events[event_id]
+            except KeyError:
+                raise APIError('The planning returns an unknow day on activities: %s'
+                               % day['datePlanning'])
+
+            event['user_booking_status'] = 'booked'
+
+
+def decompose_event(event):
+    """ Break down 'JOURNEE', 'MATIN', 'MATIN ET REPAS' and APRES MIDI' units
+        into 'Matin', 'Repas' and 'Après-midi' factice EO's ones.
+    """
+    if event['slot_id'] not in COMPOSED_UNITS.keys():
+        yield event
+        return
+
+    date = datetime.strptime(event['datetime'], DATETIME_FORMAT)
+    date_string = date.strftime('%Y-%m-%d')
+    composition = COMPOSED_UNITS[event['slot_id']]
+
+    for component_id in composition['components']:
+        component = COMPONENTS[component_id]
+        new_event = copy(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' % (
+            new_event['datetime'], event['category_id'], new_event['slot_id'])
+        new_event['text'] = component['text']
+        yield new_event
diff --git a/tests/data/maelis/child_planning_after_decomposition.json b/tests/data/maelis/child_planning_after_decomposition.json
new file mode 100644
index 00000000..9ae76523
--- /dev/null
+++ b/tests/data/maelis/child_planning_after_decomposition.json
@@ -0,0 +1,383 @@
+{
+   "data" : [
+      {
+         "category" : "MULTI ACCUEIL LES OLIVIERS",
+         "category_id" : "A10000003840",
+         "datetime" : "2020-12-14 00:00",
+         "id" : "2020-12-14 00:00-A10000003840-A10000003844",
+         "slot_id" : "A10000003844",
+         "text" : "MULTI ACCUEIL LES OLIVIERS - Réguliers",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "MULTI ACCUEIL LES OLIVIERS",
+         "category_id" : "A10000003840",
+         "datetime" : "2020-12-14 00:00",
+         "id" : "2020-12-14 00:00-A10000003840-A10000003845",
+         "slot_id" : "A10000003845",
+         "text" : "MULTI ACCUEIL LES OLIVIERS - Occasionnels",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "HALTE GARDERIE LES MAGNOLIAS",
+         "category_id" : "A10000006100",
+         "datetime" : "2020-12-14 00:00",
+         "id" : "2020-12-14 00:00-A10000006100-A10000006104",
+         "slot_id" : "A10000006104",
+         "text" : "HALTE GARDERIE LES MAGNOLIAS - Réguliers",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "HALTE GARDERIE LES MAGNOLIAS",
+         "category_id" : "A10000006100",
+         "datetime" : "2020-12-14 00:00",
+         "id" : "2020-12-14 00:00-A10000006100-A10000006105",
+         "slot_id" : "A10000006105",
+         "text" : "HALTE GARDERIE LES MAGNOLIAS - Occasionnels",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "1 2020-2021 GARDERIE MATIN",
+         "category_id" : "A10003121692",
+         "datetime" : "2020-12-14 00:00",
+         "id" : "2020-12-14 00:00-A10003121692-A10003121694",
+         "slot_id" : "A10003121694",
+         "text" : "1 2020-2021 GARDERIE MATIN",
+         "user_booking_status" : "booked"
+      },
+      {
+         "category" : "2 2020-2021  RESTAURATION SCOLAIRE",
+         "category_id" : "A10003123490",
+         "datetime" : "2020-12-14 00:00",
+         "id" : "2020-12-14 00:00-A10003123490-A10003123492",
+         "slot_id" : "A10003123492",
+         "text" : "2 2020-2021  RESTAURATION SCOLAIRE",
+         "user_booking_status" : "booked"
+      },
+      {
+         "category" : "3 2020-2021 GARDERIE SOIR",
+         "category_id" : "A10003123507",
+         "datetime" : "2020-12-14 00:00",
+         "id" : "2020-12-14 00:00-A10003123507-A10003123509",
+         "slot_id" : "A10003123509",
+         "text" : "3 2020-2021 GARDERIE SOIR",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "COURS DE DANSE",
+         "category_id" : "A10003132090",
+         "datetime" : "2020-12-14 00:00",
+         "id" : "2020-12-14 00:00-A10003132090-A10003132091",
+         "slot_id" : "A10003132091",
+         "text" : "COURS DE DANSE",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "ATELIER D'EXPRESSION THEATRALE",
+         "category_id" : "A10003132293",
+         "datetime" : "2020-12-14 00:00",
+         "id" : "2020-12-14 00:00-A10003132293-A10003132295",
+         "slot_id" : "A10003132295",
+         "text" : "ATELIER D'EXPRESSION THEATRALE",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "MULTI ACCUEIL LES OLIVIERS",
+         "category_id" : "A10000003840",
+         "datetime" : "2020-12-15 00:00",
+         "id" : "2020-12-15 00:00-A10000003840-A10000003844",
+         "slot_id" : "A10000003844",
+         "text" : "MULTI ACCUEIL LES OLIVIERS - Réguliers",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "MULTI ACCUEIL LES OLIVIERS",
+         "category_id" : "A10000003840",
+         "datetime" : "2020-12-15 00:00",
+         "id" : "2020-12-15 00:00-A10000003840-A10000003845",
+         "slot_id" : "A10000003845",
+         "text" : "MULTI ACCUEIL LES OLIVIERS - Occasionnels",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "HALTE GARDERIE LES MAGNOLIAS",
+         "category_id" : "A10000006100",
+         "datetime" : "2020-12-15 00:00",
+         "id" : "2020-12-15 00:00-A10000006100-A10000006104",
+         "slot_id" : "A10000006104",
+         "text" : "HALTE GARDERIE LES MAGNOLIAS - Réguliers",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "HALTE GARDERIE LES MAGNOLIAS",
+         "category_id" : "A10000006100",
+         "datetime" : "2020-12-15 00:00",
+         "id" : "2020-12-15 00:00-A10000006100-A10000006105",
+         "slot_id" : "A10000006105",
+         "text" : "HALTE GARDERIE LES MAGNOLIAS - Occasionnels",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "1 2020-2021 GARDERIE MATIN",
+         "category_id" : "A10003121692",
+         "datetime" : "2020-12-15 00:00",
+         "id" : "2020-12-15 00:00-A10003121692-A10003121694",
+         "slot_id" : "A10003121694",
+         "text" : "1 2020-2021 GARDERIE MATIN",
+         "user_booking_status" : "booked"
+      },
+      {
+         "category" : "2 2020-2021  RESTAURATION SCOLAIRE",
+         "category_id" : "A10003123490",
+         "datetime" : "2020-12-15 00:00",
+         "id" : "2020-12-15 00:00-A10003123490-A10003123492",
+         "slot_id" : "A10003123492",
+         "text" : "2 2020-2021  RESTAURATION SCOLAIRE",
+         "user_booking_status" : "booked"
+      },
+      {
+         "category" : "3 2020-2021 GARDERIE SOIR",
+         "category_id" : "A10003123507",
+         "datetime" : "2020-12-15 00:00",
+         "id" : "2020-12-15 00:00-A10003123507-A10003123509",
+         "slot_id" : "A10003123509",
+         "text" : "3 2020-2021 GARDERIE SOIR",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "COURS DE DANSE",
+         "category_id" : "A10003132090",
+         "datetime" : "2020-12-15 00:00",
+         "id" : "2020-12-15 00:00-A10003132090-A10003132091",
+         "slot_id" : "A10003132091",
+         "text" : "COURS DE DANSE",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "MULTI ACCUEIL LES OLIVIERS",
+         "category_id" : "A10000003840",
+         "datetime" : "2020-12-16 00:00",
+         "id" : "2020-12-16 00:00-A10000003840-A10000003844",
+         "slot_id" : "A10000003844",
+         "text" : "MULTI ACCUEIL LES OLIVIERS - Réguliers",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "MULTI ACCUEIL LES OLIVIERS",
+         "category_id" : "A10000003840",
+         "datetime" : "2020-12-16 00:00",
+         "id" : "2020-12-16 00:00-A10000003840-A10000003845",
+         "slot_id" : "A10000003845",
+         "text" : "MULTI ACCUEIL LES OLIVIERS - Occasionnels",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "HALTE GARDERIE LES MAGNOLIAS",
+         "category_id" : "A10000006100",
+         "datetime" : "2020-12-16 00:00",
+         "id" : "2020-12-16 00:00-A10000006100-A10000006104",
+         "slot_id" : "A10000006104",
+         "text" : "HALTE GARDERIE LES MAGNOLIAS - Réguliers",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "HALTE GARDERIE LES MAGNOLIAS",
+         "category_id" : "A10000006100",
+         "datetime" : "2020-12-16 00:00",
+         "id" : "2020-12-16 00:00-A10000006100-A10000006105",
+         "slot_id" : "A10000006105",
+         "text" : "HALTE GARDERIE LES MAGNOLIAS - Occasionnels",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "2020-2021 CENTRE DE LOISIRS MERCREDI",
+         "category_id" : "A10003132030",
+         "datetime" : "2020-12-16 00:00",
+         "id" : "2020-12-16 00:00-A10003132030-A10003132032",
+         "slot_id" : "A10003132032",
+         "text" : "2020-2021 CENTRE DE LOISIRS MERCREDI",
+         "user_booking_status" : "booked"
+      },
+      {
+         "category" : "COURS DE DANSE",
+         "category_id" : "A10003132090",
+         "datetime" : "2020-12-16 00:00",
+         "id" : "2020-12-16 00:00-A10003132090-A10003132091",
+         "slot_id" : "A10003132091",
+         "text" : "COURS DE DANSE",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "2020-2021 CENTRE DE LOISIRS MERCREDI",
+         "category_id" : "A10003132030",
+         "datetime" : "2020-12-16 08:00",
+         "id" : "2020-12-16 08:00-A10003132030-EO0001PART01",
+         "slot_id" : "EO0001PART01",
+         "text" : "Matinée",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "2020-2021 CENTRE DE LOISIRS MERCREDI",
+         "category_id" : "A10003132030",
+         "datetime" : "2020-12-16 12:00",
+         "id" : "2020-12-16 12:00-A10003132030-EO0001PART02",
+         "slot_id" : "EO0001PART02",
+         "text" : "Repas",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "2020-2021 CENTRE DE LOISIRS MERCREDI",
+         "category_id" : "A10003132030",
+         "datetime" : "2020-12-16 14:00",
+         "id" : "2020-12-16 14:00-A10003132030-EO0001PART03",
+         "slot_id" : "EO0001PART03",
+         "text" : "Après-midi",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "MULTI ACCUEIL LES OLIVIERS",
+         "category_id" : "A10000003840",
+         "datetime" : "2020-12-17 00:00",
+         "id" : "2020-12-17 00:00-A10000003840-A10000003844",
+         "slot_id" : "A10000003844",
+         "text" : "MULTI ACCUEIL LES OLIVIERS - Réguliers",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "MULTI ACCUEIL LES OLIVIERS",
+         "category_id" : "A10000003840",
+         "datetime" : "2020-12-17 00:00",
+         "id" : "2020-12-17 00:00-A10000003840-A10000003845",
+         "slot_id" : "A10000003845",
+         "text" : "MULTI ACCUEIL LES OLIVIERS - Occasionnels",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "HALTE GARDERIE LES MAGNOLIAS",
+         "category_id" : "A10000006100",
+         "datetime" : "2020-12-17 00:00",
+         "id" : "2020-12-17 00:00-A10000006100-A10000006104",
+         "slot_id" : "A10000006104",
+         "text" : "HALTE GARDERIE LES MAGNOLIAS - Réguliers",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "HALTE GARDERIE LES MAGNOLIAS",
+         "category_id" : "A10000006100",
+         "datetime" : "2020-12-17 00:00",
+         "id" : "2020-12-17 00:00-A10000006100-A10000006105",
+         "slot_id" : "A10000006105",
+         "text" : "HALTE GARDERIE LES MAGNOLIAS - Occasionnels",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "1 2020-2021 GARDERIE MATIN",
+         "category_id" : "A10003121692",
+         "datetime" : "2020-12-17 00:00",
+         "id" : "2020-12-17 00:00-A10003121692-A10003121694",
+         "slot_id" : "A10003121694",
+         "text" : "1 2020-2021 GARDERIE MATIN",
+         "user_booking_status" : "booked"
+      },
+      {
+         "category" : "2 2020-2021  RESTAURATION SCOLAIRE",
+         "category_id" : "A10003123490",
+         "datetime" : "2020-12-17 00:00",
+         "id" : "2020-12-17 00:00-A10003123490-A10003123492",
+         "slot_id" : "A10003123492",
+         "text" : "2 2020-2021  RESTAURATION SCOLAIRE",
+         "user_booking_status" : "booked"
+      },
+      {
+         "category" : "3 2020-2021 GARDERIE SOIR",
+         "category_id" : "A10003123507",
+         "datetime" : "2020-12-17 00:00",
+         "id" : "2020-12-17 00:00-A10003123507-A10003123509",
+         "slot_id" : "A10003123509",
+         "text" : "3 2020-2021 GARDERIE SOIR",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "COURS DE DANSE",
+         "category_id" : "A10003132090",
+         "datetime" : "2020-12-17 00:00",
+         "id" : "2020-12-17 00:00-A10003132090-A10003132091",
+         "slot_id" : "A10003132091",
+         "text" : "COURS DE DANSE",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "MULTI ACCUEIL LES OLIVIERS",
+         "category_id" : "A10000003840",
+         "datetime" : "2020-12-18 00:00",
+         "id" : "2020-12-18 00:00-A10000003840-A10000003844",
+         "slot_id" : "A10000003844",
+         "text" : "MULTI ACCUEIL LES OLIVIERS - Réguliers",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "MULTI ACCUEIL LES OLIVIERS",
+         "category_id" : "A10000003840",
+         "datetime" : "2020-12-18 00:00",
+         "id" : "2020-12-18 00:00-A10000003840-A10000003845",
+         "slot_id" : "A10000003845",
+         "text" : "MULTI ACCUEIL LES OLIVIERS - Occasionnels",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "HALTE GARDERIE LES MAGNOLIAS",
+         "category_id" : "A10000006100",
+         "datetime" : "2020-12-18 00:00",
+         "id" : "2020-12-18 00:00-A10000006100-A10000006104",
+         "slot_id" : "A10000006104",
+         "text" : "HALTE GARDERIE LES MAGNOLIAS - Réguliers",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "HALTE GARDERIE LES MAGNOLIAS",
+         "category_id" : "A10000006100",
+         "datetime" : "2020-12-18 00:00",
+         "id" : "2020-12-18 00:00-A10000006100-A10000006105",
+         "slot_id" : "A10000006105",
+         "text" : "HALTE GARDERIE LES MAGNOLIAS - Occasionnels",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "1 2020-2021 GARDERIE MATIN",
+         "category_id" : "A10003121692",
+         "datetime" : "2020-12-18 00:00",
+         "id" : "2020-12-18 00:00-A10003121692-A10003121694",
+         "slot_id" : "A10003121694",
+         "text" : "1 2020-2021 GARDERIE MATIN",
+         "user_booking_status" : "booked"
+      },
+      {
+         "category" : "2 2020-2021  RESTAURATION SCOLAIRE",
+         "category_id" : "A10003123490",
+         "datetime" : "2020-12-18 00:00",
+         "id" : "2020-12-18 00:00-A10003123490-A10003123492",
+         "slot_id" : "A10003123492",
+         "text" : "2 2020-2021  RESTAURATION SCOLAIRE",
+         "user_booking_status" : "booked"
+      },
+      {
+         "category" : "3 2020-2021 GARDERIE SOIR",
+         "category_id" : "A10003123507",
+         "datetime" : "2020-12-18 00:00",
+         "id" : "2020-12-18 00:00-A10003123507-A10003123509",
+         "slot_id" : "A10003123509",
+         "text" : "3 2020-2021 GARDERIE SOIR",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "COURS DE DANSE",
+         "category_id" : "A10003132090",
+         "datetime" : "2020-12-18 00:00",
+         "id" : "2020-12-18 00:00-A10003132090-A10003132091",
+         "slot_id" : "A10003132091",
+         "text" : "COURS DE DANSE",
+         "user_booking_status" : "not-booked"
+      }
+   ],
+   "err" : 0
+}
diff --git a/tests/data/maelis/child_planning_before_decomposition.json b/tests/data/maelis/child_planning_before_decomposition.json
new file mode 100644
index 00000000..f7eb8620
--- /dev/null
+++ b/tests/data/maelis/child_planning_before_decomposition.json
@@ -0,0 +1,392 @@
+{
+   "data" : [
+      {
+         "category" : "MULTI ACCUEIL LES OLIVIERS",
+         "category_id" : "A10000003840",
+         "datetime" : "2020-12-14 00:00",
+         "id" : "2020-12-14 00:00-A10000003840-A10000003844",
+         "slot_id" : "A10000003844",
+         "text" : "MULTI ACCUEIL LES OLIVIERS - Réguliers",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "MULTI ACCUEIL LES OLIVIERS",
+         "category_id" : "A10000003840",
+         "datetime" : "2020-12-14 00:00",
+         "id" : "2020-12-14 00:00-A10000003840-A10000003845",
+         "slot_id" : "A10000003845",
+         "text" : "MULTI ACCUEIL LES OLIVIERS - Occasionnels",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "HALTE GARDERIE LES MAGNOLIAS",
+         "category_id" : "A10000006100",
+         "datetime" : "2020-12-14 00:00",
+         "id" : "2020-12-14 00:00-A10000006100-A10000006104",
+         "slot_id" : "A10000006104",
+         "text" : "HALTE GARDERIE LES MAGNOLIAS - Réguliers",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "HALTE GARDERIE LES MAGNOLIAS",
+         "category_id" : "A10000006100",
+         "datetime" : "2020-12-14 00:00",
+         "id" : "2020-12-14 00:00-A10000006100-A10000006105",
+         "slot_id" : "A10000006105",
+         "text" : "HALTE GARDERIE LES MAGNOLIAS - Occasionnels",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "1 2020-2021 GARDERIE MATIN",
+         "category_id" : "A10003121692",
+         "datetime" : "2020-12-14 00:00",
+         "id" : "2020-12-14 00:00-A10003121692-A10003121694",
+         "slot_id" : "A10003121694",
+         "text" : "1 2020-2021 GARDERIE MATIN",
+         "user_booking_status" : "booked"
+      },
+      {
+         "category" : "2 2020-2021  RESTAURATION SCOLAIRE",
+         "category_id" : "A10003123490",
+         "datetime" : "2020-12-14 00:00",
+         "id" : "2020-12-14 00:00-A10003123490-A10003123492",
+         "slot_id" : "A10003123492",
+         "text" : "2 2020-2021  RESTAURATION SCOLAIRE",
+         "user_booking_status" : "booked"
+      },
+      {
+         "category" : "3 2020-2021 GARDERIE SOIR",
+         "category_id" : "A10003123507",
+         "datetime" : "2020-12-14 00:00",
+         "id" : "2020-12-14 00:00-A10003123507-A10003123509",
+         "slot_id" : "A10003123509",
+         "text" : "3 2020-2021 GARDERIE SOIR",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "COURS DE DANSE",
+         "category_id" : "A10003132090",
+         "datetime" : "2020-12-14 00:00",
+         "id" : "2020-12-14 00:00-A10003132090-A10003132091",
+         "slot_id" : "A10003132091",
+         "text" : "COURS DE DANSE",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "ATELIER D'EXPRESSION THEATRALE",
+         "category_id" : "A10003132293",
+         "datetime" : "2020-12-14 00:00",
+         "id" : "2020-12-14 00:00-A10003132293-A10003132295",
+         "slot_id" : "A10003132295",
+         "text" : "ATELIER D'EXPRESSION THEATRALE",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "MULTI ACCUEIL LES OLIVIERS",
+         "category_id" : "A10000003840",
+         "datetime" : "2020-12-15 00:00",
+         "id" : "2020-12-15 00:00-A10000003840-A10000003844",
+         "slot_id" : "A10000003844",
+         "text" : "MULTI ACCUEIL LES OLIVIERS - Réguliers",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "MULTI ACCUEIL LES OLIVIERS",
+         "category_id" : "A10000003840",
+         "datetime" : "2020-12-15 00:00",
+         "id" : "2020-12-15 00:00-A10000003840-A10000003845",
+         "slot_id" : "A10000003845",
+         "text" : "MULTI ACCUEIL LES OLIVIERS - Occasionnels",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "HALTE GARDERIE LES MAGNOLIAS",
+         "category_id" : "A10000006100",
+         "datetime" : "2020-12-15 00:00",
+         "id" : "2020-12-15 00:00-A10000006100-A10000006104",
+         "slot_id" : "A10000006104",
+         "text" : "HALTE GARDERIE LES MAGNOLIAS - Réguliers",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "HALTE GARDERIE LES MAGNOLIAS",
+         "category_id" : "A10000006100",
+         "datetime" : "2020-12-15 00:00",
+         "id" : "2020-12-15 00:00-A10000006100-A10000006105",
+         "slot_id" : "A10000006105",
+         "text" : "HALTE GARDERIE LES MAGNOLIAS - Occasionnels",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "1 2020-2021 GARDERIE MATIN",
+         "category_id" : "A10003121692",
+         "datetime" : "2020-12-15 00:00",
+         "id" : "2020-12-15 00:00-A10003121692-A10003121694",
+         "slot_id" : "A10003121694",
+         "text" : "1 2020-2021 GARDERIE MATIN",
+         "user_booking_status" : "booked"
+      },
+      {
+         "category" : "2 2020-2021  RESTAURATION SCOLAIRE",
+         "category_id" : "A10003123490",
+         "datetime" : "2020-12-15 00:00",
+         "id" : "2020-12-15 00:00-A10003123490-A10003123492",
+         "slot_id" : "A10003123492",
+         "text" : "2 2020-2021  RESTAURATION SCOLAIRE",
+         "user_booking_status" : "booked"
+      },
+      {
+         "category" : "3 2020-2021 GARDERIE SOIR",
+         "category_id" : "A10003123507",
+         "datetime" : "2020-12-15 00:00",
+         "id" : "2020-12-15 00:00-A10003123507-A10003123509",
+         "slot_id" : "A10003123509",
+         "text" : "3 2020-2021 GARDERIE SOIR",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "COURS DE DANSE",
+         "category_id" : "A10003132090",
+         "datetime" : "2020-12-15 00:00",
+         "id" : "2020-12-15 00:00-A10003132090-A10003132091",
+         "slot_id" : "A10003132091",
+         "text" : "COURS DE DANSE",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "MULTI ACCUEIL LES OLIVIERS",
+         "category_id" : "A10000003840",
+         "datetime" : "2020-12-16 00:00",
+         "id" : "2020-12-16 00:00-A10000003840-A10000003844",
+         "slot_id" : "A10000003844",
+         "text" : "MULTI ACCUEIL LES OLIVIERS - Réguliers",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "MULTI ACCUEIL LES OLIVIERS",
+         "category_id" : "A10000003840",
+         "datetime" : "2020-12-16 00:00",
+         "id" : "2020-12-16 00:00-A10000003840-A10000003845",
+         "slot_id" : "A10000003845",
+         "text" : "MULTI ACCUEIL LES OLIVIERS - Occasionnels",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "HALTE GARDERIE LES MAGNOLIAS",
+         "category_id" : "A10000006100",
+         "datetime" : "2020-12-16 00:00",
+         "id" : "2020-12-16 00:00-A10000006100-A10000006104",
+         "slot_id" : "A10000006104",
+         "text" : "HALTE GARDERIE LES MAGNOLIAS - Réguliers",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "HALTE GARDERIE LES MAGNOLIAS",
+         "category_id" : "A10000006100",
+         "datetime" : "2020-12-16 00:00",
+         "id" : "2020-12-16 00:00-A10000006100-A10000006105",
+         "slot_id" : "A10000006105",
+         "text" : "HALTE GARDERIE LES MAGNOLIAS - Occasionnels",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "2020-2021 CENTRE DE LOISIRS MERCREDI",
+         "category_id" : "A10003132030",
+         "datetime" : "2020-12-16 00:00",
+         "id" : "2020-12-16 00:00-A10003132030-A10003132032",
+         "slot_id" : "A10003132032",
+         "text" : "2020-2021 CENTRE DE LOISIRS MERCREDI",
+         "user_booking_status" : "booked"
+      },
+      {
+         "category" : "2020-2021 CENTRE DE LOISIRS MERCREDI",
+         "category_id" : "A10003132030",
+         "datetime" : "2020-12-16 00:00",
+         "id" : "2020-12-16 00:00-A10003132030-A10003132034",
+         "slot_id" : "A10003132034",
+         "text" : "JOURNEE",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "2020-2021 CENTRE DE LOISIRS MERCREDI",
+         "category_id" : "A10003132030",
+         "datetime" : "2020-12-16 00:00",
+         "id" : "2020-12-16 00:00-A10003132030-A10003132036",
+         "slot_id" : "A10003132036",
+         "text" : "MATIN",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "2020-2021 CENTRE DE LOISIRS MERCREDI",
+         "category_id" : "A10003132030",
+         "datetime" : "2020-12-16 00:00",
+         "id" : "2020-12-16 00:00-A10003132030-A10003132038",
+         "slot_id" : "A10003132038",
+         "text" : "MATIN ET REPAS",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "2020-2021 CENTRE DE LOISIRS MERCREDI",
+         "category_id" : "A10003132030",
+         "datetime" : "2020-12-16 00:00",
+         "id" : "2020-12-16 00:00-A10003132030-A10003132040",
+         "slot_id" : "A10003132040",
+         "text" : "APRES MIDI",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "COURS DE DANSE",
+         "category_id" : "A10003132090",
+         "datetime" : "2020-12-16 00:00",
+         "id" : "2020-12-16 00:00-A10003132090-A10003132091",
+         "slot_id" : "A10003132091",
+         "text" : "COURS DE DANSE",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "MULTI ACCUEIL LES OLIVIERS",
+         "category_id" : "A10000003840",
+         "datetime" : "2020-12-17 00:00",
+         "id" : "2020-12-17 00:00-A10000003840-A10000003844",
+         "slot_id" : "A10000003844",
+         "text" : "MULTI ACCUEIL LES OLIVIERS - Réguliers",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "MULTI ACCUEIL LES OLIVIERS",
+         "category_id" : "A10000003840",
+         "datetime" : "2020-12-17 00:00",
+         "id" : "2020-12-17 00:00-A10000003840-A10000003845",
+         "slot_id" : "A10000003845",
+         "text" : "MULTI ACCUEIL LES OLIVIERS - Occasionnels",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "HALTE GARDERIE LES MAGNOLIAS",
+         "category_id" : "A10000006100",
+         "datetime" : "2020-12-17 00:00",
+         "id" : "2020-12-17 00:00-A10000006100-A10000006104",
+         "slot_id" : "A10000006104",
+         "text" : "HALTE GARDERIE LES MAGNOLIAS - Réguliers",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "HALTE GARDERIE LES MAGNOLIAS",
+         "category_id" : "A10000006100",
+         "datetime" : "2020-12-17 00:00",
+         "id" : "2020-12-17 00:00-A10000006100-A10000006105",
+         "slot_id" : "A10000006105",
+         "text" : "HALTE GARDERIE LES MAGNOLIAS - Occasionnels",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "1 2020-2021 GARDERIE MATIN",
+         "category_id" : "A10003121692",
+         "datetime" : "2020-12-17 00:00",
+         "id" : "2020-12-17 00:00-A10003121692-A10003121694",
+         "slot_id" : "A10003121694",
+         "text" : "1 2020-2021 GARDERIE MATIN",
+         "user_booking_status" : "booked"
+      },
+      {
+         "category" : "2 2020-2021  RESTAURATION SCOLAIRE",
+         "category_id" : "A10003123490",
+         "datetime" : "2020-12-17 00:00",
+         "id" : "2020-12-17 00:00-A10003123490-A10003123492",
+         "slot_id" : "A10003123492",
+         "text" : "2 2020-2021  RESTAURATION SCOLAIRE",
+         "user_booking_status" : "booked"
+      },
+      {
+         "category" : "3 2020-2021 GARDERIE SOIR",
+         "category_id" : "A10003123507",
+         "datetime" : "2020-12-17 00:00",
+         "id" : "2020-12-17 00:00-A10003123507-A10003123509",
+         "slot_id" : "A10003123509",
+         "text" : "3 2020-2021 GARDERIE SOIR",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "COURS DE DANSE",
+         "category_id" : "A10003132090",
+         "datetime" : "2020-12-17 00:00",
+         "id" : "2020-12-17 00:00-A10003132090-A10003132091",
+         "slot_id" : "A10003132091",
+         "text" : "COURS DE DANSE",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "MULTI ACCUEIL LES OLIVIERS",
+         "category_id" : "A10000003840",
+         "datetime" : "2020-12-18 00:00",
+         "id" : "2020-12-18 00:00-A10000003840-A10000003844",
+         "slot_id" : "A10000003844",
+         "text" : "MULTI ACCUEIL LES OLIVIERS - Réguliers",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "MULTI ACCUEIL LES OLIVIERS",
+         "category_id" : "A10000003840",
+         "datetime" : "2020-12-18 00:00",
+         "id" : "2020-12-18 00:00-A10000003840-A10000003845",
+         "slot_id" : "A10000003845",
+         "text" : "MULTI ACCUEIL LES OLIVIERS - Occasionnels",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "HALTE GARDERIE LES MAGNOLIAS",
+         "category_id" : "A10000006100",
+         "datetime" : "2020-12-18 00:00",
+         "id" : "2020-12-18 00:00-A10000006100-A10000006104",
+         "slot_id" : "A10000006104",
+         "text" : "HALTE GARDERIE LES MAGNOLIAS - Réguliers",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "HALTE GARDERIE LES MAGNOLIAS",
+         "category_id" : "A10000006100",
+         "datetime" : "2020-12-18 00:00",
+         "id" : "2020-12-18 00:00-A10000006100-A10000006105",
+         "slot_id" : "A10000006105",
+         "text" : "HALTE GARDERIE LES MAGNOLIAS - Occasionnels",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "1 2020-2021 GARDERIE MATIN",
+         "category_id" : "A10003121692",
+         "datetime" : "2020-12-18 00:00",
+         "id" : "2020-12-18 00:00-A10003121692-A10003121694",
+         "slot_id" : "A10003121694",
+         "text" : "1 2020-2021 GARDERIE MATIN",
+         "user_booking_status" : "booked"
+      },
+      {
+         "category" : "2 2020-2021  RESTAURATION SCOLAIRE",
+         "category_id" : "A10003123490",
+         "datetime" : "2020-12-18 00:00",
+         "id" : "2020-12-18 00:00-A10003123490-A10003123492",
+         "slot_id" : "A10003123492",
+         "text" : "2 2020-2021  RESTAURATION SCOLAIRE",
+         "user_booking_status" : "booked"
+      },
+      {
+         "category" : "3 2020-2021 GARDERIE SOIR",
+         "category_id" : "A10003123507",
+         "datetime" : "2020-12-18 00:00",
+         "id" : "2020-12-18 00:00-A10003123507-A10003123509",
+         "slot_id" : "A10003123509",
+         "text" : "3 2020-2021 GARDERIE SOIR",
+         "user_booking_status" : "not-booked"
+      },
+      {
+         "category" : "COURS DE DANSE",
+         "category_id" : "A10003132090",
+         "datetime" : "2020-12-18 00:00",
+         "id" : "2020-12-18 00:00-A10003132090-A10003132091",
+         "slot_id" : "A10003132091",
+         "text" : "COURS DE DANSE",
+         "user_booking_status" : "not-booked"
+      }
+   ],
+   "err" : 0
+}
diff --git a/tests/data/maelis/child_planning_readActivityListResponse.xml b/tests/data/maelis/child_planning_readActivityListResponse.xml
new file mode 100644
index 00000000..61bc809c
--- /dev/null
+++ b/tests/data/maelis/child_planning_readActivityListResponse.xml
@@ -0,0 +1,1355 @@
+<?xml version="1.0"?>
+<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
+  <soap:Body>
+    <ns1:readActivityListResponse xmlns:ns1="activity.ws.maelis.sigec.com">
+      <ReadActivityPortailListResultBean>
+        <activityUnitPlacePortailList>
+          <activityPortail>
+            <idAct>A10000003840</idAct>
+            <label>MULTI ACCUEIL LES OLIVIERS</label>
+            <dateStart>2011-01-01T00:00:00+01:00</dateStart>
+            <codeConso>ENF</codeConso>
+            <schoolYear>2020</schoolYear>
+            <calendarGeneration>
+              <code>FORBIDDEN</code>
+              <value>I</value>
+            </calendarGeneration>
+            <dateStartPubli>2017-11-01T16:54:01+01:00</dateStartPubli>
+            <calendarMode>N</calendarMode>
+            <activityType>
+              <code>PE</code>
+              <libelle>Petite Enfance</libelle>
+              <natureSpec>
+                <code>E</code>
+                <libelle>Petite Enfance</libelle>
+              </natureSpec>
+            </activityType>
+            <weeklyCalendarActivityList>
+              <yearCalendar>2020</yearCalendar>
+              <weeklyCalendarStr>0000011</weeklyCalendarStr>
+            </weeklyCalendarActivityList>
+            <birthControl>N</birthControl>
+            <waitIfComplete>N</waitIfComplete>
+          </activityPortail>
+          <openDayList>2020-12-14T00:00:00+01:00</openDayList>
+          <openDayList>2020-12-15T00:00:00+01:00</openDayList>
+          <openDayList>2020-12-16T00:00:00+01:00</openDayList>
+          <openDayList>2020-12-17T00:00:00+01:00</openDayList>
+          <openDayList>2020-12-18T00:00:00+01:00</openDayList>
+          <unitPortailList>
+            <idUnit>A10000003844</idUnit>
+            <label>MULTI ACCUEIL LES OLIVIERS - R&#xE9;guliers</label>
+            <dateStart>2011-01-01T00:00:00+01:00</dateStart>
+            <consoTarifList>
+              <commune>X</commune>
+              <tarif>
+                <code>PE</code>
+                <label>PETITE ENFANCE</label>
+              </tarif>
+              <conso>
+                <code>ENF</code>
+                <label>ENFANT</label>
+              </conso>
+            </consoTarifList>
+            <calendarLetter>A</calendarLetter>
+            <subscribePublication>N</subscribePublication>
+            <numOrder>0</numOrder>
+            <placeList>
+              <id>A10000003843</id>
+              <lib>MULTI ACCUEIL LES OLIVIERS</lib>
+              <adresse>
+                <num>0</num>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>80</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <typeCtrlPlace>N</typeCtrlPlace>
+            <nbPlace>0</nbPlace>
+            <nbPlaceBoy>0</nbPlaceBoy>
+            <nbPlaceGirl>0</nbPlaceGirl>
+            <idUnitEnemyList>A10002721671</idUnitEnemyList>
+            <topCESU>O</topCESU>
+          </unitPortailList>
+          <unitPortailList>
+            <idUnit>A10000003845</idUnit>
+            <label>MULTI ACCUEIL LES OLIVIERS - Occasionnels</label>
+            <dateStart>2011-01-01T00:00:00+01:00</dateStart>
+            <consoTarifList>
+              <commune>X</commune>
+              <tarif>
+                <code>PE</code>
+                <label>PETITE ENFANCE</label>
+              </tarif>
+              <conso>
+                <code>ENF</code>
+                <label>ENFANT</label>
+              </conso>
+            </consoTarifList>
+            <calendarLetter>B</calendarLetter>
+            <subscribePublication>N</subscribePublication>
+            <numOrder>0</numOrder>
+            <placeList>
+              <id>A10000003843</id>
+              <lib>MULTI ACCUEIL LES OLIVIERS</lib>
+              <adresse>
+                <num>0</num>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <typeCtrlPlace>N</typeCtrlPlace>
+            <nbPlace>0</nbPlace>
+            <nbPlaceBoy>0</nbPlaceBoy>
+            <nbPlaceGirl>0</nbPlaceGirl>
+            <topCESU>O</topCESU>
+          </unitPortailList>
+        </activityUnitPlacePortailList>
+        <activityUnitPlacePortailList>
+          <activityPortail>
+            <idAct>A10000006100</idAct>
+            <label>HALTE GARDERIE LES MAGNOLIAS</label>
+            <dateStart>2011-01-01T00:00:00+01:00</dateStart>
+            <codeConso>ENF</codeConso>
+            <schoolYear>2020</schoolYear>
+            <calendarGeneration>
+              <code>FORBIDDEN</code>
+              <value>I</value>
+            </calendarGeneration>
+            <dateStartPubli>2017-11-01T09:28:02+01:00</dateStartPubli>
+            <calendarMode>N</calendarMode>
+            <activityType>
+              <code>PE</code>
+              <libelle>Petite Enfance</libelle>
+              <natureSpec>
+                <code>E</code>
+                <libelle>Petite Enfance</libelle>
+              </natureSpec>
+            </activityType>
+            <weeklyCalendarActivityList>
+              <yearCalendar>2020</yearCalendar>
+              <weeklyCalendarStr>0000011</weeklyCalendarStr>
+            </weeklyCalendarActivityList>
+            <birthControl>N</birthControl>
+            <waitIfComplete>N</waitIfComplete>
+          </activityPortail>
+          <openDayList>2020-12-14T00:00:00+01:00</openDayList>
+          <openDayList>2020-12-15T00:00:00+01:00</openDayList>
+          <openDayList>2020-12-16T00:00:00+01:00</openDayList>
+          <openDayList>2020-12-17T00:00:00+01:00</openDayList>
+          <openDayList>2020-12-18T00:00:00+01:00</openDayList>
+          <unitPortailList>
+            <idUnit>A10000006104</idUnit>
+            <label>HALTE GARDERIE LES MAGNOLIAS - R&#xE9;guliers</label>
+            <dateStart>2011-01-01T00:00:00+01:00</dateStart>
+            <consoTarifList>
+              <commune>X</commune>
+              <tarif>
+                <code>PE</code>
+                <label>PETITE ENFANCE</label>
+              </tarif>
+              <conso>
+                <code>ENF</code>
+                <label>ENFANT</label>
+              </conso>
+            </consoTarifList>
+            <calendarLetter>B</calendarLetter>
+            <subscribePublication>N</subscribePublication>
+            <numOrder>0</numOrder>
+            <placeList>
+              <id>A10000006103</id>
+              <lib>HALTE GARDERIE LES MAGNOLIAS</lib>
+              <adresse>
+                <num>0</num>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>15</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <typeCtrlPlace>N</typeCtrlPlace>
+            <nbPlace>15</nbPlace>
+            <nbPlaceBoy>0</nbPlaceBoy>
+            <nbPlaceGirl>0</nbPlaceGirl>
+            <topCESU>O</topCESU>
+          </unitPortailList>
+          <unitPortailList>
+            <idUnit>A10000006105</idUnit>
+            <label>HALTE GARDERIE LES MAGNOLIAS - Occasionnels</label>
+            <dateStart>2011-01-01T00:00:00+01:00</dateStart>
+            <consoTarifList>
+              <commune>X</commune>
+              <tarif>
+                <code>PE</code>
+                <label>PETITE ENFANCE</label>
+              </tarif>
+              <conso>
+                <code>ENF</code>
+                <label>ENFANT</label>
+              </conso>
+            </consoTarifList>
+            <calendarLetter>A</calendarLetter>
+            <subscribePublication>N</subscribePublication>
+            <numOrder>0</numOrder>
+            <placeList>
+              <id>A10000006103</id>
+              <lib>HALTE GARDERIE LES MAGNOLIAS</lib>
+              <adresse>
+                <num>0</num>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <typeCtrlPlace>N</typeCtrlPlace>
+            <nbPlace>5</nbPlace>
+            <nbPlaceBoy>0</nbPlaceBoy>
+            <nbPlaceGirl>0</nbPlaceGirl>
+            <topCESU>O</topCESU>
+          </unitPortailList>
+        </activityUnitPlacePortailList>
+        <activityUnitPlacePortailList>
+          <activityPortail>
+            <idAct>A10003121692</idAct>
+            <label>1 2020-2021 GARDERIE MATIN</label>
+            <dateStart>2020-09-01T00:00:00+01:00</dateStart>
+            <dateEnd>2021-07-06T00:00:00+01:00</dateEnd>
+            <codeConso>ENF</codeConso>
+            <schoolYear>2020</schoolYear>
+            <calendarGeneration>
+              <code>NOT_REQUIRED</code>
+              <value>F</value>
+            </calendarGeneration>
+            <dateStartPubli>2018-07-01T15:12:18+01:00</dateStartPubli>
+            <calendarMode>C</calendarMode>
+            <activityType>
+              <code>ACCMAT</code>
+              <libelle>Accueil du matin</libelle>
+              <natureSpec>
+                <code>A</code>
+                <libelle>Accueil P&#xE9;riscolaire</libelle>
+              </natureSpec>
+            </activityType>
+            <weeklyCalendarActivityList>
+              <yearCalendar>2020</yearCalendar>
+              <weeklyCalendarStr>0010011</weeklyCalendarStr>
+            </weeklyCalendarActivityList>
+            <birthControl>N</birthControl>
+            <waitIfComplete>N</waitIfComplete>
+          </activityPortail>
+          <openDayList>2020-12-14T00:00:00+01:00</openDayList>
+          <openDayList>2020-12-15T00:00:00+01:00</openDayList>
+          <openDayList>2020-12-17T00:00:00+01:00</openDayList>
+          <openDayList>2020-12-18T00:00:00+01:00</openDayList>
+          <unitPortailList>
+            <idUnit>A10003121694</idUnit>
+            <label>1 2020-2021 GARDERIE MATIN</label>
+            <dateStart>2020-09-01T00:00:00+01:00</dateStart>
+            <dateEnd>2021-07-06T00:00:00+01:00</dateEnd>
+            <consoTarifList>
+              <commune>X</commune>
+              <tarif>
+                <code>GPSMAT</code>
+                <label>GPS MATIN</label>
+              </tarif>
+              <conso>
+                <code>ENF</code>
+                <label>ENFANT</label>
+              </conso>
+            </consoTarifList>
+            <calendarLetter>X</calendarLetter>
+            <subscribePublication>E</subscribePublication>
+            <dateStartSubscribe>2017-09-01T00:00:00+01:00</dateStartSubscribe>
+            <numOrder>1</numOrder>
+            <placeList>
+              <id>A10000000201</id>
+              <lib>3 JEAN GIONO</lib>
+              <adresse>
+                <num>0</num>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <placeList>
+              <id>A10000000211</id>
+              <lib>2 FRANCOIS FABIE</lib>
+              <adresse>
+                <num>0</num>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <typeCtrlPlace>N</typeCtrlPlace>
+            <nbPlace>0</nbPlace>
+            <nbPlaceBoy>0</nbPlaceBoy>
+            <nbPlaceGirl>0</nbPlaceGirl>
+            <topCESU>O</topCESU>
+          </unitPortailList>
+        </activityUnitPlacePortailList>
+        <activityUnitPlacePortailList>
+          <activityPortail>
+            <idAct>A10003123490</idAct>
+            <label>2 2020-2021  RESTAURATION SCOLAIRE</label>
+            <dateStart>2020-09-02T00:00:00+01:00</dateStart>
+            <dateEnd>2021-07-03T00:00:00+01:00</dateEnd>
+            <codeConso>ENF</codeConso>
+            <schoolYear>2020</schoolYear>
+            <calendarGeneration>
+              <code>FORBIDDEN</code>
+              <value>I</value>
+            </calendarGeneration>
+            <dateStartPubli>2017-07-01T15:23:09+01:00</dateStartPubli>
+            <calendarMode>C</calendarMode>
+            <activityType>
+              <code>RESTSCOL</code>
+              <libelle>Restauration scolaire</libelle>
+              <natureSpec>
+                <code>R</code>
+                <libelle>Restauration Scolaire</libelle>
+              </natureSpec>
+            </activityType>
+            <weeklyCalendarActivityList>
+              <yearCalendar>2020</yearCalendar>
+              <weeklyCalendarStr>0010011</weeklyCalendarStr>
+            </weeklyCalendarActivityList>
+            <birthControl>N</birthControl>
+            <waitIfComplete>N</waitIfComplete>
+          </activityPortail>
+          <openDayList>2020-12-14T00:00:00+01:00</openDayList>
+          <openDayList>2020-12-15T00:00:00+01:00</openDayList>
+          <openDayList>2020-12-17T00:00:00+01:00</openDayList>
+          <openDayList>2020-12-18T00:00:00+01:00</openDayList>
+          <unitPortailList>
+            <idUnit>A10003123492</idUnit>
+            <label>2 2020-2021  RESTAURATION SCOLAIRE</label>
+            <dateStart>2020-09-02T00:00:00+01:00</dateStart>
+            <dateEnd>2021-07-03T00:00:00+01:00</dateEnd>
+            <consoTarifList>
+              <commune>X</commune>
+              <tarif>
+                <code>FAMACC</code>
+                <label>FAMILLE D'ACCUEIL</label>
+              </tarif>
+              <conso>
+                <code>ACCUE</code>
+                <label>FAMILLE ACCUEIL</label>
+              </conso>
+            </consoTarifList>
+            <consoTarifList>
+              <commune>X</commune>
+              <tarif>
+                <code>PR</code>
+                <label>PANIER REPAS</label>
+              </tarif>
+              <conso>
+                <code>PR</code>
+                <label>PANIER REPAS</label>
+              </conso>
+            </consoTarifList>
+            <consoTarifList>
+              <commune>X</commune>
+              <tarif>
+                <code>REST</code>
+                <label>RESTAURATION SCOLAIRE</label>
+              </tarif>
+              <conso>
+                <code>ENF</code>
+                <label>ENFANT</label>
+              </conso>
+            </consoTarifList>
+            <calendarLetter>X</calendarLetter>
+            <subscribePublication>E</subscribePublication>
+            <dateStartSubscribe>2017-05-01T00:00:00+01:00</dateStartSubscribe>
+            <numOrder>2</numOrder>
+            <placeList>
+              <id>A10000000211</id>
+              <lib>2 FRANCOIS FABIE</lib>
+              <adresse>
+                <num>0</num>
+              </adresse>
+              <schoolInfoList>
+                <idSchool>A10000003597</idSchool>
+                <schoolName>2  FRANCOIS FABIE</schoolName>
+                <adress>
+                  <street1>AVENUE ARISTIDE BRIAND</street1>
+                  <idStreet>8301440048</idStreet>
+                  <zipcode>83160</zipcode>
+                  <town>LA VALETTE-DU-VAR</town>
+                </adress>
+                <headmaster> </headmaster>
+              </schoolInfoList>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <typeCtrlPlace>N</typeCtrlPlace>
+            <nbPlace>0</nbPlace>
+            <nbPlaceBoy>0</nbPlaceBoy>
+            <nbPlaceGirl>0</nbPlaceGirl>
+            <topCESU>N</topCESU>
+          </unitPortailList>
+        </activityUnitPlacePortailList>
+        <activityUnitPlacePortailList>
+          <activityPortail>
+            <idAct>A10003123507</idAct>
+            <label>3 2020-2021 GARDERIE SOIR</label>
+            <dateStart>2020-09-02T00:00:00+01:00</dateStart>
+            <dateEnd>2021-07-03T00:00:00+01:00</dateEnd>
+            <codeConso>ENF</codeConso>
+            <schoolYear>2020</schoolYear>
+            <calendarGeneration>
+              <code>NOT_REQUIRED</code>
+              <value>F</value>
+            </calendarGeneration>
+            <dateStartPubli>2018-07-01T15:11:47+01:00</dateStartPubli>
+            <calendarMode>C</calendarMode>
+            <activityType>
+              <code>ACCSOIR</code>
+              <libelle>Accueil du soir</libelle>
+              <natureSpec>
+                <code>A</code>
+                <libelle>Accueil P&#xE9;riscolaire</libelle>
+              </natureSpec>
+            </activityType>
+            <weeklyCalendarActivityList>
+              <yearCalendar>2020</yearCalendar>
+              <weeklyCalendarStr>0010011</weeklyCalendarStr>
+            </weeklyCalendarActivityList>
+            <birthControl>N</birthControl>
+            <waitIfComplete>N</waitIfComplete>
+          </activityPortail>
+          <openDayList>2020-12-14T00:00:00+01:00</openDayList>
+          <openDayList>2020-12-15T00:00:00+01:00</openDayList>
+          <openDayList>2020-12-17T00:00:00+01:00</openDayList>
+          <openDayList>2020-12-18T00:00:00+01:00</openDayList>
+          <unitPortailList>
+            <idUnit>A10003123509</idUnit>
+            <label>3 2020-2021 GARDERIE SOIR</label>
+            <dateStart>2020-09-02T00:00:00+01:00</dateStart>
+            <dateEnd>2021-07-03T00:00:00+01:00</dateEnd>
+            <consoTarifList>
+              <commune>X</commune>
+              <tarif>
+                <code>GPSSOI</code>
+                <label>GPS SOIR</label>
+              </tarif>
+              <conso>
+                <code>ENF</code>
+                <label>ENFANT</label>
+              </conso>
+            </consoTarifList>
+            <calendarLetter>X</calendarLetter>
+            <subscribePublication>E</subscribePublication>
+            <dateStartSubscribe>2018-07-01T00:00:00+01:00</dateStartSubscribe>
+            <numOrder>3</numOrder>
+            <placeList>
+              <id>A10000000201</id>
+              <lib>3 JEAN GIONO</lib>
+              <adresse>
+                <num>0</num>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <placeList>
+              <id>A10000000211</id>
+              <lib>2 FRANCOIS FABIE</lib>
+              <adresse>
+                <num>0</num>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <typeCtrlPlace>N</typeCtrlPlace>
+            <nbPlace>0</nbPlace>
+            <nbPlaceBoy>0</nbPlaceBoy>
+            <nbPlaceGirl>0</nbPlaceGirl>
+            <topCESU>O</topCESU>
+          </unitPortailList>
+        </activityUnitPlacePortailList>
+        <activityUnitPlacePortailList>
+          <activityPortail>
+            <idAct>A10003131850</idAct>
+            <label>2020-2021 ALSH VACANCES PAGNOL (CAPA)</label>
+            <dateStart>2020-07-01T00:00:00+01:00</dateStart>
+            <dateEnd>2021-07-02T00:00:00+01:00</dateEnd>
+            <codeConso>ENF</codeConso>
+            <schoolYear>2020</schoolYear>
+            <calendarGeneration>
+              <code>NOT_REQUIRED</code>
+              <value>F</value>
+            </calendarGeneration>
+            <dateStartPubli>2020-07-01T11:16:21+01:00</dateStartPubli>
+            <dateEndPubli>2021-08-31T11:16:21+01:00</dateEndPubli>
+            <calendarMode>N</calendarMode>
+            <weeklyCalendarActivityList>
+              <yearCalendar>2020</yearCalendar>
+              <weeklyCalendarStr>0000011</weeklyCalendarStr>
+            </weeklyCalendarActivityList>
+            <birthControl>N</birthControl>
+            <waitIfComplete>O</waitIfComplete>
+          </activityPortail>
+          <unitPortailList>
+            <idUnit>A10003131861</idUnit>
+            <label>HIVER 2EME SEMAINE</label>
+            <dateStart>2021-02-28T00:00:00+01:00</dateStart>
+            <dateEnd>2021-03-05T00:00:00+01:00</dateEnd>
+            <consoTarifList>
+              <commune>H</commune>
+              <tarif>
+                <code>ACCLOI</code>
+                <label>ACCUEIL LOISIRS</label>
+              </tarif>
+              <conso>
+                <code>ENF</code>
+                <label>ENFANT</label>
+              </conso>
+            </consoTarifList>
+            <consoTarifList>
+              <commune>C</commune>
+              <tarif>
+                <code>ACCLOI</code>
+                <label>ACCUEIL LOISIRS</label>
+              </tarif>
+              <conso>
+                <code>ENF</code>
+                <label>ENFANT</label>
+              </conso>
+            </consoTarifList>
+            <calendarLetter>c</calendarLetter>
+            <subscribePublication>E</subscribePublication>
+            <dateStartSubscribe>2020-11-01T00:00:00+01:00</dateStartSubscribe>
+            <dateEndSubscribe>2020-12-31T00:00:00+01:00</dateEndSubscribe>
+            <numOrder>3</numOrder>
+            <placeList>
+              <id>A10000000212</id>
+              <lib>ALSH PAGNOL</lib>
+              <adresse>
+                <num>0</num>
+                <street1>PLACE MARCEL PAGNOL</street1>
+                <zipcode>83160</zipcode>
+                <town>LA VALETTE DU VAR</town>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <placeList>
+              <id>A10002132200</id>
+              <lib>ALSH MISTRAL</lib>
+              <adresse>
+                <num>0</num>
+                <zipcode>83160</zipcode>
+                <town>LA VALETTE-DU-VAR</town>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <typeCtrlPlace>N</typeCtrlPlace>
+            <nbPlace>0</nbPlace>
+            <nbPlaceBoy>0</nbPlaceBoy>
+            <nbPlaceGirl>0</nbPlaceGirl>
+            <topCESU>N</topCESU>
+          </unitPortailList>
+          <unitPortailList>
+            <idUnit>A10003131879</idUnit>
+            <label>TOUSSAINT 2EME SEMAINE</label>
+            <dateStart>2020-10-26T00:00:00+01:00</dateStart>
+            <dateEnd>2020-10-30T00:00:00+01:00</dateEnd>
+            <consoTarifList>
+              <commune>H</commune>
+              <tarif>
+                <code>ACCLOI</code>
+                <label>ACCUEIL LOISIRS</label>
+              </tarif>
+              <conso>
+                <code>ENF</code>
+                <label>ENFANT</label>
+              </conso>
+            </consoTarifList>
+            <consoTarifList>
+              <commune>C</commune>
+              <tarif>
+                <code>ACCLOI</code>
+                <label>ACCUEIL LOISIRS</label>
+              </tarif>
+              <conso>
+                <code>ENF</code>
+                <label>ENFANT</label>
+              </conso>
+            </consoTarifList>
+            <calendarLetter>D</calendarLetter>
+            <subscribePublication>E</subscribePublication>
+            <dateStartSubscribe>2020-07-01T00:00:00+01:00</dateStartSubscribe>
+            <dateEndSubscribe>2020-10-30T00:00:00+01:00</dateEndSubscribe>
+            <numOrder>2</numOrder>
+            <placeList>
+              <id>A10000000212</id>
+              <lib>ALSH PAGNOL</lib>
+              <adresse>
+                <num>0</num>
+                <street1>PLACE MARCEL PAGNOL</street1>
+                <zipcode>83160</zipcode>
+                <town>LA VALETTE DU VAR</town>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <placeList>
+              <id>A10002132200</id>
+              <lib>ALSH MISTRAL</lib>
+              <adresse>
+                <num>0</num>
+                <zipcode>83160</zipcode>
+                <town>LA VALETTE-DU-VAR</town>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <typeCtrlPlace>N</typeCtrlPlace>
+            <nbPlace>0</nbPlace>
+            <nbPlaceBoy>0</nbPlaceBoy>
+            <nbPlaceGirl>0</nbPlaceGirl>
+            <topCESU>N</topCESU>
+          </unitPortailList>
+          <unitPortailList>
+            <idUnit>A10003131882</idUnit>
+            <label>TOUSSAINT 1 ERE SEMAINE</label>
+            <dateStart>2020-10-19T00:00:00+01:00</dateStart>
+            <dateEnd>2020-10-23T00:00:00+01:00</dateEnd>
+            <consoTarifList>
+              <commune>H</commune>
+              <tarif>
+                <code>ACCLOI</code>
+                <label>ACCUEIL LOISIRS</label>
+              </tarif>
+              <conso>
+                <code>ENF</code>
+                <label>ENFANT</label>
+              </conso>
+            </consoTarifList>
+            <consoTarifList>
+              <commune>C</commune>
+              <tarif>
+                <code>ACCLOI</code>
+                <label>ACCUEIL LOISIRS</label>
+              </tarif>
+              <conso>
+                <code>ENF</code>
+                <label>ENFANT</label>
+              </conso>
+            </consoTarifList>
+            <calendarLetter>C</calendarLetter>
+            <subscribePublication>E</subscribePublication>
+            <dateStartSubscribe>2020-07-01T07:20:00+01:00</dateStartSubscribe>
+            <dateEndSubscribe>2020-10-30T00:00:00+01:00</dateEndSubscribe>
+            <numOrder>1</numOrder>
+            <placeList>
+              <id>A10000000212</id>
+              <lib>ALSH PAGNOL</lib>
+              <adresse>
+                <num>0</num>
+                <street1>PLACE MARCEL PAGNOL</street1>
+                <zipcode>83160</zipcode>
+                <town>LA VALETTE DU VAR</town>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <placeList>
+              <id>A10002132200</id>
+              <lib>ALSH MISTRAL</lib>
+              <adresse>
+                <num>0</num>
+                <zipcode>83160</zipcode>
+                <town>LA VALETTE-DU-VAR</town>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <typeCtrlPlace>N</typeCtrlPlace>
+            <nbPlace>0</nbPlace>
+            <nbPlaceBoy>0</nbPlaceBoy>
+            <nbPlaceGirl>0</nbPlaceGirl>
+            <topCESU>N</topCESU>
+          </unitPortailList>
+          <unitPortailList>
+            <idUnit>A10003131897</idUnit>
+            <label>2020-2021 ALSH VACANCES PAGNOL (CAPA)</label>
+            <dateStart>2020-07-01T00:00:00+01:00</dateStart>
+            <dateEnd>2021-07-02T00:00:00+01:00</dateEnd>
+            <consoTarifList>
+              <commune>H</commune>
+              <tarif>
+                <code>ACCLOI</code>
+                <label>ACCUEIL LOISIRS</label>
+              </tarif>
+              <conso>
+                <code>ENF</code>
+                <label>ENFANT</label>
+              </conso>
+            </consoTarifList>
+            <consoTarifList>
+              <commune>C</commune>
+              <tarif>
+                <code>ACCLOI</code>
+                <label>ACCUEIL LOISIRS</label>
+              </tarif>
+              <conso>
+                <code>ENF</code>
+                <label>ENFANT</label>
+              </conso>
+            </consoTarifList>
+            <calendarLetter>X</calendarLetter>
+            <subscribePublication>L</subscribePublication>
+            <dateStartSubscribe>2020-06-01T00:00:00+01:00</dateStartSubscribe>
+            <dateEndSubscribe>2020-08-31T00:00:00+01:00</dateEndSubscribe>
+            <numOrder>0</numOrder>
+            <placeList>
+              <id>A10000000212</id>
+              <lib>ALSH PAGNOL</lib>
+              <adresse>
+                <num>0</num>
+                <street1>PLACE MARCEL PAGNOL</street1>
+                <zipcode>83160</zipcode>
+                <town>LA VALETTE DU VAR</town>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <typeCtrlPlace>N</typeCtrlPlace>
+            <nbPlace>0</nbPlace>
+            <nbPlaceBoy>0</nbPlaceBoy>
+            <nbPlaceGirl>0</nbPlaceGirl>
+            <topCESU>O</topCESU>
+          </unitPortailList>
+          <unitPortailList>
+            <idUnit>A10003131903</idUnit>
+            <label>NOEL 2EME SEMAINE</label>
+            <dateStart>2020-12-28T00:00:00+01:00</dateStart>
+            <dateEnd>2020-12-31T00:00:00+01:00</dateEnd>
+            <consoTarifList>
+              <commune>H</commune>
+              <tarif>
+                <code>ACCLOI</code>
+                <label>ACCUEIL LOISIRS</label>
+              </tarif>
+              <conso>
+                <code>ENF</code>
+                <label>ENFANT</label>
+              </conso>
+            </consoTarifList>
+            <consoTarifList>
+              <commune>C</commune>
+              <tarif>
+                <code>ACCLOI</code>
+                <label>ACCUEIL LOISIRS</label>
+              </tarif>
+              <conso>
+                <code>ENF</code>
+                <label>ENFANT</label>
+              </conso>
+            </consoTarifList>
+            <calendarLetter>B</calendarLetter>
+            <subscribePublication>E</subscribePublication>
+            <dateStartSubscribe>2020-11-01T00:00:00+01:00</dateStartSubscribe>
+            <dateEndSubscribe>2020-12-31T00:00:00+01:00</dateEndSubscribe>
+            <numOrder>4</numOrder>
+            <placeList>
+              <id>A10000000212</id>
+              <lib>ALSH PAGNOL</lib>
+              <adresse>
+                <num>0</num>
+                <street1>PLACE MARCEL PAGNOL</street1>
+                <zipcode>83160</zipcode>
+                <town>LA VALETTE DU VAR</town>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <placeList>
+              <id>A10002132200</id>
+              <lib>ALSH MISTRAL</lib>
+              <adresse>
+                <num>0</num>
+                <zipcode>83160</zipcode>
+                <town>LA VALETTE-DU-VAR</town>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <typeCtrlPlace>N</typeCtrlPlace>
+            <nbPlace>0</nbPlace>
+            <nbPlaceBoy>0</nbPlaceBoy>
+            <nbPlaceGirl>0</nbPlaceGirl>
+            <topCESU>O</topCESU>
+          </unitPortailList>
+          <unitPortailList>
+            <idUnit>A10003131909</idUnit>
+            <label>NOEL 1ERE SEMAINE</label>
+            <dateStart>2020-12-21T00:00:00+01:00</dateStart>
+            <dateEnd>2020-12-24T00:00:00+01:00</dateEnd>
+            <consoTarifList>
+              <commune>H</commune>
+              <tarif>
+                <code>ACCLOI</code>
+                <label>ACCUEIL LOISIRS</label>
+              </tarif>
+              <conso>
+                <code>ENF</code>
+                <label>ENFANT</label>
+              </conso>
+            </consoTarifList>
+            <consoTarifList>
+              <commune>C</commune>
+              <tarif>
+                <code>ACCLOI</code>
+                <label>ACCUEIL LOISIRS</label>
+              </tarif>
+              <conso>
+                <code>ENF</code>
+                <label>ENFANT</label>
+              </conso>
+            </consoTarifList>
+            <calendarLetter>J</calendarLetter>
+            <subscribePublication>E</subscribePublication>
+            <dateStartSubscribe>2020-11-01T00:00:00+01:00</dateStartSubscribe>
+            <dateEndSubscribe>2020-12-31T00:00:00+01:00</dateEndSubscribe>
+            <numOrder>3</numOrder>
+            <placeList>
+              <id>A10000000212</id>
+              <lib>ALSH PAGNOL</lib>
+              <adresse>
+                <num>0</num>
+                <street1>PLACE MARCEL PAGNOL</street1>
+                <zipcode>83160</zipcode>
+                <town>LA VALETTE DU VAR</town>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <placeList>
+              <id>A10002132200</id>
+              <lib>ALSH MISTRAL</lib>
+              <adresse>
+                <num>0</num>
+                <zipcode>83160</zipcode>
+                <town>LA VALETTE-DU-VAR</town>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <typeCtrlPlace>N</typeCtrlPlace>
+            <nbPlace>0</nbPlace>
+            <nbPlaceBoy>0</nbPlaceBoy>
+            <nbPlaceGirl>0</nbPlaceGirl>
+            <topCESU>N</topCESU>
+          </unitPortailList>
+        </activityUnitPlacePortailList>
+        <activityUnitPlacePortailList>
+          <activityPortail>
+            <idAct>A10003132030</idAct>
+            <label>2020-2021 CENTRE DE LOISIRS MERCREDI</label>
+            <dateStart>2020-09-02T00:00:00+01:00</dateStart>
+            <dateEnd>2021-07-03T00:00:00+01:00</dateEnd>
+            <codeConso>ENF</codeConso>
+            <schoolYear>2020</schoolYear>
+            <calendarGeneration>
+              <code>NOT_REQUIRED</code>
+              <value>F</value>
+            </calendarGeneration>
+            <dateStartPubli>2020-07-01T10:51:07+01:00</dateStartPubli>
+            <calendarMode>C</calendarMode>
+            <activityType>
+              <code>LOIVAC</code>
+              <libelle>(Loisirs Vacances)</libelle>
+              <natureSpec>
+                <code>L</code>
+                <libelle>Loisirs/Vacances</libelle>
+              </natureSpec>
+            </activityType>
+            <weeklyCalendarActivityList>
+              <yearCalendar>2020</yearCalendar>
+              <weeklyCalendarStr>1101111</weeklyCalendarStr>
+            </weeklyCalendarActivityList>
+            <birthControl>N</birthControl>
+            <waitIfComplete>N</waitIfComplete>
+          </activityPortail>
+          <openDayList>2020-12-16T00:00:00+01:00</openDayList>
+          <unitPortailList>
+            <idUnit>A10003132032</idUnit>
+            <label>2020-2021 CENTRE DE LOISIRS MERCREDI</label>
+            <dateStart>2020-09-02T00:00:00+01:00</dateStart>
+            <dateEnd>2021-07-03T00:00:00+01:00</dateEnd>
+            <consoTarifList>
+              <commune>X</commune>
+              <tarif>
+                <code>ACCLOI</code>
+                <label>ACCUEIL LOISIRS</label>
+              </tarif>
+              <conso>
+                <code>ENF</code>
+                <label>ENFANT</label>
+              </conso>
+            </consoTarifList>
+            <calendarLetter>X</calendarLetter>
+            <subscribePublication>N</subscribePublication>
+            <dateStartSubscribe>2019-05-01T00:00:00+01:00</dateStartSubscribe>
+            <numOrder>0</numOrder>
+            <placeList>
+              <id>A10000000212</id>
+              <lib>ALSH PAGNOL</lib>
+              <adresse>
+                <num>0</num>
+                <street1>PLACE MARCEL PAGNOL</street1>
+                <zipcode>83160</zipcode>
+                <town>LA VALETTE DU VAR</town>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <typeCtrlPlace>N</typeCtrlPlace>
+            <nbPlace>0</nbPlace>
+            <nbPlaceBoy>0</nbPlaceBoy>
+            <nbPlaceGirl>0</nbPlaceGirl>
+            <topCESU>O</topCESU>
+          </unitPortailList>
+          <unitPortailList>
+            <idUnit>A10003132034</idUnit>
+            <label>JOURNEE</label>
+            <dateStart>2020-09-02T00:00:00+01:00</dateStart>
+            <dateEnd>2021-07-03T00:00:00+01:00</dateEnd>
+            <consoTarifList>
+              <commune>X</commune>
+              <tarif>
+                <code>ACCLOI</code>
+                <label>ACCUEIL LOISIRS</label>
+              </tarif>
+              <conso>
+                <code>ENF</code>
+                <label>ENFANT</label>
+              </conso>
+            </consoTarifList>
+            <calendarLetter>A</calendarLetter>
+            <subscribePublication>E</subscribePublication>
+            <dateStartSubscribe>2020-07-01T00:00:00+01:00</dateStartSubscribe>
+            <numOrder>4</numOrder>
+            <placeList>
+              <id>A10000000212</id>
+              <lib>ALSH PAGNOL</lib>
+              <adresse>
+                <num>0</num>
+                <street1>PLACE MARCEL PAGNOL</street1>
+                <zipcode>83160</zipcode>
+                <town>LA VALETTE DU VAR</town>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <typeCtrlPlace>C</typeCtrlPlace>
+            <nbPlace>0</nbPlace>
+            <nbPlaceBoy>0</nbPlaceBoy>
+            <nbPlaceGirl>0</nbPlaceGirl>
+            <topCESU>N</topCESU>
+          </unitPortailList>
+          <unitPortailList>
+            <idUnit>A10003132036</idUnit>
+            <label>MATIN</label>
+            <dateStart>2020-09-02T00:00:00+01:00</dateStart>
+            <dateEnd>2021-07-03T00:00:00+01:00</dateEnd>
+            <consoTarifList>
+              <commune>X</commune>
+              <tarif>
+                <code>ACCLOI</code>
+                <label>ACCUEIL LOISIRS</label>
+              </tarif>
+              <conso>
+                <code>ENF</code>
+                <label>ENFANT</label>
+              </conso>
+            </consoTarifList>
+            <calendarLetter>B</calendarLetter>
+            <subscribePublication>E</subscribePublication>
+            <dateStartSubscribe>2020-07-01T00:00:00+01:00</dateStartSubscribe>
+            <numOrder>1</numOrder>
+            <placeList>
+              <id>A10000000212</id>
+              <lib>ALSH PAGNOL</lib>
+              <adresse>
+                <num>0</num>
+                <street1>PLACE MARCEL PAGNOL</street1>
+                <zipcode>83160</zipcode>
+                <town>LA VALETTE DU VAR</town>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <typeCtrlPlace>N</typeCtrlPlace>
+            <nbPlace>0</nbPlace>
+            <nbPlaceBoy>0</nbPlaceBoy>
+            <nbPlaceGirl>0</nbPlaceGirl>
+            <topCESU>N</topCESU>
+          </unitPortailList>
+          <unitPortailList>
+            <idUnit>A10003132038</idUnit>
+            <label>MATIN ET REPAS</label>
+            <dateStart>2020-09-02T00:00:00+01:00</dateStart>
+            <dateEnd>2021-07-03T00:00:00+01:00</dateEnd>
+            <consoTarifList>
+              <commune>X</commune>
+              <tarif>
+                <code>ACCLOI</code>
+                <label>ACCUEIL LOISIRS</label>
+              </tarif>
+              <conso>
+                <code>ENF</code>
+                <label>ENFANT</label>
+              </conso>
+            </consoTarifList>
+            <calendarLetter>C</calendarLetter>
+            <subscribePublication>E</subscribePublication>
+            <dateStartSubscribe>2020-07-01T00:00:00+01:00</dateStartSubscribe>
+            <numOrder>2</numOrder>
+            <placeList>
+              <id>A10000000212</id>
+              <lib>ALSH PAGNOL</lib>
+              <adresse>
+                <num>0</num>
+                <street1>PLACE MARCEL PAGNOL</street1>
+                <zipcode>83160</zipcode>
+                <town>LA VALETTE DU VAR</town>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <typeCtrlPlace>N</typeCtrlPlace>
+            <nbPlace>0</nbPlace>
+            <nbPlaceBoy>0</nbPlaceBoy>
+            <nbPlaceGirl>0</nbPlaceGirl>
+            <topCESU>N</topCESU>
+          </unitPortailList>
+          <unitPortailList>
+            <idUnit>A10003132040</idUnit>
+            <label>APRES MIDI</label>
+            <dateStart>2020-09-02T00:00:00+01:00</dateStart>
+            <dateEnd>2021-07-03T00:00:00+01:00</dateEnd>
+            <consoTarifList>
+              <commune>X</commune>
+              <tarif>
+                <code>ACCLOI</code>
+                <label>ACCUEIL LOISIRS</label>
+              </tarif>
+              <conso>
+                <code>ENF</code>
+                <label>ENFANT</label>
+              </conso>
+            </consoTarifList>
+            <calendarLetter>D</calendarLetter>
+            <subscribePublication>E</subscribePublication>
+            <dateStartSubscribe>2020-07-01T00:00:00+01:00</dateStartSubscribe>
+            <numOrder>3</numOrder>
+            <placeList>
+              <id>A10000000212</id>
+              <lib>ALSH PAGNOL</lib>
+              <adresse>
+                <num>0</num>
+                <street1>PLACE MARCEL PAGNOL</street1>
+                <zipcode>83160</zipcode>
+                <town>LA VALETTE DU VAR</town>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <typeCtrlPlace>N</typeCtrlPlace>
+            <nbPlace>0</nbPlace>
+            <nbPlaceBoy>0</nbPlaceBoy>
+            <nbPlaceGirl>0</nbPlaceGirl>
+            <topCESU>N</topCESU>
+          </unitPortailList>
+        </activityUnitPlacePortailList>
+        <activityUnitPlacePortailList>
+          <activityPortail>
+            <idAct>A10003132090</idAct>
+            <label>COURS DE DANSE</label>
+            <dateStart>2020-01-01T00:00:00+01:00</dateStart>
+            <schoolYear>2020</schoolYear>
+            <calendarGeneration>
+              <code>FORBIDDEN</code>
+              <value>I</value>
+            </calendarGeneration>
+            <dateStartPubli>2020-07-01T10:43:16+01:00</dateStartPubli>
+            <calendarMode>N</calendarMode>
+            <activityType>
+              <code>LOIVAC</code>
+              <libelle>(Loisirs Vacances)</libelle>
+              <natureSpec>
+                <code>L</code>
+                <libelle>Loisirs/Vacances</libelle>
+              </natureSpec>
+            </activityType>
+            <weeklyCalendarActivityList>
+              <yearCalendar>2020</yearCalendar>
+              <weeklyCalendarStr>0000011</weeklyCalendarStr>
+            </weeklyCalendarActivityList>
+            <birthControl>N</birthControl>
+            <waitIfComplete>N</waitIfComplete>
+          </activityPortail>
+          <openDayList>2020-12-14T00:00:00+01:00</openDayList>
+          <openDayList>2020-12-15T00:00:00+01:00</openDayList>
+          <openDayList>2020-12-16T00:00:00+01:00</openDayList>
+          <openDayList>2020-12-17T00:00:00+01:00</openDayList>
+          <openDayList>2020-12-18T00:00:00+01:00</openDayList>
+          <unitPortailList>
+            <idUnit>A10003132091</idUnit>
+            <label>COURS DE DANSE</label>
+            <dateStart>2020-01-01T00:00:00+01:00</dateStart>
+            <calendarLetter>X</calendarLetter>
+            <subscribePublication>E</subscribePublication>
+            <dateStartSubscribe>2020-07-01T00:00:00+01:00</dateStartSubscribe>
+            <numOrder>0</numOrder>
+            <placeList>
+              <id>A10000000212</id>
+              <lib>ALSH PAGNOL</lib>
+              <adresse>
+                <num>0</num>
+                <street1>PLACE MARCEL PAGNOL</street1>
+                <zipcode>83160</zipcode>
+                <town>LA VALETTE DU VAR</town>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <typeCtrlPlace>N</typeCtrlPlace>
+            <nbPlace>0</nbPlace>
+            <nbPlaceBoy>0</nbPlaceBoy>
+            <nbPlaceGirl>0</nbPlaceGirl>
+            <topCESU>N</topCESU>
+          </unitPortailList>
+        </activityUnitPlacePortailList>
+        <activityUnitPlacePortailList>
+          <activityPortail>
+            <idAct>A10003132150</idAct>
+            <label>LASERQUEST</label>
+            <dateStart>2020-01-01T00:00:00+01:00</dateStart>
+            <schoolYear>2020</schoolYear>
+            <calendarGeneration>
+              <code>FORBIDDEN</code>
+              <value>I</value>
+            </calendarGeneration>
+            <dateStartPubli>2020-07-01T10:43:16+01:00</dateStartPubli>
+            <calendarMode>N</calendarMode>
+            <activityType>
+              <code>LOIVAC</code>
+              <libelle>(Loisirs Vacances)</libelle>
+              <natureSpec>
+                <code>L</code>
+                <libelle>Loisirs/Vacances</libelle>
+              </natureSpec>
+            </activityType>
+            <birthControl>N</birthControl>
+            <waitIfComplete>N</waitIfComplete>
+          </activityPortail>
+          <unitPortailList>
+            <idUnit>A10003132152</idUnit>
+            <label>LASERQUEST</label>
+            <dateStart>2020-01-01T00:00:00+01:00</dateStart>
+            <calendarLetter>X</calendarLetter>
+            <subscribePublication>E</subscribePublication>
+            <dateStartSubscribe>2020-07-01T00:00:00+01:00</dateStartSubscribe>
+            <numOrder>1</numOrder>
+            <placeList>
+              <id>A10000000212</id>
+              <lib>ALSH PAGNOL</lib>
+              <adresse>
+                <num>0</num>
+                <street1>PLACE MARCEL PAGNOL</street1>
+                <zipcode>83160</zipcode>
+                <town>LA VALETTE DU VAR</town>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <typeCtrlPlace>N</typeCtrlPlace>
+            <nbPlace>0</nbPlace>
+            <nbPlaceBoy>0</nbPlaceBoy>
+            <nbPlaceGirl>0</nbPlaceGirl>
+            <topCESU>N</topCESU>
+          </unitPortailList>
+        </activityUnitPlacePortailList>
+        <activityUnitPlacePortailList>
+          <activityPortail>
+            <idAct>A10003132271</idAct>
+            <label>EQUITATION</label>
+            <dateStart>2020-09-02T00:00:00+01:00</dateStart>
+            <schoolYear>2020</schoolYear>
+            <calendarGeneration>
+              <code>FORBIDDEN</code>
+              <value>I</value>
+            </calendarGeneration>
+            <dateStartPubli>2020-07-01T10:43:16+01:00</dateStartPubli>
+            <calendarMode>N</calendarMode>
+            <activityType>
+              <code>LOIVAC</code>
+              <libelle>(Loisirs Vacances)</libelle>
+              <natureSpec>
+                <code>L</code>
+                <libelle>Loisirs/Vacances</libelle>
+              </natureSpec>
+            </activityType>
+            <birthControl>B</birthControl>
+            <waitIfComplete>N</waitIfComplete>
+          </activityPortail>
+          <unitPortailList>
+            <idUnit>A10003132273</idUnit>
+            <label>EQUITATION</label>
+            <dateStart>2020-09-02T00:00:00+01:00</dateStart>
+            <calendarLetter>X</calendarLetter>
+            <subscribePublication>E</subscribePublication>
+            <dateStartSubscribe>2020-07-01T00:00:00+01:00</dateStartSubscribe>
+            <numOrder>0</numOrder>
+            <placeList>
+              <id>A10000000212</id>
+              <lib>ALSH PAGNOL</lib>
+              <adresse>
+                <num>0</num>
+                <street1>PLACE MARCEL PAGNOL</street1>
+                <zipcode>83160</zipcode>
+                <town>LA VALETTE DU VAR</town>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <birthDateStart>1970-01-01T00:00:00+01:00</birthDateStart>
+            <birthDateEnd>2014-12-31T00:00:00+01:00</birthDateEnd>
+            <typeCtrlPlace>N</typeCtrlPlace>
+            <nbPlace>0</nbPlace>
+            <nbPlaceBoy>0</nbPlaceBoy>
+            <nbPlaceGirl>0</nbPlaceGirl>
+            <topCESU>N</topCESU>
+          </unitPortailList>
+        </activityUnitPlacePortailList>
+        <activityUnitPlacePortailList>
+          <activityPortail>
+            <idAct>A10003132293</idAct>
+            <label>ATELIER D'EXPRESSION THEATRALE</label>
+            <dateStart>2020-10-05T00:00:00+01:00</dateStart>
+            <dateEnd>2020-12-15T00:00:00+01:00</dateEnd>
+            <codeConso>SEN</codeConso>
+            <schoolYear>2020</schoolYear>
+            <calendarGeneration>
+              <code>FORBIDDEN</code>
+              <value>I</value>
+            </calendarGeneration>
+            <dateStartPubli>2020-07-01T10:43:16+01:00</dateStartPubli>
+            <calendarMode>N</calendarMode>
+            <activityType>
+              <code>LOIVAC</code>
+              <libelle>(Loisirs Vacances)</libelle>
+              <natureSpec>
+                <code>L</code>
+                <libelle>Loisirs/Vacances</libelle>
+              </natureSpec>
+            </activityType>
+            <weeklyCalendarActivityList>
+              <yearCalendar>2020</yearCalendar>
+              <weeklyCalendarStr>0010011</weeklyCalendarStr>
+            </weeklyCalendarActivityList>
+            <birthControl>N</birthControl>
+            <waitIfComplete>N</waitIfComplete>
+          </activityPortail>
+          <openDayList>2020-12-14T00:00:00+01:00</openDayList>
+          <unitPortailList>
+            <idUnit>A10003132295</idUnit>
+            <label>ATELIER D'EXPRESSION THEATRALE</label>
+            <dateStart>2020-10-05T00:00:00+01:00</dateStart>
+            <dateEnd>2020-12-15T00:00:00+01:00</dateEnd>
+            <consoTarifList>
+              <commune>X</commune>
+              <tarif>
+                <code>BOXE</code>
+                <label>BOXE</label>
+              </tarif>
+              <conso>
+                <code>SEN</code>
+                <label>SENIOR</label>
+              </conso>
+            </consoTarifList>
+            <calendarLetter>X</calendarLetter>
+            <subscribePublication>E</subscribePublication>
+            <dateStartSubscribe>2020-07-01T00:00:00+01:00</dateStartSubscribe>
+            <numOrder>0</numOrder>
+            <placeList>
+              <id>A10000000212</id>
+              <lib>ALSH PAGNOL</lib>
+              <adresse>
+                <num>0</num>
+                <street1>PLACE MARCEL PAGNOL</street1>
+                <zipcode>83160</zipcode>
+                <town>LA VALETTE DU VAR</town>
+              </adresse>
+              <typeCtrlPlace>N</typeCtrlPlace>
+              <nbPlace>0</nbPlace>
+              <nbPlaceBoy>0</nbPlaceBoy>
+              <nbPlaceGirl>0</nbPlaceGirl>
+            </placeList>
+            <typeCtrlPlace>N</typeCtrlPlace>
+            <nbPlace>0</nbPlace>
+            <nbPlaceBoy>0</nbPlaceBoy>
+            <nbPlaceGirl>0</nbPlaceGirl>
+            <topCESU>N</topCESU>
+          </unitPortailList>
+        </activityUnitPlacePortailList>
+      </ReadActivityPortailListResultBean>
+    </ns1:readActivityListResponse>
+  </soap:Body>
+</soap:Envelope>
diff --git a/tests/data/maelis/child_planning_readChildMonthPlanningResponse.xml b/tests/data/maelis/child_planning_readChildMonthPlanningResponse.xml
new file mode 100644
index 00000000..05dfa81a
--- /dev/null
+++ b/tests/data/maelis/child_planning_readChildMonthPlanningResponse.xml
@@ -0,0 +1,209 @@
+<?xml version="1.0"?>
+<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
+  <soap:Body>
+    <ns1:readChildMonthPlanningResponse xmlns:ns1="activity.ws.maelis.sigec.com">
+      <ResultCalendarList>
+        <person>
+          <idMaelis>W20885</idMaelis>
+          <num>21293</num>
+          <lastname>JOHANN</lastname>
+          <firstname>AURELIE</firstname>
+        </person>
+        <calendList>
+          <unit>
+            <id>A10003121694</id>
+            <idActivity>A10003121692</idActivity>
+            <libelle>1 2020-2021 GARDERIE MATIN</libelle>
+            <motif>X</motif>
+          </unit>
+          <listDays>
+            <datePlanning>2020-12-01T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+          <listDays>
+            <datePlanning>2020-12-03T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+          <listDays>
+            <datePlanning>2020-12-04T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+          <listDays>
+            <datePlanning>2020-12-07T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+          <listDays>
+            <datePlanning>2020-12-08T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+          <listDays>
+            <datePlanning>2020-12-10T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+          <listDays>
+            <datePlanning>2020-12-11T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+          <listDays>
+            <datePlanning>2020-12-14T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+          <listDays>
+            <datePlanning>2020-12-15T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+          <listDays>
+            <datePlanning>2020-12-17T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+          <listDays>
+            <datePlanning>2020-12-18T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+        </calendList>
+        <calendList>
+          <unit>
+            <id>A10003123492</id>
+            <idActivity>A10003123490</idActivity>
+            <libelle>2 2020-2021  RESTAURATION SCOLAIRE</libelle>
+            <motif>X</motif>
+          </unit>
+          <listDays>
+            <datePlanning>2020-12-01T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+          <listDays>
+            <datePlanning>2020-12-03T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+          <listDays>
+            <datePlanning>2020-12-04T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+          <listDays>
+            <datePlanning>2020-12-07T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+          <listDays>
+            <datePlanning>2020-12-08T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+          <listDays>
+            <datePlanning>2020-12-10T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+          <listDays>
+            <datePlanning>2020-12-11T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+          <listDays>
+            <datePlanning>2020-12-14T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+          <listDays>
+            <datePlanning>2020-12-15T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+          <listDays>
+            <datePlanning>2020-12-17T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+          <listDays>
+            <datePlanning>2020-12-18T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+        </calendList>
+        <calendList>
+          <unit>
+            <id>A10003132032</id>
+            <idActivity>A10003132030</idActivity>
+            <libelle>2020-2021 CENTRE DE LOISIRS MERCREDI</libelle>
+            <motif>X</motif>
+          </unit>
+          <listDays>
+            <datePlanning>2020-12-02T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+          <listDays>
+            <datePlanning>2020-12-09T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+          <listDays>
+            <datePlanning>2020-12-16T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+        </calendList>
+        <calendList>
+          <unit>
+            <id>A10003132038</id>
+            <idActivity>A10003132030</idActivity>
+            <libelle>MATIN ET REPAS</libelle>
+            <motif>C</motif>
+          </unit>
+          <listDays>
+            <datePlanning>2020-12-23T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+          <listDays>
+            <datePlanning>2020-12-25T02:50:44.508+01:00</datePlanning>
+            <dayType>
+              <code>DAY</code>
+            </dayType>
+          </listDays>
+        </calendList>
+      </ResultCalendarList>
+    </ns1:readChildMonthPlanningResponse>
+  </soap:Body>
+</soap:Envelope>
diff --git a/tests/test_maelis.py b/tests/test_maelis.py
index 5790046b..453d70b6 100644
--- a/tests/test_maelis.py
+++ b/tests/test_maelis.py
@@ -1,26 +1,39 @@
 # -*- coding: utf-8 -*-
 
+import json
 import mock
 import os
 import pytest
 
+from django.test import override_settings
+
 from passerelle.apps.maelis.models import Maelis, Link
 
 from passerelle.utils.jsonresponse import APIError
+from passerelle.apps.maelis.utils import (
+    get_default_school_year, parse_datetime, get_week_boundaries,
+    get_months, decompose_event)
 
 import utils
 
 pytestmark = pytest.mark.django_db
 
+TEST_BASE_DIR = os.path.join(os.path.dirname(__file__), 'data', 'maelis')
+
 
 def get_xml_file(filename):
-    return open(os.path.join(os.path.dirname(__file__),
-                             'data', 'maelis', filename), 'rb').read()
+    with open(os.path.join(TEST_BASE_DIR, filename), 'rb') as desc:
+        return desc.read()
+
+
+def get_json_file(filename):
+    with open(os.path.join(TEST_BASE_DIR, "%s.json" % filename)) as fd:
+        return json.load(fd)
 
 
 @pytest.fixture
 def family_service_wsdl():
     return get_xml_file('FamilyService.wsdl')
 
 
 @pytest.fixture
@@ -193,8 +206,125 @@ def test_get_invoice_details(mocked_post, mocked_get, invoice_service_wsdl,
                                          status_code=200,
                                          headers={'Content-Type': 'text/xml'}
                                          )
     Link.objects.create(resource=connector, family_id='3264', name_id='local')
     resp = app.get('/maelis/test/regie/1/invoice/3264-53186?NameID=local')
     assert resp.json['data']
     assert resp.json['data']['label'] == 'FACTURATION SEPTEMBRE 2014'
     assert resp.json['data']['display_id'] == '53186'
+
+
+@pytest.mark.parametrize('date, schoolyear', [
+    ('2020-07-30', 2019),
+    ('2020-07-31', 2020),
+])
+def test_get_default_school_year(date, schoolyear):
+    date = parse_datetime(date)
+    assert schoolyear == get_default_school_year(date)
+
+
+@pytest.mark.parametrize('date, monday, sunday', [
+    ('2020-12-27', '2020-12-21', '2020-12-27'),
+    ('2020-12-28', '2020-12-28', '2021-01-03'),
+    ('2020-12-31', '2020-12-28', '2021-01-03'),
+    ('2021-01-01', '2020-12-28', '2021-01-03'),
+    ('2021-01-03', '2020-12-28', '2021-01-03'),
+])
+def test_get_week_boundaries(date, monday, sunday):
+    monday = parse_datetime(monday)
+    sunday = parse_datetime(sunday)
+
+    start, end = get_week_boundaries(date)
+    assert start == monday
+    assert end == sunday
+
+
+@pytest.mark.parametrize('start, end, items', [
+    ('2020-10-22', '2020-12-06', ['2020-10-01', '2020-11-01', '2020-12-01']),
+    ('2020-12-31', '2021-01-03', ['2020-12-01', '2021-01-01']),
+    ('2020-12-28', '2020-12-28', ['2020-12-01']),
+    ('2021-01-03', '2020-12-01', []),
+])
+def test_get_months(start, end, items):
+    start = parse_datetime(start)
+    end = parse_datetime(end)
+    assert [x.strftime('%Y-%m-%d') for x in get_months(start, end)] == items
+
+
+def test_decompose_event():
+    resp = get_json_file('child_planning_before_decomposition')
+    data = resp['data']
+    assert len(data) == 43
+    assert data[22]['text'] == 'JOURNEE'
+    assert data[23]['text'] == 'MATIN'
+    assert data[24]['text'] == 'MATIN ET REPAS'
+    assert data[25]['text'] == 'APRES MIDI'
+    assert not [x for x in data if x['text'] == 'REPAS']
+
+    # unit is break down into its components
+    assert [x['text'] for x in decompose_event(data[22])] == [
+        'Matinée', 'Repas', 'Après-midi']
+    assert [x['text'] for x in decompose_event(data[23])] == [
+        'Matinée']
+    assert [x['text'] for x in decompose_event(data[24])] == [
+        'Matinée', 'Repas']
+    assert [x['text'] for x in decompose_event(data[25])] == [
+        'Après-midi']
+
+    # child_planning function use a dict to remove dupplicated components
+    data = {x['id']: x for e in data for x in decompose_event(e)}.values()
+    assert len(data) == 42
+    assert len([x for x in data if x['text'] == 'Repas']) == 1
+    assert len([x for x in data if 'EO0001' in x['slot_id']]) == 3
+
+
+@override_settings(TIME_ZONE='Europe/Paris')
+@mock.patch('passerelle.utils.Request.get')
+@mock.patch('passerelle.utils.Request.post')
+def test_get_child_planning(mocked_post, mocked_get, family_service_wsdl,
+                            activity_service_wsdl, app, connector):
+    mocked_get.side_effect = (
+        utils.FakedResponse(
+            content=family_service_wsdl,
+            status_code=200,
+            headers={'Content-Type': 'text/xml'}),
+        utils.FakedResponse(
+            content=activity_service_wsdl,
+            status_code=200,
+            headers={'Content-Type': 'text/xml'}),
+        utils.FakedResponse(
+            content=activity_service_wsdl,
+            status_code=200,
+            headers={'Content-Type': 'text/xml'})
+    )
+    mocked_post.side_effect = (
+        utils.FakedResponse(
+            content=get_xml_file('readFamily.xml'),
+            status_code=200,
+            headers={'Content-Type': 'text/xml'}),
+        utils.FakedResponse(
+            content=get_xml_file('child_planning_readActivityListResponse.xml'),
+            status_code=200,
+            headers={'Content-Type': 'text/xml'}),
+        utils.FakedResponse(
+            content=get_xml_file('child_planning_readChildMonthPlanningResponse.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/child-planning?NameID=local&personID=21293&start_date=2020-12-19')
+    data = resp.json['data']
+    previous_event = {}
+    for event in data:
+        assert event['category']
+        assert event['text']
+        if previous_event:
+            assert previous_event['id'] <= event['id']
+            assert previous_event['datetime'] <= event['datetime']
+        previous_event = event
+    assert len(data) == 42
+    assert len([s for s in data if s['user_booking_status'] == 'not-booked']) == 33
+    assert len([s for s in data if s['user_booking_status'] == 'booked']) == 9
+    assert not [x for x in data if x['text'] == 'MATIN']
+    assert len([x for x in data if x['text'] == 'Matinée']) == 1
+    assert resp.json == get_json_file('child_planning_after_decomposition')
-- 
2.29.2

