# 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 . import datetime import os import xml.etree.ElementTree as ET from contextlib import contextmanager from unittest import mock import freezegun import pytest import xmlschema import tests.utils from passerelle.contrib.caluire_axel import schemas from passerelle.contrib.caluire_axel.models import CaluireAxel, Link from passerelle.contrib.utils.axel import AxelError, OperationResult, json_date_format, xml_date_format from passerelle.utils.soap import SOAPError XML_RESPONSE_TEMPLATE = ''' %s OK 10/10/2010 10:10:01 %s ''' @pytest.fixture def resource(db): return tests.utils.make_resource( CaluireAxel, slug='test', wsdl_url='http://example.net/AXEL_WS/AxelWS.php?wsdl' ) @pytest.fixture def link_params(): return { 'IDENTFAMILLE': '12345', 'NOM': 'Doe', 'PRENOM': 'John', } @pytest.fixture def family_data(): filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() resp = XML_RESPONSE_TEMPLATE % ('GetFamilleIndividus', content) return schemas.get_famille_individus.response_converter.decode(ET.fromstring(resp))['DATA']['PORTAIL'][ 'GETFAMILLE' ] @pytest.fixture def register_activity_params(): return { 'activity_id': 'CANTINE', 'child_id': '50632', 'registration_start_date': '2020-09-01', 'registration_end_date': '2021-08-31', } @pytest.fixture def activities(): filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/activities_info.xml') with open(filepath) as xml: content = xml.read() resp = XML_RESPONSE_TEMPLATE % ('GetListActivites', content) return schemas.get_list_activites.response_converter.decode(ET.fromstring(resp))['DATA']['PORTAIL'][ 'GETLISTACTIVITES' ] @pytest.fixture def activities_full(): return { 'ACTIVITE': [ { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'GARDERIES', 'LIBELLEACTIVITE': 'Garderie', }, { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'ACCMAT', 'LIBELLEACTIVITE': 'Matin', }, { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'CJ MER', 'LIBELLEACTIVITE': 'Mercredi', }, { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'ETUDES', 'LIBELLEACTIVITE': 'Etudes', }, { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'CJ1', 'LIBELLEACTIVITE': 'Des vacances', }, { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'ECOLELEM', 'LIBELLEACTIVITE': 'Cantine', }, { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'NAV MATIN', 'LIBELLEACTIVITE': 'Navette du matin', }, { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'NAV SOIR', 'LIBELLEACTIVITE': 'Navette du soir', }, { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'DECFOO', 'LIBELLEACTIVITE': 'Une classe découverte', }, ] } @pytest.fixture def booking_params(): return { 'child_id': '50632', 'booking_list': [], 'start_date': '2020-09-01', 'end_date': '2021-08-31', } @pytest.fixture def changes_params(): return { 'child_id': '50632', 'changes': [], 'start_date': '2020-09-01', 'end_date': '2021-08-31', } @pytest.fixture def week_booking_params(): return { 'child_id': '50632', 'activity_id': 'ELEM', 'booking_list': [], 'start_date': '2020-09-01', 'end_date': '2021-08-31', } @pytest.fixture def upload_attachments_params(): return { 'child_id': '50632', 'reference_date': '2020-09-01', 'attachments': [ { 'attachment_type': '1234', 'label': 'ID card', 'url': 'https://example.org/file1.pdf', }, { 'attachment_type': '1234', 'label': 'Passport', 'url': 'https://example.org/file2.pdf', }, ], } @contextmanager def mock_data(content, operation, data_method='getData'): with mock.patch('passerelle.contrib.caluire_axel.models.CaluireAxel.soap_client') as client: resp = XML_RESPONSE_TEMPLATE % (operation, content) getattr(client.return_value.service, data_method).return_value = resp yield def test_operation_status_error(resource): resp = ''' FindIndividus NOK '''.strip() with mock.patch('passerelle.contrib.caluire_axel.models.CaluireAxel.soap_client') as client: client.return_value.service.getData.return_value = resp with pytest.raises(AxelError, match='Foo reason'): schemas.find_individus( resource, { 'PORTAIL': { 'FINDINDIVIDU': { 'NOM': 'Doe', 'PRENOM': 'John', 'NAISSANCE': None, 'CODEPOSTAL': None, 'VILLE': None, 'TEL': None, 'MAIL': None, } } }, ) def test_link_endpoint_nameid_empty(app, resource, link_params): resp = app.post_json('/caluire-axel/test/link?NameID=', params=link_params, status=400) assert resp.json['err_desc'] == 'NameID is empty' assert resp.json['err'] == 'bad-request' def test_link_endpoint_axel_error(app, resource, link_params): with mock.patch('passerelle.contrib.caluire_axel.schemas.find_individus') as operation: operation.side_effect = AxelError('FooBar') resp = app.post_json('/caluire-axel/test/link?NameID=yyy', params=link_params) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' assert resp.json['data'] == {'xml_request': None, 'xml_response': None} # test xml_request and xml_response only for this endpoint xml_request = """ Doe John """ with mock_data('', 'FindIndividus'): with mock.patch('xmlschema.XMLSchema.validate') as xml_validate: xml_validate.side_effect = xmlschema.XMLSchemaValidationError(None, None) resp = app.post_json('/caluire-axel/test/link?NameID=yyy', params=link_params) assert resp.json['err_desc'].startswith('Axel error: invalid request') assert resp.json['err'] == 'error' assert resp.json['data']['xml_request'] == xml_request assert resp.json['data']['xml_response'] is None xml_response = """ FINDINDIVIDUS NOK Foo reason """ response = """ FINDINDIVIDUS NOK """.strip() with mock.patch('passerelle.contrib.caluire_axel.models.CaluireAxel.soap_client') as client: client.return_value.service.getData.return_value = response resp = app.post_json('/caluire-axel/test/link?NameID=yyy', params=link_params) assert resp.json['err_desc'] == 'Axel error: Foo reason' assert resp.json['err'] == 'error' assert resp.json['data']['xml_request'] == xml_request assert resp.json['data']['xml_response'] == xml_response content = """ 123 Doe John 12345 2 """ xml_response = ( """ FindIndividus OK 10/10/2010 10:10:01 %s """ % content ) with mock_data(content, 'FindIndividus'): with mock.patch('passerelle.contrib.utils.axel.AxelSchema.decode') as decode: decode.side_effect = xmlschema.XMLSchemaValidationError(None, None) resp = app.post_json('/caluire-axel/test/link?NameID=yyy', params=link_params) assert resp.json['err_desc'].startswith('Axel error: invalid response') assert resp.json['err'] == 'error' assert resp.json['data']['xml_request'] == xml_request assert resp.json['data']['xml_response'] == xml_response with mock.patch('passerelle.contrib.caluire_axel.models.CaluireAxel.soap_client') as client: client.side_effect = SOAPError('SOAP service is down') resp = app.post_json('/caluire-axel/test/link?NameID=yyy', params=link_params) assert resp.json['err_desc'] == 'SOAP service is down' @pytest.mark.parametrize( 'xml_response', [ '', """ 123 AN 12346 2 12347 1 """, """ 123 AN 12345 3 """, ], ) def test_link_endpoint_no_result(app, resource, link_params, xml_response): content = ( ''' 42 %s ''' % xml_response ) with mock_data(content, 'FindIndividus'): resp = app.post_json('/caluire-axel/test/link?NameID=yyy', params=link_params) assert resp.json['err_desc'] == 'Person not found' assert resp.json['err'] == 'not-found' def test_link_endpoint_conflict(app, resource, link_params): content = """ 42 123 AN 12345 2 """ # existing link but family_id is wrong link = Link.objects.create(resource=resource, name_id='yyy', family_id='YYY', person_id='42') with mock_data(content, 'FindIndividus'): resp = app.post_json('/caluire-axel/test/link?NameID=yyy', params=link_params) assert resp.json['err_desc'] == 'Data conflict' assert resp.json['err'] == 'conflict' # existing link but person_id is wrong link.family_id = '12345' link.person_id = '35' link.save() with mock_data(content, 'FindIndividus'): resp = app.post_json('/caluire-axel/test/link?NameID=yyy', params=link_params) assert resp.json['err_desc'] == 'Data conflict' assert resp.json['err'] == 'conflict' @pytest.mark.parametrize('place', [1, 2]) def test_link_endpoint(app, resource, link_params, place): content = ( """ 42 123 AN 12345 %s """ % place ) with mock_data(content, 'FindIndividus'): resp = app.post_json('/caluire-axel/test/link?NameID=yyy', params=link_params) assert set(resp.json.keys()) == {'err', 'link', 'created', 'family_id', 'data'} assert resp.json['err'] == 0 assert resp.json['family_id'] == '12345' assert resp.json['created'] is True assert 'xml_request' in resp.json['data'] assert 'xml_response' in resp.json['data'] # again with mock_data(content, 'FindIndividus'): resp = app.post_json('/caluire-axel/test/link?NameID=yyy', params=link_params) assert set(resp.json.keys()) == {'err', 'link', 'created', 'family_id', 'data'} assert resp.json['err'] == 0 assert resp.json['family_id'] == '12345' assert resp.json['created'] is False # link already exists assert 'xml_request' in resp.json['data'] assert 'xml_response' in resp.json['data'] def test_link_endpoint_having_homonyme_with_empty_familly(app, resource, link_params): content = """ 42 123 AN 456 AN 12345 2 """ with mock_data(content, 'FindIndividus'): resp = app.post_json('/caluire-axel/test/link?NameID=yyy', params=link_params) assert resp.json['err'] == 0 assert resp.json['family_id'] == '12345' assert resp.json['created'] is True def test_unlink_endpoint_no_result(app, resource): resp = app.post('/caluire-axel/test/unlink?NameID=yyy') assert resp.json['err_desc'] == 'Person not found' assert resp.json['err'] == 'not-found' def test_unlink_endpoint(app, resource): link = Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') resp = app.post('/caluire-axel/test/unlink?NameID=yyy') assert Link.objects.exists() is False assert resp.json['err'] == 0 assert resp.json['link'] == link.pk assert resp.json['family_id'] == 'XXX' assert resp.json['deleted'] is True def test_family_info_endpoint_axel_error(app, resource): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') with mock.patch('passerelle.contrib.caluire_axel.schemas.get_famille_individus') as operation: operation.side_effect = AxelError('FooBar') resp = app.get('/caluire-axel/test/family_info?NameID=yyy') assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' def test_family_info_endpoint_no_result(app, resource): resp = app.get('/caluire-axel/test/family_info?NameID=yyy') assert resp.json['err_desc'] == 'Person not found' assert resp.json['err'] == 'not-found' def test_family_info_endpoint(app, resource): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): resp = app.get('/caluire-axel/test/family_info?NameID=yyy') assert resp.json['err'] == 0 assert set(resp.json['data'].keys()) == {'family_id', 'CODE', 'MEMBRE', 'RESPONSABLE1', 'RESPONSABLE2'} assert resp.json['data']['CODE'] == 0 assert resp.json['data']['family_id'] == 'XXX' assert resp.json['data']['MEMBRE'][0]['id'] == '50632' assert resp.json['data']['MEMBRE'][0]['text'] == 'Enfant 1 CALUIRE TEST' assert resp.json['data']['MEMBRE'][1]['id'] == '50633' assert resp.json['data']['MEMBRE'][1]['text'] == 'Enfant 2 CALUIRE TEST' assert resp.json['data']['MEMBRE'][2]['id'] == '54621' assert resp.json['data']['MEMBRE'][2]['text'] == 'Enfant 3 CALUIRE TEST' assert resp.json['data']['MEMBRE'][3]['id'] == '59509' assert resp.json['data']['MEMBRE'][3]['text'] == 'Enfant 5 CALUIRE TEST' assert resp.json['data']['RESPONSABLE1']['IDENT'] == '50630' # again - data are in cache resp = app.get('/caluire-axel/test/family_info?NameID=yyy') assert resp.json['err'] == 0 # misordered XML (one MEMBER before RESPONSABLE1) Link.objects.create(resource=resource, name_id='bar', family_id='YYY', person_id='24') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info_misordered.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): resp = app.get('/caluire-axel/test/family_info?NameID=bar') assert resp.json['err'] == 0 assert set(resp.json['data'].keys()) == {'family_id', 'CODE', 'MEMBRE', 'RESPONSABLE1', 'RESPONSABLE2'} assert resp.json['data']['family_id'] == 'YYY' assert resp.json['data']['MEMBRE'][0]['id'] == '11111' assert resp.json['data']['MEMBRE'][0]['text'] == 'CALUIRE TEST' assert resp.json['data']['MEMBRE'][1]['id'] == '22222' assert resp.json['data']['MEMBRE'][1]['text'] == 'Enfant 2 CALUIRE TEST' def test_children_info_endpoint_axel_error(app, resource): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') with mock.patch('passerelle.contrib.caluire_axel.schemas.get_famille_individus') as operation: operation.side_effect = AxelError('FooBar') resp = app.get('/caluire-axel/test/children_info?NameID=yyy') assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' def test_children_info_endpoint_no_result(app, resource): resp = app.get('/caluire-axel/test/children_info?NameID=yyy') assert resp.json['err_desc'] == 'Person not found' assert resp.json['err'] == 'not-found' def test_children_info_endpoint(app, resource): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): resp = app.get('/caluire-axel/test/children_info?NameID=yyy') assert resp.json['err'] == 0 assert len(resp.json['data']) == 4 assert resp.json['data'][0]['id'] == '50632' assert resp.json['data'][0]['text'] == 'Enfant 1 CALUIRE TEST' assert resp.json['data'][1]['id'] == '50633' assert resp.json['data'][1]['text'] == 'Enfant 2 CALUIRE TEST' assert resp.json['data'][2]['id'] == '54621' assert resp.json['data'][2]['text'] == 'Enfant 3 CALUIRE TEST' assert resp.json['data'][3]['id'] == '59509' assert resp.json['data'][3]['text'] == 'Enfant 5 CALUIRE TEST' # again - data are in cache resp = app.get('/caluire-axel/test/children_info?NameID=yyy') assert resp.json['err'] == 0 def test_child_info_endpoint_axel_error(app, resource): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') with mock.patch('passerelle.contrib.caluire_axel.schemas.get_famille_individus') as operation: operation.side_effect = AxelError('FooBar') resp = app.get('/caluire-axel/test/child_info?NameID=yyy&idpersonne=50632') assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' def test_child_info_endpoint_no_result(app, resource): resp = app.get('/caluire-axel/test/child_info?NameID=yyy&idpersonne=50632') assert resp.json['err_desc'] == 'Person not found' assert resp.json['err'] == 'not-found' Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): resp = app.get('/caluire-axel/test/child_info?NameID=yyy&idpersonne=zzz') assert resp.json['err_desc'] == 'Child not found' assert resp.json['err'] == 'not-found' def test_child_info_endpoint(app, resource): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): resp = app.get('/caluire-axel/test/child_info?NameID=yyy&idpersonne=50632') assert resp.json['err'] == 0 assert set(resp.json['data'].keys()) == { 'ADRESSE', 'CIVILITE', 'FAMILLE', 'GARDEALTERNEE', 'IDENT', 'MAIL', 'NAISSANCE', 'NOM', 'NOMJF', 'PAI', 'PRENOM', 'SEXE', 'TELFIXE', 'TELPORTABLE', 'id', 'text', } assert resp.json['data']['id'] == '50632' assert resp.json['data']['text'] == 'Enfant 1 CALUIRE TEST' # again - data are in cache resp = app.get('/caluire-axel/test/child_info?NameID=yyy&idpersonne=50632') assert resp.json['err'] == 0 def test_school_list_endpoint_axel_error(app, resource): with mock.patch('passerelle.contrib.caluire_axel.schemas.get_list_ecole') as operation: operation.side_effect = AxelError('FooBar') resp = app.get( '/caluire-axel/test/school_list?num=42&street=street=rue%20Pasteur&zipcode=69300&city=Caluire%20et%20Cuire&schooling_date=2021-05-10' ) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' def test_school_list_endpoint(app, resource): filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/school_list.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetListEcole'): resp = app.get( '/caluire-axel/test/school_list?num=42&street=street=rue%20Pasteur&zipcode=69300&city=Caluire%20et%20Cuire&schooling_date=2021-05-10' ) assert resp.json['err'] == 0 assert set(resp.json['data'].keys()) == {'CODE', 'ECOLE'} assert len(resp.json['data']['ECOLE']) == 2 assert resp.json['data']['ECOLE'][0]['id'] == 'MAT' assert resp.json['data']['ECOLE'][0]['text'] == 'Ecole Maternelle' assert resp.json['data']['ECOLE'][1]['id'] == 'ELEM' assert resp.json['data']['ECOLE'][1]['text'] == 'Ecole Elémentaire' def test_child_schooling_info_endpoint_axel_error(app, resource): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') with mock.patch('passerelle.contrib.caluire_axel.schemas.get_famille_individus') as operation: operation.side_effect = AxelError('FooBar') resp = app.get( '/caluire-axel/test/child_schooling_info?NameID=yyy&idpersonne=50632&schooling_date=2021-05-10' ) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): with mock.patch('passerelle.contrib.caluire_axel.schemas.get_individu') as operation: operation.side_effect = AxelError('FooBar') resp = app.get( '/caluire-axel/test/child_schooling_info?NameID=yyy&idpersonne=50632&schooling_date=2021-05-10' ) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' @pytest.mark.parametrize('value', ['foo', '20/01/2020', '2020']) def test_child_schooling_info_endpoint_bad_date_format(app, resource, value): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') resp = app.get( '/caluire-axel/test/child_schooling_info?NameID=yyy&idpersonne=50632&schooling_date=%s' % value, status=400, ) assert resp.json['err_desc'] == 'bad date format, should be YYYY-MM-DD' assert resp.json['err'] == 'bad-request' def test_child_schooling_info_endpoint_no_result(app, resource): resp = app.get( '/caluire-axel/test/child_schooling_info?NameID=yyy&idpersonne=50632&schooling_date=2021-05-10' ) assert resp.json['err_desc'] == 'Person not found' assert resp.json['err'] == 'not-found' Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): resp = app.get( '/caluire-axel/test/child_schooling_info?NameID=yyy&idpersonne=zzz&schooling_date=2021-05-10' ) assert resp.json['err_desc'] == 'Child not found' assert resp.json['err'] == 'not-found' def test_child_schooling_info(app, resource, family_data): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/schooling_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetIndividu'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): resp = app.get( '/caluire-axel/test/child_schooling_info?NameID=yyy&idpersonne=50632&schooling_date=2021-05-10' ) assert resp.json['err'] == 0 assert set(resp.json['data'].keys()) == {'CODE', 'INDIVIDU', 'SCOLAIRE'} def test_child_activities_info_endpoint_axel_error(app, resource): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') with mock.patch('passerelle.contrib.caluire_axel.schemas.get_famille_individus') as operation: operation.side_effect = AxelError('FooBar') resp = app.get( '/caluire-axel/test/child_activities_info?NameID=yyy&idpersonne=50632&schooling_date=2021-05-10' ) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): with mock.patch('passerelle.contrib.caluire_axel.schemas.get_list_activites') as operation: operation.side_effect = AxelError('FooBar') resp = app.get( '/caluire-axel/test/child_activities_info?NameID=yyy&idpersonne=50632&schooling_date=2021-05-10' ) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' @pytest.mark.parametrize('value', ['foo', '20/01/2020', '2020']) def test_child_activities_info_endpoint_bad_date_format(app, resource, value): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') resp = app.get( '/caluire-axel/test/child_activities_info?NameID=yyy&idpersonne=50632&schooling_date=%s' % value, status=400, ) assert resp.json['err_desc'] == 'bad date format, should be YYYY-MM-DD' assert resp.json['err'] == 'bad-request' def test_child_activities_info_endpoint_no_result(app, resource): resp = app.get( '/caluire-axel/test/child_activities_info?NameID=yyy&idpersonne=50632&schooling_date=2021-05-10' ) assert resp.json['err_desc'] == 'Person not found' assert resp.json['err'] == 'not-found' Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): resp = app.get( '/caluire-axel/test/child_activities_info?NameID=yyy&idpersonne=zzz&schooling_date=2021-05-10' ) assert resp.json['err_desc'] == 'Child not found' assert resp.json['err'] == 'not-found' def test_child_activities_info(app, resource, family_data): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/activities_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetListActivites'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): resp = app.get( '/caluire-axel/test/child_activities_info?NameID=yyy&idpersonne=50632&schooling_date=2021-05-10' ) assert resp.json['err'] == 0 assert set(resp.json['data'].keys()) == {'CODE', 'ACTIVITE'} # again - data are in cache with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): resp = app.get( '/caluire-axel/test/child_activities_info?NameID=yyy&idpersonne=50632&schooling_date=2021-05-10' ) assert resp.json['err'] == 0 def test_register_activity_endpoint_axel_error(app, resource, register_activity_params): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') with mock.patch('passerelle.contrib.caluire_axel.schemas.get_famille_individus') as operation: operation.side_effect = AxelError('FooBar') resp = app.post_json( '/caluire-axel/test/register_activity?NameID=yyy', params=register_activity_params ) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): with mock.patch('passerelle.contrib.caluire_axel.schemas.create_inscription_activite') as operation: operation.side_effect = AxelError('FooBar') resp = app.post_json( '/caluire-axel/test/register_activity?NameID=yyy', params=register_activity_params ) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' def test_register_activity_endpoint_no_result(app, resource, register_activity_params): register_activity_params['child_id'] = 'zzz' resp = app.post_json('/caluire-axel/test/register_activity?NameID=yyy', params=register_activity_params) assert resp.json['err_desc'] == 'Person not found' assert resp.json['err'] == 'not-found' Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): resp = app.post_json( '/caluire-axel/test/register_activity?NameID=yyy', params=register_activity_params ) assert resp.json['err_desc'] == 'Child not found' assert resp.json['err'] == 'not-found' def test_register_activity_endpoint_date_error(app, resource, register_activity_params): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): register_activity_params['registration_start_date'] = '2021-09-01' register_activity_params['registration_end_date'] = '2021-08-31' resp = app.post_json( '/caluire-axel/test/register_activity?NameID=yyy', params=register_activity_params, status=400 ) assert resp.json['err_desc'] == 'start_date should be before end_date' assert resp.json['err'] == 'bad-request' register_activity_params['registration_end_date'] = '2022-09-01' resp = app.post_json( '/caluire-axel/test/register_activity?NameID=yyy', params=register_activity_params, status=400 ) assert ( resp.json['err_desc'] == 'start_date and end_date are in different reference year (2021 != 2022)' ) assert resp.json['err'] == 'bad-request' def test_register_activity_endpoint(app, resource, family_data, register_activity_params): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') content = ''' 0 50632 ''' with mock_data(content, 'CreateInscriptionActivite', data_method='setData'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch('django.core.cache.cache.delete') as mock_cache_delete: resp = app.post_json( '/caluire-axel/test/register_activity?NameID=yyy', params=register_activity_params ) assert mock_cache_delete.call_args_list == [ mock.call('caluire-axel-%s-child-activities-50632-2020' % resource.pk), ] assert resp.json['err'] == 0 assert resp.json['created'] is True assert 'xml_request' in resp.json['data'] assert 'xml_response' in resp.json['data'] @pytest.mark.parametrize('code', [-1, -2, -3, -4]) def test_register_activity_endpoint_wrong_code(app, resource, family_data, register_activity_params, code): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') content = ( ''' %s ''' % code ) with mock_data(content, 'CreateInscriptionActivite', data_method='setData'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): resp = app.post_json( '/caluire-axel/test/register_activity?NameID=yyy', params=register_activity_params ) if code == -1: assert resp.json['err'] == 0 assert resp.json['created'] is False else: assert resp.json['err_desc'] == 'Wrong register-activity status' assert resp.json['err'] == 'register-activity-code-error-%s' % code def test_get_agenda_endpoint_axel_error(app, resource, family_data): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') with mock.patch('passerelle.contrib.caluire_axel.schemas.get_famille_individus') as operation: operation.side_effect = AxelError('FooBar') resp = app.get( '/caluire-axel/test/get_agenda?NameID=yyy&idpersonne=50632&activity_id=FOOBAR&start_date=2020-09-01&end_date=2021-08-31' ) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): with mock.patch('passerelle.contrib.caluire_axel.schemas.get_list_activites') as operation: operation.side_effect = AxelError('FooBar') resp = app.get( '/caluire-axel/test/get_agenda?NameID=yyy&idpersonne=50632&activity_id=FOOBAR&start_date=2020-09-01&end_date=2021-08-31' ) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/activities_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetListActivites'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.get_agenda') as operation: operation.side_effect = AxelError('FooBar') resp = app.get( '/caluire-axel/test/get_agenda?NameID=yyy&idpersonne=50632&activity_id=ELEM&start_date=2020-09-01&end_date=2021-08-31' ) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' @pytest.mark.parametrize('value', ['foo', '20/01/2020', '2020']) def test_get_agenda_endpoint_bad_date_format(app, resource, value): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') resp = app.get( '/caluire-axel/test/get_agenda?NameID=yyy&idpersonne=50632&activity_id=FOOBAR&start_date=%s&end_date=2021-08-31' % value, status=400, ) assert resp.json['err_desc'] == 'bad date format, should be YYYY-MM-DD' assert resp.json['err'] == 'bad-request' resp = app.get( '/caluire-axel/test/get_agenda?NameID=yyy&idpersonne=50632&activity_id=FOOBAR&start_date=2020-09-01&end_date=%s' % value, status=400, ) assert resp.json['err_desc'] == 'bad date format, should be YYYY-MM-DD' assert resp.json['err'] == 'bad-request' def test_get_agenda_endpoint_no_result(app, resource, family_data): resp = app.get( '/caluire-axel/test/get_agenda?NameID=yyy&idpersonne=50632&activity_id=FOOBAR&start_date=2020-09-01&end_date=2021-08-31' ) assert resp.json['err_desc'] == 'Person not found' assert resp.json['err'] == 'not-found' Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): resp = app.get( '/caluire-axel/test/get_agenda?NameID=yyy&idpersonne=zzz&activity_id=FOOBAR&start_date=2020-09-01&end_date=2021-08-31' ) assert resp.json['err_desc'] == 'Child not found' assert resp.json['err'] == 'not-found' filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/activities_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetListActivites'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): resp = app.get( '/caluire-axel/test/get_agenda?NameID=yyy&idpersonne=50632&activity_id=FOOBAR&start_date=2020-09-01&end_date=2021-08-31' ) assert resp.json['err_desc'] == 'Activity not found' assert resp.json['err'] == 'not-found' def test_get_agenda_endpoint_date_error(app, resource): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): resp = app.get( '/caluire-axel/test/get_agenda?NameID=yyy&idpersonne=50632&activity_id=FOOBAR&start_date=2021-05-31&end_date=2021-05-30', status=400, ) assert resp.json['err_desc'] == 'start_date should be before end_date' assert resp.json['err'] == 'bad-request' resp = app.get( '/caluire-axel/test/get_agenda?NameID=yyy&idpersonne=50632&activity_id=FOOBAR&start_date=2021-09-01&end_date=2022-09-01', status=400, ) assert ( resp.json['err_desc'] == 'start_date and end_date are in different reference year (2021 != 2022)' ) assert resp.json['err'] == 'bad-request' @freezegun.freeze_time('2020-09-01') def test_get_agenda_endpoint(app, resource, family_data, activities): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') content = ''' 1 30/10/2020 . N ''' with mock_data(content, 'GetAgenda'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value=activities, ): resp = app.get( '/caluire-axel/test/get_agenda?NameID=yyy&idpersonne=50632&activity_id=ELEM&start_date=2020-09-01&end_date=2021-08-31' ) assert resp.json['err'] == 0 assert resp.json['data'] == [ { 'id': '50632:ELEM:2020-10-30', 'text': 'Friday 30 October 2020', 'disabled': False, 'prefill': False, 'details': { 'JOURDATE': '2020-10-30', 'MATIN': '.', 'MIDI': None, 'APRESMIDI': None, 'FERME': False, 'status_color': 'white', 'out_of_delay': False, 'activity_id': 'ELEM', 'activity_label': 'Restaurant Elémentaire', 'activity_type': 'midi', 'child_id': '50632', }, }, ] @pytest.mark.parametrize( 'value, ignored', [ ('O', True), ('N', False), ], ) def test_get_agenda_endpoint_closed(app, resource, family_data, activities, value, ignored): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') content = ( ''' 1 30/10/2020 . %s ''' % value ) with mock_data(content, 'GetAgenda'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value=activities, ): resp = app.get( '/caluire-axel/test/get_agenda?NameID=yyy&idpersonne=50632&activity_id=ELEM&start_date=2020-09-01&end_date=2021-08-31' ) if ignored: assert len(resp.json['data']) == 0 else: assert resp.json['data'][0] @pytest.mark.parametrize( 'value, expected', [ ['X', True], ['H', True], ['R', True], ['', False], ['', False], ['.', False], ['F', False], ['S', False], ['T', False], ['D', False], ['C', False], ['M', False], ['A', False], ['N', False], ['Z', False], # unknown ], ) @freezegun.freeze_time('2020-09-01') def test_get_agenda_endpoint_prefill(app, resource, family_data, activities, value, expected): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') content = ( ''' 1 30/10/2020 %s N ''' % value ) with mock_data(content, 'GetAgenda'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value=activities, ): resp = app.get( '/caluire-axel/test/get_agenda?NameID=yyy&idpersonne=50632&activity_id=ELEM&start_date=2020-09-01&end_date=2021-08-31' ) assert resp.json['data'][0]['prefill'] == expected @pytest.mark.parametrize( 'value, color, disabled_future', [ ['X', 'green', False], ['H', 'yellow', True], ['R', 'green', False], ['', 'grey', True], ['', 'grey', True], ['.', 'white', False], ['F', 'grey', True], ['S', 'grey', True], ['T', 'grey', True], ['D', 'orange', False], ['C', 'orange', True], ['M', 'orange', True], ['A', 'red', True], ['N', 'red', True], ['Z', 'grey', True], # unknown ], ) def test_get_agenda_endpoint_status(app, resource, family_data, activities, value, color, disabled_future): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') content = ( ''' 1 30/10/2020 %s N ''' % value ) with mock_data(content, 'GetAgenda'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value=activities, ): with freezegun.freeze_time('2020-10-31'): resp = app.get( '/caluire-axel/test/get_agenda?NameID=yyy&idpersonne=50632&activity_id=ELEM&start_date=2020-09-01&end_date=2021-08-31' ) assert resp.json['data'][0]['details']['status_color'] == color assert resp.json['data'][0]['disabled'] is True assert resp.json['data'][0]['details']['out_of_delay'] is True with freezegun.freeze_time('2020-10-20'): resp = app.get( '/caluire-axel/test/get_agenda?NameID=yyy&idpersonne=50632&activity_id=ELEM&start_date=2020-09-01&end_date=2021-08-31' ) assert resp.json['data'][0]['details']['status_color'] == color assert resp.json['data'][0]['disabled'] == disabled_future assert resp.json['data'][0]['details']['out_of_delay'] is False @pytest.mark.parametrize( 'today, hour, booking_date, out_of_delay', [ # monday 12H => thursday ('2021-05-31', '09:59:59', '2021-06-03', False), ('2021-05-31', '10:00:00', '2021-06-03', True), # tuesday 12H => friday ('2021-06-01', '09:59:59', '2021-06-04', False), ('2021-06-01', '10:00:00', '2021-06-04', True), # wednesday => monday ('2021-06-02', '09:59:59', '2021-06-04', True), ('2021-06-02', '10:00:00', '2021-06-04', True), ('2021-06-02', '09:59:59', '2021-06-05', True), ('2021-06-02', '10:00:00', '2021-06-05', True), ('2021-06-02', '09:59:59', '2021-06-06', True), ('2021-06-02', '10:00:00', '2021-06-06', True), ('2021-06-02', '09:59:59', '2021-06-07', False), ('2021-06-02', '10:00:00', '2021-06-07', False), # thursday 12H => monday ('2021-06-03', '09:59:59', '2021-06-07', False), ('2021-06-03', '10:00:00', '2021-06-07', True), # friday 12H => tuesday ('2021-06-04', '09:59:59', '2021-06-08', False), ('2021-06-04', '10:00:00', '2021-06-08', True), # saturday => thursday ('2021-06-05', '09:59:59', '2021-06-08', True), ('2021-06-05', '10:00:00', '2021-06-08', True), ('2021-06-05', '09:59:59', '2021-06-09', True), ('2021-06-05', '10:00:00', '2021-06-09', True), ('2021-06-05', '09:59:59', '2021-06-10', False), ('2021-06-05', '10:00:00', '2021-06-10', False), # sunday => thursday ('2021-06-06', '09:59:59', '2021-06-08', True), ('2021-06-06', '10:00:00', '2021-06-08', True), ('2021-06-06', '09:59:59', '2021-06-09', True), ('2021-06-06', '10:00:00', '2021-06-09', True), ('2021-06-06', '09:59:59', '2021-06-10', False), ('2021-06-06', '10:00:00', '2021-06-10', False), ], ) def test_get_agenda_endpoint_delay_periscolaire( settings, app, resource, family_data, activities_full, today, hour, booking_date, out_of_delay ): settings.TIME_ZONE = 'Europe/Paris' settings.USE_TZ = True booking = datetime.datetime.strptime(booking_date, json_date_format).date() Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') content = ''' 1 %s X N ''' % booking.strftime( xml_date_format ) with mock_data(content, 'GetAgenda'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value=activities_full, ): with freezegun.freeze_time('%s %s' % (today, hour)): for activity_id, activity_type in [ ('ACCMAT', 'matin'), ('GARDERIES', 'soir'), ('ETUDES', 'soir'), ('ECOLELEM', 'midi'), ('NAV MATIN', 'matin'), ('NAV SOIR', 'soir'), ]: resp = app.get( '/caluire-axel/test/get_agenda?NameID=yyy&idpersonne=50632&activity_id=%s&start_date=%s&end_date=%s' % (activity_id, booking_date, booking_date) ) assert resp.json['data'][0]['disabled'] == out_of_delay assert resp.json['data'][0]['details']['out_of_delay'] == out_of_delay assert resp.json['data'][0]['details']['activity_type'] == activity_type @pytest.mark.parametrize( 'activity_id, activity_type', [ ('CJ MER', 'mercredi'), ('CJ1', 'vacances'), ], ) def test_get_agenda_endpoint_delay_extrascolaire( app, resource, family_data, activities_full, activity_id, activity_type ): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') content = ''' 1 12/07/2021 X N ''' with mock_data(content, 'GetAgenda'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value=activities_full, ): # always disabled with freezegun.freeze_time('2021-05-31'): resp = app.get( '/caluire-axel/test/get_agenda?NameID=yyy&idpersonne=50632&activity_id=%s&start_date=2021-06-02&end_date=2021-06-02' % activity_id ) assert resp.json['data'][0]['disabled'] is True assert resp.json['data'][0]['details']['out_of_delay'] is True assert resp.json['data'][0]['details']['activity_type'] == activity_type with freezegun.freeze_time('2021-07-11'): resp = app.get( '/caluire-axel/test/get_agenda?NameID=yyy&idpersonne=50632&activity_id=%s&start_date=2021-06-02&end_date=2021-06-02' % activity_id ) assert resp.json['data'][0]['disabled'] is True assert resp.json['data'][0]['details']['out_of_delay'] is True assert resp.json['data'][0]['details']['activity_type'] == activity_type def test_get_agenda_endpoint_delay_class_decouverte(app, resource, family_data, activities_full): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') content = ''' 1 12/07/2021 X N ''' with mock_data(content, 'GetAgenda'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value=activities_full, ): # always disabled with freezegun.freeze_time('2021-05-31'): resp = app.get( '/caluire-axel/test/get_agenda?NameID=yyy&idpersonne=50632&activity_id=%s&start_date=2021-06-02&end_date=2021-06-02' % 'DECFOO' ) assert len(resp.json['data']) == 0 @pytest.mark.parametrize('code', [0, -1, -2, -3, -4]) def test_get_agenda_endpoint_wrong_code(app, resource, family_data, activities, code): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') content = ( ''' %s ''' % code ) with mock_data(content, 'GetAgenda'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value=activities, ): resp = app.get( '/caluire-axel/test/get_agenda?NameID=yyy&idpersonne=50632&activity_id=ELEM&start_date=2020-09-01&end_date=2021-08-31' ) assert resp.json['err_desc'] == 'Wrong agenda status' assert resp.json['err'] == 'agenda-code-error-%s' % code def test_get_agenda_periscolaire_endpoint_axel_error(app, resource, family_data): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') with mock.patch('passerelle.contrib.caluire_axel.schemas.get_famille_individus') as operation: operation.side_effect = AxelError('FooBar') resp = app.get( '/caluire-axel/test/get_agenda_periscolaire?NameID=yyy&idpersonne=50632&start_date=2020-09-01&end_date=2021-08-31' ) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): with mock.patch('passerelle.contrib.caluire_axel.schemas.get_list_activites') as operation: operation.side_effect = AxelError('FooBar') resp = app.get( '/caluire-axel/test/get_agenda_periscolaire?NameID=yyy&idpersonne=50632&start_date=2020-09-01&end_date=2021-08-31' ) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/activities_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetListActivites'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.get_agenda') as operation: operation.side_effect = AxelError('FooBar') resp = app.get( '/caluire-axel/test/get_agenda_periscolaire?NameID=yyy&idpersonne=50632&start_date=2020-09-01&end_date=2021-08-31' ) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' @pytest.mark.parametrize('value', ['foo', '20/01/2020', '2020']) def test_get_agenda_periscolaire_endpoint_bad_date_format(app, resource, value): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') resp = app.get( '/caluire-axel/test/get_agenda_periscolaire?NameID=yyy&idpersonne=50632&start_date=%s&end_date=2021-08-31' % value, status=400, ) assert resp.json['err_desc'] == 'bad date format, should be YYYY-MM-DD' assert resp.json['err'] == 'bad-request' resp = app.get( '/caluire-axel/test/get_agenda_periscolaire?NameID=yyy&idpersonne=50632&start_date=2020-09-01&end_date=%s' % value, status=400, ) assert resp.json['err_desc'] == 'bad date format, should be YYYY-MM-DD' assert resp.json['err'] == 'bad-request' def test_get_agenda_periscolaire_endpoint_no_result(app, resource): resp = app.get( '/caluire-axel/test/get_agenda_periscolaire?NameID=yyy&idpersonne=50632&start_date=2020-09-01&end_date=2021-08-31' ) assert resp.json['err_desc'] == 'Person not found' assert resp.json['err'] == 'not-found' Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): resp = app.get( '/caluire-axel/test/get_agenda_periscolaire?NameID=yyy&idpersonne=zzz&start_date=2020-09-01&end_date=2021-08-31' ) assert resp.json['err_desc'] == 'Child not found' assert resp.json['err'] == 'not-found' def test_get_agenda_periscolaire_endpoint_date_error(app, resource): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): resp = app.get( '/caluire-axel/test/get_agenda_periscolaire?NameID=yyy&idpersonne=50632&start_date=2021-05-31&end_date=2021-05-30', status=400, ) assert resp.json['err_desc'] == 'start_date should be before end_date' assert resp.json['err'] == 'bad-request' resp = app.get( '/caluire-axel/test/get_agenda_periscolaire?NameID=yyy&idpersonne=50632&start_date=2021-09-01&end_date=2022-09-01', status=400, ) assert ( resp.json['err_desc'] == 'start_date and end_date are in different reference year (2021 != 2022)' ) assert resp.json['err'] == 'bad-request' def test_get_agenda_periscolaire_endpoint(app, resource, family_data, activities_full): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') content = ''' 7 26/10/2020 . N 27/10/2020 . N 28/10/2020 . N 29/10/2020 . N 30/10/2020 . N 31/10/2020 . N 01/11/2020 . N ''' with mock_data(content, 'GetAgenda'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value=activities_full, ): resp = app.get( '/caluire-axel/test/get_agenda_periscolaire?NameID=yyy&idpersonne=50632&start_date=2020-09-01&end_date=2021-08-31' ) assert len(resp.json['data']) == 24 assert resp.json['data'][0]['id'] == '50632:NAV MATIN:2020-10-26' assert resp.json['data'][1]['id'] == '50632:ACCMAT:2020-10-26' assert resp.json['data'][2]['id'] == '50632:ECOLELEM:2020-10-26' assert resp.json['data'][3]['id'] == '50632:ETUDES:2020-10-26' assert resp.json['data'][4]['id'] == '50632:GARDERIES:2020-10-26' assert resp.json['data'][5]['id'] == '50632:NAV SOIR:2020-10-26' assert resp.json['data'][6]['id'] == '50632:NAV MATIN:2020-10-27' assert resp.json['data'][7]['id'] == '50632:ACCMAT:2020-10-27' assert resp.json['data'][8]['id'] == '50632:ECOLELEM:2020-10-27' assert resp.json['data'][9]['id'] == '50632:ETUDES:2020-10-27' assert resp.json['data'][10]['id'] == '50632:GARDERIES:2020-10-27' assert resp.json['data'][11]['id'] == '50632:NAV SOIR:2020-10-27' assert resp.json['data'][12]['id'] == '50632:NAV MATIN:2020-10-29' assert resp.json['data'][13]['id'] == '50632:ACCMAT:2020-10-29' assert resp.json['data'][14]['id'] == '50632:ECOLELEM:2020-10-29' assert resp.json['data'][15]['id'] == '50632:ETUDES:2020-10-29' assert resp.json['data'][16]['id'] == '50632:GARDERIES:2020-10-29' assert resp.json['data'][17]['id'] == '50632:NAV SOIR:2020-10-29' assert resp.json['data'][18]['id'] == '50632:NAV MATIN:2020-10-30' assert resp.json['data'][19]['id'] == '50632:ACCMAT:2020-10-30' assert resp.json['data'][20]['id'] == '50632:ECOLELEM:2020-10-30' assert resp.json['data'][21]['id'] == '50632:ETUDES:2020-10-30' assert resp.json['data'][22]['id'] == '50632:GARDERIES:2020-10-30' assert resp.json['data'][23]['id'] == '50632:NAV SOIR:2020-10-30' @pytest.mark.parametrize('code', [0, -1, -2, -3, -4]) def test_get_agenda_periscolaire_endpoint_wrong_code(app, resource, family_data, activities, code): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') content = ( ''' %s ''' % code ) with mock_data(content, 'GetAgenda'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value=activities, ): resp = app.get( '/caluire-axel/test/get_agenda_periscolaire?NameID=yyy&idpersonne=50632&start_date=2020-09-01&end_date=2021-08-31' ) assert resp.json['err_desc'] == 'Wrong agenda status' assert resp.json['err'] == 'agenda-code-error-%s' % code def test_get_agenda_full_endpoint_axel_error(app, resource, family_data): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') with mock.patch('passerelle.contrib.caluire_axel.schemas.get_famille_individus') as operation: operation.side_effect = AxelError('FooBar') resp = app.get( '/caluire-axel/test/get_agenda_full?NameID=yyy&idpersonne=50632&start_date=2020-09-01&end_date=2021-08-31' ) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): with mock.patch('passerelle.contrib.caluire_axel.schemas.get_list_activites') as operation: operation.side_effect = AxelError('FooBar') resp = app.get( '/caluire-axel/test/get_agenda_full?NameID=yyy&idpersonne=50632&start_date=2020-09-01&end_date=2021-08-31' ) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/activities_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetListActivites'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.get_agenda') as operation: operation.side_effect = AxelError('FooBar') resp = app.get( '/caluire-axel/test/get_agenda_full?NameID=yyy&idpersonne=50632&start_date=2020-09-01&end_date=2021-08-31' ) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' @pytest.mark.parametrize('value', ['foo', '20/01/2020', '2020']) def test_get_agenda_full_endpoint_bad_date_format(app, resource, value): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') resp = app.get( '/caluire-axel/test/get_agenda_full?NameID=yyy&idpersonne=50632&start_date=%s&end_date=2021-08-31' % value, status=400, ) assert resp.json['err_desc'] == 'bad date format, should be YYYY-MM-DD' assert resp.json['err'] == 'bad-request' resp = app.get( '/caluire-axel/test/get_agenda_full?NameID=yyy&idpersonne=50632&start_date=2020-09-01&end_date=%s' % value, status=400, ) assert resp.json['err_desc'] == 'bad date format, should be YYYY-MM-DD' assert resp.json['err'] == 'bad-request' def test_get_agenda_full_endpoint_no_result(app, resource): resp = app.get( '/caluire-axel/test/get_agenda_full?NameID=yyy&idpersonne=50632&start_date=2020-09-01&end_date=2021-08-31' ) assert resp.json['err_desc'] == 'Person not found' assert resp.json['err'] == 'not-found' Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): resp = app.get( '/caluire-axel/test/get_agenda_full?NameID=yyy&idpersonne=zzz&start_date=2020-09-01&end_date=2021-08-31' ) assert resp.json['err_desc'] == 'Child not found' assert resp.json['err'] == 'not-found' def test_get_agenda_full_endpoint_date_error(app, resource): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): resp = app.get( '/caluire-axel/test/get_agenda_full?NameID=yyy&idpersonne=50632&start_date=2021-05-31&end_date=2021-05-30', status=400, ) assert resp.json['err_desc'] == 'start_date should be before end_date' assert resp.json['err'] == 'bad-request' resp = app.get( '/caluire-axel/test/get_agenda_full?NameID=yyy&idpersonne=50632&start_date=2021-09-01&end_date=2022-09-01', status=400, ) assert ( resp.json['err_desc'] == 'start_date and end_date are in different reference year (2021 != 2022)' ) assert resp.json['err'] == 'bad-request' def test_get_agenda_full_endpoint(app, resource, family_data, activities_full): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') content = ''' 7 26/10/2020 . N 27/10/2020 . N 28/10/2020 . N 29/10/2020 . N 30/10/2020 . N 31/10/2020 . N 01/11/2020 . N ''' with mock_data(content, 'GetAgenda'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value=activities_full, ): resp = app.get( '/caluire-axel/test/get_agenda_full?NameID=yyy&idpersonne=50632&start_date=2020-09-01&end_date=2021-08-31' ) assert len(resp.json['data']) == 40 assert resp.json['data'][0]['id'] == '50632:NAV MATIN:2020-10-26' assert resp.json['data'][1]['id'] == '50632:ACCMAT:2020-10-26' assert resp.json['data'][2]['id'] == '50632:ECOLELEM:2020-10-26' assert resp.json['data'][3]['id'] == '50632:ETUDES:2020-10-26' assert resp.json['data'][4]['id'] == '50632:GARDERIES:2020-10-26' assert resp.json['data'][5]['id'] == '50632:NAV SOIR:2020-10-26' assert resp.json['data'][6]['id'] == '50632:CJ MER:2020-10-26' assert resp.json['data'][7]['id'] == '50632:CJ1:2020-10-26' assert resp.json['data'][8]['id'] == '50632:NAV MATIN:2020-10-27' assert resp.json['data'][9]['id'] == '50632:ACCMAT:2020-10-27' assert resp.json['data'][10]['id'] == '50632:ECOLELEM:2020-10-27' assert resp.json['data'][11]['id'] == '50632:ETUDES:2020-10-27' assert resp.json['data'][12]['id'] == '50632:GARDERIES:2020-10-27' assert resp.json['data'][13]['id'] == '50632:NAV SOIR:2020-10-27' assert resp.json['data'][14]['id'] == '50632:CJ MER:2020-10-27' assert resp.json['data'][15]['id'] == '50632:CJ1:2020-10-27' assert resp.json['data'][16]['id'] == '50632:NAV MATIN:2020-10-28' assert resp.json['data'][17]['id'] == '50632:ACCMAT:2020-10-28' assert resp.json['data'][18]['id'] == '50632:ECOLELEM:2020-10-28' assert resp.json['data'][19]['id'] == '50632:ETUDES:2020-10-28' assert resp.json['data'][20]['id'] == '50632:GARDERIES:2020-10-28' assert resp.json['data'][21]['id'] == '50632:NAV SOIR:2020-10-28' assert resp.json['data'][22]['id'] == '50632:CJ MER:2020-10-28' assert resp.json['data'][23]['id'] == '50632:CJ1:2020-10-28' assert resp.json['data'][24]['id'] == '50632:NAV MATIN:2020-10-29' assert resp.json['data'][25]['id'] == '50632:ACCMAT:2020-10-29' assert resp.json['data'][26]['id'] == '50632:ECOLELEM:2020-10-29' assert resp.json['data'][27]['id'] == '50632:ETUDES:2020-10-29' assert resp.json['data'][28]['id'] == '50632:GARDERIES:2020-10-29' assert resp.json['data'][29]['id'] == '50632:NAV SOIR:2020-10-29' assert resp.json['data'][30]['id'] == '50632:CJ MER:2020-10-29' assert resp.json['data'][31]['id'] == '50632:CJ1:2020-10-29' assert resp.json['data'][32]['id'] == '50632:NAV MATIN:2020-10-30' assert resp.json['data'][33]['id'] == '50632:ACCMAT:2020-10-30' assert resp.json['data'][34]['id'] == '50632:ECOLELEM:2020-10-30' assert resp.json['data'][35]['id'] == '50632:ETUDES:2020-10-30' assert resp.json['data'][36]['id'] == '50632:GARDERIES:2020-10-30' assert resp.json['data'][37]['id'] == '50632:NAV SOIR:2020-10-30' assert resp.json['data'][38]['id'] == '50632:CJ MER:2020-10-30' assert resp.json['data'][39]['id'] == '50632:CJ1:2020-10-30' @freezegun.freeze_time('2020-09-01') def test_set_agenda_endpoint_axel_error(app, resource, family_data, activities, booking_params): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') booking_params['booking_list'] = ['50632:ELEM:2020-10-30'] with mock.patch('passerelle.contrib.caluire_axel.schemas.get_famille_individus') as operation: operation.side_effect = AxelError('FooBar') resp = app.post_json('/caluire-axel/test/set_agenda?NameID=yyy', params=booking_params) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): with mock.patch('passerelle.contrib.caluire_axel.schemas.get_list_activites') as operation: operation.side_effect = AxelError('FooBar') resp = app.post_json('/caluire-axel/test/set_agenda?NameID=yyy', params=booking_params) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/activities_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetListActivites'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.get_agenda') as operation: operation.side_effect = AxelError('FooBar') resp = app.post_json('/caluire-axel/test/set_agenda?NameID=yyy', params=booking_params) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' content = ''' 1 30/10/2020 . N ''' with mock_data(content, 'GetAgenda'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value=activities, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.set_agenda') as operation: operation.side_effect = AxelError('FooBar') resp = app.post_json('/caluire-axel/test/set_agenda?NameID=yyy', params=booking_params) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' def test_set_agenda_endpoint_no_result(app, resource, booking_params): booking_params['child_id'] = 'zzz' resp = app.post_json('/caluire-axel/test/set_agenda?NameID=yyy', params=booking_params) assert resp.json['err_desc'] == 'Person not found' assert resp.json['err'] == 'not-found' Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): resp = app.post_json('/caluire-axel/test/set_agenda?NameID=yyy', params=booking_params) assert resp.json['err_desc'] == 'Child not found' assert resp.json['err'] == 'not-found' def test_set_agenda_endpoint_date_error(app, resource, booking_params): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): booking_params['start_date'] = '2021-09-01' booking_params['end_date'] = '2021-08-31' resp = app.post_json('/caluire-axel/test/set_agenda?NameID=yyy', params=booking_params, status=400) assert resp.json['err_desc'] == 'start_date should be before end_date' assert resp.json['err'] == 'bad-request' booking_params['end_date'] = '2022-09-01' resp = app.post_json('/caluire-axel/test/set_agenda?NameID=yyy', params=booking_params, status=400) assert ( resp.json['err_desc'] == 'start_date and end_date are in different reference year (2021 != 2022)' ) assert resp.json['err'] == 'bad-request' def test_set_agenda_endpoint(app, resource, family_data, activities, booking_params): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') booking_params['end_date'] = '2020-09-01' with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value=activities, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_bookings', return_value=[], ): resp = app.post_json( '/caluire-axel/test/set_agenda?NameID=yyy', params=booking_params, ) assert resp.json['err'] == 0 assert resp.json['updated'] is True assert resp.json['count'] == 0 @freezegun.freeze_time('2020-08-01') def test_set_agenda_endpoint_multi(app, resource, family_data, booking_params): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') activities = [ { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'ACCMAT', 'LIBELLEACTIVITE': 'Matin', }, { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'ECOLELEM', 'LIBELLEACTIVITE': 'Cantine', }, ] booking_params['end_date'] = '2020-09-11' booking_params['booking_list'] = [ '50632:ACCMAT:2020-09-07', '50632:ACCMAT:2020-09-08', '50632:ECOLELEM:2020-09-07', '50632:ECOLELEM:2020-09-10', ] bookings = [] for activity_id in ['ACCMAT', 'ECOLELEM']: for day in ['2020-09-07', '2020-09-08']: bookings.append( { 'id': '50632:%s:%s' % (activity_id, day), 'disabled': False, 'prefill': False, } ) for day in ['2020-09-10', '2020-09-11']: bookings.append( { 'id': '50632:%s:%s' % (activity_id, day), 'disabled': False, 'prefill': True, } ) with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value={'ACTIVITE': activities}, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_bookings', return_value=bookings, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.set_agenda') as operation: operation.return_value = OperationResult( json_response={'DATA': {'PORTAIL': {'SETAGENDA': {'CODE': 0}}}}, xml_request='', xml_response='', ) resp = app.post_json( '/caluire-axel/test/set_agenda?NameID=yyy', params=booking_params, ) assert resp.json['err'] == 0 assert resp.json['updated'] is True assert resp.json['count'] == 6 assert resp.json['changes'] == [ {'activity_id': 'ACCMAT', 'activity_label': 'Matin', 'day': '2020-09-07', 'booked': True}, {'activity_id': 'ACCMAT', 'activity_label': 'Matin', 'day': '2020-09-08', 'booked': True}, {'activity_id': 'ECOLELEM', 'activity_label': 'Cantine', 'day': '2020-09-07', 'booked': True}, {'activity_id': 'ACCMAT', 'activity_label': 'Matin', 'day': '2020-09-10', 'booked': False}, {'activity_id': 'ACCMAT', 'activity_label': 'Matin', 'day': '2020-09-11', 'booked': False}, {'activity_id': 'ECOLELEM', 'activity_label': 'Cantine', 'day': '2020-09-11', 'booked': False}, ] assert len(operation.call_args_list) == 2 assert operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['IDENTINDIVIDU'] == '50632' assert operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['IDENTACTIVITE'] == 'ACCMAT' assert len(operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR']) == 4 assert ( operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][0]['JOURDATE'] == '2020-09-07' ) assert operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][0]['MATIN'] == 'X' assert ( operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][1]['JOURDATE'] == '2020-09-08' ) assert operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][1]['MATIN'] == 'X' assert ( operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][2]['JOURDATE'] == '2020-09-10' ) assert operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][2]['MATIN'] == 'D' assert ( operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][3]['JOURDATE'] == '2020-09-11' ) assert operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][3]['MATIN'] == 'D' assert operation.call_args_list[1][0][1]['PORTAIL']['SETAGENDA']['IDENTINDIVIDU'] == '50632' assert ( operation.call_args_list[1][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['IDENTACTIVITE'] == 'ECOLELEM' ) assert len(operation.call_args_list[1][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR']) == 2 assert ( operation.call_args_list[1][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][0]['JOURDATE'] == '2020-09-07' ) assert operation.call_args_list[1][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][0]['MATIN'] == 'X' assert ( operation.call_args_list[1][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][1]['JOURDATE'] == '2020-09-11' ) assert operation.call_args_list[1][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][1]['MATIN'] == 'D' @pytest.mark.parametrize( 'booked, ok', [ ([], True), (['50632:ACCMAT:2020-09-07', '50632:CANTINE:2020-09-07'], True), # cantine & accmat are not exlusive (['50632:ACCMAT:2020-09-07', '50632:ACCMAT:2020-09-07'], True), # same day sent twice (['50642:ACCMAT:2020-09-07', '50632:NAV MATIN:2020-09-07'], True), # not the same child (['50632:ACCMAT:2020-09-07', '50632:NAV MATIN:2020-09-07'], False), ], ) @freezegun.freeze_time('2020-08-01') def test_set_agenda_endpoint_multi_matin(app, resource, family_data, booking_params, booked, ok): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') activities = [ { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'CANTINE', 'LIBELLEACTIVITE': 'Cantine', }, { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'ACCMAT', 'LIBELLEACTIVITE': 'Matin', }, { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'NAV MATIN', 'LIBELLEACTIVITE': 'Navette du matin', }, ] booking_params['end_date'] = '2020-09-07' booking_params['booking_list'] = booked bookings = [] for activity_id in ['ACCMAT', 'CANTINE', 'NAV MATIN']: bookings.append( { 'id': '50632:%s:2020-09-07' % activity_id, 'disabled': False, 'prefill': False, } ) with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value={'ACTIVITE': activities}, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_bookings', return_value=bookings, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.set_agenda') as operation: operation.return_value = OperationResult( json_response={'DATA': {'PORTAIL': {'SETAGENDA': {'CODE': 0}}}}, xml_request='', xml_response='', ) if ok: resp = app.post_json( '/caluire-axel/test/set_agenda?NameID=yyy', params=booking_params, ) assert resp.json['err'] == 0 else: resp = app.post_json( '/caluire-axel/test/set_agenda?NameID=yyy', params=booking_params, status=400, ) assert resp.json['err_desc'] == 'not possible to book %s the same day' % ' and '.join( booked ) assert resp.json['err'] == 'bad-request' @pytest.mark.parametrize('prefill', [True, False]) @freezegun.freeze_time('2020-08-01') def test_set_agenda_endpoint_multi_matin_no_changes(app, resource, family_data, booking_params, prefill): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') activities = [ { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'ACCMAT', 'LIBELLEACTIVITE': 'Matin', }, { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'NAV MATIN', 'LIBELLEACTIVITE': 'Navette du matin', }, ] booking_params['end_date'] = '2020-09-07' booking_params['booking_list'] = ['50632:ACCMAT:2020-09-07', '50632:NAV MATIN:2020-09-07'] bookings = [] for activity_id in ['ACCMAT', 'NAV MATIN']: bookings.append( { 'id': '50632:%s:2020-09-07' % activity_id, 'disabled': False, 'prefill': prefill, } ) with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value={'ACTIVITE': activities}, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_bookings', return_value=bookings, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.set_agenda') as operation: operation.return_value = OperationResult( json_response={'DATA': {'PORTAIL': {'SETAGENDA': {'CODE': 0}}}}, xml_request='', xml_response='', ) if prefill: # was already booked, no changes => no error resp = app.post_json( '/caluire-axel/test/set_agenda?NameID=yyy', params=booking_params, ) assert resp.json['err'] == 0 else: resp = app.post_json( '/caluire-axel/test/set_agenda?NameID=yyy', params=booking_params, status=400, ) assert resp.json['err_desc'] == 'not possible to book %s the same day' % ' and '.join( booking_params['booking_list'] ) assert resp.json['err'] == 'bad-request' @pytest.mark.parametrize( 'booked, ok', [ ([], True), (['50632:ETUDES:2020-09-07', '50632:CANTINE:2020-09-07'], True), # cantine & etudes are not exlusive (['50632:GARDERIES:2020-09-07', '50632:GARDERIES:2020-09-07'], True), # same day sent twice (['50632:ETUDES:2020-09-07', '50642:GARDERIES:2020-09-07'], True), # not the same child (['50632:ETUDES:2020-09-07', '50632:GARDERIES:2020-09-07'], False), (['50632:ETUDES:2020-09-07', '50632:NAV SOIR:2020-09-07'], False), (['50632:GARDERIES:2020-09-07', '50632:NAV SOIR:2020-09-07'], False), (['50632:ETUDES:2020-09-07', '50632:GARDERIES:2020-09-07', '50632:NAV SOIR:2020-09-07'], False), ], ) @freezegun.freeze_time('2020-08-01') def test_set_agenda_endpoint_multi_soir(app, resource, family_data, booking_params, booked, ok): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') activities = [ { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'CANTINE', 'LIBELLEACTIVITE': 'Cantine', }, { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'GARDERIES', 'LIBELLEACTIVITE': 'Garderie', }, { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'ETUDES', 'LIBELLEACTIVITE': 'Etudes', }, { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'NAV SOIR', 'LIBELLEACTIVITE': 'Navette du soir', }, ] booking_params['end_date'] = '2020-09-07' booking_params['booking_list'] = booked bookings = [] for activity_id in ['GARDERIES', 'ETUDES', 'CANTINE', 'NAV SOIR']: bookings.append( { 'id': '50632:%s:2020-09-07' % activity_id, 'disabled': False, 'prefill': False, } ) with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value={'ACTIVITE': activities}, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_bookings', return_value=bookings, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.set_agenda') as operation: operation.return_value = OperationResult( json_response={'DATA': {'PORTAIL': {'SETAGENDA': {'CODE': 0}}}}, xml_request='', xml_response='', ) if ok: resp = app.post_json( '/caluire-axel/test/set_agenda?NameID=yyy', params=booking_params, ) assert resp.json['err'] == 0 else: resp = app.post_json( '/caluire-axel/test/set_agenda?NameID=yyy', params=booking_params, status=400, ) assert resp.json['err_desc'] == 'not possible to book %s the same day' % ' and '.join( booked ) assert resp.json['err'] == 'bad-request' @pytest.mark.parametrize('prefill', [True, False]) @freezegun.freeze_time('2020-08-01') def test_set_agenda_endpoint_multi_soir_no_changes(app, resource, family_data, booking_params, prefill): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') activities = [ { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'GARDERIES', 'LIBELLEACTIVITE': 'Garderie', }, { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'ETUDES', 'LIBELLEACTIVITE': 'Etudes', }, { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'NAV SOIR', 'LIBELLEACTIVITE': 'Navette du soir', }, ] booking_params['end_date'] = '2020-09-07' booking_params['booking_list'] = [ '50632:ETUDES:2020-09-07', '50632:GARDERIES:2020-09-07', '50632:NAV SOIR:2020-09-07', ] bookings = [] for activity_id in ['GARDERIES', 'ETUDES', 'NAV SOIR']: bookings.append( { 'id': '50632:%s:2020-09-07' % activity_id, 'disabled': False, 'prefill': prefill, } ) with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value={'ACTIVITE': activities}, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_bookings', return_value=bookings, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.set_agenda') as operation: operation.return_value = OperationResult( json_response={'DATA': {'PORTAIL': {'SETAGENDA': {'CODE': 0}}}}, xml_request='', xml_response='', ) if prefill: # was already booked, no changes => no error resp = app.post_json( '/caluire-axel/test/set_agenda?NameID=yyy', params=booking_params, ) assert resp.json['err'] == 0 else: resp = app.post_json( '/caluire-axel/test/set_agenda?NameID=yyy', params=booking_params, status=400, ) assert resp.json['err_desc'] == 'not possible to book %s the same day' % ' and '.join( booking_params['booking_list'] ) assert resp.json['err'] == 'bad-request' @pytest.mark.parametrize( 'prefill, wanted, expected', [ (True, True, None), # no changes (True, False, False), (False, True, True), (False, False, None), # no changes ], ) @freezegun.freeze_time('2020-08-01') def test_set_agenda_endpoint_prefill_periscolaire( app, resource, family_data, booking_params, prefill, wanted, expected ): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') booking_params['end_date'] = '2020-09-01' for activity_id in ['ACCMAT', 'GARDERIES', 'ETUDES', 'CANTINE', 'FOOBAR', 'NAV MATIN', 'NAV SOIR']: activity = { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': activity_id, 'LIBELLEACTIVITE': 'FOOBAR', } if wanted: booking_params['booking_list'] = ['50632:%s:2020-09-01' % activity_id] with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value={'ACTIVITE': [activity]}, ): bookings = [ { 'id': '50632:%s:2020-09-01' % activity_id, 'disabled': False, 'prefill': prefill, }, ] with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_bookings', return_value=bookings, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.set_agenda') as operation: operation.return_value = OperationResult( json_response={'DATA': {'PORTAIL': {'SETAGENDA': {'CODE': 0}}}}, xml_request='', xml_response='', ) resp = app.post_json( '/caluire-axel/test/set_agenda?NameID=yyy', params=booking_params, ) assert resp.json['err'] == 0 assert resp.json['updated'] is True if expected is not None: assert operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['IDENTINDIVIDU'] == '50632' assert ( operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['IDENTACTIVITE'] == activity_id ) assert len(operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR']) == 1 assert ( operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][0]['JOURDATE'] == '2020-09-01' ) assert ( operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][0]['MATIN'] == 'X' if expected else 'D' ) else: assert len(operation.call_args_list) == 0 @pytest.mark.parametrize('prefill', [True, False]) @pytest.mark.parametrize('wanted', [True, False]) @freezegun.freeze_time('2020-08-01') def test_set_agenda_endpoint_prefill_extrascolaire_and_classe_decouverte( app, resource, family_data, booking_params, prefill, wanted ): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') booking_params['end_date'] = '2020-09-01' for activity_id in ['CJ MER', 'CJVACANCES', 'DECFOO']: activity = { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': activity_id, 'LIBELLEACTIVITE': 'FOOBAR', } if wanted: booking_params['booking_list'] = ['50632:%s:2020-09-01' % activity_id] with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value={'ACTIVITE': [activity]}, ): bookings = [ { 'id': '50632:%s:2020-09-01' % activity_id, 'disabled': False, 'prefill': prefill, }, ] with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_bookings', return_value=bookings, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.set_agenda') as operation: operation.return_value = OperationResult( json_response={'DATA': {'PORTAIL': {'SETAGENDA': {'CODE': 0}}}}, xml_request='', xml_response='', ) resp = app.post_json( '/caluire-axel/test/set_agenda?NameID=yyy', params=booking_params, ) assert resp.json['err'] == 0 assert resp.json['updated'] is True assert len(operation.call_args_list) == 0 # not bookable @pytest.mark.parametrize('disabled', [True, False, None]) @freezegun.freeze_time('2020-08-01') def test_set_agenda_endpoint_disabled(app, resource, family_data, booking_params, disabled): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') activity = { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'FOOBAR', 'LIBELLEACTIVITE': 'FOOBAR', } booking_params['end_date'] = '2020-09-01' booking_params['booking_list'] = ['50632:FOOBAR:2020-09-01'] with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value={'ACTIVITE': [activity]}, ): bookings = [] if disabled is not None: bookings = [ { 'id': '50632:FOOBAR:2020-09-01', 'disabled': disabled, 'prefill': False, }, ] with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_bookings', return_value=bookings, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.set_agenda') as operation: operation.return_value = OperationResult( json_response={'DATA': {'PORTAIL': {'SETAGENDA': {'CODE': 0}}}}, xml_request='', xml_response='', ) resp = app.post_json( '/caluire-axel/test/set_agenda?NameID=yyy', params=booking_params, ) assert resp.json['err'] == 0 assert resp.json['updated'] is True if disabled is False: assert operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['IDENTINDIVIDU'] == '50632' assert ( operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['IDENTACTIVITE'] == 'FOOBAR' ) assert len(operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR']) == 1 assert ( operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][0]['JOURDATE'] == '2020-09-01' ) assert ( operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][0]['MATIN'] == 'X' ) else: assert len(operation.call_args_list) == 0 @pytest.mark.parametrize('code', [-1, -2, -3, -4]) def test_set_agenda_endpoint_wrong_code(app, resource, family_data, activities, booking_params, code): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') booking_params['end_date'] = '2020-09-01' bookings = [ { 'id': '50632:ELEM:2020-09-01', 'disabled': False, 'prefill': True, }, ] content = ( ''' %s ''' % code ) with mock_data(content, 'SetAgenda', data_method='setData'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value=activities, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_bookings', return_value=bookings, ): resp = app.post_json( '/caluire-axel/test/set_agenda?NameID=yyy', params=booking_params, ) assert resp.json['err_desc'] == 'Wrong agenda status' assert resp.json['err'] == 'agenda-code-error-%s' % code @freezegun.freeze_time('2020-09-01') def test_set_agenda_apply_changes_endpoint_axel_error(app, resource, family_data, changes_params): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') changes_params['changes'] = [ {'activity_id': 'ACCMAT', 'activity_label': 'Matin', 'day': '2020-10-30', 'booked': True}, ] with mock.patch('passerelle.contrib.caluire_axel.schemas.get_famille_individus') as operation: operation.side_effect = AxelError('FooBar') resp = app.post_json('/caluire-axel/test/set_agenda_apply_changes?NameID=yyy', params=changes_params) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): with mock.patch('passerelle.contrib.caluire_axel.schemas.get_list_activites') as operation: operation.side_effect = AxelError('FooBar') resp = app.post_json( '/caluire-axel/test/set_agenda_apply_changes?NameID=yyy', params=changes_params ) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/activities_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetListActivites'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.get_agenda') as operation: operation.side_effect = AxelError('FooBar') resp = app.post_json( '/caluire-axel/test/set_agenda_apply_changes?NameID=yyy', params=changes_params ) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' activities = [ { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'ACCMAT', 'LIBELLEACTIVITE': 'Matin', }, ] content = ''' 1 30/10/2020 . N ''' with mock_data(content, 'GetAgenda'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value={'ACTIVITE': activities}, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.set_agenda') as operation: operation.side_effect = AxelError('FooBar') resp = app.post_json( '/caluire-axel/test/set_agenda_apply_changes?NameID=yyy', params=changes_params ) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' def test_set_agenda_apply_changes_endpoint_no_result(app, resource, changes_params): changes_params['child_id'] = 'zzz' resp = app.post_json('/caluire-axel/test/set_agenda_apply_changes?NameID=yyy', params=changes_params) assert resp.json['err_desc'] == 'Person not found' assert resp.json['err'] == 'not-found' Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): resp = app.post_json('/caluire-axel/test/set_agenda_apply_changes?NameID=yyy', params=changes_params) assert resp.json['err_desc'] == 'Child not found' assert resp.json['err'] == 'not-found' def test_set_agenda_apply_changes_endpoint_date_error(app, resource, changes_params): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): changes_params['start_date'] = '2021-09-01' changes_params['end_date'] = '2021-08-31' resp = app.post_json( '/caluire-axel/test/set_agenda_apply_changes?NameID=yyy', params=changes_params, status=400 ) assert resp.json['err_desc'] == 'start_date should be before end_date' assert resp.json['err'] == 'bad-request' changes_params['end_date'] = '2022-09-01' resp = app.post_json( '/caluire-axel/test/set_agenda_apply_changes?NameID=yyy', params=changes_params, status=400 ) assert ( resp.json['err_desc'] == 'start_date and end_date are in different reference year (2021 != 2022)' ) assert resp.json['err'] == 'bad-request' def test_set_agenda_apply_changes_endpoint(app, resource, family_data, activities, changes_params): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') changes_params['end_date'] = '2020-09-01' with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value=activities, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_bookings', return_value=[], ): resp = app.post_json( '/caluire-axel/test/set_agenda_apply_changes?NameID=yyy', params=changes_params, ) assert resp.json['err'] == 0 assert resp.json['updated'] is True assert resp.json['count'] == 0 @freezegun.freeze_time('2020-08-01') def test_set_agenda_apply_changes_endpoint_multi(app, resource, family_data, changes_params): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') activities = [ { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'ACCMAT', 'LIBELLEACTIVITE': 'Matin', }, { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'ECOLELEM', 'LIBELLEACTIVITE': 'Cantine', }, { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'CJ MER', 'LIBELLEACTIVITE': 'FOOBAR', }, { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'CJVACANCES', 'LIBELLEACTIVITE': 'FOOBAR', }, { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'DECFOO', 'LIBELLEACTIVITE': 'FOOBAR', }, ] changes_params['end_date'] = '2020-09-11' changes_params['changes'] = [ {'activity_id': 'ACCMAT', 'activity_label': 'Matin', 'day': '2020-09-07', 'booked': False}, {'activity_id': 'ACCMAT', 'activity_label': 'Matin', 'day': '2020-09-08', 'booked': True}, { 'activity_id': 'ECOLELEM2', 'activity_label': 'Cantine', 'day': '2020-09-07', 'booked': True, }, # cantine, not the same id { 'activity_id': 'ECOLELEM2', 'activity_label': 'Cantine', 'day': '2020-09-10', 'booked': False, }, # cantine, not the same id {'activity_id': 'CJ MER', 'activity_label': 'FOOBAR', 'day': '2020-09-08', 'booked': True}, # ignored { 'activity_id': 'CJVACANCES', 'activity_label': 'FOOBAR', 'day': '2020-09-08', 'booked': True, }, # ignored { 'activity_id': 'DECFOO', 'activity_label': 'FOOBAR', 'day': '2020-09-08', 'booked': True, }, # ignored ] bookings = [] for activity_id in ['ACCMAT', 'ECOLELEM']: for day in ['2020-09-07', '2020-09-08']: bookings.append( { 'id': '50632:%s:%s' % (activity_id, day), 'disabled': False, 'prefill': False, } ) for day in ['2020-09-10', '2020-09-11']: bookings.append( { 'id': '50632:%s:%s' % (activity_id, day), 'disabled': False, 'prefill': True, } ) with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value={'ACTIVITE': activities}, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_bookings', return_value=bookings, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.set_agenda') as operation: operation.return_value = OperationResult( json_response={'DATA': {'PORTAIL': {'SETAGENDA': {'CODE': 0}}}}, xml_request='', xml_response='', ) resp = app.post_json( '/caluire-axel/test/set_agenda_apply_changes?NameID=yyy', params=changes_params, ) assert resp.json['err'] == 0 assert resp.json['updated'] is True assert resp.json['count'] == 3 assert resp.json['changes'] == [ {'activity_id': 'ACCMAT', 'activity_label': 'Matin', 'day': '2020-09-08', 'booked': True}, {'activity_id': 'ECOLELEM', 'activity_label': 'Cantine', 'day': '2020-09-07', 'booked': True}, {'activity_id': 'ECOLELEM', 'activity_label': 'Cantine', 'day': '2020-09-10', 'booked': False}, ] assert len(operation.call_args_list) == 2 assert operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['IDENTINDIVIDU'] == '50632' assert operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['IDENTACTIVITE'] == 'ACCMAT' assert len(operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR']) == 1 assert ( operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][0]['JOURDATE'] == '2020-09-08' ) assert operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][0]['MATIN'] == 'X' assert operation.call_args_list[1][0][1]['PORTAIL']['SETAGENDA']['IDENTINDIVIDU'] == '50632' assert ( operation.call_args_list[1][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['IDENTACTIVITE'] == 'ECOLELEM' ) assert len(operation.call_args_list[1][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR']) == 2 assert ( operation.call_args_list[1][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][0]['JOURDATE'] == '2020-09-07' ) assert operation.call_args_list[1][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][0]['MATIN'] == 'X' assert ( operation.call_args_list[1][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][1]['JOURDATE'] == '2020-09-10' ) assert operation.call_args_list[1][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][1]['MATIN'] == 'D' @freezegun.freeze_time('2020-08-01') def test_set_agenda_apply_changes_endpoint_multi_too_many_cantine_activities( app, resource, family_data, changes_params ): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') # more than one activity "midi" activities = [ { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'ECOLELEM', 'LIBELLEACTIVITE': 'Cantine', }, { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'ECOLELEM2', 'LIBELLEACTIVITE': 'Cantine', }, ] changes_params['end_date'] = '2020-09-11' changes_params['changes'] = [ { 'activity_id': 'ECOLELEM2', 'activity_label': 'Cantine', 'day': '2020-09-07', 'booked': True, }, ] bookings = [ { 'id': '50632:MIDI:2020-09-07', 'disabled': False, 'prefill': False, }, ] with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value={'ACTIVITE': activities}, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_bookings', return_value=bookings, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.set_agenda') as operation: operation.return_value = OperationResult( json_response={'DATA': {'PORTAIL': {'SETAGENDA': {'CODE': 0}}}}, xml_request='', xml_response='', ) resp = app.post_json( '/caluire-axel/test/set_agenda_apply_changes?NameID=yyy', params=changes_params, status=400, ) assert ( resp.json['err_desc'] == 'more than one activity cantine found for this child (ECOLELEM, ECOLELEM2)' ) assert resp.json['err'] == 'bad-request' @freezegun.freeze_time('2020-08-01') def test_set_agenda_apply_changes_endpoint_multi_unkown_activity(app, resource, family_data, changes_params): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') activities = [ { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'ACCMAT', 'LIBELLEACTIVITE': 'Matin', }, ] changes_params['end_date'] = '2020-09-11' changes_params['changes'] = [ {'activity_id': 'ACCMAT', 'activity_label': 'Matin', 'day': '2020-09-07', 'booked': False}, {'activity_id': 'ACCMAT', 'activity_label': 'Matin', 'day': '2020-09-08', 'booked': True}, { 'activity_id': 'ECOLELEM2', 'activity_label': 'Cantine', 'day': '2020-09-07', 'booked': True, }, # cantine, child is not registered { 'activity_id': 'ECOLELEM2', 'activity_label': 'Cantine', 'day': '2020-09-10', 'booked': False, }, # cantine, child is not registered ] bookings = [] for day in ['2020-09-07', '2020-09-08']: bookings.append( { 'id': '50632:ACCMAT:%s' % day, 'disabled': False, 'prefill': False, } ) for day in ['2020-09-10', '2020-09-11']: bookings.append( { 'id': '50632:ACCMAT:%s' % day, 'disabled': False, 'prefill': True, } ) with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value={'ACTIVITE': activities}, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_bookings', return_value=bookings, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.set_agenda') as operation: operation.return_value = OperationResult( json_response={'DATA': {'PORTAIL': {'SETAGENDA': {'CODE': 0}}}}, xml_request='', xml_response='', ) resp = app.post_json( '/caluire-axel/test/set_agenda_apply_changes?NameID=yyy', params=changes_params, ) assert resp.json['err'] == 0 assert resp.json['updated'] is True assert resp.json['count'] == 1 assert resp.json['changes'] == [ {'activity_id': 'ACCMAT', 'activity_label': 'Matin', 'day': '2020-09-08', 'booked': True}, ] assert len(operation.call_args_list) == 1 assert operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['IDENTINDIVIDU'] == '50632' assert operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['IDENTACTIVITE'] == 'ACCMAT' assert len(operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR']) == 1 assert ( operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][0]['JOURDATE'] == '2020-09-08' ) assert operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][0]['MATIN'] == 'X' @freezegun.freeze_time('2020-08-01') def test_set_agenda_apply_changes_endpoint_multi_soir(app, resource, family_data, changes_params): # just a little check, booking exclusivity is handled by _set_agenda method, # already tested for set_agenda endpoint Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') activities = [ { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'GARDERIES', 'LIBELLEACTIVITE': 'Garderie', }, { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'ETUDES', 'LIBELLEACTIVITE': 'Etudes', }, ] changes_params['end_date'] = '2020-09-11' changes_params['changes'] = [ {'activity_id': 'GARDERIES', 'activity_label': 'Garderie', 'day': '2020-09-07', 'booked': True}, ] bookings = [ { 'id': '50632:GARDERIES:2020-09-07', 'disabled': False, 'prefill': False, }, { 'id': '50632:ETUDES:2020-09-07', 'disabled': False, 'prefill': True, }, ] with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value={'ACTIVITE': activities}, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_bookings', return_value=bookings, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.set_agenda') as operation: operation.return_value = OperationResult( json_response={'DATA': {'PORTAIL': {'SETAGENDA': {'CODE': 0}}}}, xml_request='', xml_response='', ) resp = app.post_json( '/caluire-axel/test/set_agenda_apply_changes?NameID=yyy', params=changes_params, status=400, ) assert ( resp.json['err_desc'] == 'not possible to book 50632:ETUDES:2020-09-07 and 50632:GARDERIES:2020-09-07 the same day' ) assert resp.json['err'] == 'bad-request' # already booked, no error bookings = [ { 'id': '50632:GARDERIES:2020-09-07', 'disabled': False, 'prefill': True, }, { 'id': '50632:ETUDES:2020-09-07', 'disabled': False, 'prefill': True, }, ] with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value={'ACTIVITE': activities}, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_bookings', return_value=bookings, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.set_agenda') as operation: operation.return_value = OperationResult( json_response={'DATA': {'PORTAIL': {'SETAGENDA': {'CODE': 0}}}}, xml_request='', xml_response='', ) resp = app.post_json( '/caluire-axel/test/set_agenda_apply_changes?NameID=yyy', params=changes_params, ) assert resp.json['err'] == 0 @freezegun.freeze_time('2020-08-01') def test_set_activity_agenda_typical_week_endpoint_axel_error( app, resource, family_data, activities, week_booking_params ): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') week_booking_params['booking_list'] = ['monday'] with mock.patch('passerelle.contrib.caluire_axel.schemas.get_famille_individus') as operation: operation.side_effect = AxelError('FooBar') resp = app.post_json( '/caluire-axel/test/set_activity_agenda_typical_week?NameID=yyy', params=week_booking_params ) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): with mock.patch('passerelle.contrib.caluire_axel.schemas.get_list_activites') as operation: operation.side_effect = AxelError('FooBar') resp = app.post_json( '/caluire-axel/test/set_activity_agenda_typical_week?NameID=yyy', params=week_booking_params ) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/activities_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetListActivites'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.get_agenda') as operation: operation.side_effect = AxelError('FooBar') resp = app.post_json( '/caluire-axel/test/set_activity_agenda_typical_week?NameID=yyy', params=week_booking_params, ) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' content = ''' 1 07/09/2020 . N ''' with mock_data(content, 'GetAgenda'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value=activities, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.set_agenda') as operation: operation.side_effect = AxelError('FooBar') resp = app.post_json( '/caluire-axel/test/set_activity_agenda_typical_week?NameID=yyy', params=week_booking_params, ) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' def test_set_activity_agenda_typical_week_endpoint_no_result(app, resource, week_booking_params): week_booking_params['child_id'] = 'zzz' resp = app.post_json( '/caluire-axel/test/set_activity_agenda_typical_week?NameID=yyy', params=week_booking_params ) assert resp.json['err_desc'] == 'Person not found' assert resp.json['err'] == 'not-found' Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): resp = app.post_json( '/caluire-axel/test/set_activity_agenda_typical_week?NameID=yyy', params=week_booking_params ) assert resp.json['err_desc'] == 'Child not found' assert resp.json['err'] == 'not-found' def test_set_activity_agenda_typical_week_endpoint_date_error(app, resource, week_booking_params): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/family_info.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'GetFamilleIndividus'): week_booking_params['start_date'] = '2021-09-01' week_booking_params['end_date'] = '2021-08-31' resp = app.post_json( '/caluire-axel/test/set_activity_agenda_typical_week?NameID=yyy', params=week_booking_params, status=400, ) assert resp.json['err_desc'] == 'start_date should be before end_date' assert resp.json['err'] == 'bad-request' week_booking_params['end_date'] = '2022-09-01' resp = app.post_json( '/caluire-axel/test/set_activity_agenda_typical_week?NameID=yyy', params=week_booking_params, status=400, ) assert ( resp.json['err_desc'] == 'start_date and end_date are in different reference year (2021 != 2022)' ) assert resp.json['err'] == 'bad-request' def test_set_activity_agenda_typical_week_endpoint( app, resource, family_data, activities, week_booking_params ): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value=activities, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_bookings', return_value=[], ): resp = app.post_json( '/caluire-axel/test/set_activity_agenda_typical_week?NameID=yyy', params=week_booking_params, ) assert resp.json['err'] == 0 assert resp.json['updated'] is True assert resp.json['count'] == 0 @pytest.mark.parametrize('prefill', [True, False]) @freezegun.freeze_time('2020-08-01') def test_set_activity_agenda_typical_week_endpoint_prefill_periscolaire( app, resource, family_data, week_booking_params, prefill ): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') for activity_id in ['ACCMAT', 'GARDERIES', 'ETUDES', 'CANTINE', 'FOOBAR', 'NAV MATIN', 'NAV SOIR']: activity = { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': activity_id, 'LIBELLEACTIVITE': 'FOOBAR', } week_booking_params['booking_list'] = ['monday'] week_booking_params['activity_id'] = activity_id with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value={'ACTIVITE': [activity]}, ): bookings = [ { 'id': '50632:%s:2020-09-07' % activity_id, 'disabled': False, 'prefill': prefill, }, { 'id': '50632:%s:2020-09-08' % activity_id, 'disabled': False, 'prefill': prefill, }, { 'id': '50632:%s:2020-09-10' % activity_id, 'disabled': False, 'prefill': prefill, }, { 'id': '50632:%s:2020-09-11' % activity_id, 'disabled': False, 'prefill': prefill, }, ] with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_bookings', return_value=bookings, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.set_agenda') as operation: operation.return_value = OperationResult( json_response={'DATA': {'PORTAIL': {'SETAGENDA': {'CODE': 0}}}}, xml_request='', xml_response='', ) resp = app.post_json( '/caluire-axel/test/set_activity_agenda_typical_week?NameID=yyy', params=week_booking_params, ) assert resp.json['err'] == 0 assert resp.json['updated'] is True assert operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['IDENTINDIVIDU'] == '50632' assert ( operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['IDENTACTIVITE'] == activity_id ) if prefill is True: assert len(operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR']) == 3 for i, day in enumerate(['2020-09-08', '2020-09-10', '2020-09-11']): assert ( operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][i][ 'JOURDATE' ] == day ) assert ( operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][i]['MATIN'] == 'D' ) else: assert len(operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR']) == 1 assert ( operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][0]['JOURDATE'] == '2020-09-07' ) assert ( operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][0]['MATIN'] == 'X' ) @freezegun.freeze_time('2020-08-01') def test_set_activity_agenda_typical_week_endpoint_extrascolaire_and_classe_decouverte( app, resource, family_data, week_booking_params, ): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') for activity_id in ['CJ MER', 'CJVACANCES', 'DECFOO']: activity = { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': activity_id, 'LIBELLEACTIVITE': 'FOOBAR', } week_booking_params['booking_list'] = ['monday'] week_booking_params['activity_id'] = activity_id with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value={'ACTIVITE': [activity]}, ): bookings = [ { 'id': '50632:%s:2020-09-07' % activity_id, 'disabled': False, 'prefill': False, }, ] with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_bookings', return_value=bookings, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.set_agenda') as operation: operation.return_value = OperationResult( json_response={'DATA': {'PORTAIL': {'SETAGENDA': {'CODE': 0}}}}, xml_request='', xml_response='', ) resp = app.post_json( '/caluire-axel/test/set_activity_agenda_typical_week?NameID=yyy', params=week_booking_params, status=400, ) assert resp.json['err_desc'] == 'Not available for this activity' assert resp.json['err'] == 'bad-request' @pytest.mark.parametrize('disabled', [True, False, None]) @freezegun.freeze_time('2020-08-01') def test_set_activity_agenda_typical_week_endpoint_disabled( app, resource, family_data, week_booking_params, disabled ): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') activity = { 'ENTREE': '2020-09-02', 'SORTIE': '2021-08-31', 'IDENTACTIVITE': 'FOOBAR', 'LIBELLEACTIVITE': 'FOOBAR', } week_booking_params['booking_list'] = ['monday'] week_booking_params['activity_id'] = 'FOOBAR' with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value={'ACTIVITE': [activity]}, ): bookings = [] if disabled is not None: bookings = [ { 'id': '50632:FOOBAR:2020-09-07', 'disabled': disabled, 'prefill': False, }, ] with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_bookings', return_value=bookings, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.set_agenda') as operation: operation.return_value = OperationResult( json_response={'DATA': {'PORTAIL': {'SETAGENDA': {'CODE': 0}}}}, xml_request='', xml_response='', ) resp = app.post_json( '/caluire-axel/test/set_activity_agenda_typical_week?NameID=yyy', params=week_booking_params, ) assert resp.json['err'] == 0 assert resp.json['updated'] is True if disabled is False: assert operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['IDENTINDIVIDU'] == '50632' assert ( operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['IDENTACTIVITE'] == 'FOOBAR' ) assert len(operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR']) == 1 assert ( operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][0]['JOURDATE'] == '2020-09-07' ) assert ( operation.call_args_list[0][0][1]['PORTAIL']['SETAGENDA']['ACTIVITE']['JOUR'][0]['MATIN'] == 'X' ) else: assert len(operation.call_args_list) == 0 @pytest.mark.parametrize('code', [-1, -2, -3, -4]) def test_set_activity_agenda_typical_week_endpoint_wrong_code( app, resource, family_data, activities, week_booking_params, code ): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') bookings = [ { 'id': '50632:ELEM:2020-09-07', 'disabled': False, 'prefill': True, }, ] content = ( ''' %s ''' % code ) with mock_data(content, 'SetAgenda', data_method='setData'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_child_activities', return_value=activities, ): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_bookings', return_value=bookings, ): resp = app.post_json( '/caluire-axel/test/set_activity_agenda_typical_week?NameID=yyy', params=week_booking_params, ) assert resp.json['err_desc'] == 'Wrong agenda status' assert resp.json['err'] == 'agenda-code-error-%s' % code def test_invoices_endpoint_axel_error(app, resource): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') with mock.patch('passerelle.contrib.caluire_axel.schemas.get_factures_a_payer') as operation: operation.side_effect = AxelError('FooBar') resp = app.get('/caluire-axel/test/regie/MAREGIE/invoices?NameID=yyy') assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' content = ''' -3 ''' with mock_data(content, 'GetFacturesaPayer'): resp = app.get('/caluire-axel/test/regie/MAREGIE/invoices?NameID=yyy') assert resp.json['err_desc'] == 'Wrong get-invoices status' assert resp.json['err'] == 'get-invoices-code-error--3' def test_invoices_endpoint_no_result(app, resource): resp = app.get('/caluire-axel/test/regie/MAREGIE/invoices?NameID=yyy') assert resp.json['err_desc'] == 'Person not found' assert resp.json['err'] == 'not-found' def test_invoices_endpoint_no_invoice(app, resource): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') content = ''' 0 ''' with mock_data(content, 'GetFacturesaPayer'): resp = app.get('/caluire-axel/test/regie/MAREGIE/invoices?NameID=yyy') assert resp.json['err'] == 0 assert resp.json['data'] == [] @freezegun.freeze_time('2019-12-12') def test_invoices_endpoint(app, resource): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/invoices.xml') with open(filepath) as xml: content = ( ''' %s ''' % xml.read() ) with mock_data(content, 'GetFacturesaPayer'): resp = app.get('/caluire-axel/test/regie/MAREGIE/invoices?NameID=yyy') assert resp.json['err'] == 0 assert resp.json['data'] == [ { 'id': 'XXX-42', 'display_id': '42', 'label': 'PRESTATIONS PERISCOLAIRES SEPTEMBRE-OCTOBRE 2019', 'amount': '4.94', 'total_amount': '44.94', 'amount_paid': '40.00', 'online_payment': False, 'created': '2019-11-12', 'pay_limit_date': '2019-12-04', 'has_pdf': True, 'paid': False, 'vendor': { 'caluire-axel': { 'IDFACTURE': 42, 'MONTANT': '44.94', 'ENCAISSE': '40.00', 'FACTURATION': 'PRESTATIONS PERISCOLAIRES SEPTEMBRE-OCTOBRE 2019', 'ECHEANCE': '2019-12-04', 'EMISSION': '2019-11-12', 'EXISTEPDF': True, } }, }, { 'id': 'XXX-43', 'display_id': '43', 'label': 'PRESTATIONS PERISCOLAIRES NOVEMBRE 2019', 'amount': '44.94', 'total_amount': '44.94', 'amount_paid': '0.00', 'online_payment': True, 'created': '2019-12-12', 'pay_limit_date': '2020-01-04', 'has_pdf': False, 'paid': False, 'vendor': { 'caluire-axel': { 'IDFACTURE': 43, 'FACTURATION': 'PRESTATIONS PERISCOLAIRES NOVEMBRE 2019', 'MONTANT': '44.94', 'ENCAISSE': '0.00', 'ECHEANCE': '2020-01-04', 'EMISSION': '2019-12-12', 'EXISTEPDF': False, } }, }, ] def test_invoices_history_endpoint_axel_error(app, resource): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') with mock.patch('passerelle.contrib.caluire_axel.schemas.get_list_factures') as operation: operation.side_effect = AxelError('FooBar') resp = app.get('/caluire-axel/test/regie/MAREGIE/invoices/history?NameID=yyy') assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' content = ''' -3 ''' with mock_data(content, 'GetListFactures'): resp = app.get('/caluire-axel/test/regie/MAREGIE/invoices/history?NameID=yyy') assert resp.json['err_desc'] == 'Wrong get-historical-invoices status' assert resp.json['err'] == 'get-historical-invoices-code-error--3' def test_invoices_history_endpoint_bad_request(app, resource): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') with mock_data(None, 'GetListFactures'): resp = app.get( '/caluire-axel/test/regie/MAREGIE/invoices/history?NameID=yyy&nb_mounts_limit=not_a_number', status=400, ) assert resp.json['err_desc'] == 'nb_mounts_limit must be an integer' assert resp.json['err'] == 'bad-request' def test_invoices_history_endpoint_no_result(app, resource): resp = app.get('/caluire-axel/test/regie/MAREGIE/invoices/history?NameID=yyy') assert resp.json['err_desc'] == 'Person not found' assert resp.json['err'] == 'not-found' def test_invoices_history_endpoint_no_invoice(app, resource): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') content = ''' 0 ''' with mock_data(content, 'GetListFactures'): resp = app.get('/caluire-axel/test/regie/MAREGIE/invoices/history?NameID=yyy') assert resp.json['err'] == 0 assert resp.json['data'] == [] @freezegun.freeze_time('2019-12-12') def test_invoices_history_endpoint(app, resource): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/invoices.xml') with open(filepath) as xml: content = ( ''' %s ''' % xml.read() ) with mock_data(content, 'GetListFactures'): resp = app.get('/caluire-axel/test/regie/MAREGIE/invoices/history?NameID=yyy') assert resp.json['err'] == 0 assert resp.json['data'] == [ { 'id': 'historical-XXX-42', 'display_id': '42', 'label': 'PRESTATIONS PERISCOLAIRES SEPTEMBRE-OCTOBRE 2019', 'amount': 0, 'created': '2019-11-12', 'total_amount': '44.94', 'online_payment': False, 'pay_limit_date': '', 'has_pdf': True, 'paid': False, 'vendor': { 'caluire-axel': { 'IDFACTURE': 42, 'MONTANT': '44.94', 'ENCAISSE': '40.00', 'FACTURATION': 'PRESTATIONS PERISCOLAIRES SEPTEMBRE-OCTOBRE 2019', 'ECHEANCE': '2019-12-04', 'EMISSION': '2019-11-12', 'EXISTEPDF': True, } }, }, { 'id': 'historical-XXX-43', 'display_id': '43', 'label': 'PRESTATIONS PERISCOLAIRES NOVEMBRE 2019', 'amount': 0, 'created': '2019-12-12', 'total_amount': '44.94', 'online_payment': False, 'pay_limit_date': '', 'has_pdf': False, 'paid': False, 'vendor': { 'caluire-axel': { 'IDFACTURE': 43, 'FACTURATION': 'PRESTATIONS PERISCOLAIRES NOVEMBRE 2019', 'MONTANT': '44.94', 'ENCAISSE': '0.00', 'ECHEANCE': '2020-01-04', 'EMISSION': '2019-12-12', 'EXISTEPDF': False, } }, }, ] def test_invoice_endpoint_axel_error(app, resource): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') with mock.patch('passerelle.contrib.caluire_axel.schemas.get_factures_a_payer') as operation: operation.side_effect = AxelError('FooBar') resp = app.get('/caluire-axel/test/regie/MAREGIE/invoice/XXX-42?NameID=yyy') assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' def test_invoice_endpoint_bad_request(app, resource): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') with mock_data(None, 'GetListFactures'): resp = app.get( '/caluire-axel/test/regie/MAREGIE/invoice/historical-XXX-42?NameID=yyy&nb_mounts_limit=not_a_number', status=400, ) assert resp.json['err_desc'] == 'nb_mounts_limit must be an integer' assert resp.json['err'] == 'bad-request' content = ''' -3 ''' with mock_data(content, 'GetFacturesaPayer'): resp = app.get('/caluire-axel/test/regie/MAREGIE/invoice/XXX-42?NameID=yyy') assert resp.json['err_desc'] == 'Wrong get-invoices status' assert resp.json['err'] == 'get-invoices-code-error--3' content = ''' -3 ''' with mock_data(content, 'GetListFactures'): resp = app.get('/caluire-axel/test/regie/MAREGIE/invoice/historical-XXX-42?NameID=yyy') assert resp.json['err_desc'] == 'Wrong get-historical-invoices status' assert resp.json['err'] == 'get-historical-invoices-code-error--3' @freezegun.freeze_time('2019-12-12') def test_invoice_endpoint_no_result(app, resource): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/invoices.xml') with open(filepath) as xml: invoices = xml.read() content = ( ''' %s ''' % invoices ) with mock_data(content, 'GetFacturesaPayer'): resp = app.get('/caluire-axel/test/regie/MAREGIE/invoice/XXX-35?NameID=yyy') assert resp.json['err_desc'] == 'Invoice not found' assert resp.json['err'] == 'not-found' with mock_data(content, 'GetFacturesaPayer'): resp = app.get('/caluire-axel/test/regie/MAREGIE/invoice/XXX-44?NameID=yyy') assert resp.json['err_desc'] == 'Invoice not found' assert resp.json['err'] == 'not-found' content = ( ''' %s ''' % invoices ) with mock_data(content, 'GetListFactures'): resp = app.get('/caluire-axel/test/regie/MAREGIE/invoice/historical-XXX-35?NameID=yyy') assert resp.json['err_desc'] == 'Invoice not found' assert resp.json['err'] == 'not-found' with mock_data(content, 'GetListFactures'): resp = app.get('/caluire-axel/test/regie/MAREGIE/invoice/historical-XXX-44?NameID=yyy') assert resp.json['err_desc'] == 'Invoice not found' assert resp.json['err'] == 'not-found' @freezegun.freeze_time('2019-12-04') def test_invoice_endpoint(app, resource): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/invoices.xml') with open(filepath) as xml: invoices = xml.read() content = ( ''' %s ''' % invoices ) with mock_data(content, 'GetFacturesaPayer'): resp = app.get('/caluire-axel/test/regie/MAREGIE/invoice/XXX-42?NameID=yyy') assert resp.json['err'] == 0 assert resp.json['data'] == { 'id': 'XXX-42', 'display_id': '42', 'label': 'PRESTATIONS PERISCOLAIRES SEPTEMBRE-OCTOBRE 2019', 'amount': '4.94', 'total_amount': '44.94', 'amount_paid': '40.00', 'online_payment': True, 'created': '2019-11-12', 'pay_limit_date': '2019-12-04', 'has_pdf': True, 'paid': False, 'vendor': { 'caluire-axel': { 'IDFACTURE': 42, 'MONTANT': '44.94', 'ENCAISSE': '40.00', 'FACTURATION': 'PRESTATIONS PERISCOLAIRES SEPTEMBRE-OCTOBRE 2019', 'ECHEANCE': '2019-12-04', 'EMISSION': '2019-11-12', 'EXISTEPDF': True, } }, } content = ( ''' %s ''' % invoices ) with mock_data(content, 'GetListFactures'): resp = app.get('/caluire-axel/test/regie/MAREGIE/invoice/historical-XXX-42?NameID=yyy') assert resp.json['err'] == 0 assert resp.json['data'] == { 'id': 'historical-XXX-42', 'display_id': '42', 'label': 'PRESTATIONS PERISCOLAIRES SEPTEMBRE-OCTOBRE 2019', 'amount': 0, 'total_amount': '44.94', 'online_payment': False, 'created': '2019-11-12', 'pay_limit_date': '', 'has_pdf': True, 'paid': False, 'vendor': { 'caluire-axel': { 'IDFACTURE': 42, 'MONTANT': '44.94', 'ENCAISSE': '40.00', 'FACTURATION': 'PRESTATIONS PERISCOLAIRES SEPTEMBRE-OCTOBRE 2019', 'ECHEANCE': '2019-12-04', 'EMISSION': '2019-11-12', 'EXISTEPDF': True, }, }, } @freezegun.freeze_time('2019-12-04') def test_invoice_endpoint_anonymously(app, resource): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/invoices.xml') with open(filepath) as xml: invoices = xml.read() content = ( ''' %s ''' % invoices ) with mock_data(content, 'GetFacturesaPayer'): resp = app.get('/caluire-axel/test/regie/MAREGIE/invoice/XXX-42') assert resp.json['err'] == 0 assert resp.json['data'] == { 'id': 'XXX-42', 'display_id': '42', 'label': 'PRESTATIONS PERISCOLAIRES SEPTEMBRE-OCTOBRE 2019', 'amount': '4.94', 'total_amount': '44.94', 'amount_paid': '40.00', 'online_payment': True, 'created': '2019-11-12', 'pay_limit_date': '2019-12-04', 'has_pdf': True, 'paid': False, 'vendor': { 'caluire-axel': { 'IDFACTURE': 42, 'MONTANT': '44.94', 'ENCAISSE': '40.00', 'FACTURATION': 'PRESTATIONS PERISCOLAIRES SEPTEMBRE-OCTOBRE 2019', 'ECHEANCE': '2019-12-04', 'EMISSION': '2019-11-12', 'EXISTEPDF': True, } }, } content = ( ''' %s ''' % invoices ) with mock_data(content, 'GetListFactures'): resp = app.get('/caluire-axel/test/regie/MAREGIE/invoice/historical-XXX-42') assert resp.json['err'] == 0 assert resp.json['data'] == { 'id': 'historical-XXX-42', 'display_id': '42', 'label': 'PRESTATIONS PERISCOLAIRES SEPTEMBRE-OCTOBRE 2019', 'amount': 0, 'total_amount': '44.94', 'online_payment': False, 'created': '2019-11-12', 'pay_limit_date': '', 'has_pdf': True, 'paid': False, 'vendor': { 'caluire-axel': { 'IDFACTURE': 42, 'MONTANT': '44.94', 'ENCAISSE': '40.00', 'FACTURATION': 'PRESTATIONS PERISCOLAIRES SEPTEMBRE-OCTOBRE 2019', 'ECHEANCE': '2019-12-04', 'EMISSION': '2019-11-12', 'EXISTEPDF': True, }, }, } def test_invoice_pdf_endpoint_axel_error(app, resource): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') with mock.patch('passerelle.contrib.caluire_axel.schemas.get_factures_a_payer') as operation: operation.side_effect = AxelError('FooBar') resp = app.get('/caluire-axel/test/regie/MAREGIE/invoice/XXX-42/pdf?NameID=yyy', status=404) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/invoices.xml') with open(filepath) as xml: content = ( ''' %s ''' % xml.read() ) with mock_data(content, 'GetFacturesaPayer'): with mock.patch('passerelle.contrib.caluire_axel.schemas.get_pdf_facture') as operation: operation.side_effect = AxelError('FooBar') resp = app.get('/caluire-axel/test/regie/MAREGIE/invoice/XXX-42/pdf?NameID=yyy', status=404) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' def test_invoice_pdf_endpoint_bad_request(app, resource): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') with mock_data(None, 'GetListFactures'): resp = app.get( '/caluire-axel/test/regie/MAREGIE/invoice/historical-XXX-42/pdf?NameID=yyy&nb_mounts_limit=not_a_number', status=404, ) assert resp.json['err_desc'] == 'nb_mounts_limit must be an integer' assert resp.json['err'] == 'bad-request' @freezegun.freeze_time('2019-12-13') def test_invoice_pdf_endpoint_no_result(app, resource): resp = app.get('/caluire-axel/test/regie/MAREGIE/invoice/XXX-42/pdf?NameID=yyy', status=404) assert resp.json['err_desc'] == 'Person not found' assert resp.json['err'] == 'not-found' Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/invoices.xml') with open(filepath) as xml: content = ( ''' %s ''' % xml.read() ) with mock_data(content, 'GetFacturesaPayer'): resp = app.get('/caluire-axel/test/regie/MAREGIE/invoice/XXX-35/pdf?NameID=yyy', status=404) assert resp.json['err_desc'] == 'Invoice not found' assert resp.json['err'] == 'not-found' with mock_data(content, 'GetFacturesaPayer'): resp = app.get('/caluire-axel/test/regie/MAREGIE/invoice/XXX-44/pdf?NameID=yyy', status=404) assert resp.json['err_desc'] == 'Invoice not found' assert resp.json['err'] == 'not-found' with mock_data(content, 'GetFacturesaPayer'): resp = app.get('/caluire-axel/test/regie/MAREGIE/invoice/XXX-43/pdf?NameID=yyy', status=404) assert resp.json['err_desc'] == 'PDF not available' assert resp.json['err'] == 'not-available' pdf_content = ''' 1 ''' with mock.patch('passerelle.contrib.caluire_axel.models.CaluireAxel.get_invoice') as invoice: invoice.return_value = {'has_pdf': True, 'display_id': '42'} with mock_data(pdf_content, 'GetPdfFacture'): resp = app.get('/caluire-axel/test/regie/MAREGIE/invoice/XXX-42/pdf?NameID=yyy', status=404) assert resp.json['err_desc'] == 'PDF error' assert resp.json['err'] == 'error' def test_invoice_pdf_endpoint(app, resource): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') pdf_content = ''' 1 aGVsbG8gd29ybGQ= ''' with mock.patch('passerelle.contrib.caluire_axel.models.CaluireAxel.get_invoice') as invoice: invoice.return_value = {'has_pdf': True, 'display_id': '42'} with mock_data(pdf_content, 'GetPdfFacture'): app.get('/caluire-axel/test/regie/MAREGIE/invoice/XXX-42/pdf?NameID=yyy') assert invoice.call_args_list[0][1]['historical'] is False with mock.patch('passerelle.contrib.caluire_axel.models.CaluireAxel.get_invoice') as invoice: invoice.return_value = {'has_pdf': True, 'display_id': '42'} with mock_data(pdf_content, 'GetPdfFacture'): app.get('/caluire-axel/test/regie/MAREGIE/invoice/historical-XXX-42/pdf?NameID=yyy') assert invoice.call_args_list[0][1]['historical'] is True def test_pay_invoice_endpoint_axel_error(app, resource): payload = { 'transaction_date': '2021-06-15T12:00:00', 'transaction_id': 'foo', } Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') with mock.patch('passerelle.contrib.caluire_axel.schemas.get_factures_a_payer') as operation: operation.side_effect = AxelError('FooBar') resp = app.post_json('/caluire-axel/test/regie/MAREGIE/invoice/XXX-42/pay?NameID=yyy', params=payload) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/invoices.xml') with open(filepath) as xml: content = ( ''' %s ''' % xml.read() ) with mock_data(content, 'GetFacturesaPayer'): with mock.patch('passerelle.contrib.caluire_axel.schemas.set_paiement') as operation: operation.side_effect = AxelError('FooBar') resp = app.post_json( '/caluire-axel/test/regie/MAREGIE/invoice/XXX-42/pay?NameID=yyy', params=payload ) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' for key in ('xml_request', 'xml_response', 'regie_id', 'family_id', 'invoice', 'post_data', 'kwargs'): assert key in resp.json['data'].keys() content2 = ''' -3 ''' with mock.patch('passerelle.contrib.caluire_axel.models.CaluireAxel.soap_client') as client: client.return_value.service.getData.return_value = XML_RESPONSE_TEMPLATE % ( 'GetFacturesaPayer', content, ) client.return_value.service.setData.return_value = XML_RESPONSE_TEMPLATE % ('SetPaiement', content2) resp = app.post_json('/caluire-axel/test/regie/MAREGIE/invoice/XXX-42/pay?NameID=yyy', params=payload) assert resp.json['err_desc'] == 'Wrong pay-invoice status' assert resp.json['err'] == 'pay-invoice-code-error--3' def test_pay_invoice_endpoint_bad_request(app, resource): resp = app.post_json( '/caluire-axel/test/regie/MAREGIE/invoice/XXX-42/pay?NameID=yyy', params={}, status=400 ) assert resp.json['err_desc'] == "'transaction_date' is a required property" @freezegun.freeze_time('2019-12-04') def test_pay_invoice_endpoint_no_result(app, resource): payload = { 'transaction_date': '2021-06-15T12:00:00', 'transaction_id': 'foo', } filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/invoices.xml') with open(filepath) as xml: content = ( ''' %s ''' % xml.read() ) with mock_data(content, 'GetFacturesaPayer'): resp = app.post_json('/caluire-axel/test/regie/MAREGIE/invoice/XXX-35/pay?NameID=yyy', params=payload) assert resp.json['err_desc'] == 'Invoice not found' assert resp.json['err'] == 'not-found' with mock_data(content, 'GetFacturesaPayer'): resp = app.post_json('/caluire-axel/test/regie/MAREGIE/invoice/XXX-44/pay?NameID=yyy', params=payload) assert resp.json['err_desc'] == 'Invoice not found' assert resp.json['err'] == 'not-found' def test_pay_invoice_endpoint_wrong_response(app, resource): payload = { 'transaction_date': '2021-06-15T12:00:00', 'transaction_id': 'foo', } with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_invoice', return_value={'amount': '44.9'}, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.set_paiement') as operation: operation.return_value = OperationResult( json_response={'DATA': {'PORTAIL': {}}}, xml_request='', xml_response='', ) resp = app.post_json( '/caluire-axel/test/regie/MAREGIE/invoice/XXX-42/pay?NameID=yyy', params=payload, status=500, ) assert resp.json['err'] == 'pay-invoice-code-response-error' assert resp.json['err_desc'] == 'Wrong pay-invoice response' for key in 'regie_id', 'family_id', 'invoice', 'post_data', 'kwargs', 'result': assert key in resp.json['data'].keys() with mock.patch('passerelle.contrib.caluire_axel.schemas.set_paiement') as operation: operation.return_value = OperationResult( json_response={'DATA': {'PORTAIL': {'SETPAIEMENT': {'CODE': 'oups'}}}}, xml_request='', xml_response='', ) resp = app.post_json( '/caluire-axel/test/regie/MAREGIE/invoice/XXX-42/pay?NameID=yyy', params=payload, status=500, ) assert resp.json['err'] == 'pay-invoice-code-response-error' assert resp.json['err_desc'] == 'Wrong pay-invoice response' for key in 'regie_id', 'family_id', 'invoice', 'post_data', 'kwargs', 'result': assert key in resp.json['data'].keys() def test_pay_invoice_endpoint(app, resource): payload = { 'transaction_date': '2021-06-15T12:00:00', 'transaction_id': 'foo', } Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/invoices.xml') with open(filepath) as xml: content = ( ''' %s ''' % xml.read() ) content2 = ''' 0 ''' with mock.patch('passerelle.contrib.caluire_axel.models.CaluireAxel.soap_client') as client: client.return_value.service.getData.return_value = XML_RESPONSE_TEMPLATE % ( 'GetFacturesaPayer', content, ) client.return_value.service.setData.return_value = XML_RESPONSE_TEMPLATE % ('SetPaiement', content2) resp = app.post_json('/caluire-axel/test/regie/MAREGIE/invoice/XXX-42/pay?NameID=yyy', params=payload) assert resp.json['err'] == 0 assert resp.json['created'] is True def test_pay_invoice_providing_mode_reglement(app, resource): payload = { 'transaction_date': '2021-06-15T12:00:00', 'transaction_id': 'foo', } with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_invoice', return_value={'amount': '44.9'}, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.set_paiement') as operation: operation.return_value = OperationResult( json_response={'DATA': {'PORTAIL': {'SETPAIEMENT': {'CODE': 0}}}}, xml_request='', xml_response='', ) resp = app.post_json( '/caluire-axel/test/regie/MAREGIE/invoice/XXX-42/pay?NameID=yyy', params=payload ) assert operation.call_args[0][1]['PORTAIL']['SETPAIEMENT']['IDENTMODEREGLEMENT'] == 'INCB' assert resp.json['err'] == 0 assert resp.json['created'] is True def test_upload_attachments_endpoint_axel_error(app, resource, family_data, upload_attachments_params): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') with mock.patch('passerelle.contrib.caluire_axel.schemas.get_famille_individus') as operation: operation.side_effect = AxelError('FooBar') resp = app.post_json( '/caluire-axel/test/upload_attachments?NameID=yyy', params=upload_attachments_params ) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): with mock.patch('passerelle.contrib.caluire_axel.schemas.set_pieces') as operation: operation.side_effect = AxelError('FooBar') resp = app.post_json( '/caluire-axel/test/upload_attachments?NameID=yyy', params=upload_attachments_params ) assert resp.json['err_desc'] == 'Axel error: FooBar' assert resp.json['err'] == 'error' @pytest.mark.parametrize('value', ['foo', '20/01/2020', '2020']) def test_upload_attachments_endpoint_bad_date_format(app, resource, upload_attachments_params, value): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') upload_attachments_params['reference_date'] = value resp = app.post_json( '/caluire-axel/test/upload_attachments?NameID=yyy', params=upload_attachments_params, status=400, ) assert resp.json['err_desc'] == "reference_date: '%s' does not match '[0-9]{4}-[0-9]{2}-[0-9]{2}'" % value assert resp.json['err'] == 1 def test_upload_attachments_endpoint_no_result(app, resource, family_data, upload_attachments_params): resp = app.post_json('/caluire-axel/test/upload_attachments?NameID=yyy', params=upload_attachments_params) assert resp.json['err_desc'] == 'Person not found' assert resp.json['err'] == 'not-found' Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): upload_attachments_params['child_id'] = 'zzz' resp = app.post_json( '/caluire-axel/test/upload_attachments?NameID=yyy', params=upload_attachments_params, ) assert resp.json['err_desc'] == 'Child not found' assert resp.json['err'] == 'not-found' def test_upload_attachments(app, resource, family_data, upload_attachments_params): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') filepath = os.path.join(os.path.dirname(__file__), 'data/caluire_axel/upload_attachments.xml') with open(filepath) as xml: content = xml.read() with mock_data(content, 'SetPieces', data_method='setData'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): resp = app.post_json( '/caluire-axel/test/upload_attachments?NameID=yyy', params=upload_attachments_params, ) assert resp.json['err'] == 0 assert resp.json['created'] def test_upload_attachments_wrong_code(app, resource, family_data, upload_attachments_params): Link.objects.create(resource=resource, name_id='yyy', family_id='XXX', person_id='42') code = -1 content = ( ''' 0 ID card %s Passport ''' % code ) with mock_data(content, 'SetPieces', data_method='setData'): with mock.patch( 'passerelle.contrib.caluire_axel.models.CaluireAxel.get_family_data', return_value=family_data, ): resp = app.post_json( '/caluire-axel/test/upload_attachments?NameID=yyy', params=upload_attachments_params, ) assert resp.json['err_desc'] == 'Wrong upload-attachments status' assert resp.json['err'] == 'upload-attachments-code-error-%s' % code