Projet

Général

Profil

0001-toulouse-maelis-add-webservices-to-manage-childs-673.patch

Nicolas Roche, 18 juillet 2022 02:11

Télécharger (12,8 ko)

Voir les différences:

Subject: [PATCH] toulouse-maelis: add webservices to manage childs (#67328)

 passerelle/contrib/toulouse_maelis/models.py  | 33 ++++++++-
 passerelle/contrib/toulouse_maelis/schemas.py | 73 ++++++++++++++++++-
 .../toulouse_maelis/R_is_child_exists.xml     |  8 ++
 tests/test_toulouse_maelis.py                 | 62 ++++++++++++++++
 4 files changed, 174 insertions(+), 2 deletions(-)
 create mode 100644 tests/data/toulouse_maelis/R_is_child_exists.xml
passerelle/contrib/toulouse_maelis/models.py
320 320
            if str(person['numPerson']) == person_id:
321 321
                break
322 322
        else:
323 323
            raise APIError(
324 324
                "no '%s' %s person on '%s' family" % (person_id, kind, family_id), err_code='not-found'
325 325
            )
326 326
        return {'data': person}
327 327

  
328
    @endpoint(
329
        display_category=_('Family'),
330
        description="Informations sur un enfant",
331
        perm='can_access',
332
        name='read-child',
333
        parameters={
334
            'NameID': {'description': _('Publik ID')},
335
            'child_id': {'description': "Numéro de l'enfant"},
336
        },
337
    )
338
    def read_child(self, request, NameID, child_id):
339
        family_id = self.get_link(NameID).family_id
340
        data = self.get_family(family_id)
341
        for child in data['childList']:
342
            if child['num'] == child_id:
343
                break
344
        else:
345
            raise APIError("no '%s' child on '%s' family" % (child_id, family_id), err_code='not-found')
346
        return {'data': child}
347

  
328 348
    @endpoint(
329 349
        display_category=_('Family'),
330 350
        description="Vérifier qu'un responsable légal existe en base",
331 351
        perm='can_access',
332 352
        name='is-rl-exists',
333
        post={'request_body': {'schema': {'application/json': schemas.ISRLEXISTS_SCHEMA}}},
353
        post={'request_body': {'schema': {'application/json': schemas.ISEXISTS_SCHEMA}}},
334 354
    )
335 355
    def is_rl_exists(self, request, post_data):
336 356
        response = self.call('Family', 'isRLExists', **post_data)
337 357
        return {'data': response}
338 358

  
359
    @endpoint(
360
        display_category=_('Family'),
361
        description="Vérifier qu'un responsable légal existe en base",
362
        perm='can_access',
363
        name='is-child-exists',
364
        post={'request_body': {'schema': {'application/json': schemas.ISEXISTS_SCHEMA}}},
365
    )
366
    def is_child_exists(self, request, post_data):
367
        response = self.call('Family', 'isChildExists', **post_data)
368
        return {'data': response}
369

  
339 370
    @endpoint(
340 371
        display_category=_('Family'),
341 372
        description='Création de la famille',
342 373
        name='create-family',
343 374
        perm='can_access',
344 375
        parameters={'NameID': {'description': _('Publik ID')}},
345 376
        post={'request_body': {'schema': {'application/json': schemas.FAMILY_SCHEMA}}},
346 377
    )
passerelle/contrib/toulouse_maelis/schemas.py
45 45
        'dateBirth': {
46 46
            'description': 'Date de naissance du RL1',
47 47
            'type': 'string',
48 48
            'pattern': '^[0-9]{4}-[0-9]{2}-[0-9]{2}$',
49 49
        },
50 50
    },
