caluire-axel: code factorization (#53704)
This commit is contained in:
parent
59186c7cf9
commit
183e7700eb
|
@ -32,7 +32,7 @@ from passerelle.utils.api import endpoint
|
|||
from passerelle.utils.jsonresponse import APIError
|
||||
from . import schemas
|
||||
from . import utils
|
||||
from .exceptions import AxelError
|
||||
from passerelle.contrib.utils import axel
|
||||
|
||||
logger = logging.getLogger('passerelle.contrib.toulouse_axel')
|
||||
|
||||
|
@ -120,7 +120,7 @@ class ToulouseAxel(BaseResource):
|
|||
|
||||
try:
|
||||
result = schemas.ref_date_gestion_dui(self)
|
||||
except AxelError as e:
|
||||
except axel.AxelError as e:
|
||||
raise APIError(
|
||||
'Axel error: %s' % e,
|
||||
err_code='error',
|
||||
|
@ -141,7 +141,7 @@ class ToulouseAxel(BaseResource):
|
|||
def check_dui(self, post_data):
|
||||
try:
|
||||
result = schemas.ref_verif_dui(self, {'PORTAIL': {'DUI': post_data}})
|
||||
except AxelError as e:
|
||||
except axel.AxelError as e:
|
||||
raise APIError(
|
||||
'Axel error: %s' % e,
|
||||
err_code='error',
|
||||
|
@ -292,7 +292,7 @@ class ToulouseAxel(BaseResource):
|
|||
def get_family_data(self, dui, check_registrations=False, with_management_dates=False):
|
||||
try:
|
||||
result = schemas.ref_famille_dui(self, {'PORTAIL': {'DUI': {'IDDUI': dui}}})
|
||||
except AxelError as e:
|
||||
except axel.AxelError as e:
|
||||
raise APIError(
|
||||
'Axel error: %s' % e,
|
||||
err_code='error',
|
||||
|
@ -452,7 +452,7 @@ class ToulouseAxel(BaseResource):
|
|||
flags = sorted(schemas.UPDATE_FAMILY_FLAGS.keys())
|
||||
for flag in flags:
|
||||
flag_value = post_data.get(flag)
|
||||
flag_value = utils.encode_bool(flag_value)
|
||||
flag_value = axel.encode_bool(flag_value)
|
||||
|
||||
# no update for the related block
|
||||
if flag_value == 'OUI':
|
||||
|
@ -579,7 +579,7 @@ class ToulouseAxel(BaseResource):
|
|||
# transform ALLERGIE block
|
||||
new_allergie = []
|
||||
for key in ['ASTHME', 'MEDICAMENTEUSES', 'ALIMENTAIRES']:
|
||||
if utils.encode_bool(child['SANITAIRE']['ALLERGIE'][key]) == 'OUI':
|
||||
if axel.encode_bool(child['SANITAIRE']['ALLERGIE'][key]) == 'OUI':
|
||||
new_allergie.append(
|
||||
{
|
||||
'TYPE': key,
|
||||
|
@ -642,7 +642,7 @@ class ToulouseAxel(BaseResource):
|
|||
|
||||
# prepare data
|
||||
post_data['IDDUI'] = link.dui
|
||||
post_data['DATEDEMANDE'] = datetime.date.today().strftime(utils.json_date_format)
|
||||
post_data['DATEDEMANDE'] = datetime.date.today().strftime(axel.json_date_format)
|
||||
|
||||
self.sanitize_update_family_data(dui=link.dui, post_data=post_data)
|
||||
|
||||
|
@ -653,7 +653,7 @@ class ToulouseAxel(BaseResource):
|
|||
|
||||
try:
|
||||
result = schemas.form_maj_famille_dui(self, {'PORTAIL': {'DUI': post_data}})
|
||||
except AxelError as e:
|
||||
except axel.AxelError as e:
|
||||
raise APIError(
|
||||
'Axel error: %s' % e,
|
||||
err_code='error',
|
||||
|
@ -680,7 +680,7 @@ class ToulouseAxel(BaseResource):
|
|||
|
||||
try:
|
||||
result = schemas.ref_facture_a_payer(self, {'PORTAIL': {'DUI': {'IDDUI': dui}}})
|
||||
except AxelError as e:
|
||||
except axel.AxelError as e:
|
||||
raise APIError(
|
||||
'Axel error: %s' % e,
|
||||
err_code='error',
|
||||
|
@ -701,7 +701,7 @@ class ToulouseAxel(BaseResource):
|
|||
result = schemas.list_dui_factures(
|
||||
self, {'LISTFACTURE': {'NUMDUI': link.dui, 'DEBUT': '1970-01-01'}}
|
||||
)
|
||||
except AxelError as e:
|
||||
except axel.AxelError as e:
|
||||
raise APIError(
|
||||
'Axel error: %s' % e,
|
||||
err_code='error',
|
||||
|
@ -829,7 +829,7 @@ class ToulouseAxel(BaseResource):
|
|||
result = schemas.ref_facture_pdf(
|
||||
self, {'PORTAIL': {'FACTUREPDF': {'IDFACTURE': int(invoice['display_id'])}}}
|
||||
)
|
||||
except AxelError as e:
|
||||
except axel.AxelError as e:
|
||||
raise APIError(
|
||||
'Axel error: %s' % e,
|
||||
err_code='error',
|
||||
|
@ -876,10 +876,10 @@ class ToulouseAxel(BaseResource):
|
|||
|
||||
transaction_amount = invoice['amount']
|
||||
transaction_id = data['transaction_id']
|
||||
transaction_date = utils.parse_datetime(data['transaction_date'])
|
||||
transaction_date = axel.parse_datetime(data['transaction_date'])
|
||||
if transaction_date is None:
|
||||
raise APIError('invalid transaction_date')
|
||||
transaction_date = utils.encode_datetime(transaction_date)
|
||||
transaction_date = axel.encode_datetime(transaction_date)
|
||||
post_data = {
|
||||
'IDFACTURE': int(invoice_id),
|
||||
'IDREGIEENCAISSEMENT': '',
|
||||
|
@ -889,7 +889,7 @@ class ToulouseAxel(BaseResource):
|
|||
}
|
||||
try:
|
||||
schemas.form_paiement_dui(self, {'PORTAIL': {'DUI': post_data}})
|
||||
except AxelError as e:
|
||||
except axel.AxelError as e:
|
||||
raise APIError(
|
||||
'Axel error: %s' % e,
|
||||
err_code='error',
|
||||
|
@ -913,7 +913,7 @@ class ToulouseAxel(BaseResource):
|
|||
}
|
||||
},
|
||||
)
|
||||
except AxelError as e:
|
||||
except axel.AxelError as e:
|
||||
raise APIError(
|
||||
'Axel error: %s' % e,
|
||||
err_code='error',
|
||||
|
@ -993,8 +993,8 @@ class ToulouseAxel(BaseResource):
|
|||
{
|
||||
'IDACTIVITE': activity_id,
|
||||
'ANNEEREFERENCE': str(reference_year),
|
||||
'DATEDEBUT': start_date.strftime(utils.json_date_format),
|
||||
'DATEDFIN': end_date.strftime(utils.json_date_format),
|
||||
'DATEDEBUT': start_date.strftime(axel.json_date_format),
|
||||
'DATEDFIN': end_date.strftime(axel.json_date_format),
|
||||
}
|
||||
)
|
||||
try:
|
||||
|
@ -1012,7 +1012,7 @@ class ToulouseAxel(BaseResource):
|
|||
}
|
||||
},
|
||||
)
|
||||
except AxelError as e:
|
||||
except axel.AxelError as e:
|
||||
raise APIError(
|
||||
'Axel error: %s' % e,
|
||||
err_code='error',
|
||||
|
@ -1044,12 +1044,12 @@ class ToulouseAxel(BaseResource):
|
|||
|
||||
for activity in child_activities.get('ACTIVITE', []):
|
||||
activity['id'] = activity['IDACTIVITE']
|
||||
start_date = datetime.datetime.strptime(activity['DATEENTREE'], utils.json_date_format)
|
||||
end_date = datetime.datetime.strptime(activity['DATESORTIE'], utils.json_date_format)
|
||||
start_date = datetime.datetime.strptime(activity['DATEENTREE'], axel.json_date_format)
|
||||
end_date = datetime.datetime.strptime(activity['DATESORTIE'], axel.json_date_format)
|
||||
activity['text'] = u'{} (inscription du {} au {})'.format(
|
||||
activity['LIBELLEACTIVITE'],
|
||||
start_date.strftime(utils.xml_date_format),
|
||||
end_date.strftime(utils.xml_date_format),
|
||||
start_date.strftime(axel.xml_date_format),
|
||||
end_date.strftime(axel.xml_date_format),
|
||||
)
|
||||
activity['annee_reference'] = reference_year
|
||||
activity['annee_reference_short'] = str(reference_year)[2:]
|
||||
|
@ -1080,7 +1080,7 @@ class ToulouseAxel(BaseResource):
|
|||
# get pivot date
|
||||
try:
|
||||
pivot_date = datetime.datetime.strptime(
|
||||
'%s-%s' % (reference_year, pivot_date), utils.json_date_format
|
||||
'%s-%s' % (reference_year, pivot_date), axel.json_date_format
|
||||
).date()
|
||||
except ValueError:
|
||||
raise APIError('bad date format, should be MM-DD', err_code='bad-request', http_status=400)
|
||||
|
@ -1094,7 +1094,7 @@ class ToulouseAxel(BaseResource):
|
|||
'id': str(reference_year),
|
||||
'text': '%s/%s' % (reference_year, reference_year + 1),
|
||||
'type': 'encours',
|
||||
'refdate': today.strftime(utils.json_date_format),
|
||||
'refdate': today.strftime(axel.json_date_format),
|
||||
}
|
||||
]
|
||||
if today < pivot_date:
|
||||
|
@ -1115,7 +1115,7 @@ class ToulouseAxel(BaseResource):
|
|||
'id': str(reference_year + 1),
|
||||
'text': '%s/%s' % (reference_year + 1, reference_year + 2),
|
||||
'type': 'suivante',
|
||||
'refdate': next_ref_date.strftime(utils.json_date_format),
|
||||
'refdate': next_ref_date.strftime(axel.json_date_format),
|
||||
}
|
||||
)
|
||||
return {'data': data}
|
||||
|
@ -1133,7 +1133,7 @@ class ToulouseAxel(BaseResource):
|
|||
def clae_children_activities_info(self, request, NameID, booking_date):
|
||||
link = self.get_link(NameID)
|
||||
try:
|
||||
booking_date = datetime.datetime.strptime(booking_date, utils.json_date_format)
|
||||
booking_date = datetime.datetime.strptime(booking_date, axel.json_date_format)
|
||||
except ValueError:
|
||||
raise APIError('bad date format, should be YYYY-MM-DD', err_code='bad-request', http_status=400)
|
||||
|
||||
|
@ -1159,8 +1159,8 @@ class ToulouseAxel(BaseResource):
|
|||
def clae_booking_activities_info(self, request, NameID, idpersonne, start_date, end_date):
|
||||
link = self.get_link(NameID)
|
||||
try:
|
||||
start_date = datetime.datetime.strptime(start_date, utils.json_date_format).date()
|
||||
end_date = datetime.datetime.strptime(end_date, utils.json_date_format).date()
|
||||
start_date = datetime.datetime.strptime(start_date, axel.json_date_format).date()
|
||||
end_date = datetime.datetime.strptime(end_date, axel.json_date_format).date()
|
||||
except ValueError:
|
||||
raise APIError('bad date format, should be YYYY-MM-DD', err_code='bad-request', http_status=400)
|
||||
|
||||
|
@ -1174,8 +1174,8 @@ class ToulouseAxel(BaseResource):
|
|||
booking_data = {d['TYPEACTIVITE']: d for d in booking_data}
|
||||
start_date, end_date = utils.get_week_dates_from_date(week_start_date)
|
||||
week = 'week:%s:%s' % (
|
||||
start_date.strftime(utils.json_date_format),
|
||||
end_date.strftime(utils.json_date_format),
|
||||
start_date.strftime(axel.json_date_format),
|
||||
end_date.strftime(axel.json_date_format),
|
||||
)
|
||||
day_date = week_start_date
|
||||
while day_date <= week_end_date:
|
||||
|
@ -1187,7 +1187,7 @@ class ToulouseAxel(BaseResource):
|
|||
booked = activity['booking']['days'][day]
|
||||
if booked is not None:
|
||||
yield {
|
||||
'day': day_date.strftime(utils.json_date_format),
|
||||
'day': day_date.strftime(axel.json_date_format),
|
||||
'activity_id': activity['id'],
|
||||
'activity_type': activity_type,
|
||||
'activity_label': activity['LIBELLEACTIVITE'],
|
||||
|
@ -1218,8 +1218,8 @@ class ToulouseAxel(BaseResource):
|
|||
entree_dates = [act['DATEENTREE'] for act in child_activities.get('ACTIVITE', [])]
|
||||
sortie_dates = [act['DATESORTIE'] for act in child_activities.get('ACTIVITE', [])]
|
||||
return (
|
||||
datetime.datetime.strptime(max(entree_dates), utils.json_date_format).date(),
|
||||
datetime.datetime.strptime(min(sortie_dates), utils.json_date_format).date(),
|
||||
datetime.datetime.strptime(max(entree_dates), axel.json_date_format).date(),
|
||||
datetime.datetime.strptime(min(sortie_dates), axel.json_date_format).date(),
|
||||
)
|
||||
|
||||
@endpoint(
|
||||
|
@ -1240,8 +1240,8 @@ class ToulouseAxel(BaseResource):
|
|||
):
|
||||
link = self.get_link(NameID)
|
||||
try:
|
||||
start_date = datetime.datetime.strptime(start_date, utils.json_date_format).date()
|
||||
end_date = datetime.datetime.strptime(end_date, utils.json_date_format).date()
|
||||
start_date = datetime.datetime.strptime(start_date, axel.json_date_format).date()
|
||||
end_date = datetime.datetime.strptime(end_date, axel.json_date_format).date()
|
||||
except ValueError:
|
||||
raise APIError('bad date format, should be YYYY-MM-DD', err_code='bad-request', http_status=400)
|
||||
if activity_type not in ['MAT', 'MIDI', 'SOIR', 'GARD']:
|
||||
|
@ -1286,7 +1286,7 @@ class ToulouseAxel(BaseResource):
|
|||
day = WEEKDAYS[day_date.weekday()]
|
||||
activity_day = {
|
||||
'id': '{}:{}:{}:{}'.format(
|
||||
idpersonne, activity_type, activity['id'], day_date.strftime(utils.json_date_format)
|
||||
idpersonne, activity_type, activity['id'], day_date.strftime(axel.json_date_format)
|
||||
),
|
||||
'text': dateformat.format(day_date, 'l j F Y'),
|
||||
'disabled': activity['booking']['days'][day] is None,
|
||||
|
@ -1328,7 +1328,7 @@ class ToulouseAxel(BaseResource):
|
|||
):
|
||||
link = self.get_link(NameID)
|
||||
try:
|
||||
booking_date = datetime.datetime.strptime(booking_date, utils.json_date_format).date()
|
||||
booking_date = datetime.datetime.strptime(booking_date, axel.json_date_format).date()
|
||||
except ValueError:
|
||||
raise APIError('bad date format, should be YYYY-MM-DD', err_code='bad-request', http_status=400)
|
||||
if activity_type not in ['MAT', 'MIDI', 'SOIR', 'GARD']:
|
||||
|
@ -1408,12 +1408,10 @@ class ToulouseAxel(BaseResource):
|
|||
# check dates
|
||||
today = datetime.date.today()
|
||||
start_date_min = today + datetime.timedelta(days=8)
|
||||
start_date = datetime.datetime.strptime(
|
||||
post_data['booking_start_date'], utils.json_date_format
|
||||
).date()
|
||||
start_date = datetime.datetime.strptime(post_data['booking_start_date'], axel.json_date_format).date()
|
||||
reference_year = utils.get_reference_year_from_date(start_date)
|
||||
end_date_max = datetime.date(reference_year + 1, 7, 31)
|
||||
end_date = datetime.datetime.strptime(post_data['booking_end_date'], utils.json_date_format).date()
|
||||
end_date = datetime.datetime.strptime(post_data['booking_end_date'], axel.json_date_format).date()
|
||||
if start_date > end_date:
|
||||
raise APIError(
|
||||
'booking_start_date should be before booking_end_date',
|
||||
|
@ -1461,7 +1459,7 @@ class ToulouseAxel(BaseResource):
|
|||
post_data['child_id'],
|
||||
activity_type,
|
||||
activity_id,
|
||||
day_date.strftime(utils.json_date_format),
|
||||
day_date.strftime(axel.json_date_format),
|
||||
)
|
||||
if key in post_data['booking_list_%s' % activity_type]:
|
||||
week_pattern = (
|
||||
|
@ -1483,8 +1481,8 @@ class ToulouseAxel(BaseResource):
|
|||
week_pattern = get_week_pattern(real_start_date, real_end_date, activity_type, activity_id)
|
||||
activity['PERIODE'].append(
|
||||
{
|
||||
'DATEDEBUT': real_start_date.strftime(utils.json_date_format),
|
||||
'DATEDFIN': real_end_date.strftime(utils.json_date_format),
|
||||
'DATEDEBUT': real_start_date.strftime(axel.json_date_format),
|
||||
'DATEDFIN': real_end_date.strftime(axel.json_date_format),
|
||||
'SEMAINETYPE': week_pattern,
|
||||
}
|
||||
)
|
||||
|
@ -1494,7 +1492,7 @@ class ToulouseAxel(BaseResource):
|
|||
# build data
|
||||
data = {
|
||||
'IDDUI': link.dui,
|
||||
'DATEDEMANDE': today.strftime(utils.json_date_format),
|
||||
'DATEDEMANDE': today.strftime(axel.json_date_format),
|
||||
'ENFANT': [
|
||||
{
|
||||
'IDPERSONNE': post_data['child_id'],
|
||||
|
@ -1510,7 +1508,7 @@ class ToulouseAxel(BaseResource):
|
|||
|
||||
try:
|
||||
result = schemas.reservation_annuelle(self, {'PORTAIL': {'DUI': data}})
|
||||
except AxelError as e:
|
||||
except axel.AxelError as e:
|
||||
raise APIError(
|
||||
'Axel error: %s' % e,
|
||||
err_code='error',
|
||||
|
@ -1562,7 +1560,7 @@ class ToulouseAxel(BaseResource):
|
|||
# build dates of the period
|
||||
today = datetime.date.today()
|
||||
start_date_min = today + datetime.timedelta(days=8)
|
||||
start_date = datetime.datetime.strptime(post_data['booking_date'], utils.json_date_format).date()
|
||||
start_date = datetime.datetime.strptime(post_data['booking_date'], axel.json_date_format).date()
|
||||
start_date = max(start_date, start_date_min)
|
||||
reference_year = utils.get_reference_year_from_date(start_date)
|
||||
end_date = datetime.date(reference_year + 1, 7, 31)
|
||||
|
@ -1593,8 +1591,8 @@ class ToulouseAxel(BaseResource):
|
|||
'ANNEEREFERENCE': str(reference_year),
|
||||
'PERIODE': [
|
||||
{
|
||||
'DATEDEBUT': start_date.strftime(utils.json_date_format),
|
||||
'DATEDFIN': end_date.strftime(utils.json_date_format),
|
||||
'DATEDEBUT': start_date.strftime(axel.json_date_format),
|
||||
'DATEDFIN': end_date.strftime(axel.json_date_format),
|
||||
'SEMAINETYPE': week_pattern,
|
||||
}
|
||||
],
|
||||
|
@ -1603,7 +1601,7 @@ class ToulouseAxel(BaseResource):
|
|||
# build data
|
||||
data = {
|
||||
'IDDUI': link.dui,
|
||||
'DATEDEMANDE': today.strftime(utils.json_date_format),
|
||||
'DATEDEMANDE': today.strftime(axel.json_date_format),
|
||||
'ENFANT': [
|
||||
{
|
||||
'IDPERSONNE': post_data['child_id'],
|
||||
|
@ -1619,7 +1617,7 @@ class ToulouseAxel(BaseResource):
|
|||
|
||||
try:
|
||||
result = schemas.reservation_annuelle(self, {'PORTAIL': {'DUI': data}})
|
||||
except AxelError as e:
|
||||
except axel.AxelError as e:
|
||||
raise APIError(
|
||||
'Axel error: %s' % e,
|
||||
err_code='error',
|
||||
|
|
|
@ -15,156 +15,16 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import copy
|
||||
import datetime
|
||||
import os
|
||||
import re
|
||||
import xml.etree.ElementTree as ET
|
||||
from collections import namedtuple
|
||||
|
||||
from django.utils.encoding import force_text
|
||||
|
||||
import xmlschema
|
||||
|
||||
from passerelle.utils.xml import JSONSchemaFromXMLSchema
|
||||
from . import utils
|
||||
from .exceptions import AxelError
|
||||
from passerelle.contrib.utils import axel
|
||||
|
||||
BASE_XSD_PATH = os.path.join(os.path.dirname(__file__), 'xsd')
|
||||
|
||||
|
||||
class AxelSchema(JSONSchemaFromXMLSchema):
|
||||
type_map = {
|
||||
'{urn:AllAxelTypes}DATEREQUIREDType': 'date',
|
||||
'{urn:AllAxelTypes}DATEType': 'date_optional',
|
||||
'{urn:AllAxelTypes}OUINONREQUIREDType': 'bool',
|
||||
'{urn:AllAxelTypes}OUINONType': 'bool_optional',
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def schema_date(cls):
|
||||
return {
|
||||
'type': 'string',
|
||||
'pattern': '[0-9]{4}-[0-9]{2}-[0-9]{2}',
|
||||
}
|
||||
|
||||
def encode_date(self, obj):
|
||||
try:
|
||||
return datetime.datetime.strptime(obj, utils.json_date_format).strftime(utils.xml_date_format)
|
||||
except ValueError:
|
||||
return obj
|
||||
|
||||
def encode_date_optional(self, obj):
|
||||
if not obj:
|
||||
return obj
|
||||
return self.encode_date(obj)
|
||||
|
||||
def decode_date(self, data):
|
||||
value = datetime.datetime.strptime(data.text, utils.xml_date_format).strftime(utils.json_date_format)
|
||||
return xmlschema.ElementData(
|
||||
tag=data.tag, text=value, content=data.content, attributes=data.attributes
|
||||
)
|
||||
|
||||
def decode_date_optional(self, data):
|
||||
if not data.text:
|
||||
return data
|
||||
return self.decode_date(data)
|
||||
|
||||
@classmethod
|
||||
def schema_bool(cls):
|
||||
return copy.deepcopy(utils.boolean_type)
|
||||
|
||||
def encode_bool(self, obj):
|
||||
return utils.encode_bool(obj)
|
||||
|
||||
def decode_bool(self, data):
|
||||
value = False
|
||||
if data.text.lower() == 'oui':
|
||||
value = True
|
||||
return xmlschema.ElementData(
|
||||
tag=data.tag, text=value, content=data.content, attributes=data.attributes
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def schema_bool_optional(cls):
|
||||
schema_bool_optional = cls.schema_bool()
|
||||
schema_bool_optional['oneOf'].append({'type': 'string', 'enum': ['']})
|
||||
return schema_bool_optional
|
||||
|
||||
def encode_bool_optional(self, obj):
|
||||
return self.encode_bool(obj)
|
||||
|
||||
def decode_bool_optional(self, data):
|
||||
if not data.text:
|
||||
return data
|
||||
return self.decode_bool(data)
|
||||
|
||||
|
||||
def xml_schema_converter(name, root_element):
|
||||
xsd_path = os.path.join(BASE_XSD_PATH, name)
|
||||
if not os.path.exists(xsd_path):
|
||||
return None
|
||||
return AxelSchema(xsd_path, root_element)
|
||||
|
||||
|
||||
OperationResult = namedtuple('OperationResult', ['json_response', 'xml_request', 'xml_response'])
|
||||
|
||||
|
||||
class Operation(object):
|
||||
def __init__(self, operation, prefix='Dui/', request_root_element='PORTAIL'):
|
||||
self.operation = operation
|
||||
self.request_converter = xml_schema_converter(
|
||||
'%sQ_%s.xsd' % (prefix, operation), request_root_element
|
||||
)
|
||||
self.response_converter = xml_schema_converter('%sR_%s.xsd' % (prefix, operation), 'PORTAILSERVICE')
|
||||
self.name = re.sub(
|
||||
'(.?)([A-Z])', lambda s: s.group(1) + ('-' if s.group(1) else '') + s.group(2).lower(), operation
|
||||
)
|
||||
self.snake_name = self.name.replace('-', '_')
|
||||
|
||||
@property
|
||||
def request_schema(self):
|
||||
schema = self.request_converter.json_schema
|
||||
schema['flatten'] = True
|
||||
schema['merge_extra'] = True
|
||||
return schema
|
||||
|
||||
def __call__(self, resource, request_data=None):
|
||||
client = resource.soap_client()
|
||||
|
||||
serialized_request = ''
|
||||
if self.request_converter:
|
||||
try:
|
||||
serialized_request = self.request_converter.encode(request_data)
|
||||
except xmlschema.XMLSchemaValidationError as e:
|
||||
raise AxelError('invalid request %s' % str(e))
|
||||
utils.indent(serialized_request)
|
||||
serialized_request = force_text(ET.tostring(serialized_request))
|
||||
try:
|
||||
self.request_converter.xml_schema.validate(serialized_request)
|
||||
except xmlschema.XMLSchemaValidationError as e:
|
||||
raise AxelError('invalid request %s' % str(e), xml_request=serialized_request)
|
||||
|
||||
result = client.service.getData(
|
||||
self.operation, serialized_request, ''
|
||||
) # FIXME: What is the user parameter for ?
|
||||
|
||||
xml_result = ET.fromstring(result.encode('utf-8'))
|
||||
utils.indent(xml_result)
|
||||
pretty_result = force_text(ET.tostring(xml_result))
|
||||
if xml_result.find('RESULTAT/STATUS').text != 'OK':
|
||||
msg = xml_result.find('RESULTAT/COMMENTAIRES').text
|
||||
raise AxelError(msg, xml_request=serialized_request, xml_response=pretty_result)
|
||||
|
||||
try:
|
||||
return OperationResult(
|
||||
json_response=self.response_converter.decode(xml_result),
|
||||
xml_request=serialized_request,
|
||||
xml_response=pretty_result,
|
||||
)
|
||||
except xmlschema.XMLSchemaValidationError as e:
|
||||
raise AxelError(
|
||||
'invalid response %s' % str(e), xml_request=serialized_request, xml_response=pretty_result
|
||||
)
|
||||
class Operation(axel.Operation):
|
||||
base_xsd_path = BASE_XSD_PATH
|
||||
default_prefix = 'Dui/'
|
||||
|
||||
|
||||
ref_date_gestion_dui = Operation('RefDateGestionDui')
|
||||
|
@ -183,7 +43,7 @@ reservation_annuelle = Operation('ReservationAnnuelle')
|
|||
PAYMENT_SCHEMA = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'transaction_date': copy.deepcopy(utils.datetime_type),
|
||||
'transaction_date': copy.deepcopy(axel.datetime_type),
|
||||
'transaction_id': {
|
||||
'type': 'string',
|
||||
},
|
||||
|
@ -229,7 +89,7 @@ UPDATE_FAMILY_SCHEMA = copy.deepcopy(
|
|||
)
|
||||
|
||||
for flag in sorted(UPDATE_FAMILY_FLAGS.keys()):
|
||||
flag_type = copy.deepcopy(utils.boolean_type)
|
||||
flag_type = copy.deepcopy(axel.boolean_type)
|
||||
if flag not in UPDATE_FAMILY_REQUIRED_FLAGS:
|
||||
flag_type['oneOf'].append({'type': 'null'})
|
||||
flag_type['oneOf'].append({'type': 'string', 'enum': ['']})
|
||||
|
@ -283,7 +143,7 @@ sanitaire_properties['ALLERGIE'] = {
|
|||
}
|
||||
sanitaire_required.append('ALLERGIE')
|
||||
for key in ['ASTHME', 'MEDICAMENTEUSES', 'ALIMENTAIRES']:
|
||||
flag_type = copy.deepcopy(utils.boolean_type)
|
||||
flag_type = copy.deepcopy(axel.boolean_type)
|
||||
flag_type['oneOf'].append({'type': 'null'})
|
||||
flag_type['oneOf'].append({'type': 'string', 'enum': ['']})
|
||||
sanitaire_properties['ALLERGIE']['properties'][key] = flag_type
|
||||
|
@ -303,8 +163,8 @@ UPDATE_FAMILY_SCHEMA['unflatten'] = True
|
|||
BOOKING_SCHEMA = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'booking_start_date': copy.deepcopy(utils.date_type),
|
||||
'booking_end_date': copy.deepcopy(utils.date_type),
|
||||
'booking_start_date': copy.deepcopy(axel.date_type),
|
||||
'booking_end_date': copy.deepcopy(axel.date_type),
|
||||
'booking_list_MAT': {
|
||||
'oneOf': [
|
||||
{'type': 'null'},
|
||||
|
@ -429,7 +289,7 @@ ANNUAL_BOOKING_SCHEMA = {
|
|||
'maxLength': 8,
|
||||
},
|
||||
'regime': {'oneOf': [{'type': 'null'}, {'type': 'string', 'enum': ['', 'SV', 'AV']}]},
|
||||
'booking_date': copy.deepcopy(utils.date_type),
|
||||
'booking_date': copy.deepcopy(axel.date_type),
|
||||
},
|
||||
'required': [
|
||||
'booking_list_MAT',
|
||||
|
|
|
@ -19,39 +19,12 @@ from __future__ import unicode_literals
|
|||
|
||||
from collections import OrderedDict
|
||||
import datetime
|
||||
import unicodedata
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
import pytz
|
||||
|
||||
from django.utils.six import string_types
|
||||
|
||||
from passerelle.utils.conversion import normalize
|
||||
|
||||
|
||||
boolean_type = {
|
||||
'oneOf': [
|
||||
{'type': 'boolean'},
|
||||
{
|
||||
'type': 'string',
|
||||
'pattern': '[Oo][Uu][Ii]|[Nn][Oo][Nn]|[Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee]|1|0',
|
||||
},
|
||||
]
|
||||
}
|
||||
date_type = {
|
||||
'type': 'string',
|
||||
'pattern': '[0-9]{4}-[0-9]{2}-[0-9]{2}',
|
||||
}
|
||||
datetime_type = {
|
||||
'type': 'string',
|
||||
'pattern': '[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}',
|
||||
}
|
||||
json_date_format = '%Y-%m-%d'
|
||||
json_datetime_format = '%Y-%m-%dT%H:%M:%S'
|
||||
xml_date_format = '%d/%m/%Y'
|
||||
xml_datetime_format = '%d/%m/%Y %H:%M:%S'
|
||||
|
||||
|
||||
situation_familiale_mapping = OrderedDict(
|
||||
[
|
||||
('C', 'Célibataire'),
|
||||
|
@ -113,63 +86,6 @@ def get_label(mapping, code):
|
|||
return mapping.get(code, code)
|
||||
|
||||
|
||||
def indent(tree, space=" ", level=0):
|
||||
# backport from Lib/xml/etree/ElementTree.py python 3.9
|
||||
if isinstance(tree, ET.ElementTree):
|
||||
tree = tree.getroot()
|
||||
if level < 0:
|
||||
raise ValueError("Initial indentation level must be >= 0, got {level}".format(level))
|
||||
if not len(tree):
|
||||
return
|
||||
|
||||
# Reduce the memory consumption by reusing indentation strings.
|
||||
indentations = ["\n" + level * space]
|
||||
|
||||
def _indent_children(elem, level):
|
||||
# Start a new indentation level for the first child.
|
||||
child_level = level + 1
|
||||
try:
|
||||
child_indentation = indentations[child_level]
|
||||
except IndexError:
|
||||
child_indentation = indentations[level] + space
|
||||
indentations.append(child_indentation)
|
||||
|
||||
if not elem.text or not elem.text.strip():
|
||||
elem.text = child_indentation
|
||||
|
||||
for child in elem:
|
||||
if len(child):
|
||||
_indent_children(child, child_level)
|
||||
if not child.tail or not child.tail.strip():
|
||||
child.tail = child_indentation
|
||||
|
||||
# Dedent after the last child by overwriting the previous indentation.
|
||||
if not child.tail.strip():
|
||||
child.tail = indentations[level]
|
||||
|
||||
_indent_children(tree, 0)
|
||||
|
||||
|
||||
def encode_bool(obj):
|
||||
if obj is True or str(obj).lower() in ['true', 'oui', '1']:
|
||||
return 'OUI'
|
||||
if obj is False or str(obj).lower() in ['false', 'non', '0']:
|
||||
return 'NON'
|
||||
return obj
|
||||
|
||||
|
||||
def parse_datetime(value):
|
||||
try:
|
||||
dt = datetime.datetime.strptime(value, json_datetime_format)
|
||||
except ValueError:
|
||||
return None
|
||||
return pytz.utc.localize(dt)
|
||||
|
||||
|
||||
def encode_datetime(dt):
|
||||
return dt.astimezone(pytz.timezone('Europe/Paris')).strftime(xml_datetime_format)
|
||||
|
||||
|
||||
def upperize(data):
|
||||
if isinstance(data, dict):
|
||||
for key, val in data.items():
|
||||
|
|
|
@ -0,0 +1,264 @@
|
|||
# passerelle - uniform access to multiple data sources and services
|
||||
# Copyright (C) 2021 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 copy
|
||||
import datetime
|
||||
import os
|
||||
import re
|
||||
import xml.etree.ElementTree as ET
|
||||
from collections import namedtuple
|
||||
|
||||
import pytz
|
||||
|
||||
from django.utils.encoding import force_text
|
||||
|
||||
import xmlschema
|
||||
|
||||
from passerelle.utils.xml import JSONSchemaFromXMLSchema
|
||||
|
||||
|
||||
boolean_type = {
|
||||
'oneOf': [
|
||||
{'type': 'boolean'},
|
||||
{
|
||||
'type': 'string',
|
||||
'pattern': '[Oo][Uu][Ii]|[Nn][Oo][Nn]|[Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee]|1|0',
|
||||
},
|
||||
]
|
||||
}
|
||||
date_type = {
|
||||
'type': 'string',
|
||||
'pattern': '[0-9]{4}-[0-9]{2}-[0-9]{2}',
|
||||
}
|
||||
datetime_type = {
|
||||
'type': 'string',
|
||||
'pattern': '[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}',
|
||||
}
|
||||
json_date_format = '%Y-%m-%d'
|
||||
json_datetime_format = '%Y-%m-%dT%H:%M:%S'
|
||||
xml_date_format = '%d/%m/%Y'
|
||||
xml_datetime_format = '%d/%m/%Y %H:%M:%S'
|
||||
|
||||
|
||||
def indent(tree, space=" ", level=0):
|
||||
# backport from Lib/xml/etree/ElementTree.py python 3.9
|
||||
if isinstance(tree, ET.ElementTree):
|
||||
tree = tree.getroot()
|
||||
if level < 0:
|
||||
raise ValueError("Initial indentation level must be >= 0, got {level}".format(level=level))
|
||||
if not len(tree):
|
||||
return
|
||||
|
||||
# Reduce the memory consumption by reusing indentation strings.
|
||||
indentations = ["\n" + level * space]
|
||||
|
||||
def _indent_children(elem, level):
|
||||
# Start a new indentation level for the first child.
|
||||
child_level = level + 1
|
||||
try:
|
||||
child_indentation = indentations[child_level]
|
||||
except IndexError:
|
||||
child_indentation = indentations[level] + space
|
||||
indentations.append(child_indentation)
|
||||
|
||||
if not elem.text or not elem.text.strip():
|
||||
elem.text = child_indentation
|
||||
|
||||
for child in elem:
|
||||
if len(child):
|
||||
_indent_children(child, child_level)
|
||||
if not child.tail or not child.tail.strip():
|
||||
child.tail = child_indentation
|
||||
|
||||
# Dedent after the last child by overwriting the previous indentation.
|
||||
if not child.tail.strip():
|
||||
child.tail = indentations[level]
|
||||
|
||||
_indent_children(tree, 0)
|
||||
|
||||
|
||||
def encode_bool(obj):
|
||||
if obj is True or str(obj).lower() in ['true', 'oui', '1']:
|
||||
return 'OUI'
|
||||
if obj is False or str(obj).lower() in ['false', 'non', '0']:
|
||||
return 'NON'
|
||||
return obj
|
||||
|
||||
|
||||
def parse_datetime(value):
|
||||
try:
|
||||
dt = datetime.datetime.strptime(value, json_datetime_format)
|
||||
except ValueError:
|
||||
return None
|
||||
return pytz.utc.localize(dt)
|
||||
|
||||
|
||||
def encode_datetime(dt):
|
||||
return dt.astimezone(pytz.timezone('Europe/Paris')).strftime(xml_datetime_format)
|
||||
|
||||
|
||||
class AxelError(Exception):
|
||||
def __init__(self, message, xml_request=None, xml_response=None, *args):
|
||||
self.message = message
|
||||
self.xml_request = xml_request
|
||||
self.xml_response = xml_response
|
||||
super(AxelError, self).__init__(message, *args)
|
||||
|
||||
def __str__(self):
|
||||
return self.message
|
||||
|
||||
|
||||
class AxelSchema(JSONSchemaFromXMLSchema):
|
||||
type_map = {
|
||||
'{urn:AllAxelTypes}DATEREQUIREDType': 'date',
|
||||
'{urn:AllAxelTypes}DATEType': 'date_optional',
|
||||
'{urn:AllAxelTypes}OUINONREQUIREDType': 'bool',
|
||||
'{urn:AllAxelTypes}OUINONType': 'bool_optional',
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def schema_date(cls):
|
||||
return {
|
||||
'type': 'string',
|
||||
'pattern': '[0-9]{4}-[0-9]{2}-[0-9]{2}',
|
||||
}
|
||||
|
||||
def encode_date(self, obj):
|
||||
try:
|
||||
return datetime.datetime.strptime(obj, json_date_format).strftime(xml_date_format)
|
||||
except ValueError:
|
||||
return obj
|
||||
|
||||
def encode_date_optional(self, obj):
|
||||
if not obj:
|
||||
return obj
|
||||
return self.encode_date(obj)
|
||||
|
||||
def decode_date(self, data):
|
||||
value = datetime.datetime.strptime(data.text, xml_date_format).strftime(json_date_format)
|
||||
return xmlschema.ElementData(
|
||||
tag=data.tag, text=value, content=data.content, attributes=data.attributes
|
||||
)
|
||||
|
||||
def decode_date_optional(self, data):
|
||||
if not data.text:
|
||||
return data
|
||||
return self.decode_date(data)
|
||||
|
||||
@classmethod
|
||||
def schema_bool(cls):
|
||||
return copy.deepcopy(boolean_type)
|
||||
|
||||
def encode_bool(self, obj):
|
||||
return encode_bool(obj)
|
||||
|
||||
def decode_bool(self, data):
|
||||
value = False
|
||||
if data.text.lower() == 'oui':
|
||||
value = True
|
||||
return xmlschema.ElementData(
|
||||
tag=data.tag, text=value, content=data.content, attributes=data.attributes
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def schema_bool_optional(cls):
|
||||
schema_bool_optional = cls.schema_bool()
|
||||
schema_bool_optional['oneOf'].append({'type': 'string', 'enum': ['']})
|
||||
return schema_bool_optional
|
||||
|
||||
def encode_bool_optional(self, obj):
|
||||
return self.encode_bool(obj)
|
||||
|
||||
def decode_bool_optional(self, data):
|
||||
if not data.text:
|
||||
return data
|
||||
return self.decode_bool(data)
|
||||
|
||||
|
||||
def xml_schema_converter(base_xsd_path, name, root_element):
|
||||
xsd_path = os.path.join(base_xsd_path, name)
|
||||
if not os.path.exists(xsd_path):
|
||||
return None
|
||||
return AxelSchema(xsd_path, root_element)
|
||||
|
||||
|
||||
OperationResult = namedtuple('OperationResult', ['json_response', 'xml_request', 'xml_response'])
|
||||
|
||||
|
||||
class Operation(object):
|
||||
base_xsd_path = None
|
||||
default_prefix = ''
|
||||
|
||||
def __init__(self, operation, prefix=None, request_root_element='PORTAIL'):
|
||||
if prefix is None:
|
||||
prefix = self.default_prefix
|
||||
self.operation = operation
|
||||
self.request_converter = xml_schema_converter(
|
||||
self.base_xsd_path, '%sQ_%s.xsd' % (prefix, operation), request_root_element
|
||||
)
|
||||
self.response_converter = xml_schema_converter(
|
||||
self.base_xsd_path, '%sR_%s.xsd' % (prefix, operation), 'PORTAILSERVICE'
|
||||
)
|
||||
self.name = re.sub(
|
||||
'(.?)([A-Z])', lambda s: s.group(1) + ('-' if s.group(1) else '') + s.group(2).lower(), operation
|
||||
)
|
||||
self.snake_name = self.name.replace('-', '_')
|
||||
|
||||
@property
|
||||
def request_schema(self):
|
||||
schema = self.request_converter.json_schema
|
||||
schema['flatten'] = True
|
||||
schema['merge_extra'] = True
|
||||
return schema
|
||||
|
||||
def __call__(self, resource, request_data=None):
|
||||
client = resource.soap_client()
|
||||
|
||||
serialized_request = ''
|
||||
if self.request_converter:
|
||||
try:
|
||||
serialized_request = self.request_converter.encode(request_data)
|
||||
except xmlschema.XMLSchemaValidationError as e:
|
||||
raise AxelError('invalid request %s' % str(e))
|
||||
indent(serialized_request)
|
||||
serialized_request = force_text(ET.tostring(serialized_request))
|
||||
try:
|
||||
self.request_converter.xml_schema.validate(serialized_request)
|
||||
except xmlschema.XMLSchemaValidationError as e:
|
||||
raise AxelError('invalid request %s' % str(e), xml_request=serialized_request)
|
||||
|
||||
result = client.service.getData(
|
||||
self.operation, serialized_request, ''
|
||||
) # FIXME: What is the user parameter for ?
|
||||
|
||||
xml_result = ET.fromstring(result.encode('utf-8'))
|
||||
indent(xml_result)
|
||||
pretty_result = force_text(ET.tostring(xml_result))
|
||||
if xml_result.find('RESULTAT/STATUS').text != 'OK':
|
||||
msg = xml_result.find('RESULTAT/COMMENTAIRES').text
|
||||
raise AxelError(msg, xml_request=serialized_request, xml_response=pretty_result)
|
||||
|
||||
try:
|
||||
return OperationResult(
|
||||
json_response=self.response_converter.decode(xml_result),
|
||||
xml_request=serialized_request,
|
||||
xml_response=pretty_result,
|
||||
)
|
||||
except xmlschema.XMLSchemaValidationError as e:
|
||||
raise AxelError(
|
||||
'invalid response %s' % str(e), xml_request=serialized_request, xml_response=pretty_result
|
||||
)
|
|
@ -1,5 +1,5 @@
|
|||
# passerelle - uniform access to multiple data sources and services
|
||||
# Copyright (C) 2020 Entr'ouvert
|
||||
# Copyright (C) 2021 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
|
||||
|
@ -14,13 +14,20 @@
|
|||
# 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 passerelle.contrib.utils.axel import (
|
||||
parse_datetime,
|
||||
encode_datetime,
|
||||
)
|
||||
|
||||
class AxelError(Exception):
|
||||
def __init__(self, message, xml_request=None, xml_response=None, *args):
|
||||
self.message = message
|
||||
self.xml_request = xml_request
|
||||
self.xml_response = xml_response
|
||||
super(AxelError, self).__init__(message, *args)
|
||||
|
||||
def __str__(self):
|
||||
return self.message
|
||||
def test_parse_datetime():
|
||||
# wrong format
|
||||
assert parse_datetime('foo') is None
|
||||
assert parse_datetime('2019-12-12') is None
|
||||
assert parse_datetime('2019-12-12T12:01:72') is None
|
||||
# ok
|
||||
assert parse_datetime('2019-12-12T12:01:42').isoformat() == '2019-12-12T12:01:42+00:00'
|
||||
|
||||
|
||||
def test_encode_datetime():
|
||||
assert encode_datetime(parse_datetime('2019-12-12T23:40:42')) == '13/12/2019 00:40:42'
|
|
@ -33,7 +33,6 @@ import pytest
|
|||
import xmlschema
|
||||
import jsonschema
|
||||
|
||||
from passerelle.contrib.toulouse_axel.exceptions import AxelError
|
||||
from passerelle.contrib.toulouse_axel.models import (
|
||||
Link,
|
||||
Lock,
|
||||
|
@ -48,6 +47,8 @@ from passerelle.contrib.toulouse_axel.utils import (
|
|||
regime_mapping,
|
||||
upperize,
|
||||
)
|
||||
from passerelle.contrib.utils.axel import AxelError
|
||||
from passerelle.contrib.utils.axel import OperationResult
|
||||
from passerelle.utils.jsonresponse import APIError
|
||||
from passerelle.utils.soap import SOAPError
|
||||
import utils
|
||||
|
@ -675,7 +676,7 @@ def test_link_endpoint_axel_error(app, resource, link_params):
|
|||
% content
|
||||
)
|
||||
with mock_getdata(content, 'RefVerifDui'):
|
||||
with mock.patch('passerelle.contrib.toulouse_axel.schemas.AxelSchema.decode') as decode:
|
||||
with mock.patch('passerelle.contrib.utils.axel.AxelSchema.decode') as decode:
|
||||
decode.side_effect = xmlschema.XMLSchemaValidationError(None, None)
|
||||
resp = app.post_json('/toulouse-axel/test/link?NameID=yyy', params=link_params)
|
||||
assert resp.json['err_desc'].startswith("Axel error: invalid response")
|
||||
|
@ -1278,7 +1279,7 @@ def test_update_family_info_endpoint(app, resource, update_params, family_data):
|
|||
assert 'xml_response' in resp.json['data']
|
||||
|
||||
with mock.patch('passerelle.contrib.toulouse_axel.schemas.form_maj_famille_dui') as operation:
|
||||
operation.return_value = schemas.OperationResult(json_response={}, xml_request='', xml_response='')
|
||||
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
|
||||
with mock.patch(
|
||||
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data
|
||||
):
|
||||
|
@ -1292,7 +1293,7 @@ def test_update_family_info_endpoint(app, resource, update_params, family_data):
|
|||
link.person_id = '35'
|
||||
link.save()
|
||||
with mock.patch('passerelle.contrib.toulouse_axel.schemas.form_maj_famille_dui') as operation:
|
||||
operation.return_value = schemas.OperationResult(json_response={}, xml_request='', xml_response='')
|
||||
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
|
||||
with mock.patch(
|
||||
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_family_data', return_value=family_data
|
||||
):
|
||||
|
@ -2735,9 +2736,7 @@ def test_clae_children_activities_info_check(app, resource, activities, expected
|
|||
}
|
||||
}
|
||||
with mock.patch('passerelle.contrib.toulouse_axel.schemas.enfants_activites') as operation:
|
||||
operation.return_value = schemas.OperationResult(
|
||||
json_response=result, xml_request='', xml_response=''
|
||||
)
|
||||
operation.return_value = OperationResult(json_response=result, xml_request='', xml_response='')
|
||||
resp = app.get('/toulouse-axel/test/clae_children_activities_info?NameID=yyy&booking_date=2020-01-20')
|
||||
assert resp.json['err'] == 0
|
||||
assert len(resp.json['data']) == expected and 1 or 0
|
||||
|
@ -4000,9 +3999,7 @@ def test_clae_booking_endpoint(app, resource, booking_params, child_activities_d
|
|||
assert 'xml_response' in resp.json['data']
|
||||
|
||||
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
|
||||
operation.return_value = schemas.OperationResult(
|
||||
json_response={}, xml_request='', xml_response=''
|
||||
)
|
||||
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
|
||||
resp = app.post_json('/toulouse-axel/test/clae_booking?NameID=yyy', params=booking_params)
|
||||
payload = operation.call_args_list[0][0][1]['PORTAIL']['DUI']
|
||||
assert payload == {
|
||||
|
@ -4069,9 +4066,7 @@ def test_clae_booking_endpoint(app, resource, booking_params, child_activities_d
|
|||
new_booking_params['booking_list_SOIR'] = []
|
||||
new_booking_params['booking_list_GARD'] = []
|
||||
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
|
||||
operation.return_value = schemas.OperationResult(
|
||||
json_response={}, xml_request='', xml_response=''
|
||||
)
|
||||
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
|
||||
resp = app.post_json('/toulouse-axel/test/clae_booking?NameID=yyy', params=new_booking_params)
|
||||
payload = operation.call_args_list[0][0][1]['PORTAIL']['DUI']
|
||||
assert len(payload['ENFANT']) == 1
|
||||
|
@ -4109,9 +4104,7 @@ def test_clae_booking_endpoint(app, resource, booking_params, child_activities_d
|
|||
new_booking_params['booking_list_SOIR'] = None
|
||||
new_booking_params['booking_list_GARD'] = None
|
||||
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
|
||||
operation.return_value = schemas.OperationResult(
|
||||
json_response={}, xml_request='', xml_response=''
|
||||
)
|
||||
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
|
||||
resp = app.post_json('/toulouse-axel/test/clae_booking?NameID=yyy', params=new_booking_params)
|
||||
payload = operation.call_args_list[0][0][1]['PORTAIL']['DUI']
|
||||
assert 'ACTIVITE' not in payload['ENFANT'][0]
|
||||
|
@ -4134,9 +4127,7 @@ def test_clae_booking_endpoint(app, resource, booking_params, child_activities_d
|
|||
new_booking_params['booking_list_SOIR'] = None
|
||||
new_booking_params['booking_list_GARD'] = None
|
||||
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
|
||||
operation.return_value = schemas.OperationResult(
|
||||
json_response={}, xml_request='', xml_response=''
|
||||
)
|
||||
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
|
||||
with mock.patch('django.core.cache.cache.delete') as mock_cache_delete:
|
||||
resp = app.post_json('/toulouse-axel/test/clae_booking?NameID=yyy', params=new_booking_params)
|
||||
assert mock_cache_delete.call_args_list == [
|
||||
|
@ -4180,25 +4171,19 @@ def test_clae_booking_regime(app, resource, booking_params, child_activities_dat
|
|||
):
|
||||
booking_params['regime'] = None
|
||||
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
|
||||
operation.return_value = schemas.OperationResult(
|
||||
json_response={}, xml_request='', xml_response=''
|
||||
)
|
||||
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
|
||||
app.post_json('/toulouse-axel/test/clae_booking?NameID=yyy', params=booking_params)
|
||||
payload = operation.call_args_list[0][0][1]['PORTAIL']['DUI']
|
||||
assert payload['ENFANT'][0]['REGIME'] == 'SV'
|
||||
booking_params['regime'] = ''
|
||||
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
|
||||
operation.return_value = schemas.OperationResult(
|
||||
json_response={}, xml_request='', xml_response=''
|
||||
)
|
||||
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
|
||||
app.post_json('/toulouse-axel/test/clae_booking?NameID=yyy', params=booking_params)
|
||||
payload = operation.call_args_list[0][0][1]['PORTAIL']['DUI']
|
||||
assert payload['ENFANT'][0]['REGIME'] == 'SV'
|
||||
del booking_params['regime']
|
||||
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
|
||||
operation.return_value = schemas.OperationResult(
|
||||
json_response={}, xml_request='', xml_response=''
|
||||
)
|
||||
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
|
||||
app.post_json('/toulouse-axel/test/clae_booking?NameID=yyy', params=booking_params)
|
||||
payload = operation.call_args_list[0][0][1]['PORTAIL']['DUI']
|
||||
assert payload['ENFANT'][0]['REGIME'] == 'SV'
|
||||
|
@ -4228,9 +4213,7 @@ def test_clae_booking_endpoint_next_year(app, resource, child_activities_data):
|
|||
) as mock_activities:
|
||||
mock_activities.return_value = activities
|
||||
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
|
||||
operation.return_value = schemas.OperationResult(
|
||||
json_response={}, xml_request='', xml_response=''
|
||||
)
|
||||
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
|
||||
app.post_json('/toulouse-axel/test/clae_booking?NameID=yyy', params=booking_params)
|
||||
assert mock_activities.call_args_list == [
|
||||
mock.call(child_id='3535', dui='XXX', reference_year=2020),
|
||||
|
@ -4305,9 +4288,7 @@ def test_clae_booking_annual_endpoint(app, resource, annual_booking_params, chil
|
|||
assert 'xml_response' in resp.json['data']
|
||||
|
||||
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
|
||||
operation.return_value = schemas.OperationResult(
|
||||
json_response={}, xml_request='', xml_response=''
|
||||
)
|
||||
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
|
||||
resp = app.post_json(
|
||||
'/toulouse-axel/test/clae_booking_annual?NameID=yyy', params=annual_booking_params
|
||||
)
|
||||
|
@ -4360,9 +4341,7 @@ def test_clae_booking_annual_endpoint(app, resource, annual_booking_params, chil
|
|||
new_booking_params['booking_list_SOIR'] = []
|
||||
new_booking_params['booking_list_GARD'] = []
|
||||
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
|
||||
operation.return_value = schemas.OperationResult(
|
||||
json_response={}, xml_request='', xml_response=''
|
||||
)
|
||||
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
|
||||
resp = app.post_json(
|
||||
'/toulouse-axel/test/clae_booking_annual?NameID=yyy', params=new_booking_params
|
||||
)
|
||||
|
@ -4402,9 +4381,7 @@ def test_clae_booking_annual_endpoint(app, resource, annual_booking_params, chil
|
|||
new_booking_params['booking_list_SOIR'] = None
|
||||
new_booking_params['booking_list_GARD'] = None
|
||||
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
|
||||
operation.return_value = schemas.OperationResult(
|
||||
json_response={}, xml_request='', xml_response=''
|
||||
)
|
||||
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
|
||||
resp = app.post_json(
|
||||
'/toulouse-axel/test/clae_booking_annual?NameID=yyy', params=new_booking_params
|
||||
)
|
||||
|
@ -4434,9 +4411,7 @@ def test_clae_booking_annual_next_year(app, resource, child_activities_data):
|
|||
'passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities', return_value=activities
|
||||
):
|
||||
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
|
||||
operation.return_value = schemas.OperationResult(
|
||||
json_response={}, xml_request='', xml_response=''
|
||||
)
|
||||
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
|
||||
app.post_json('/toulouse-axel/test/clae_booking_annual?NameID=yyy', params=annual_booking_params)
|
||||
payload = operation.call_args_list[0][0][1]['PORTAIL']['DUI']
|
||||
assert payload['ENFANT'][0]['ACTIVITE'][0]['PERIODE'][0]['DATEDEBUT'] == '2020-08-01'
|
||||
|
@ -4452,25 +4427,19 @@ def test_clae_booking_annual_regime(app, resource, annual_booking_params, child_
|
|||
):
|
||||
annual_booking_params['regime'] = None
|
||||
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
|
||||
operation.return_value = schemas.OperationResult(
|
||||
json_response={}, xml_request='', xml_response=''
|
||||
)
|
||||
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
|
||||
app.post_json('/toulouse-axel/test/clae_booking_annual?NameID=yyy', params=annual_booking_params)
|
||||
payload = operation.call_args_list[0][0][1]['PORTAIL']['DUI']
|
||||
assert payload['ENFANT'][0]['REGIME'] == 'SV'
|
||||
annual_booking_params['regime'] = ''
|
||||
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
|
||||
operation.return_value = schemas.OperationResult(
|
||||
json_response={}, xml_request='', xml_response=''
|
||||
)
|
||||
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
|
||||
app.post_json('/toulouse-axel/test/clae_booking_annual?NameID=yyy', params=annual_booking_params)
|
||||
payload = operation.call_args_list[0][0][1]['PORTAIL']['DUI']
|
||||
assert payload['ENFANT'][0]['REGIME'] == 'SV'
|
||||
del annual_booking_params['regime']
|
||||
with mock.patch('passerelle.contrib.toulouse_axel.schemas.reservation_annuelle') as operation:
|
||||
operation.return_value = schemas.OperationResult(
|
||||
json_response={}, xml_request='', xml_response=''
|
||||
)
|
||||
operation.return_value = OperationResult(json_response={}, xml_request='', xml_response='')
|
||||
app.post_json('/toulouse-axel/test/clae_booking_annual?NameID=yyy', params=annual_booking_params)
|
||||
payload = operation.call_args_list[0][0][1]['PORTAIL']['DUI']
|
||||
assert payload['ENFANT'][0]['REGIME'] == 'SV'
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
import os
|
||||
|
||||
from passerelle.contrib.toulouse_axel.schemas import AxelSchema
|
||||
from passerelle.contrib.utils.axel import AxelSchema
|
||||
|
||||
import pytest
|
||||
import xmlschema
|
||||
|
|
|
@ -18,26 +18,11 @@ import datetime
|
|||
import pytest
|
||||
|
||||
from passerelle.contrib.toulouse_axel.utils import (
|
||||
parse_datetime,
|
||||
encode_datetime,
|
||||
get_booking,
|
||||
get_reference_year_from_date,
|
||||
get_week_dates_from_date,
|
||||
json_date_format,
|
||||
)
|
||||
|
||||
|
||||
def test_parse_datetime():
|
||||
# wrong format
|
||||
assert parse_datetime('foo') is None
|
||||
assert parse_datetime('2019-12-12') is None
|
||||
assert parse_datetime('2019-12-12T12:01:72') is None
|
||||
# ok
|
||||
assert parse_datetime('2019-12-12T12:01:42').isoformat() == '2019-12-12T12:01:42+00:00'
|
||||
|
||||
|
||||
def test_encode_datetime():
|
||||
assert encode_datetime(parse_datetime('2019-12-12T23:40:42')) == '13/12/2019 00:40:42'
|
||||
from passerelle.contrib.utils.axel import json_date_format
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
|
Loading…
Reference in New Issue