Projet

Général

Profil

0003-toulouse_maelis-add-PAI-webservice-69045.patch

Nicolas Roche, 13 septembre 2022 19:43

Télécharger (16,8 ko)

Voir les différences:

Subject: [PATCH 3/5] toulouse_maelis: add PAI webservice (#69045)

 passerelle/contrib/toulouse_maelis/models.py  | 23 +++++++
 passerelle/contrib/toulouse_maelis/schemas.py |  7 +-
 .../toulouse_maelis/Q_update_child_pai.xml    | 18 +++++
 .../toulouse_maelis/R_update_child_pai.xml    |  5 ++
 .../R_update_child_pai_soap_error.xml         | 15 +++++
 tests/test_toulouse_maelis.py                 | 66 +++++++++++++++++++
 6 files changed, 131 insertions(+), 3 deletions(-)
 create mode 100644 tests/data/toulouse_maelis/Q_update_child_pai.xml
 create mode 100644 tests/data/toulouse_maelis/R_update_child_pai.xml
 create mode 100644 tests/data/toulouse_maelis/R_update_child_pai_soap_error.xml
passerelle/contrib/toulouse_maelis/models.py
148 148
        for rlg in 'RL1', 'RL2':
149 149
            add_text_value('Civility', data, [rlg, 'civility'])
150 150
            add_text_value('Quality', data, [rlg, 'quality'])
151 151
            add_text_value('Complement', data, [rlg, 'adresse', 'numComp'])
152 152
            add_text_value('CSP', data, [rlg, 'profession', 'codeCSP'])
153 153
        for child in data['childList']:
154 154
            add_text_value('Sex', child, ['sexe'])
155 155
            add_text_value('DietCode', child, ['dietcode'])
156
            add_text_value('PAI', child, ['paiInfoBean', 'code'])
156 157
        for kind in ('authorized', 'emergency'):
157 158
            for person in data[kind + 'PersonList']:
158 159
                add_text_value('Civility', person, ['civility'])
159 160
                add_text_value('Quality', person, ['quality'])
160 161
        return data
161 162

  
162 163
    def replace_null_values(self, dico):
163 164
        '''send null fields as empty SOAP tag to tell maelis to empty the value'''
......
596 597
        methods=['post'],
597 598
    )
598 599
    def update_child_dietcode(self, request, NameID, child_id, dietcode):
599 600
        self.get_link(NameID)
600 601

  
601 602
        self.call('Family', 'createOrUpdateChildDiet', personNumber=child_id, code=dietcode)
602 603
        return {'data': 'ok'}
603 604

  
605
    @endpoint(
606
        display_category='Famille',
607
        description="Créer ou mettre à jour les informations relatives au PAI d'un enfant",
608
        name='update-child-pai',
609
        perm='can_access',
610
        parameters={
611
            'NameID': {'description': 'Publik NameID'},
612
            'child_id': {'description': "Numéro de l'enfant"},
613
        },
614
        post={'request_body': {'schema': {'application/json': schemas.PAIINFO_SCHEMA}}},
615
    )
616
    def update_child_pai(self, request, NameID, child_id, post_data):
617
        self.get_link(NameID)
618

  
619
        # use None to empty date passed as an empty string by date filter
620
        for key in 'dateDeb', 'dateFin':
621
            if post_data[key] == '':
622
                post_data[key] = None
623

  
624
        self.call('Family', 'updateChildPAI', personNumber=child_id, **post_data)
625
        return {'data': 'ok'}
626

  
604 627

  
605 628
class Link(models.Model):
606 629
    resource = models.ForeignKey(ToulouseMaelis, on_delete=models.CASCADE)
607 630
    name_id = models.CharField(blank=False, max_length=256)
608 631
    family_id = models.CharField(blank=False, max_length=128)
609 632
    created = models.DateTimeField(auto_now_add=True)
610 633
    updated = models.DateTimeField(auto_now=True)
