Projet

Général

Profil

0003-toulouse-maelis-provide-add-supplied-document-endpoi.patch

Nicolas Roche, 20 décembre 2022 20:52

Télécharger (17,7 ko)

Voir les différences:

Subject: [PATCH 3/3] toulouse-maelis: provide add-supplied-document endpoint
 (#72532)

 functests/toulouse_maelis/conftest.py         |   3 +-
 functests/toulouse_maelis/data/201x201.jpg    | Bin 0 -> 795 bytes
 functests/toulouse_maelis/test_family.py      |  39 +++++++
 .../contrib/toulouse_maelis/family_schemas.py |  60 ++++++++++
 passerelle/contrib/toulouse_maelis/models.py  |  32 +++++
 tests/data/toulouse_maelis/201x201.jpg        | Bin 0 -> 795 bytes
 .../R_add_supplied_document.xml               |   7 ++
 tests/test_toulouse_maelis.py                 | 110 ++++++++++++++++++
 8 files changed, 250 insertions(+), 1 deletion(-)
 create mode 100644 functests/toulouse_maelis/data/201x201.jpg
 create mode 100644 tests/data/toulouse_maelis/201x201.jpg
 create mode 100644 tests/data/toulouse_maelis/R_add_supplied_document.xml
functests/toulouse_maelis/conftest.py
408 408
    create_result = resp.json()
409 409
    assert create_result['err'] == 0
410 410
    print('\ncreate DUI: %s' % str(create_result['data']['number']))
411 411
    data = diff_family(conn, name_id, 'test_create_family.json')
412 412

  
413 413
    return {
414 414
        'name_id': name_id,  # linked
415 415
        'family_id': str(create_result['data']['number']),
416
        'family_payload': create_family_payload,
416 417
        'lastname': lastname,
417 418
        'rl1_num': data['RL1']['num'],
418
        'family_payload': create_family_payload,
419
        'bart_num': data['childList'][0]['num'],
419 420
        'data': data,
420 421
    }
421 422

  
422 423

  
423 424
@pytest.fixture(scope='session')
424 425
def update_data(request, conn):
425 426
    name_id = request.config.getoption('--nameid')
426 427
    lastname = request.config.getoption('--lastname')
functests/toulouse_maelis/test_family.py
1
import base64
1 2
import copy
2 3

  
3 4
import pytest
4 5
import requests
6
from django.utils.encoding import force_str
5 7

  
6 8
from .conftest import diff, diff_child, diff_family, diff_rlg, link, read_family, unlink
7 9

  
8 10
FAMILY_RESET_PAYLOAD = {
9 11
    'category': 'AUTR',
10 12
    'situation': 'AUTR',
11 13
    'rl1': {
12 14
        'civility': 'MR',  # no effect
......
871 873
        child_id,
872 874
        person_id,
873 875
    )
874 876
    resp = requests.get(url)
875 877
    resp.raise_for_status()
876 878
    res = resp.json()
877 879
    assert res['err'] == 0
878 880
    assert res['data']['personInfo']['firstname'] == 'ABRAHAM JEBEDIAH'
881

  
882

  
883
def test_add_supplied_document(conn, create_data):
884
    unlink(conn, create_data['name_id'])
885
    link(conn, create_data)
886

  
887
    # push on family
888
    payload = {
889
        'documentList/0/code': '46',
890
        'documentList/0/depositDate': '2022-12-20',
891
        'documentList/0/file': {  # w.c.s. file field
892
            'filename': '201x201.jpg',
893
            'content_type': 'image/jpeg',
894
            'content': force_str(base64.b64encode(open('data/201x201.jpg', 'rb').read())),
895
        },
896
    }
897
    url = conn + '/add-supplied-document?NameID=%s' % create_data['name_id']
898
    resp = requests.post(url, json=payload)
899
    resp.raise_for_status()
900
    res = resp.json()
901
    assert res['err'] == 0
902

  
903
    # push on RL
904
    payload['numPerson'] = create_data['rl1_num']
905
    url = conn + '/add-supplied-document?NameID=%s' % create_data['name_id']
906
    resp = requests.post(url, json=payload)
907
    resp.raise_for_status()
908
    res = resp.json()
909
    assert res['err'] == 0
910

  
911
    # push on childe
912
    payload['numPerson'] = create_data['bart_num']
913
    url = conn + '/add-supplied-document?NameID=%s' % create_data['name_id']
914
    resp = requests.post(url, json=payload)
915
    resp.raise_for_status()
916
    res = resp.json()
917
    assert res['err'] == 0
passerelle/contrib/toulouse_maelis/family_schemas.py
712 712
        'cdquo': {
713 713
            'description': 'Code du quotient (depuis référentiel)',
714 714
            'type': 'string',
715 715
            'pattern': '.+',
716 716
        },
717 717
    },
718 718
    'additionalProperties': False,
719 719
}
720

  
721
WCS_FILE_SCHEMA = {
722
    '$schema': 'http://json-schema.org/draft-04/schema#',
723
    'title': 'WCS File',
724
    'description': 'Champ W.C.S. de type ficher',
725
    'type': 'object',
726
    'required': ['filename', 'content_type', 'content'],
727
    'properties': {
728
        'filename': {
729
            'description': "Nom du ficher",
730
            'type': 'string',
731
        },
732
        'content_type': {
733
            'description': "Type MIME",
734
            'type': 'string',
735
        },
736
        'content': {
737
            'description': "Contenu",
738
            'type': 'string',
739
        },
740
    },
741
}
742

  
743
SUPPLIED_DOCUMENT_SCHEMA = {
744
    '$schema': 'http://json-schema.org/draft-04/schema#',
745
    'title': 'Supplied document',
746
    'description': 'Ajoute un document pour une famille, un responsable légal ou un enfant',
747
    'type': 'object',
748
    'required': ['code', 'file'],
749
    'properties': {
750
        'code': {
751
            'description': 'Code de la pièce (depuis référentiel)',
752
            'type': 'string',
753
            'pattern': '.+',
754
        },
755
        'depositDate': {
756
            'description': 'Date de dépôt (date du jour si non transmise) ',
757
            'type': 'string',
758
            'pattern': '^([0-9]{4}-[0-9]{2}-[0-9]{2}){0,1}$',
759
        },
760
        'file': WCS_FILE_SCHEMA,
761
    },
762
}
763

  
764
SUPPLIED_DOCUMENTS_SCHEMA = {
765
    '$schema': 'http://json-schema.org/draft-04/schema#',
766
    'title': 'Supplied documents',
767
    'description': 'Ajoute des documents pour une famille, un responsable légal ou un enfant',
768
    'type': 'object',
769
    'required': ['documentList'],
770
    'properties': {
771
        'numPerson': {
772
            'description': "Numéro du responsable légal de l'enfant",
773
            'type': 'string',
774
        },
775
        'documentList': {'type': 'array', 'items': SUPPLIED_DOCUMENT_SCHEMA},
776
    },
777
    'unflatten': True,
778
    'additionalProperties': False,
779
}
passerelle/contrib/toulouse_maelis/models.py
8 8
# This program is distributed in the hope that it will be useful,
9 9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10 10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 11
# GNU Affero General Public License for more details.
12 12
#
13 13
# You should have received a copy of the GNU Affero General Public License
14 14
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
15 15

  
16
import base64
16 17
from urllib.parse import urljoin
17 18

  
18 19
import zeep
19 20
from django.contrib.postgres.fields import JSONField
20 21
from django.db import models
21 22
from django.utils.timezone import now
22 23
from zeep.helpers import serialize_object
23 24
from zeep.wsse.username import UsernameToken
......
1557 1558
    )
