0003-toulouse_maelis-add-PAI-webservice-69045.patch
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 |
- |