611 634

  
passerelle/contrib/toulouse_maelis/schemas.py
454 454
PAIINFO_SCHEMA = {
455 455
    '$schema': 'http://json-schema.org/draft-04/schema#',
456 456
    'title': 'PAI Info',
457 457
    'description': "Informations médicales",
458 458
    'oneOf': [
459 459
        {'type': 'null'},
460 460
        {
461 461
            'type': 'object',
462
            'required': ['code'],
462 463
            'properties': {
463 464
                'code': {
464 465
                    'description': 'Code',
465
                    'oneOf': [{'type': 'null'}, {'type': 'string'}],
466
                    'type': 'string',
466 467
                },
467 468
                'dateDeb': {
468 469
                    'description': 'Date de début',
469 470
                    'type': 'string',
470
                    'pattern': '^[0-9]{4}-[0-9]{2}-[0-9]{2}$',
471
                    'pattern': '^([0-9]{4}-[0-9]{2}-[0-9]{2}){0,1}$',
471 472
                },
472 473
                'dateFin': {
473 474
                    'description': 'Date de fin',
474 475
                    'type': 'string',
475
                    'pattern': '^[0-9]{4}-[0-9]{2}-[0-9]{2}$',
476
                    'pattern': '^([0-9]{4}-[0-9]{2}-[0-9]{2}){0,1}$',
476 477
                },
477 478
                'description': {
478 479
                    'description': 'Texte libre de description (max 500 caractères)',
479 480
                    'oneOf': [{'type': 'null'}, {'type': 'string'}],
480 481
                },
481 482
            },
482 483
        },
483 484
    ],
tests/data/toulouse_maelis/Q_update_child_pai.xml
1
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
2
  <soap-env:Header>
3
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
4
      <wsse:UsernameToken>
5
        <wsse:Username>maelis-webservice</wsse:Username>
6
        <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">maelis-password</wsse:Password>
7
      </wsse:UsernameToken>
8
    </wsse:Security>
9
  </soap-env:Header>
10
  <soap-env:Body>
11
    <ns0:updateChildPAI xmlns:ns0="family.ws.maelis.sigec.com">
12
      <personNumber>613878</personNumber>
13
      <code>PAIALI</code>
14
      <dateDeb>2022-01-01</dateDeb>
15
      <description>some text</description>
16
    </ns0:updateChildPAI>
17
  </soap-env:Body>
18
</soap-env:Envelope>
tests/data/toulouse_maelis/R_update_child_pai.xml
1
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
2
  <soap:Body>
3
    <ns2:updateChildPAIResponse xmlns:ns2="family.ws.maelis.sigec.com"/>
4
  </soap:Body>
5
</soap:Envelope>
tests/data/toulouse_maelis/R_update_child_pai_soap_error.xml
1
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
2
  <soap:Body>
3
    <soap:Fault>
4
      <faultcode>soap:Server</faultcode>
5
      <faultstring>Une erreur est survenue : java.sql.SQLException: ORA-12899: valeur trop grande pour la colonne "MAELIS"."H_PERS"."ER_DESCPAI" (réelle : 800, maximum : 500)
6
</faultstring>
7
      <detail>
8
        <ns1:MaelisFamilyException xmlns:ns1="family.ws.maelis.sigec.com">
9
          <message xmlns:ns2="family.ws.maelis.sigec.com">Une erreur est survenue : java.sql.SQLException: ORA-12899: valeur trop grande pour la colonne "MAELIS"."H_PERS"."ER_DESCPAI" (réelle : 800, maximum : 500)
10
</message>
11
        </ns1:MaelisFamilyException>
12
      </detail>
13
    </soap:Fault>
14
  </soap:Body>
15
</soap:Envelope>
tests/test_toulouse_maelis.py
60 60
    content=get_xml_file('R_is_child_exists.xml') % b'false', status_code=200
61 61
)
62 62
CREATE_FAMILY = FakedResponse(content=get_xml_file('R_create_family.xml'), status_code=200)
63 63
CREATE_FAMILY_ERR = FakedResponse(content=get_xml_file('R_create_family_error.xml'), status_code=200)
64 64
UPDATE_FAMILY = FakedResponse(content=get_xml_file('R_update_family.xml'), status_code=200)
65 65
UPDATE_FAMILY_ERR = FakedResponse(content=get_xml_file('R_update_family_error.xml'), status_code=200)
66 66
UPDATE_FAMILY_500 = FakedResponse(content=get_xml_file('R_update_family_soap_error.xml'), status_code=500)
67 67
UPDATE_DIETCODE = FakedResponse(content=get_xml_file('R_update_child_dietcode.xml'), status_code=200)
68
UPDATE_PAI = FakedResponse(content=get_xml_file('R_update_child_pai.xml'), status_code=200)
69
UPDATE_PAI_500 = FakedResponse(content=get_xml_file('R_update_child_pai_soap_error.xml'), status_code=500)
68 70

  
69 71

  
70 72
def assert_sent_payload(mocked_post, query_file):
71 73
    soap_sent = etree.tostring(etree.fromstring(mocked_post.call_args.kwargs['data']), pretty_print=True)
72 74
    expected = etree.tostring(etree.fromstring(get_xml_file(query_file)), pretty_print=True)
73 75
    assert soap_sent.decode() == expected.decode()
74 76

  
75 77

  
......
519 521
    mocked_post.side_effect = [
520 522
        READ_FAMILY,
521 523
        READ_CATEGORIES,
522 524
        READ_SITUATIONS,
523 525
        READ_CIVILITIES,
524 526
        READ_QUALITIES,
525 527
        READ_CSP,
526 528
        READ_DIETCODE,
529
        READ_PAI,
527 530
    ]
528 531
    url = get_endpoint('read-family')