1558 1559
    def update_child_indicator(self, request, NameID, child_id, post_data):
1559 1560
        self.get_link(NameID)
1560 1561
        self.assert_update_indicator_payload_in_referential('ChildIndicator', post_data)
1561 1562

  
1562 1563
        self.call('Family', 'updatePersonIndicatorList', numPerson=child_id, **post_data)
1563 1564
        return {'data': 'ok'}
1564 1565

  
1566
    @endpoint(
1567
        display_category='Famille',
1568
        description='Ajoute un document pour une famille, un responsable légal ou un enfant',
1569
        name='add-supplied-document',
1570
        perm='can_access',
1571
        parameters={
1572
            'NameID': {'description': 'Publik NameID'},
1573
        },
1574
        post={'request_body': {'schema': {'application/json': family_schemas.SUPPLIED_DOCUMENTS_SCHEMA}}},
1575
    )
1576
    def add_supplied_document(self, request, NameID, post_data):
1577
        family_id = self.get_link(NameID).family_id
1578
        for i in range(0, len(post_data.get('documentList', []))):
1579
            self.assert_post_data_in_referential('Document', post_data, ['documentList', i, 'code'])
1580

  
1581
        for item in post_data['documentList']:
1582
            file = item.pop('file')
1583
            item['filename'] = file['filename']
1584
            item['fileSupplied'] = {
1585
                'dataHandler': base64.b64decode(file['content']),
1586
                'fileType': file['content_type'],
1587
                'name': file['filename'],
1588
            }
