toulouse_maelis: initial commit (#62464)

This commit is contained in:
Nicolas Roche 2022-07-12 18:50:20 +02:00
parent a0d07da11a
commit 1a551ab9e5
12 changed files with 3827 additions and 0 deletions

View File

@ -0,0 +1,109 @@
# Generated by Django 2.2.26 on 2022-07-11 14:30
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('base', '0029_auto_20210202_1627'),
]
operations = [
migrations.CreateModel(
name='ToulouseMaelis',
fields=[
(
'id',
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
('title', models.CharField(max_length=50, verbose_name='Title')),
('slug', models.SlugField(unique=True, verbose_name='Identifier')),
('description', models.TextField(verbose_name='Description')),
(
'basic_auth_username',
models.CharField(
blank=True, max_length=128, verbose_name='Basic authentication username'
),
),
(
'basic_auth_password',
models.CharField(
blank=True, max_length=128, verbose_name='Basic authentication password'
),
),
(
'client_certificate',
models.FileField(
blank=True, null=True, upload_to='', verbose_name='TLS client certificate'
),
),
(
'trusted_certificate_authorities',
models.FileField(blank=True, null=True, upload_to='', verbose_name='TLS trusted CAs'),
),
(
'verify_cert',
models.BooleanField(blank=True, default=True, verbose_name='TLS verify certificates'),
),
(
'http_proxy',
models.CharField(blank=True, max_length=128, verbose_name='HTTP and HTTPS proxy'),
),
(
'base_wsdl_url',
models.CharField(
default='https://demo-toulouse.sigec.fr/maelisws-toulouse/services/',
help_text='Toulouse Maelis base WSDL URL',
max_length=128,
verbose_name='Base WSDL URL',
),
),
(
'zeep_wsse_username',
models.CharField(blank=True, default='', max_length=64, verbose_name='WSSE Username'),
),
(
'zeep_wsse_password',
models.CharField(blank=True, default='', max_length=64, verbose_name='WSSE Password'),
),
(
'users',
models.ManyToManyField(
blank=True,
related_name='_toulousemaelis_users_+',
related_query_name='+',
to='base.ApiUser',
),
),
],
options={
'verbose_name': 'Toulouse Maelis',
},
),
migrations.CreateModel(
name='Link',
fields=[
(
'id',
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
('name_id', models.CharField(max_length=256)),
('family_id', models.CharField(max_length=128)),
('created', models.DateTimeField(auto_now_add=True)),
('updated', models.DateTimeField(auto_now=True)),
(
'resource',
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to='toulouse_maelis.ToulouseMaelis'
),
),
],
options={
'unique_together': {('resource', 'name_id')},
},
),
]

View File

@ -0,0 +1,136 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2022 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# 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 urllib.parse import urljoin
import zeep
from django.db import models
from django.utils.translation import ugettext_lazy as _
from zeep.helpers import serialize_object
from zeep.wsse.username import UsernameToken
from passerelle.base.models import BaseResource, HTTPResource
from passerelle.utils.api import endpoint
from passerelle.utils.jsonresponse import APIError
from . import schemas
class ToulouseMaelis(BaseResource, HTTPResource):
base_wsdl_url = models.CharField(
max_length=128,
blank=False,
verbose_name=_('Base WSDL URL'),
help_text=_('Toulouse Maelis base WSDL URL'),
default='https://demo-toulouse.sigec.fr/maelisws-toulouse/services/',
)
zeep_wsse_username = models.CharField(
max_length=64, blank=True, default='', verbose_name=_('WSSE Username')
)
zeep_wsse_password = models.CharField(
max_length=64, blank=True, default='', verbose_name=_('WSSE Password')
)
category = _('Business Process Connectors')
_category_ordering = [_('Family'), _('Activities')]
class Meta:
verbose_name = _('Toulouse Maelis')
def get_client(self, wsdl_short_name):
wsse = UsernameToken(self.zeep_wsse_username, self.zeep_wsse_password)
wsdl_name = wsdl_short_name + 'Service?wsdl'
wsdl_url = urljoin(self.base_wsdl_url, wsdl_name)
return self.soap_client(wsdl_url=wsdl_url, wsse=wsse)
def call(self, wsdl_short_name, service, **kwargs):
client = self.get_client(wsdl_short_name)
method = getattr(client.service, service)
try:
return method(**kwargs)
except zeep.exceptions.Fault as e:
raise APIError(e.message, err_code='%s-%s-%s' % (wsdl_short_name, service, e.code))
def check_status(self):
assert self.call('Family', 'isWSRunning')
assert self.call('Activity', 'isWSRunning')
def get_link(self, NameID):
try:
return self.link_set.get(name_id=NameID)
except Link.DoesNotExist:
raise APIError('User not linked to family', err_code='not-linked')
def get_family(self, family_id):
response = self.call('Family', 'readFamily', dossierNumber=family_id)
data = serialize_object(response)
return data
@endpoint(
display_category=_('Family'),
description=_('Create link between user and family'),
perm='can_access',
parameters={'NameID': {'description': _('Publik ID')}},
post={'request_body': {'schema': {'application/json': schemas.LINK_SCHEMA}}},
)
def link(self, request, NameID, post_data):
family_id = post_data['family_id']
response = self.call('Family', 'readFamily', dossierNumber=family_id)
if not (
response['RL1']['firstname'] == post_data['firstname'].upper()
and response['RL1']['lastname'] == post_data['lastname'].upper()
and response['RL1']['dateBirth'].strftime('%Y-%m-%d') == post_data['dateBirth']
):
raise APIError("RL1 does not match '%s' family" % family_id, err_code='not-found')
Link.objects.update_or_create(resource=self, name_id=NameID, defaults={'family_id': family_id})
return {'data': 'ok'}
@endpoint(
display_category=_('Family'),
description=_('Delete link between user and family'),
methods=['post'],
perm='can_access',
parameters={
'NameID': {'description': _('Publik ID')},
},
)
def unlink(self, request, NameID):
link = self.get_link(NameID)
link.delete()
return {'data': 'ok'}
@endpoint(
display_category=_('Family'),
description='Informations sur la famille',
perm='can_access',
name='read-family',
parameters={'NameID': {'description': _('Publik ID')}},
)
def read_family(self, request, NameID):
family_id = self.get_link(NameID).family_id
data = self.get_family(family_id)
return {'data': data}
class Link(models.Model):
resource = models.ForeignKey(ToulouseMaelis, 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)
class Meta:
unique_together = ('resource', 'name_id')

View File

@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2022 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# 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/>.
LINK_SCHEMA = {
'$schema': 'http://json-schema.org/draft-04/schema#',
'title': 'Link',
'description': "Appairage d'un usager Publik à une famille dans Maelis",
'type': 'object',
'required': ['family_id', 'firstname', 'lastname', 'dateBirth'],
'properties': {
'family_id': {
'description': 'Numéro DUI',
'type': 'string',
},
'firstname': {
'description': 'Prénom du RL1',
'type': 'string',
},
'lastname': {
'description': 'Nom du RL1',
'type': 'string',
},
'dateBirth': {
'description': 'Date de naissance du RL1',
'type': 'string',
'pattern': '[0-9]{4}-[0-9]{2}-[0-9]{2}',
},
},
}

View File

@ -0,0 +1,885 @@
<?xml version='1.0' encoding='UTF-8'?><wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="activity.ws.maelis.sigec.com" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="ActivityService" targetNamespace="activity.ws.maelis.sigec.com">
<wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="bean.persistence.ws.maelis.sigec.com" version="1.0">
<xs:complexType name="weeklyCalendarActivityBean">
<xs:sequence>
<xs:element minOccurs="0" name="yearCalendar" type="xs:int"/>
<xs:element minOccurs="0" name="weeklyCalendarStr" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="bean.persistence.family.ws.maelis.sigec.com" version="1.0">
<xs:complexType name="personInfoBean">
<xs:sequence>
<xs:element name="num" type="xs:int"/>
<xs:element minOccurs="0" name="lastname" type="xs:string"/>
<xs:element minOccurs="0" name="firstname" type="xs:string"/>
<xs:element minOccurs="0" name="civility" type="xs:string"/>
<xs:element minOccurs="0" name="sexe" type="xs:string"/>
<xs:element minOccurs="0" name="phone" type="xs:string"/>
<xs:element minOccurs="0" name="mobile" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="bean.persistence.activity.ws.maelis.sigec.com" xmlns:ns3="bean.persistence.family.ws.maelis.sigec.com" xmlns:ns2="bean.persistence.ws.maelis.sigec.com" xmlns:ns1="activity.ws.maelis.sigec.com" targetNamespace="bean.persistence.activity.ws.maelis.sigec.com" version="1.0">
<xs:import namespace="activity.ws.maelis.sigec.com"/>
<xs:import namespace="bean.persistence.ws.maelis.sigec.com"/>
<xs:import namespace="bean.persistence.family.ws.maelis.sigec.com"/>
<xs:complexType name="updateRealCalendarsRequestBean">
<xs:sequence>
<xs:element maxOccurs="unbounded" name="unitPersonDayInfoList" type="tns:unitPersonDayInfoBean"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="unitPersonDayInfoBean">
<xs:sequence>
<xs:element name="numPerson" type="xs:int"/>
<xs:element name="idAct" type="xs:string"/>
<xs:element name="idUni" type="xs:string"/>
<xs:element name="date" type="xs:dateTime"/>
<xs:element name="action" type="ns1:dayInfoAction"/>
<xs:element name="idPlace" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="updateRealCalendarsResultBean">
<xs:sequence>
<xs:element name="result" type="xs:boolean"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="unitPersonDayInfoList" nillable="true" type="tns:unitPersonDayInfoErrorBean"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="unitPersonDayInfoErrorBean">
<xs:sequence>
<xs:element minOccurs="0" name="errorMessage" type="xs:string"/>
<xs:element minOccurs="0" name="unitPersonDayInfoBean" type="tns:unitPersonDayInfoBean"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="readActivityPortailListResultBean">
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="activityUnitPlacePortailList" nillable="true" type="tns:activityUnitPlacePortailBean"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="activityUnitPlacePortailBean">
<xs:sequence>
<xs:element minOccurs="0" name="activityPortail" type="tns:activityPortailBean"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="openDayList" nillable="true" type="xs:dateTime"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="unitPortailList" nillable="true" type="tns:unitPortailBean"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="activityPortailBean">
<xs:sequence>
<xs:element minOccurs="0" name="idAct" type="xs:string"/>
<xs:element minOccurs="0" name="label" type="xs:string"/>
<xs:element minOccurs="0" name="code" type="xs:string"/>
<xs:element minOccurs="0" name="dateStart" type="xs:dateTime"/>
<xs:element minOccurs="0" name="dateEnd" type="xs:dateTime"/>
<xs:element minOccurs="0" name="birthControl" type="xs:string"/>
<xs:element minOccurs="0" name="email" type="xs:string"/>
<xs:element minOccurs="0" name="schoolYear" type="xs:int"/>
<xs:element minOccurs="0" name="calendarGeneration" type="ns1:activityCalendarGenerationBean"/>
<xs:element minOccurs="0" name="dateStartPubli" type="xs:dateTime"/>
<xs:element minOccurs="0" name="dateEndPubli" type="xs:dateTime"/>
<xs:element minOccurs="0" name="schoolControl" type="xs:string"/>
<xs:element minOccurs="0" name="calendarMode" type="xs:string"/>
<xs:element minOccurs="0" name="activityType" type="tns:activityTypeBean"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="weeklyCalendarActivityList" nillable="true" type="ns2:weeklyCalendarActivityBean"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="activityPeriodList" nillable="true" type="tns:activityPeriodCapacityBean"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="activityBusList" nillable="true" type="tns:activityUnitPlaceBean"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="activityTypeBean">
<xs:sequence>
<xs:element minOccurs="0" name="code" type="xs:string"/>
<xs:element minOccurs="0" name="libelle" type="xs:string"/>
<xs:element minOccurs="0" name="natureSpec" type="tns:activityNatureBean"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="activityNatureBean">
<xs:sequence>
<xs:element minOccurs="0" name="code" type="xs:string"/>
<xs:element minOccurs="0" name="libelle" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="activityPeriodCapacityBean">
<xs:complexContent>
<xs:extension base="ns1:abstractSpecBean">
<xs:sequence>
<xs:element minOccurs="0" name="period" type="ns1:periodBean"/>
<xs:element minOccurs="0" name="capacity" type="xs:int"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="calendCapacityExceptList" nillable="true" type="ns1:calendCapacityBean"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="activityUnitPlaceBean">
<xs:complexContent>
<xs:extension base="ns1:abstractSpecBean">
<xs:sequence>
<xs:element minOccurs="0" name="activity" type="ns1:activity3Bean"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="unitList" nillable="true" type="ns1:unitPlaceBean"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="placeBean">
<xs:sequence>
<xs:element minOccurs="0" name="id" type="xs:string"/>
<xs:element minOccurs="0" name="lib" type="xs:string"/>
<xs:element minOccurs="0" name="lib2" type="xs:string"/>
<xs:element minOccurs="0" name="adresse" type="tns:adressBean"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="activityPeriscolList" nillable="true" type="tns:activityPeriscolBean"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="adressBean">
<xs:sequence>
<xs:element minOccurs="0" name="num" type="xs:int"/>
<xs:element minOccurs="0" name="street1" type="xs:string"/>
<xs:element minOccurs="0" name="street2" type="xs:string"/>
<xs:element minOccurs="0" name="idStreet" type="xs:string"/>
<xs:element minOccurs="0" name="zipcode" type="xs:string"/>
<xs:element minOccurs="0" name="town" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="activityPeriscolBean">
<xs:complexContent>
<xs:extension base="ns1:abstractSpecBean">
<xs:sequence>
<xs:element minOccurs="0" name="activity" type="ns1:activity3Bean"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="activityPeriodList" nillable="true" type="tns:activityPeriodCapacityBean"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="unitList" nillable="true" type="tns:unitPeriscolBean"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="unitPeriscolBean">
<xs:complexContent>
<xs:extension base="ns1:abstractSpecBean">
<xs:sequence>
<xs:element minOccurs="0" name="idUnit" type="xs:string"/>
<xs:element minOccurs="0" name="label" type="xs:string"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="periodList" nillable="true" type="ns1:periodBean"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="unitPortailBean">
<xs:sequence>
<xs:element minOccurs="0" name="idUnit" type="xs:string"/>
<xs:element minOccurs="0" name="label" type="xs:string"/>
<xs:element minOccurs="0" name="codeExt" type="xs:string"/>
<xs:element minOccurs="0" name="dateStart" type="xs:dateTime"/>
<xs:element minOccurs="0" name="dateEnd" type="xs:dateTime"/>
<xs:element minOccurs="0" name="birthDateStart" type="xs:dateTime"/>
<xs:element minOccurs="0" name="birthDateEnd" type="xs:dateTime"/>
<xs:element minOccurs="0" name="calendarLetter" type="xs:string"/>
<xs:element minOccurs="0" name="subscribePublication" type="xs:string"/>
<xs:element minOccurs="0" name="dateStartSubscribe" type="xs:dateTime"/>
<xs:element minOccurs="0" name="dateEndSubscribe" type="xs:dateTime"/>
<xs:element minOccurs="0" name="numOrder" type="xs:int"/>
<xs:element minOccurs="0" name="calendarPublication" type="xs:string"/>
<xs:element minOccurs="0" name="recordAbsence" type="xs:string"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="calendList" nillable="true" type="tns:calendPortailBean"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="placeList" nillable="true" type="tns:placeBean"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="periodList" nillable="true" type="ns1:periodBean"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="calendPortailBean">
<xs:sequence>
<xs:element minOccurs="0" name="dateConso" type="xs:dateTime"/>
<xs:element minOccurs="0" name="dateMin" type="xs:dateTime"/>
<xs:element minOccurs="0" name="dateMax" type="xs:dateTime"/>
<xs:element minOccurs="0" name="dateMinVisu" type="xs:dateTime"/>
<xs:element minOccurs="0" name="dateMaxVisu" type="xs:dateTime"/>
<xs:element minOccurs="0" name="dateMaxMajPrev" type="xs:dateTime"/>
<xs:element minOccurs="0" name="dateMaxAddPres" type="xs:dateTime"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="resultCalendarListBean">
<xs:sequence>
<xs:element minOccurs="0" name="person" type="ns3:personInfoBean"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="calendList" nillable="true" type="tns:calendarUnitDayBean"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="calendarUnitDayBean">
<xs:sequence>
<xs:element minOccurs="0" name="unit" type="tns:unitBean"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="listDays" nillable="true" type="tns:dayBean"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="unitBean">
<xs:sequence>
<xs:element minOccurs="0" name="idUnit" type="xs:string"/>
<xs:element minOccurs="0" name="label" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="dayBean">
<xs:sequence>
<xs:element minOccurs="0" name="datePlanning" type="xs:dateTime"/>
<xs:element minOccurs="0" name="dayType" type="tns:dayTypeBean"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="dayTypeBean">
<xs:sequence>
<xs:element minOccurs="0" name="code" type="ns1:code"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="updateScheduleCalendarsRequestBean">
<xs:sequence>
<xs:element maxOccurs="unbounded" name="unitPersonDayInfoList" type="tns:unitPersonDayInfoBean"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="updateScheduleCalendarsResultBean">
<xs:sequence>
<xs:element name="result" type="xs:boolean"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="unitPersonDayInfoList" nillable="true" type="tns:unitPersonDayInfoErrorBean"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="activity.ws.maelis.sigec.com" xmlns:ns2="bean.persistence.family.ws.maelis.sigec.com" xmlns:ns1="bean.persistence.activity.ws.maelis.sigec.com" attributeFormDefault="unqualified" elementFormDefault="unqualified" targetNamespace="activity.ws.maelis.sigec.com">
<xs:import namespace="bean.persistence.activity.ws.maelis.sigec.com"/>
<xs:import namespace="bean.persistence.family.ws.maelis.sigec.com"/>
<xs:import namespace="bean.persistence.ws.maelis.sigec.com"/>
<xs:element name="getNbAvailablePlacesPortalOther" type="tns:getNbAvailablePlacesPortalOther"/>
<xs:element name="getNbAvailablePlacesPortalOtherResponse" type="tns:getNbAvailablePlacesPortalOtherResponse"/>
<xs:element name="isWSRunning" type="tns:isWSRunning"/>
<xs:element name="isWSRunningResponse" type="tns:isWSRunningResponse"/>
<xs:element name="readActivityList" type="tns:readActivityList"/>
<xs:element name="readActivityListResponse" type="tns:readActivityListResponse"/>
<xs:element name="readChildMonthPlanning" type="tns:readChildMonthPlanning"/>
<xs:element name="readChildMonthPlanningResponse" type="tns:readChildMonthPlanningResponse"/>
<xs:element name="updateRealCalendars" type="tns:updateRealCalendars"/>
<xs:element name="updateRealCalendarsResponse" type="tns:updateRealCalendarsResponse"/>
<xs:element name="updateScheduleCalendars" type="tns:updateScheduleCalendars"/>
<xs:element name="updateScheduleCalendarsResponse" type="tns:updateScheduleCalendarsResponse"/>
<xs:element name="updateWeekCalendar" type="tns:updateWeekCalendar"/>
<xs:element name="updateWeekCalendarResponse" type="tns:updateWeekCalendarResponse"/>
<xs:complexType name="updateRealCalendars">
<xs:sequence>
<xs:element name="updateRealCalendarsRequestBean" type="ns1:updateRealCalendarsRequestBean"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="updateRealCalendarsResponse">
<xs:sequence>
<xs:element minOccurs="0" name="return" type="ns1:updateRealCalendarsResultBean"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="getNbAvailablePlacesPortalOther">
<xs:sequence>
<xs:element minOccurs="0" name="arg0" type="xs:string"/>
<xs:element minOccurs="0" name="arg1" type="xs:string"/>
<xs:element minOccurs="0" name="arg2" type="xs:string"/>
<xs:element minOccurs="0" name="arg3" type="xs:string"/>
<xs:element minOccurs="0" name="arg4" type="xs:dateTime"/>
<xs:element minOccurs="0" name="arg5" type="xs:dateTime"/>
<xs:element minOccurs="0" name="arg6" type="xs:int"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="getNbAvailablePlacesPortalOtherResponse">
<xs:sequence>
<xs:element minOccurs="0" name="return" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="isWSRunning">
<xs:sequence/>
</xs:complexType>
<xs:complexType name="isWSRunningResponse">
<xs:sequence>
<xs:element name="isWSRunning" type="xs:boolean"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="updateWeekCalendar">
<xs:sequence>
<xs:element name="idActivity" type="xs:string"/>
<xs:element name="numPerson" type="xs:int"/>
<xs:element name="dateStart" type="xs:dateTime"/>
<xs:element minOccurs="0" name="dateEnd" type="xs:dateTime"/>
<xs:element name="weeklyPlanningAM" type="xs:string"/>
<xs:element name="weeklyPlanningPM" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="updateWeekCalendarResponse">
<xs:sequence/>
</xs:complexType>
<xs:complexType name="readActivityList">
<xs:sequence>
<xs:element name="schoolyear" type="xs:int"/>
<xs:element name="dateStartCalend" type="xs:dateTime"/>
<xs:element name="dateEndCalend" type="xs:dateTime"/>
<xs:element minOccurs="0" name="numPerson" type="xs:int"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="readActivityListResponse">
<xs:sequence>
<xs:element minOccurs="0" name="ReadActivityPortailListResultBean" type="ns1:readActivityPortailListResultBean"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="activityCalendarGenerationBean">
<xs:sequence>
<xs:element minOccurs="0" name="code" type="tns:activityCalendarGenerationMode"/>
<xs:element minOccurs="0" name="value" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType abstract="true" name="abstractSpecBean">
<xs:sequence/>
</xs:complexType>
<xs:complexType name="periodBean">
<xs:complexContent>
<xs:extension base="tns:abstractSpecBean">
<xs:sequence>
<xs:element minOccurs="0" name="code" type="xs:string"/>
<xs:element minOccurs="0" name="label" type="xs:string"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="calendCapacityBean">
<xs:complexContent>
<xs:extension base="tns:abstractSpecBean">
<xs:sequence>
<xs:element minOccurs="0" name="capacity" type="xs:int"/>
<xs:element minOccurs="0" name="dayDate" type="xs:dateTime"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="activity3Bean">
<xs:complexContent>
<xs:extension base="tns:abstractSpecBean">
<xs:sequence>
<xs:element minOccurs="0" name="id" type="xs:string"/>
<xs:element minOccurs="0" name="label" type="xs:string"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="unitPlaceBean">
<xs:complexContent>
<xs:extension base="tns:abstractSpecBean">
<xs:sequence>
<xs:element minOccurs="0" name="idUnit" type="xs:string"/>
<xs:element minOccurs="0" name="label" type="xs:string"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="placeList" nillable="true" type="ns1:placeBean"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="activityUnitPlace2KernelBean">
<xs:sequence>
<xs:element minOccurs="0" name="activityKernel" type="xs:anyType"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="unitKernelList" nillable="true" type="xs:anyType"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="codeLabelKernelBean">
<xs:sequence>
<xs:element minOccurs="0" name="code" type="xs:string"/>
<xs:element minOccurs="0" name="label" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="consoTarifKernelBean">
<xs:sequence>
<xs:element minOccurs="0" name="commune" type="xs:string"/>
<xs:element minOccurs="0" name="consoKernelBean" type="tns:codeLabelKernelBean"/>
<xs:element minOccurs="0" name="tarifKernelBean" type="tns:codeLabelKernelBean"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="activityPeriodCapacityKernelBean">
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="calendCapacityExceptKernelList" nillable="true" type="tns:calendCapacityKernelBean"/>
<xs:element minOccurs="0" name="capacity" type="xs:int"/>
<xs:element minOccurs="0" name="periodKernel" type="tns:codeLabelKernelBean"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="calendCapacityKernelBean">
<xs:sequence>
<xs:element minOccurs="0" name="capacity" type="xs:int"/>
<xs:element minOccurs="0" name="dayDate" type="xs:dateTime"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="readChildMonthPlanning">
<xs:sequence>
<xs:element name="numPerson" type="xs:int"/>
<xs:element minOccurs="0" name="idActivity" type="xs:string"/>
<xs:element minOccurs="0" name="idUnit" type="xs:string"/>
<xs:element name="year" type="xs:int"/>
<xs:element name="numMonth" type="xs:int"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="readChildMonthPlanningResponse">
<xs:sequence>
<xs:element minOccurs="0" name="ResultCalendarList" type="ns1:resultCalendarListBean"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="updateScheduleCalendars">
<xs:sequence>
<xs:element name="updateScheduleCalendarsRequestBean" type="ns1:updateScheduleCalendarsRequestBean"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="updateScheduleCalendarsResponse">
<xs:sequence>
<xs:element minOccurs="0" name="return" type="ns1:updateScheduleCalendarsResultBean"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="dayInfoAction">
<xs:restriction base="xs:string">
<xs:enumeration value="ADD_PRES_PREVI"/>
<xs:enumeration value="DEL_PRES_PREVI"/>
<xs:enumeration value="ADD_ABSENCE"/>
<xs:enumeration value="DEL_ABSENCE"/>
<xs:enumeration value="ADD_PRES_REAL"/>
<xs:enumeration value="DEL_PRES_REAL"/>
<xs:enumeration value="ADD_DEDUCTED_ABSENCE"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="activityCalendarGenerationMode">
<xs:restriction base="xs:string">
<xs:enumeration value="REQUIRED"/>
<xs:enumeration value="FORBIDDEN"/>
<xs:enumeration value="NOT_REQUIRED"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="code">
<xs:restriction base="xs:string">
<xs:enumeration value="AM"/>
<xs:enumeration value="PM"/>
<xs:enumeration value="DAY"/>
<xs:enumeration value="NONE"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="MaelisActivityException" type="tns:MaelisActivityException"/>
<xs:complexType name="MaelisActivityException">
<xs:sequence>
<xs:element minOccurs="0" name="message" type="xs:string"/>
<xs:element minOccurs="0" name="message" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:element name="MaelisSiteException" type="tns:MaelisSiteException"/>
<xs:complexType name="MaelisSiteException">
<xs:sequence>
<xs:element minOccurs="0" name="message" type="xs:string"/>
<xs:element minOccurs="0" name="code" type="xs:string"/>
<xs:element minOccurs="0" name="message" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:element name="MaelisFamilyException" type="tns:MaelisFamilyException"/>
<xs:complexType name="MaelisFamilyException">
<xs:sequence>
<xs:element minOccurs="0" name="message" type="xs:string"/>
<xs:element minOccurs="0" name="message" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:message name="updateScheduleCalendarsResponse">
<wsdl:part element="tns:updateScheduleCalendarsResponse" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getNbAvailablePlacesPortalOther">
<wsdl:part element="tns:getNbAvailablePlacesPortalOther" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="readActivityList">
<wsdl:part element="tns:readActivityList" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="readChildMonthPlanning">
<wsdl:part element="tns:readChildMonthPlanning" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="isWSRunningResponse">
<wsdl:part element="tns:isWSRunningResponse" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="readActivityListResponse">
<wsdl:part element="tns:readActivityListResponse" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="MaelisActivityException">
<wsdl:part element="tns:MaelisActivityException" name="MaelisActivityException">
</wsdl:part>
</wsdl:message>
<wsdl:message name="updateScheduleCalendars">
<wsdl:part element="tns:updateScheduleCalendars" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="updateRealCalendars">
<wsdl:part element="tns:updateRealCalendars" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getNbAvailablePlacesPortalOtherResponse">
<wsdl:part element="tns:getNbAvailablePlacesPortalOtherResponse" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="updateWeekCalendarResponse">
<wsdl:part element="tns:updateWeekCalendarResponse" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="isWSRunning">
<wsdl:part element="tns:isWSRunning" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="updateWeekCalendar">
<wsdl:part element="tns:updateWeekCalendar" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="MaelisSiteException">
<wsdl:part element="tns:MaelisSiteException" name="MaelisSiteException">
</wsdl:part>
</wsdl:message>
<wsdl:message name="MaelisFamilyException">
<wsdl:part element="tns:MaelisFamilyException" name="MaelisFamilyException">
</wsdl:part>
</wsdl:message>
<wsdl:message name="readChildMonthPlanningResponse">
<wsdl:part element="tns:readChildMonthPlanningResponse" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="updateRealCalendarsResponse">
<wsdl:part element="tns:updateRealCalendarsResponse" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="ActivityService">
<wsdl:operation name="updateRealCalendars">
<wsdl:documentation> Méthode de mise à jour du calendrier de régularisation
Elle permet d'effectuer les opérations suivantes :
- Ajouter une présence réelle
- Supprimer une présence réelle
- Ajouter une absence déductible
- Ajouter une absence non déductible
- Supprimer une absence
La mise à jour est effectuée pour toutes les requêtes sans erreur et une erreur est renvoyée avec la liste des requêtes qui posent problème le cas échéant.
Les motifs d'absence déductible et non déductible, utilisés lors de l'ajout d'absence, sont paramétrables. Le paramétrage correspondant aux motifs « A » et « AN » est fourni sous forme d'un script de base mais il peut être modifié depuis Maelis Connect : Paramétrage / Paramètres généraux/ Correspondances externes/Valeurs par défaut
------------------------------
unitPersonDayInfoList : liste des modifications
- numPerson : numéro de personne
- idActivity : identifiant de l'activité
- idUnit : identifiant de l'unité
- idPlace : identifiant de l'unité
- day : date du jour dans le calendrier (obligatoire)
- action : action sur le calendrier enum DayInfoAction { ADD_ABSENCE, ADD_DEDUCTED_ABSENCE, DEL_ABSENCE, ADD_PRES_REAL, DEL_PRES_REAL}
-------------------------------
Traitement :
Pour chaque élément de la liste
Si l'enfant est inscrit à l'unité
Si l'enfant est inscrit au lieu
Si action = ajout de présence
Si le calendrier prévisionnel n'existe pas
Création du calendrier
Si pas de présence prévisionnelle existante
Si pas de présence réelle existante
Ajout de la présence réelle
Sinon retour erreur « Présence réelle existante »
Sinon retour erreur « Présence prévisionnelle existante »
Si action = suppression de présence
Si présence réelle existante
Suppression de la présence
Sinon retour erreur « pas de présence »
Si action = ajout d'une absence déductible/non déductible
Si présence prévisionnelle existante
Si absence n'existe pas
Si la codification de l'absence existe
Ajout de l'absence déductible/non déductible
Sinon retour erreur « Le motif d'absence n'a pas été paramétré »
Sinon retour erreur « Absence existante »
Sinon retour erreur « Pas de présence prévisionnelle existante »
Si action = suppression d'absence
Si absence réelle existante
Suppression de l'absence
Sinon retour erreur « pas d'absence existante »
Sinon Retour erreur « non inscrit au lieu »
Sinon Retour erreur « non inscrit à l'unité »
------------------------------
Retour :
UpdateRealCalendarsResultBean
- result : résultat de l'opération : vrai si pas d'erreur, faux si une ou plusieurs erreurs recontrées
- List UnitPersonScheduleDayError
- UnitPersonScheduleDayInfo
- ErrorMessage : constitué d'un code numérique suivi d'un libellé</wsdl:documentation>
<wsdl:input message="tns:updateRealCalendars" name="updateRealCalendars">
</wsdl:input>
<wsdl:output message="tns:updateRealCalendarsResponse" name="updateRealCalendarsResponse">
</wsdl:output>
<wsdl:fault message="tns:MaelisActivityException" name="MaelisActivityException">
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="getNbAvailablePlacesPortalOther">
<wsdl:input message="tns:getNbAvailablePlacesPortalOther" name="getNbAvailablePlacesPortalOther">
</wsdl:input>
<wsdl:output message="tns:getNbAvailablePlacesPortalOtherResponse" name="getNbAvailablePlacesPortalOtherResponse">
</wsdl:output>
<wsdl:fault message="tns:MaelisActivityException" name="MaelisActivityException">
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="isWSRunning">
<wsdl:input message="tns:isWSRunning" name="isWSRunning">
</wsdl:input>
<wsdl:output message="tns:isWSRunningResponse" name="isWSRunningResponse">
</wsdl:output>
<wsdl:fault message="tns:MaelisActivityException" name="MaelisActivityException">
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="updateWeekCalendar">
<wsdl:documentation> Méthode de mise à jour du calendrier hebdomadaire
----------------------
idActivity : identifiant de l'activité
numPerson : Numéro de personne
weeklyPlanningAM : modèle hebdomadaire matin
weeklyPlanningPM : modèle hebdomadaire après-midi
dateStart : date de début d'application
dateEnd : date de fin d'application, facultatif, si non fourni date de fin de l'inscription
------------------------------
Traitement :
La méthode enregistre le nouveau calendrier hebdomadaire et effectue une mise à jour du calendrier annuel calculé à partir du modèle hebdomadaire à partir de la date d'application passée en paramètre jusqu'à la date de fin.
Le modèle hebdomadaire est une chaine sur 7 positions constituée suivant la codification existante dans Maelis :
- 1 = jour fermé pour l'activité,
- 0 = jour ouvert sans présence,
- lettre = présence à l'unité correspondant à cette lettre</wsdl:documentation>
<wsdl:input message="tns:updateWeekCalendar" name="updateWeekCalendar">
</wsdl:input>
<wsdl:output message="tns:updateWeekCalendarResponse" name="updateWeekCalendarResponse">
</wsdl:output>
<wsdl:fault message="tns:MaelisActivityException" name="MaelisActivityException">
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="readActivityList">
<wsdl:documentation> Méthode de lecture des paramétrages des activités
Cette méthode permet la lecture des paramétrages des activités, des unités et des lieux afin de fournir les informations nécessaires pour les inscriptions et la mise à jour des calendriers.
Un paramètre optionnel en entrée, numéro d'un enfant, est utilisé afin de pouvoir filtrer les activités, les unités et les lieux par rapport à cet enfant et l'établissement de son inscription scolaire.
Les activités qui sont renvoyées sont celles ouvertes sur la plage de date passée en paramètre.
Les différents paramétrages concernant la publication des activités/unités sont renvoyées par la méthode permettant ainsi côté GRC la gestion des modalités d'inscription
-------------------------------
schoolyear : année scolaire (obligatoire)
dateStartCalend : date de début des jours du calendrier (obligatoire)
dateEndCalend : date de fin des jours du calendrier (obligatoire)
numPerson : numéro de l'enfant (facultatif)
-------------------------------
Traitement :
Les activités renvoyées sont celles qui sont publiables (en lecture ou écriture) et qui correspondent à l'année scolaire passée en paramètre ou n'ont pas d'année scolaire paramétrée.
Les unités renvoyées sont celles qui sont publiables (en lecture ou écriture) pour les inscriptions
Lorsque le numéro de l'enfant est fourni en paramètre d'entrée, les activités/unités/lieux renvoyés sont filtrés par rapport aux paramétrages de contrôle de tranche d'âge, de scolarité et aux associations des établissement aux activités/unités/lieux</wsdl:documentation>
<wsdl:input message="tns:readActivityList" name="readActivityList">
</wsdl:input>
<wsdl:output message="tns:readActivityListResponse" name="readActivityListResponse">
</wsdl:output>
<wsdl:fault message="tns:MaelisActivityException" name="MaelisActivityException">
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="readChildMonthPlanning">
<wsdl:documentation> Méthode de lecture du calendrier mensuel d'un enfant
-------------------------------
numPerson : numéro de personne (obligatoire)
idActivity : identifiant de l'activité (filtre facultatif)
idUnit : identifiant de l'unité (filtre facultatif)
year : année du calendrier (obligatire)
numMonth : numéro du mois à récupérer (Mois 1 à 12) (obligatoire)
-------------------------------
Traitement :
L'identifiant de l'activité et de l'unité sont facultatifs.
Les calendriers renvoyés sont filtrés par rapport aux identifiants fournis.
Si inscription existe et calendrier prévisionnel existe
Retour ResultCalendBean
Sinon
Retour erreur « Non inscrit »</wsdl:documentation>
<wsdl:input message="tns:readChildMonthPlanning" name="readChildMonthPlanning">
</wsdl:input>
<wsdl:output message="tns:readChildMonthPlanningResponse" name="readChildMonthPlanningResponse">
</wsdl:output>
<wsdl:fault message="tns:MaelisActivityException" name="MaelisActivityException">
</wsdl:fault>
<wsdl:fault message="tns:MaelisSiteException" name="MaelisSiteException">
</wsdl:fault>
<wsdl:fault message="tns:MaelisFamilyException" name="MaelisFamilyException">
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="updateScheduleCalendars">
<wsdl:documentation> Méthode de mise à jour du calendrier prévisionnel
Méthode permettant une mise à jour de masse pour une liste de dates
La mise à jour est effectuée pour toutes les requêtes sans erreur et une erreur est renvoyée avec la liste des requêtes qui posent problème le cas échéant.
-------------------------------
unitPersonDayInfoList : liste des jours du calendrier (obligatoire)
- numPerson : numéro de personne (obligatoire)
- idAct : identifiant de l'activité (obligatoire)
- idUni : identifiant de l'unité (obligatoire)
- idPlace : identifiant de l'unité (obligatoire)
- date : date du jour dans le calendrier (obligatoire)
- action : action sur le calendrier enum DayInfoAction {ADD_PRES_PREVI, DEL_PRES_PREVI}
-------------------------------
Traitement :
Pour chaque élément de la liste
Si l'enfant est inscrit à l'unité
Si l'enfant est inscrit au lieu
Si action = ajout de présence
Si le calendrier prévisionnel n'existe pas
Création du calendrier
Sinon si la présence prévisionnelle existe déjà
Retour erreur « Il y a déjà un prévisionnel à cette unité pour cet enfant »
Sinon si pas de présence réelle existante
Mise à jour du calendrierSinon retour erreur « présence réelle déjà existante »
Si action = suppression de présence
Si le calendrier prévisionnel existe
Si présence prévisionnelle existante
Mise à jour calendrier
Sinon retour erreur « pas de présence »
Sinon retour erreur « Il n'y a pas de prévisionnel pour cette unité »
Sinon Retour erreur « non inscrit au lieu »
Sinon Retour erreur « non inscrit à l'unité »
------------------------------
Retour :
UpdateScheduleCalendarsResultBean
result : résultat de l'opération : vrai si aucune erreur, faux si une ou plusieurs erreurs rencontrées avec la liste des mises à jour qui n'ont pas été effectuées</wsdl:documentation>
<wsdl:input message="tns:updateScheduleCalendars" name="updateScheduleCalendars">
</wsdl:input>
<wsdl:output message="tns:updateScheduleCalendarsResponse" name="updateScheduleCalendarsResponse">
</wsdl:output>
<wsdl:fault message="tns:MaelisActivityException" name="MaelisActivityException">
</wsdl:fault>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="ActivityServiceSoapBinding" type="tns:ActivityService">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="updateRealCalendars">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="updateRealCalendars">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="updateRealCalendarsResponse">
<soap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="MaelisActivityException">
<soap:fault name="MaelisActivityException" use="literal"/>
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="getNbAvailablePlacesPortalOther">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="getNbAvailablePlacesPortalOther">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="getNbAvailablePlacesPortalOtherResponse">
<soap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="MaelisActivityException">
<soap:fault name="MaelisActivityException" use="literal"/>
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="isWSRunning">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="isWSRunning">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="isWSRunningResponse">
<soap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="MaelisActivityException">
<soap:fault name="MaelisActivityException" use="literal"/>
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="updateWeekCalendar">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="updateWeekCalendar">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="updateWeekCalendarResponse">
<soap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="MaelisActivityException">
<soap:fault name="MaelisActivityException" use="literal"/>
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="readActivityList">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="readActivityList">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="readActivityListResponse">
<soap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="MaelisActivityException">
<soap:fault name="MaelisActivityException" use="literal"/>
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="readChildMonthPlanning">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="readChildMonthPlanning">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="readChildMonthPlanningResponse">
<soap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="MaelisActivityException">
<soap:fault name="MaelisActivityException" use="literal"/>
</wsdl:fault>
<wsdl:fault name="MaelisSiteException">
<soap:fault name="MaelisSiteException" use="literal"/>
</wsdl:fault>
<wsdl:fault name="MaelisFamilyException">
<soap:fault name="MaelisFamilyException" use="literal"/>
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="updateScheduleCalendars">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="updateScheduleCalendars">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="updateScheduleCalendarsResponse">
<soap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="MaelisActivityException">
<soap:fault name="MaelisActivityException" use="literal"/>
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="ActivityService">
<wsdl:port binding="tns:ActivityServiceSoapBinding" name="ActivityServiceImplPort">
<soap:address location="https://demo-toulouse.sigec.fr/maelisws-toulouse/services/ActivityService"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,9 @@
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode xmlns:ns1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">ns1:FailedAuthentication</faultcode>
<faultstring>The security token could not be authenticated or authorized</faultstring>
</soap:Fault>
</soap:Body>
</soap:Envelope>

View File

@ -0,0 +1,8 @@
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:isWSRunningResponse xmlns:ns2="family.ws.maelis.sigec.com">
<isWSRunning>%s</isWSRunning>
</ns2:isWSRunningResponse>
</soap:Body>
</soap:Envelope>

View File

@ -0,0 +1,91 @@
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:readFamilyResponse xmlns:ns2="family.ws.maelis.sigec.com">
<familyResult>
<number>196514</number>
<category>BI</category>
<situation>M</situation>
<nbChild>2</nbChild>
<nbTotalChild>2</nbTotalChild>
<RL1>
<num>613878</num>
<lastname>COSTANZE</lastname>
<firstname>DAMIEN</firstname>
<quality>PERE</quality>
<civility>M.</civility>
<dateBirth>1980-10-07T00:00:00+01:00</dateBirth>
<adresse>
<idStreet>AV0044</idStreet>
<num>9</num>
<street1>AVENUE VALDILETTA</street1>
<street2>LES MANDARINIERS</street2>
<town>NICE</town>
<zipcode>06100</zipcode>
</adresse>
<contact>
<phone>0664107085</phone>
<mobile>0637957391</mobile>
<mail>petro.costache@yahoo.com</mail>
<isContactMail>true</isContactMail>
<isContactSms>true</isContactSms>
<isInvoicePdf>true</isInvoicePdf>
</contact>
<CAFInfo>
<number>51</number>
</CAFInfo>
</RL1>
<RL2>
<num>613879</num>
<lastname>COSTANZE</lastname>
<firstname>JENNIFER</firstname>
<quality>MERE</quality>
<civility>MME</civility>
<dateBirth>1987-05-21T00:00:00+02:00</dateBirth>
<adresse>
<idStreet>AV0044</idStreet>
<num>9</num>
<street1>AVENUE VALDILETTA</street1>
<street2>LES MANDARINIERS</street2>
<town>NICE</town>
<zipcode>06100</zipcode>
</adresse>
<contact>
<isContactMail>false</isContactMail>
<isContactSms>false</isContactSms>
<isInvoicePdf>false</isInvoicePdf>
</contact>
<CAFInfo>
<number>51</number>
</CAFInfo>
</RL2>
<childList>
<num>613880</num>
<lastname>COSTANZE</lastname>
<firstname>CASSANDRA</firstname>
<sexe>F</sexe>
<birth>
<dateBirth>2021-06-22T00:00:00+02:00</dateBirth>
</birth>
<dietcode>STD</dietcode>
<bPhoto>false</bPhoto>
<bLeaveAlone>false</bLeaveAlone>
<paiInfoBean/>
</childList>
<childList>
<num>613881</num>
<lastname>COSTANZE</lastname>
<firstname>ALESSANDRO</firstname>
<sexe>M</sexe>
<birth>
<dateBirth>2015-02-17T00:00:00+01:00</dateBirth>
</birth>
<dietcode>STD</dietcode>
<bPhoto>false</bPhoto>
<bLeaveAlone>false</bLeaveAlone>
<paiInfoBean/>
</childList>
</familyResult>
</ns2:readFamilyResponse>
</soap:Body>
</soap:Envelope>

View File

@ -40,6 +40,7 @@ INSTALLED_APPS += ( # noqa pylint: disable=undefined-variable
'passerelle.contrib.tcl',
'passerelle.contrib.toulouse_axel',
'passerelle.contrib.toulouse_foederis',
'passerelle.contrib.toulouse_maelis',
'passerelle.contrib.toulouse_smart',
'passerelle.contrib.lille_kimoce',
)

View File

@ -0,0 +1,207 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2022 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# 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/>.
import os
import mock
import pytest
from requests.exceptions import ConnectionError
from passerelle.contrib.toulouse_maelis.models import Link, ToulouseMaelis
from passerelle.utils.jsonresponse import APIError
from passerelle.utils.soap import SOAPError
from tests.utils import FakedResponse, generic_endpoint_url, setup_access_rights
TEST_BASE_DIR = os.path.join(os.path.dirname(__file__), 'data', 'toulouse_maelis')
def get_xml_file(filename):
with open(os.path.join(TEST_BASE_DIR, filename), 'rb') as desc:
return desc.read()
CONNECTION_ERROR = ConnectionError('No address associated with hostname')
FAMILY_SERVICE_WSDL = FakedResponse(content=get_xml_file('FamilyService.wsdl'), status_code=200)
ACTIVITY_SERVICE_WSDL = FakedResponse(content=get_xml_file('ActivityService.wsdl'), status_code=200)
FAILED_AUTH = FakedResponse(content=get_xml_file('R_failed_authentication.xml'), status_code=500)
ISWSRUNNING_TRUE = FakedResponse(content=get_xml_file('R_is_ws_running.xml') % b'true', status_code=200)
ISWSRUNNING_FALSE = FakedResponse(content=get_xml_file('R_is_ws_running.xml') % b'false', status_code=200)
READ_FAMILY = FakedResponse(content=get_xml_file('R_read_family.xml'), status_code=200)
def get_endpoint(name):
url = generic_endpoint_url('toulouse-maelis', name)
assert url == '/toulouse-maelis/test/%s' % name
return url
@pytest.fixture
def con(db):
return setup_access_rights(
ToulouseMaelis.objects.create(
slug='test',
zeep_wsse_username='maelis-webservice',
zeep_wsse_password='maelis-password',
)
)
@mock.patch('passerelle.utils.Request.get')
def test_call_with_wrong_wsdl_url(mocked_get, con):
mocked_get.side_effect = CONNECTION_ERROR
with pytest.raises(
SOAPError,
match='cannot be loaded: No address associated with hostname',
) as e:
con.call('Family', 'isWSRunning')
assert e.value.err == 1
assert e.value.http_status == 200
assert e.value.url == 'https://demo-toulouse.sigec.fr/maelisws-toulouse/services/FamilyService?wsdl'
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_call_with_wrong_credentials(mocked_post, mocked_get, con):
mocked_get.side_effect = [FAMILY_SERVICE_WSDL]
mocked_post.side_effect = [FAILED_AUTH]
with pytest.raises(
APIError,
match='The security token could not be authenticated or authorized',
) as e:
con.call('Family', 'isWSRunning')
assert e.value.__dict__ == {
'err': 1,
'log_error': False,
'http_status': 200,
'err_code': 'Family-isWSRunning-ns1:FailedAuthentication',
}
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_call(mocked_post, mocked_get, con):
mocked_get.side_effect = [FAMILY_SERVICE_WSDL]
mocked_post.side_effect = [ISWSRUNNING_TRUE]
resp = con.call('Family', 'isWSRunning')
assert resp is True
@pytest.mark.parametrize(
'get_responses, post_responses, exception',
[
([FAMILY_SERVICE_WSDL, ACTIVITY_SERVICE_WSDL], [ISWSRUNNING_TRUE, ISWSRUNNING_TRUE], None),
([FAMILY_SERVICE_WSDL, CONNECTION_ERROR], [ISWSRUNNING_TRUE, ISWSRUNNING_TRUE], SOAPError),
([FAMILY_SERVICE_WSDL, ACTIVITY_SERVICE_WSDL], [ISWSRUNNING_TRUE, FAILED_AUTH], APIError),
([FAMILY_SERVICE_WSDL, ACTIVITY_SERVICE_WSDL], [ISWSRUNNING_TRUE, ISWSRUNNING_FALSE], AssertionError),
],
)
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_check_status(mocked_post, mocked_get, get_responses, post_responses, exception, con):
mocked_get.side_effect = get_responses
mocked_post.side_effect = post_responses
if exception:
with pytest.raises(Exception):
con.check_status()
else:
con.check_status()
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_link(mocked_post, mocked_get, con, app):
mocked_get.return_value = FAMILY_SERVICE_WSDL
mocked_post.return_value = READ_FAMILY
url = get_endpoint('link')
assert Link.objects.count() == 0
params = {
'family_id': '1312',
'firstname': 'Damien',
'lastname': 'Costanze',
'dateBirth': '1980-10-07',
}
resp = app.post_json(url + '?NameID=local', params=params)
assert Link.objects.count() == 1
assert resp.json['err'] == 0
assert resp.json['data'] == 'ok'
params['lastname'] = 'John'
resp = app.post_json(url + '?NameID=local', params=params)
assert Link.objects.count() == 1
assert resp.json['err'] == 'not-found'
assert resp.json['err_desc'] == "RL1 does not match '1312' family"
def test_unlink(con, app):
url = get_endpoint('unlink')
Link.objects.create(resource=con, family_id='1312', name_id='local')
resp = app.post_json(url + '?NameID=local')
assert Link.objects.count() == 0
assert resp.json['err'] == 0
assert resp.json['data'] == 'ok'
resp = app.post_json(url + '?NameID=local')
assert resp.json['err'] == 'not-linked'
assert resp.json['err_desc'] == 'User not linked to family'
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_read_family(mocked_post, mocked_get, con, app):
mocked_get.return_value = FAMILY_SERVICE_WSDL
mocked_post.side_effect = [READ_FAMILY]
url = get_endpoint('read-family')
Link.objects.create(resource=con, family_id='1312', name_id='local')
resp = app.get(url + '?NameID=local')
assert resp.json['err'] == 0
assert resp.json['data']['RL1'] == {
'num': '613878',
'lastname': 'COSTANZE',
'firstname': 'DAMIEN',
'quality': 'PERE',
'civility': 'M.',
'dateBirth': '1980-10-07T00:00:00+01:00',
'adresse': {
'idStreet': 'AV0044',
'num': 9,
'numComp': None,
'street1': 'AVENUE VALDILETTA',
'street2': 'LES MANDARINIERS',
'town': 'NICE',
'zipcode': '06100',
},
'contact': {
'phone': '0664107085',
'mobile': '0637957391',
'mail': 'petro.costache@yahoo.com',
'isContactMail': True,
'isContactSms': True,
'isInvoicePdf': True,
},
'profession': None,
'CAFInfo': {'number': '51', 'organ': None},
}
def test_read_family_not_linked_error(con, app):
url = get_endpoint('read-family')
resp = app.get(url + '?NameID=')
assert resp.json['err'] == 'not-linked'
assert resp.json['err_desc'] == 'User not linked to family'