529 532
    Link.objects.create(resource=con, family_id='1312', name_id='local')
530 533

  
531 534
    resp = app.get(url + '?NameID=local')
532 535
    assert resp.json['err'] == 0
533 536
    data = resp.json['data']
534 537
    del data['RL1']
......
598 601
        'indicatorList': [],
599 602
        'subscribeSchoolList': [],
600 603
        'mother': {'num': 613963, 'civility': 'MME', 'firstname': 'JANE', 'lastname': 'DOE'},
601 604
        'father': {'num': 613878, 'civility': 'M.', 'firstname': 'JHON', 'lastname': 'DOE'},
602 605
        'rl': None,
603 606
        'subscribeActivityList': [],
604 607
        'paiInfoBean': {
605 608
            'code': 'PAIALI',
609
            'code_text': 'ALIMENTAIRE',
606 610
            'dateDeb': '2022-01-01T00:00:00+01:00',
607 611
            'dateFin': '2022-12-31T00:00:00+01:00',
608 612
            'description': 'bla bla PAI',
609 613
        },
610 614
    }
611 615
    assert resp.json['data']['childList'][0]['fsl'] == {
612 616
        'dateDeb': '2022-01-01T00:00:00+01:00',
613 617
        'dateFin': '2022-12-31T00:00:00+01:00',
......
683 687
    mocked_post.side_effect = [
684 688
        READ_FAMILY,
685 689
        READ_CATEGORIES,
686 690
        READ_SITUATIONS,
687 691
        READ_CIVILITIES,
688 692
        READ_QUALITIES,
689 693
        READ_CSP,
690 694
        READ_DIETCODE,
695
        READ_PAI,
691 696
    ]
692 697
    url = get_endpoint('read-rl')
693 698
    Link.objects.create(resource=con, family_id='1312', name_id='local')
694 699

  
695 700
    resp = app.get(url + '?NameID=local&rl_id=613878')
696 701
    assert resp.json['err'] == 0
697 702
    assert resp.json['data']['firstname'] == 'JHON'
698 703

  
......
704 709
    mocked_post.side_effect = [
705 710
        READ_FAMILY,
706 711
        READ_CATEGORIES,
707 712
        READ_SITUATIONS,
708 713
        READ_CIVILITIES,
709 714
        READ_QUALITIES,
710 715
        READ_CSP,
711 716
        READ_DIETCODE,
717
        READ_PAI,
712 718
    ]
713 719
    url = get_endpoint('read-rl')
714 720
    Link.objects.create(resource=con, family_id='1312', name_id='local')
715 721

  
716 722
    resp = app.get(url + '?NameID=local&rl_id=613879')
717 723
    assert resp.json['err'] == 0
718 724
    assert resp.json['data'] == {
719 725
        'num': '613879',
......
768 774
    mocked_post.side_effect = [
769 775
        READ_FAMILY,
770 776
        READ_CATEGORIES,
771 777
        READ_SITUATIONS,
772 778
        READ_CIVILITIES,
773 779
        READ_QUALITIES,
774 780
        READ_CSP,
775 781
        READ_DIETCODE,
782
        READ_PAI,
776 783
    ]
777 784
    url = get_endpoint('read-rl')
778 785
    Link.objects.create(resource=con, family_id='1312', name_id='local')
779 786

  
780 787
    resp = app.get(url + '?NameID=local&rl_id=000000')
781 788
    assert resp.json['err'] == 'not-found'
782 789
    assert resp.json['err_desc'] == "no '000000' RL on '1312' family"
783 790

  
......
789 796
    mocked_post.side_effect = [
790 797
        READ_FAMILY,
791 798
        READ_CATEGORIES,
792 799
        READ_SITUATIONS,
793 800
        READ_CIVILITIES,
794 801
        READ_QUALITIES,
795 802
        READ_CSP,
796 803
        READ_DIETCODE,
804
        READ_PAI,
797 805
    ]
798 806
    url = get_endpoint('read-person')
799 807
    Link.objects.create(resource=con, family_id='1312', name_id='local')
800 808

  
801 809
    resp = app.get(url + '?NameID=local&person_id=614059&kind=emergency')
802 810
    assert resp.json['err'] == 0
803 811
    assert resp.json['data']['firstname'] == 'KENY'
804 812

  
......
826 834
    mocked_post.side_effect = [
827 835
        READ_FAMILY,
828 836
        READ_CATEGORIES,
829 837
        READ_SITUATIONS,
830 838
        READ_CIVILITIES,
831 839
        READ_QUALITIES,
832 840
        READ_CSP,
833 841
        READ_DIETCODE,
842
        READ_PAI,
834 843
    ]
835 844
    url = get_endpoint('read-person')
836 845
    Link.objects.create(resource=con, family_id='1312', name_id='local')
837 846

  
838 847
    resp = app.get(url + '?NameID=local&person_id=000000&kind=emergency')
839 848
    assert resp.json['err'] == 'not-found'
840 849
    assert resp.json['err_desc'] == "no '000000' emergency person on '1312' family"
841 850

  
......
847 856
    mocked_post.side_effect = [
848 857
        READ_FAMILY,
849 858
        READ_CATEGORIES,
850 859
        READ_SITUATIONS,
851 860
        READ_CIVILITIES,
852 861
        READ_QUALITIES,
853 862
        READ_CSP,
854 863
        READ_DIETCODE,
864
        READ_PAI,
855 865
    ]
856 866
    url = get_endpoint('read-child')
857 867
    Link.objects.create(resource=con, family_id='1312', name_id='local')
858 868

  
859 869
    resp = app.get(url + '?NameID=local&child_id=613880')
860 870
    assert resp.json['err'] == 0
861 871
    assert resp.json['data']['firstname'] == 'JANNIS'
862 872

  
......
876 886
    mocked_post.side_effect = [
877 887
        READ_FAMILY,
878 888
        READ_CATEGORIES,
879 889
        READ_SITUATIONS,
880 890
        READ_CIVILITIES,
881 891
        READ_QUALITIES,
882 892
        READ_CSP,
883 893
        READ_DIETCODE,
894
        READ_PAI,
884 895
    ]
885 896
    url = get_endpoint('read-child')
886 897
    Link.objects.create(resource=con, family_id='1312', name_id='local')
887 898

  
888 899
    resp = app.get(url + '?NameID=local&child_id=000000')
889 900
    assert resp.json['err'] == 'not-found'
890 901
    assert resp.json['err_desc'] == "no '000000' child on '1312' family"
891 902

  
......
1390 1401

  
1391 1402

  
1392 1403
def test_update_child_dietcode_not_linked_error(con, app):
1393 1404
    url = get_endpoint('update-child-dietcode')
1394 1405

  
1395 1406
    resp = app.post_json(url + '?NameID=local&child_id=613878&dietcode=RVS')
1396 1407
    assert resp.json['err'] == 'not-linked'
1397 1408
    assert resp.json['err_desc'] == 'User not linked to family'
1409

  
1410

  
1411
@mock.patch('passerelle.utils.Request.get')
1412
@mock.patch('passerelle.utils.Request.post')
1413
def test_update_child_pai(mocked_post, mocked_get, con, app):
1414
    mocked_get.return_value = FAMILY_SERVICE_WSDL
1415
    mocked_post.return_value = UPDATE_PAI
1416
    url = get_endpoint('update-child-pai')
1417
    params = {
1418
        'code': 'PAIALI',
1419
        'dateDeb': '2022-01-01',
1420
        'dateFin': '',
1421
        'description': 'some text',
1422
    }
1423

  
1424
    Link.objects.create(resource=con, family_id='1312', name_id='local')
1425
    resp = app.post_json(url + '?NameID=local&child_id=613878', params=params)
1426
    assert_sent_payload(mocked_post, 'Q_update_child_pai.xml')
1427
    assert resp.json['err'] == 0
1428
    assert resp.json['data'] == 'ok'
1429

  
1430

  
1431
def test_update_child_pai_not_linked_error(con, app):
1432
    url = get_endpoint('update-child-pai')
1433
    params = {
1434
        'code': 'PAIALI',
1435
        'dateDeb': '2022-01-01',
1436
        'dateFin': '',
1437
        'description': 'some text',
1438
    }
1439

  
1440
    resp = app.post_json(url + '?NameID=local&child_id=613878', params=params)
1441
    assert resp.json['err'] == 'not-linked'
1442
    assert resp.json['err_desc'] == 'User not linked to family'
1443

  
1444

  
1445
@mock.patch('passerelle.utils.Request.get')
1446
@mock.patch('passerelle.utils.Request.post')
1447
def test_update_child_pai_soap_error(mocked_post, mocked_get, con, app):
1448
    mocked_get.return_value = FAMILY_SERVICE_WSDL
1449
    mocked_post.return_value = UPDATE_PAI_500
1450
    url = get_endpoint('update-child-pai')
1451
    params = {
1452
        'code': 'PAIALI',
1453
        'dateDeb': '2022-01-01',
1454
        'dateFin': '',
1455
        'description': 'a' * 501,
1456
    }
1457

  
1458
    Link.objects.create(resource=con, family_id='1312', name_id='local')
1459
    resp = app.post_json(url + '?NameID=local&child_id=613878', params=params)
1460
    assert resp.json['err'] == 'Family-updateChildPAI-soap:Server'
1461
    assert 'Une erreur est survenue' in resp.json['err_desc']
1462
    assert 'valeur trop grande' in resp.json['err_desc']
1463
    assert 'maximum : 500' in resp.json['err_desc']
1398
-