1589
        payload = {'addSuppliedDocumentRequestBean': post_data}
1590
        payload['addSuppliedDocumentRequestBean']['numDossier'] = family_id
1591
        response = self.call('Family', 'addSuppliedDocument', **payload)
1592
        data = serialize_object(response)
1593
        if data != 'OK':
1594
            raise APIError('maelis fails to add the supplied document')
1595
        return {'data': 'ok'}
1596

  
1565 1597
    @endpoint(
1566 1598
        display_category='Facture',
1567 1599
        description="Ajout d'autorisation de prélèvement",
1568 1600
        name='add-direct-debit-order',
1569 1601
        perm='can_access',
1570 1602
        parameters={'NameID': {'description': 'Publik NameID'}},
1571 1603
        post={
1572 1604
            'request_body': {'schema': {'application/json': invoice_schemas.ADD_DIRECT_DEBIT_ORDER_SCHEMA}}
tests/data/toulouse_maelis/R_add_supplied_document.xml
1
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
2
  <soap:Body>
3
    <ns2:addSuppliedDocumentResponse xmlns:ns2="family.ws.maelis.sigec.com">
4
      <addSuppliedDocumentResultBean>%s</addSuppliedDocumentResultBean>
5
    </ns2:addSuppliedDocumentResponse>
6
  </soap:Body>
7
</soap:Envelope>
tests/test_toulouse_maelis.py
8 8
# This program is distributed in the hope that it will be useful,
9 9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10 10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 11
# GNU Affero General Public License for more details.
12 12
#
13 13
# You should have received a copy of the GNU Affero General Public License
14 14
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
15 15

  
16
import base64
16 17
import logging
17 18
import os
18 19
from unittest import mock
19 20

  
20 21
import pytest
21 22
import responses
23
from django.utils.encoding import force_str
22 24
from requests.exceptions import ConnectionError
23 25
from zeep import Settings
24 26

  
25 27
from passerelle.contrib.toulouse_maelis.models import Link, Referential, ToulouseMaelis
26 28
from passerelle.utils.jsonresponse import APIError
27 29
from passerelle.utils.soap import SOAPError
28 30
from tests.utils import FakedResponse, ResponsesSoap, generic_endpoint_url, setup_access_rights
29 31

  
30 32
TEST_BASE_DIR = os.path.join(os.path.dirname(__file__), 'data', 'toulouse_maelis')
31 33

  
32 34

  
33 35
def get_xml_file(filename):
34 36
    with open(os.path.join(TEST_BASE_DIR, filename), 'rb') as desc:
35 37
        return desc.read()
36 38

  
37 39

  
40
def get_media_file(filename):
41
    with open(os.path.join(TEST_BASE_DIR, "%s" % filename), 'rb') as desc:
42
        return desc.read()
43

  
44

  
38 45
CONNECTION_ERROR = ConnectionError('No address associated with hostname')
39 46
FAMILY_SERVICE_WSDL = FakedResponse(content=get_xml_file('FamilyService.wsdl'), status_code=200)
40 47
ACTIVITY_SERVICE_WSDL = FakedResponse(content=get_xml_file('ActivityService.wsdl'), status_code=200)
41 48
INVOICE_SERVICE_WSDL = FakedResponse(content=get_xml_file('InvoiceService.wsdl'), status_code=200)
42 49
FAILED_AUTH = FakedResponse(content=get_xml_file('R_failed_authentication.xml'), status_code=500)
43 50
ISWSRUNNING_TRUE = FakedResponse(content=get_xml_file('R_is_ws_running.xml') % b'true', status_code=200)
44 51
ISWSRUNNING_FALSE = FakedResponse(content=get_xml_file('R_is_ws_running.xml') % b'false', status_code=200)
45 52

  
......
3302 3309
    resp = app.post_json(url + '?NameID=local&child_id=613880', params=params)
3303 3310
    assert resp.json['err'] == 'wrong-key'
3304 3311
    assert (
3305 3312
        resp.json['err_desc']
3306 3313
        == "indicatorList/0/code key value 'plop' do not belong to 'ChildIndicator' required referential"
3307 3314
    )
3308 3315

  
3309 3316

  
3317
def test_add_supplied_document(family_service, con, app):
3318
    def request_check(request):
3319
        assert request.documentList[0]['fileSupplied']['dataHandler'] == get_media_file('201x201.jpg')
3320

  
3321
    family_service.add_soap_response(
3322
        'addSuppliedDocument',
3323
        get_xml_file('R_add_supplied_document.xml') % b'OK',
3324
        request_check=request_check,
3325
    )
3326
    url = get_endpoint('add-supplied-document')
3327
    params = {
3328
        'numPerson': '613880',
3329
        'documentList/0/code': '46',
3330
        'documentList/0/depositDate': '2022-12-20',
3331
        'documentList/0/file': {  # w.c.s. file field
3332
            'filename': '201x201.jpg',
3333
            'content_type': 'image/jpeg',
3334
            'content': force_str(base64.b64encode(get_media_file('201x201.jpg'))),
3335
        },
3336
    }
3337

  
3338
    Link.objects.create(resource=con, family_id='1312', name_id='local')
3339
    resp = app.post_json(url + '?NameID=local', params=params)
3340
    assert resp.json['err'] == 0
3341
    assert resp.json['data'] == 'ok'
3342

  
3343

  
3344
def test_add_supplied_document_not_linked_error(con, app):
3345
    url = get_endpoint('add-supplied-document')
3346
    params = {
3347
        'documentList': [],
3348
    }
3349

  
3350
    resp = app.post_json(url + '?NameID=local', params=params)
3351
    assert resp.json['err'] == 'not-linked'
3352
    assert resp.json['err_desc'] == 'User not linked to family'
3353

  
3354

  
3355
def test_add_supplied_document_empty_referential_key_error(con, app):
3356
    url = get_endpoint('add-supplied-document')
3357
    params = {
3358
        'documentList/0/code': '',
3359
        'documentList/0/depositDate': '2022-12-20',
3360
        'documentList/0/file': {  # w.c.s. file field
3361
            'filename': '201x201.jpg',
3362
            'content_type': 'image/jpeg',
3363
            'content': force_str(base64.b64encode(get_media_file('201x201.jpg'))),
3364
        },
3365
    }
3366

  
3367
    Link.objects.create(resource=con, family_id='1312', name_id='local')
3368
    resp = app.post_json(url + '?NameID=local', params=params, status=400)
3369
    assert resp.json['err'] == 1
3370
    assert resp.json['err_desc'] == "documentList/0/code: '' does not match '.+'"
3371

  
3372

  
3373
def test_add_supplied_document_wrong_referential_key_error(con, app):
3374
    url = get_endpoint('add-supplied-document')
3375
    params = {
3376
        'documentList/0/code': 'plop',
3377
        'documentList/0/depositDate': '2022-12-20',
3378
        'documentList/0/file': {  # w.c.s. file field
3379
            'filename': '201x201.jpg',
3380
            'content_type': 'image/jpeg',
3381
            'content': force_str(base64.b64encode(get_media_file('201x201.jpg'))),
3382
        },
3383
    }
3384

  
3385
    Link.objects.create(resource=con, family_id='1312', name_id='local')
3386
    resp = app.post_json(url + '?NameID=local', params=params)
3387
    assert resp.json['err'] == 'wrong-key'
3388
    assert (
3389
        resp.json['err_desc']
3390
        == "documentList/0/code key value 'plop' do not belong to 'Document' required referential"
3391
    )
3392

  
3393

  
3394
def test_add_supplied_document_maelis_error(family_service, con, app):
3395
    def request_check(request):
3396
        assert request.documentList[0]['fileSupplied']['dataHandler'] == get_media_file('201x201.jpg')
3397

  
3398
    family_service.add_soap_response(
3399
        'addSuppliedDocument',
3400
        get_xml_file('R_add_supplied_document.xml') % b'KO',
3401
        request_check=request_check,
3402
    )
3403
    url = get_endpoint('add-supplied-document')
3404
    params = {
3405
        'documentList/0/code': '46',
3406
        'documentList/0/depositDate': '2022-12-20',
3407
        'documentList/0/file': {  # w.c.s. file field
3408
            'filename': '201x201.jpg',
3409
            'content_type': 'image/jpeg',
3410
            'content': force_str(base64.b64encode(get_media_file('201x201.jpg'))),
3411
        },
3412
    }
3413

  
3414
    Link.objects.create(resource=con, family_id='1312', name_id='local')
3415
    resp = app.post_json(url + '?NameID=local', params=params)
3416
    assert resp.json['err'] == 1
3417
    assert resp.json['err_desc'] == 'maelis fails to add the supplied document'
3418

  
3419

  
3310 3420
def test_add_direct_debit_order(invoice_service, con, app):
3311 3421
    def request_check(request):
3312 3422
        assert request.dossierNumber == 1312
3313 3423

  
3314 3424
    invoice_service.add_soap_response(
3315 3425
        'addDirectDebitOrder', get_xml_file('R_add_direct_debit_order.xml'), request_check=request_check
3316 3426
    )
3317 3427
    url = get_endpoint('add-direct-debit-order')
3318
-