51 51
}
52 52

  
53
ISRLEXISTS_SCHEMA = {
53
ISEXISTS_SCHEMA = {
54 54
    '$schema': 'http://json-schema.org/draft-04/schema#',
55 55
    'title': 'Link',
56 56
    'description': "Appairage d'un usager Publik à une famille dans Maelis",
57 57
    'type': 'object',
58 58
    'required': ['firstname', 'lastname', 'datebirth'],
59 59
    'properties': {
60 60
        'firstname': {
61 61
            'description': 'Prénom',
......
258 258
        },
259 259
        'adresse': ADDRESS_SCHEMA,
260 260
        'contact': CONTACT_SCHEMA,
261 261
        'profession': PROFESSION_SCHEMA,
262 262
        'CAFInfo': CAFINFO_SCHEMA,
263 263
    },
264 264
}
265 265

  
266
CHILDBIRTH_SCHEMA = {
267
    '$schema': 'http://json-schema.org/draft-04/schema#',
268
    'title': 'Child birth',
269
    'description': "Informations sur la naissance d'un enfant",
270
    'type': 'object',
271
    'required': ['dateBirth'],
272
    'properties': {
273
        'dateBirth': {
274
            'description': 'Date de naissance',
275
            'type': 'string',
276
            'pattern': '^[0-9]{4}-[0-9]{2}-[0-9]{2}$',
277
        },
278
        'place': {
279
            'description': 'Lieu de naissance',
280
            'oneOf': [{'type': 'null'}, {'type': 'string'}],
281
        },
282
    },
283
}
284

  
285
CHILD_SCHEMA = {
286
    '$schema': 'http://json-schema.org/draft-04/schema#',
287
    'title': 'Child',
288
    'description': "Informations sur la création d'un enfant",
289
    'type': 'object',
290
    'required': ['sexe', 'firstname', 'lastname'],
291
    'oneOf': [
292
        {'required': ['dateBirth']},  # createFamily
293
        {'required': ['birth']},  # updateFamily
294
    ],
295
    'properties': {
296
        'firstname': {
297
            'description': 'Prénom',
298
            'type': 'string',
299
        },
300
        'lastname': {
301
            'description': 'Nom',
302
            'type': 'string',
303
        },
304
        'sexe': {
305
            'description': 'Sexe',
306
            'type': 'string',
307
        },
308
        'dateBirth': {
309
            'description': 'Date de naissance',
310
            'type': 'string',
311
            'pattern': '^[0-9]{4}-[0-9]{2}-[0-9]{2}$',
312
        },
313
        'birth': CHILDBIRTH_SCHEMA,
314
        'dietcode': {
315
            'description': 'Code de régime alimentaire',
316
            'oneOf': [{'type': 'null'}, {'type': 'string'}],
317
        },
318
        'bPhoto': {
319
            'description': 'Autorisation photo',
320
            'oneOf': BOOLEAN_TYPES,
321
        },
322
        'bLeaveAlone': {
323
            'description': 'Autorisation à partir seul',
324
            'oneOf': BOOLEAN_TYPES,
325
        },
326
    },
327
}
266 328

  
267 329
CONTACTLIGHT_SCHEMA = {
268 330
    '$schema': 'http://json-schema.org/draft-04/schema#',
269 331
    'title': 'Contact',
270 332
    'description': "Informations de contact pour les personnes authorisées à récupérer les enfants ou à prévenir en cas d'urgence",
271 333
    'oneOf': [
272 334
        {'type': 'null'},
273 335
        {
......
387 449
            'oneOf': [
388 450
                {'type': 'null'},
389 451
                {
390 452
                    'type': 'array',
391 453
                    'items': AUTHORIZEDPERSON_SCHEMA,
392 454
                },
393 455
            ],
394 456
        },
457
        'childList': {
458
            'oneOf': [
459
                {'type': 'null'},
460
                {
461
                    'type': 'array',
462
                    'items': CHILD_SCHEMA,
463
                },
464
            ],
465
        },
395 466
    },
396 467
    'unflatten': True,
397 468
}
398 469

  
399 470
"""Schemas below describe parameters of Maelis wrapper around updateFamily endpoint"""
400 471

  
401 472
UPDATE_COORDINATE_SCHEMA = {
402 473
    '$schema': 'http://json-schema.org/draft-04/schema#',
tests/data/toulouse_maelis/R_is_child_exists.xml
1
<?xml version="1.0" encoding="utf-8"?>
2
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
3
  <soap:Body>
4
    <ns2:isChildExistsResponse xmlns:ns2="family.ws.maelis.sigec.com">
5
      <result>%s</result>
6
    </ns2:isChildExistsResponse>
7
  </soap:Body>
8
</soap:Envelope>
tests/test_toulouse_maelis.py
44 44
READ_FAMILY = FakedResponse(content=get_xml_file('R_read_family.xml'), status_code=200)
45 45
READ_CATEGORIES = FakedResponse(content=get_xml_file('R_read_category_list.xml'), status_code=200)
46 46
READ_CIVILITIES = FakedResponse(content=get_xml_file('R_read_civility_list.xml'), status_code=200)
47 47
READ_CSP = FakedResponse(content=get_xml_file('R_read_csp_list.xml'), status_code=200)
48 48
READ_QUALITIES = FakedResponse(content=get_xml_file('R_read_quality_list.xml'), status_code=200)
49 49
READ_SITUATIONS = FakedResponse(content=get_xml_file('R_read_situation_list.xml'), status_code=200)
50 50
IS_RL_EXISTS_TRUE = FakedResponse(content=get_xml_file('R_is_rl_exists.xml') % b'true', status_code=200)
51 51
IS_RL_EXISTS_FALSE = FakedResponse(content=get_xml_file('R_is_rl_exists.xml') % b'false', status_code=200)
52
IS_CHILD_EXISTS_TRUE = FakedResponse(content=get_xml_file('R_is_child_exists.xml') % b'true', status_code=200)
53
IS_CHILD_EXISTS_FALSE = FakedResponse(
54
    content=get_xml_file('R_is_child_exists.xml') % b'false', status_code=200
55
)
52 56
CREATE_FAMILY = FakedResponse(content=get_xml_file('R_create_family.xml'), status_code=200)
53 57
CREATE_FAMILY_ERR = FakedResponse(content=get_xml_file('R_create_family_error.xml'), status_code=200)
54 58
UPDATE_FAMILY = FakedResponse(content=get_xml_file('R_update_family.xml'), status_code=200)
55 59
UPDATE_FAMILY_ERR = FakedResponse(content=get_xml_file('R_update_family_error.xml'), status_code=200)
56 60
UPDATE_FAMILY_500 = FakedResponse(content=get_xml_file('R_update_family_soap_error.xml'), status_code=500)
57 61

  
58 62

  
59 63
def assert_sent_payload(mocked_post, query_file):
......
582 586
    url = get_endpoint('read-person')
583 587
    Link.objects.create(resource=con, family_id='1312', name_id='local')
584 588

  
585 589
    resp = app.get(url + '?NameID=local&person_id=000000&kind=emergency')
586 590
    assert resp.json['err'] == 'not-found'
587 591
    assert resp.json['err_desc'] == "no '000000' emergency person on '1312' family"
588 592

  
589 593

  
594
@mock.patch('passerelle.utils.Request.get')
595
@mock.patch('passerelle.utils.Request.post')
596
def test_read_child(mocked_post, mocked_get, con, app):
597
    mocked_get.return_value = FAMILY_SERVICE_WSDL
598
    mocked_post.side_effect = [READ_FAMILY, READ_CATEGORIES, READ_SITUATIONS, READ_CIVILITIES, READ_QUALITIES]
599
    url = get_endpoint('read-child')
600
    Link.objects.create(resource=con, family_id='1312', name_id='local')
601

  
602
    resp = app.get(url + '?NameID=local&child_id=613880')
603
    assert resp.json['err'] == 0
604
    assert resp.json['data']['firstname'] == 'CASSANDRA'
605

  
606

  
607
def test_read_child_not_linked_error(con, app):
608
    url = get_endpoint('read-child')
609

  
610
    resp = app.get(url + '?NameID=local&child_id=613880')
611
    assert resp.json['err'] == 'not-linked'
612
    assert resp.json['err_desc'] == 'User not linked to family'
613

  
614

  
615
@mock.patch('passerelle.utils.Request.get')
616
@mock.patch('passerelle.utils.Request.post')
617
def test_read_child_not_found(mocked_post, mocked_get, con, app):
618
    mocked_get.return_value = FAMILY_SERVICE_WSDL
619
    mocked_post.side_effect = [READ_FAMILY, READ_CATEGORIES, READ_SITUATIONS, READ_CIVILITIES, READ_QUALITIES]
620
    url = get_endpoint('read-child')
621
    Link.objects.create(resource=con, family_id='1312', name_id='local')
622

  
623
    resp = app.get(url + '?NameID=local&child_id=000000')
624
    assert resp.json['err'] == 'not-found'
625
    assert resp.json['err_desc'] == "no '000000' child on '1312' family"
626

  
627

  
590 628
@pytest.mark.parametrize(
591 629
    'post_response, result',
592 630
    [
593 631
        (IS_RL_EXISTS_TRUE, True),
594 632
        (IS_RL_EXISTS_FALSE, False),
595 633
    ],
596 634
)
597 635
@mock.patch('passerelle.utils.Request.get')
......
619 657
        'lastname': 'Costanze',
620 658
        'datebirth': '1980-10-07 more text',
621 659
    }
622 660
    resp = app.post_json(url, params=params, status=400)
623 661
    assert resp.json['err'] == 1
624 662
    assert "does not match '^[0-9]{4}-[0-9]{2}-[0-9]{2}$'" in resp.json['err_desc']
625 663

  
626 664

  
665
@pytest.mark.parametrize(
666
    'post_response, result',
667
    [
668
        (IS_CHILD_EXISTS_TRUE, True),
669
        (IS_CHILD_EXISTS_FALSE, False),
670
    ],
671
)
672
@mock.patch('passerelle.utils.Request.get')
673
@mock.patch('passerelle.utils.Request.post')
674
def test_is_child_exists(mocked_post, mocked_get, post_response, result, con, app):
675
    mocked_get.return_value = FAMILY_SERVICE_WSDL
676
    mocked_post.return_value = post_response
677
    url = get_endpoint('is-child-exists')
678

  
679
    params = {
680
        'firstname': 'Cassandra',
681
        'lastname': 'Costanze',
682
        'datebirth': '2021-06-22',
683
    }
684
    resp = app.post_json(url, params=params)
685
    assert resp.json['err'] == 0
686
    assert resp.json['data'] == result
687

  
688

  
627 689
@mock.patch('passerelle.utils.Request.get')
628 690
@mock.patch('passerelle.utils.Request.post')
629 691
def test_create_family(mocked_post, mocked_get, con, app):
630 692
    mocked_get.return_value = FAMILY_SERVICE_WSDL
631 693
    mocked_post.return_value = CREATE_FAMILY
632 694
    url = get_endpoint('create-family')
633 695
    params = {
634 696
        'categorie': 'ACCEUI',
635
-