Projet

Général

Profil

0003-toulouse-maelis-manage-indicators-71964.patch

Nicolas Roche, 09 décembre 2022 11:15

Télécharger (53,1 ko)

Voir les différences:

Subject: [PATCH 3/3] toulouse-maelis: manage indicators (#71964)

 functests/toulouse_maelis/conftest.py         |  22 ++
 .../data/test_child_indicator.json            |   1 +
 .../data/test_create_family.json              |  17 +-
 .../data/test_rl_indicator.json               |   1 +
 .../data/test_update_child.json               |  17 +-
 .../data/test_update_family.json              |  34 ++-
 .../toulouse_maelis/data/test_update_rl2.json |  17 +-
 functests/toulouse_maelis/test_family.py      |  83 ++++++-
 passerelle/contrib/toulouse_maelis/models.py  |  67 ++++++
 passerelle/contrib/toulouse_maelis/schemas.py |  61 +++++
 .../Q_update_child_indicator.xml              |  24 ++
 .../toulouse_maelis/Q_update_rl_indicator.xml |  24 ++
 tests/data/toulouse_maelis/R_read_family.xml  |  18 ++
 .../toulouse_maelis/R_read_family_relax.xml   |  18 ++
 .../R_read_family_reordered.xml               |  18 ++
 .../toulouse_maelis/R_update_indicator.xml    |   6 +
 tests/test_toulouse_maelis.py                 | 210 +++++++++++++++++-
 17 files changed, 623 insertions(+), 15 deletions(-)
 create mode 100644 functests/toulouse_maelis/data/test_child_indicator.json
 create mode 100644 functests/toulouse_maelis/data/test_rl_indicator.json
 create mode 100644 tests/data/toulouse_maelis/Q_update_child_indicator.xml
 create mode 100644 tests/data/toulouse_maelis/Q_update_rl_indicator.xml
 create mode 100644 tests/data/toulouse_maelis/R_update_indicator.xml
functests/toulouse_maelis/conftest.py
57 57
            'employerName': 'Burns',
58 58
            'phone': '0133333333',
59 59
            'profession': 'Inspecteur de sécurité',
60 60
        },
61 61
        'CAFInfo': {
62 62
            'number': '123',
63 63
            'organ': 'A10007752822',
64 64
        },
65
        'indicatorList': [
66
            {
67
                'code': 'AVL',
68
                'isActive': True,
69
            },
70
            {
71
                'code': 'ETABSPEC',
72
                'note': 'SNPP',
73
                'isActive': True,
74
            },
75
        ],
65 76
    },
66 77
    'childList': [
67 78
        {
68 79
            'sexe': 'M',
69 80
            'firstname': 'Bart',
70 81
            'lastname': 'Simpson',
71 82
            'birth': {'dateBirth': '1978-04-01'},
72 83
            'bPhoto': True,
......
102 113
                        'vaccinationDate': '2011-01-11',
103 114
                    },
104 115
                    {
105 116
                        'code': 'ROR',
106 117
                        'vaccinationDate': '2022-02-22',
107 118
                    },
108 119
                ],
109 120
            },
121
            'indicatorList': [
122
                {
123
                    'code': 'LUNETTE',
124
                    'isActive': True,
125
                },
126
                {
127
                    'code': 'AUTRE',
128
                    'note': 'rebellious',
129
                    'isActive': True,
130
                },
131
            ],
110 132
            'authorizedPersonList': [
111 133
                {
112 134
                    'personInfo': {
113 135
                        'civility': 'M.',
114 136
                        'firstname': 'Abraham Jebediah',
115 137
                        'lastname': 'Simpson',
116 138
                        'dateBirth': '1927-05-24',
117 139
                        'sexe': 'M',
functests/toulouse_maelis/data/test_child_indicator.json
1
[]
functests/toulouse_maelis/data/test_create_family.json
102 102
          },
103 103
          "personQuality": {
104 104
            "code": "GMP",
105 105
            "libelle": "GRAND-MERE PATERNELLE",
106 106
            "code_text": "GRAND-MERE PATERNELLE"
107 107
          }
108 108
        }
109 109
      ],
110
      "indicatorList": [],
110
      "indicatorList": [
111
        {
112
          "code": "AUTRE",
113
          "label": "Autre",
114
          "note": "rebellious",
115
          "choice": null,
116
          "code_text": "Autre"
117
        },
118
        {
119
          "code": "LUNETTE",
120
          "label": "Port de lunettes",
121
          "note": null,
122
          "choice": null,
123
          "code_text": "Port de lunettes"
124
        }
125
      ],
111 126
      "medicalRecord": {
112 127
        "familyDoctor": {
113 128
          "name": "MONROE",
114 129
          "phone": "0612341234",
115 130
          "address": {
116 131
            "street1": "Alameda",
117 132
            "zipcode": "90701",
118 133
            "town": "Springfield"
functests/toulouse_maelis/data/test_rl_indicator.json
1
[]
functests/toulouse_maelis/data/test_update_child.json
53 53
      },
54 54
      "personQuality": {
55 55
        "code": "GMP",
56 56
        "libelle": "GRAND-MERE PATERNELLE",
57 57
        "code_text": "GRAND-MERE PATERNELLE"
58 58
      }
59 59
    }
60 60
  ],
61
  "indicatorList": [],
61
  "indicatorList": [
62
    {
63
      "code": "AUTRE",
64
      "label": "Autre",
65
      "note": "rebellious",
66
      "choice": null,
67
      "code_text": "Autre"
68
    },
69
    {
70
      "code": "LUNETTE",
71
      "label": "Port de lunettes",
72
      "note": null,
73
      "choice": null,
74
      "code_text": "Port de lunettes"
75
    }
76
  ],
62 77
  "medicalRecord": {
63 78
    "familyDoctor": {
64 79
      "name": "MONROE",
65 80
      "phone": "0612341234",
66 81
      "address": {
67 82
        "street1": "Alameda",
68 83
        "zipcode": "90701",
69 84
        "town": "Springfield"
functests/toulouse_maelis/data/test_update_family.json
87 87
      },
88 88
      "codeCSP_text": "CADRE SUPERIEUR"
89 89
    },
90 90
    "CAFInfo": {
91 91
      "number": "123",
92 92
      "organ": "A10007752822",
93 93
      "organ_text": "LA COLLE SUR LOUP"
94 94
    },
95
    "indicatorList": [],
95
    "indicatorList": [
96
      {
97
        "code": "AVL",
98
        "label": "Auxiliaire de Vie loisirs",
99
        "note": null,
100
        "choice": null,
101
        "code_text": "Auxiliaire de Vie loisirs"
102
      },
103
      {
104
        "code": "ETABSPEC",
105
        "label": "Etablissement sp\u00e9cialis\u00e9",
106
        "note": "SNPP",
107
        "choice": null,
108
        "code_text": "Etablissement sp\u00e9cialis\u00e9"
109
      }
110
    ],
96 111
    "quotientList": [],
97 112
    "subscribeActivityList": [],
98 113
    "civility_text": "Monsieur",
99 114
    "quality_text": "PERE"
100 115
  },
101 116
  "quotientList": [],
102 117
  "childList": [
103 118
    {
......
155 170
          },
156 171
          "personQuality": {
157 172
            "code": "GMP",
158 173
            "libelle": "GRAND-MERE PATERNELLE",
159 174
            "code_text": "GRAND-MERE PATERNELLE"
160 175
          }
161 176
        }
162 177
      ],
163
      "indicatorList": [],
178
      "indicatorList": [
179
        {
180
          "code": "AUTRE",
181
          "label": "Autre",
182
          "note": "rebellious",
183
          "choice": null,
184
          "code_text": "Autre"
185
        },
186
        {
187
          "code": "LUNETTE",
188
          "label": "Port de lunettes",
189
          "note": null,
190
          "choice": null,
191
          "code_text": "Port de lunettes"
192
        }
193
      ],
164 194
      "medicalRecord": {
165 195
        "familyDoctor": {
166 196
          "name": "MONROE",
167 197
          "phone": "0612341234",
168 198
          "address": {
169 199
            "street1": "Alameda",
170 200
            "zipcode": "90701",
171 201
            "town": "Springfield"
functests/toulouse_maelis/data/test_update_rl2.json
41 41
    },
42 42
    "codeCSP_text": "CADRE SUPERIEUR"
43 43
  },
44 44
  "CAFInfo": {
45 45
    "number": "123",
46 46
    "organ": "A10007752822",
47 47
    "organ_text": "LA COLLE SUR LOUP"
48 48
  },
49
  "indicatorList": [],
49
  "indicatorList": [
50
    {
51
      "code": "AVL",
52
      "label": "Auxiliaire de Vie loisirs",
53
      "note": null,
54
      "choice": null,
55
      "code_text": "Auxiliaire de Vie loisirs"
56
    },
57
    {
58
      "code": "ETABSPEC",
59
      "label": "Etablissement sp\u00e9cialis\u00e9",
60
      "note": "SNPP",
61
      "choice": null,
62
      "code_text": "Etablissement sp\u00e9cialis\u00e9"
63
    }
64
  ],
50 65
  "quotientList": [],
51 66
  "subscribeActivityList": [],
52 67
  "civility_text": "Monsieur",
53 68
  "quality_text": "AUTRE"
54 69
}
functests/toulouse_maelis/test_family.py
45 45
            'employerName': '',
46 46
            'phone': '',
47 47
            'profession': '',
48 48
        },
49 49
        'CAFInfo': {
50 50
            'number': 'reset',  # cannot be removed
51 51
            'organ': '',
52 52
        },
53
        'indicatorList': [
54
            {
55
                'code': 'AVL',
56
                'isActive': False,
57
            },
58
            {
59
                'code': 'ETABSPEC',
60
                'isActive': False,
61
            },
62
        ],
53 63
    },
54 64
    'childList': [
55 65
        {
56 66
            'num': 'place holder',  # required for update
57 67
            'sexe': 'F',
58 68
            'firstname': 'Bartolome',  # some side effects, cf test_update_child
59 69
            'lastname': 'Simps',
60 70
            'birth': {'dateBirth': '1970-01-01'},
......
82 92
                'comment1': '',
83 93
                'comment2': '',
84 94
                'observ1': '',
85 95
                'observ2': '',
86 96
                'isAuthHospital': False,
87 97
                'hospital': '',
88 98
                'vaccinList': [],
89 99
            },
100
            'indicatorList': [
101
                {
102
                    'code': 'LUNETTE',
103
                    'isActive': False,
104
                },
105
                {
106
                    'code': 'AUTRE',
107
                    'note': 'rebellious',
108
                    'isActive': False,
109
                },
110
            ],
90 111
            # setting authorizedPersonList to None will remove the list
91 112
            'authorizedPersonList': [
92 113
                {
93 114
                    'personInfo': {
94 115
                        'civility': None,
95 116
                        'firstname': 'reset',  # E704 : Le prénom de la personne est obligatoire
96 117
                        'lastname': 'reset',  # E705 : Le nom de la personne est obligatoire
97 118
                        'dateBirth': '1970-01-01',
......
279 300
    link(conn, create_data)
280 301

  
281 302
    data = read_family(conn, create_data['name_id'])
282 303
    assert data['RL2'] is None
283 304

  
284 305
    # no unicity restriction on RL2 (duplicate RL2 from update_data)
285 306
    url = conn + '/create-rl2?NameID=%s' % create_data['name_id']
286 307
    payload = copy.deepcopy(update_data['family_payload']['rl2'])
287
    for key in 'contact', 'profession', 'CAFInfo':
308
    for key in 'contact', 'profession', 'CAFInfo', 'indicatorList':
288 309
        del payload[key]
289 310
    resp = requests.post(url, json=payload)
290 311
    resp.raise_for_status()
291 312
    assert resp.json()['err'] == 0
292 313
    assert diff_rlg(conn, create_data['name_id'], 2, 'test_create_rl2.json')
293 314

  
294 315

  
295 316
@pytest.mark.parametrize("rl", ['1', '2'])
......
297 318
    rlg = 'rl' + rl
298 319
    RLG = 'RL' + rl
299 320
    unlink(conn, update_data['name_id'])
300 321
    link(conn, update_data)
301 322
    url = conn + '/update-rl%s?NameID=%s' % (rl, update_data['name_id'])
302 323

  
303 324
    # reset responsable legal
304 325
    payload = copy.deepcopy(FAMILY_RESET_PAYLOAD[rlg])
305
    for key in 'adresse', 'contact', 'profession', 'CAFInfo':
326
    for key in 'adresse', 'contact', 'profession', 'CAFInfo', 'indicatorList':
306 327
        if key in payload:
307 328
            del payload[key]
308 329
    resp = requests.post(url, json=payload)
309 330
    resp.raise_for_status()
310 331
    assert resp.json()['err'] == 0
311 332
    data = diff_rlg(conn, update_data['name_id'], rl, 'test_update_rl%s.json' % rl)
312 333

  
313 334
    # unchanged values
......
351 372
            "Le Responsable légal %s transmis n'est pas celui qui existe pour la famille" % rl
352 373
            in res['err_desc']
353 374
        )
354 375
    else:
355 376
        assert "La date de naissance ne peut pas être modifiée" in res['err_desc']
356 377

  
357 378
    # restore RL1
358 379
    payload = copy.deepcopy(update_data['family_payload'][rlg])
359
    for key in 'adresse', 'contact', 'profession', 'CAFInfo':
380
    for key in 'adresse', 'contact', 'profession', 'CAFInfo', 'indicatorList':
360 381
        if payload.get(key):
361 382
            del payload[key]
362 383
    resp = requests.post(url, json=payload)
363 384
    resp.raise_for_status()
364 385
    assert resp.json()['err'] == 0
365 386
    data = diff_family(conn, update_data['name_id'], 'test_update_family.json')
366 387

  
367 388

  
......
463 484
def test_update_child(conn, update_data, create_data):
464 485
    unlink(conn, update_data['name_id'])
465 486
    link(conn, update_data)
466 487

  
467 488
    # renaming using existing child names on same family will in fact target the existing child
468 489
    # side effect: the authorized person list is copied by the connector (from Lisa to Maggie)
469 490
    url = conn + '/update-child?NameID=%s&child_id=%s' % (update_data['name_id'], update_data['lisa_num'])
470 491
    payload = copy.deepcopy(update_data['family_payload']['childList'][2])  # Maggie content
471
    for key in 'dietcode', 'paiInfoBean', 'medicalRecord', 'authorizedPersonList':
492
    for key in 'dietcode', 'paiInfoBean', 'medicalRecord', 'authorizedPersonList', 'indicatorList':
472 493
        if key in payload:
473 494
            del payload[key]
474 495
    assert payload['firstname'] == 'Maggie'
475 496
    payload['sexe'] = 'M'
476 497
    resp = requests.post(url, json=payload)  # use Lisa id in url
477 498
    resp.raise_for_status()
478 499
    assert resp.json()['err'] == 0
479 500
    data = read_family(conn, update_data['name_id'])
480 501
    assert data['childList'][1]['num'] == update_data['lisa_num']
481 502
    assert data['childList'][1]['firstname'] == 'LISA'  # Lisa unchanged
482 503
    assert data['childList'][2]['sexe'] == 'M'  # Maggie updated
483 504

  
484 505
    # restore Maggie
485 506
    url = conn + '/update-child?NameID=%s&child_id=%s' % (update_data['name_id'], update_data['maggie_num'])
486 507
    payload = copy.deepcopy(update_data['family_payload']['childList'][2])
487
    for key in 'dietcode', 'paiInfoBean', 'medicalRecord', 'authorizedPersonList':
508
    for key in 'dietcode', 'paiInfoBean', 'medicalRecord', 'authorizedPersonList', 'indicatorList':
488 509
        if key in payload:
489 510
            del payload[key]
490 511
    resp = requests.post(url, json=payload)
491 512
    resp.raise_for_status()
492 513
    assert resp.json()['err'] == 0
493 514
    assert diff_family(conn, update_data['name_id'], 'test_update_family.json')
494 515

  
495 516
    # rename to an existing child on other family
496 517
    url = conn + '/update-child?NameID=%s&child_id=%s' % (update_data['name_id'], update_data['bart_num'])
497 518
    payload = copy.deepcopy(create_data['family_payload']['childList'][1])
498
    for key in 'dietcode', 'paiInfoBean', 'medicalRecord', 'authorizedPersonList':
519
    for key in 'dietcode', 'paiInfoBean', 'medicalRecord', 'authorizedPersonList', 'indicatorList':
499 520
        if key in payload:
500 521
            del payload[key]
501 522
    resp = requests.post(url, json=payload)
502 523
    resp.raise_for_status()
503 524
    assert resp.json()['err'] == 0
504 525
    data = read_family(conn, update_data['name_id'])
505 526
    assert data['childList'][0]['num'] == update_data['bart_num']
506 527
    assert data['childList'][0]['firstname'] == 'MAGGIE'
507 528

  
508 529
    # reset Bart
509 530
    payload = copy.deepcopy(FAMILY_RESET_PAYLOAD['childList'][0])
510
    for key in 'dietcode', 'paiInfoBean', 'medicalRecord', 'authorizedPersonList':
531
    for key in 'dietcode', 'paiInfoBean', 'medicalRecord', 'authorizedPersonList', 'indicatorList':
511 532
        if key in payload:
512 533
            del payload[key]
513 534
    resp = requests.post(url, json=payload)
514 535
    resp.raise_for_status()
515 536
    assert resp.json()['err'] == 0
516 537
    assert diff_child(conn, update_data['name_id'], 0, 'test_update_child.json')
517 538

  
518 539
    # restore Bart
519 540
    payload = copy.deepcopy(update_data['family_payload']['childList'][0])
520
    for key in 'dietcode', 'paiInfoBean', 'medicalRecord', 'authorizedPersonList':
541
    for key in 'dietcode', 'paiInfoBean', 'medicalRecord', 'authorizedPersonList', 'indicatorList':
521 542
        if key in payload:
522 543
            del payload[key]
523 544
    resp = requests.post(url, json=payload)
524 545
    resp.raise_for_status()
525 546
    assert resp.json()['err'] == 0
526 547
    assert diff_family(conn, update_data['name_id'], 'test_update_family.json')
527 548

  
528 549

  
......
680 701
        update_data['bart_num'],
681 702
        abi_num,
682 703
    )
683 704
    payload = update_data['family_payload']['childList'][0]['authorizedPersonList'][0]
684 705
    resp = requests.post(url, json=payload)
685 706
    resp.raise_for_status()
686 707
    assert resp.json()['err'] == 0
687 708
    assert diff_family(conn, update_data['name_id'], 'test_update_family.json')
709

  
710

  
711
def test_update_rl_indicator(conn, update_data):
712
    unlink(conn, update_data['name_id'])
713
    link(conn, update_data)
714
    url = conn + '/update-rl-indicator?NameID=%s&rl_id=%s' % (
715
        update_data['name_id'],
716
        update_data['rl2_num'],
717
    )
718

  
719
    # reset RL indicators
720
    payload = {'indicatorList': FAMILY_RESET_PAYLOAD['rl2']['indicatorList']}
721
    resp = requests.post(url, json=payload)
722
    resp.raise_for_status()
723
    assert resp.json()['err'] == 0
724
    assert diff_rlg(conn, update_data['name_id'], 1, 'test_rl_indicator.json', key='indicatorList')
725

  
726
    # restore RL indicators
727
    payload = {'indicatorList': update_data['family_payload']['rl2']['indicatorList']}
728
    resp = requests.post(url, json=payload)
729
    resp.raise_for_status()
730
    assert resp.json()['err'] == 0
731
    assert diff_family(conn, update_data['name_id'], 'test_update_family.json')
732

  
733

  
734
def test_update_child_indicator(conn, update_data):
735
    unlink(conn, update_data['name_id'])
736
    link(conn, update_data)
737
    url = conn + '/update-child-indicator?NameID=%s&child_id=%s' % (
738
        update_data['name_id'],
739
        update_data['bart_num'],
740
    )
741

  
742
    # reset Bart indicators
743
    payload = {'indicatorList': FAMILY_RESET_PAYLOAD['childList'][0]['indicatorList']}
744
    resp = requests.post(url, json=payload)
745
    resp.raise_for_status()
746
    assert resp.json()['err'] == 0
747
    assert diff_child(conn, update_data['name_id'], 0, 'test_child_indicator.json', key='indicatorList')
748

  
749
    # restore Bart indicators
750
    payload = {'indicatorList': update_data['family_payload']['childList'][0]['indicatorList']}
751
    resp = requests.post(url, json=payload)
752
    resp.raise_for_status()
753
    assert resp.json()['err'] == 0
754
    assert diff_family(conn, update_data['name_id'], 'test_update_family.json')
passerelle/contrib/toulouse_maelis/models.py
230 230
        last_key = keys.pop()
231 231
        for key in keys:
232 232
            if not isinstance(data, dict) or not key in data:
233 233
                return
234 234
            data = data[key]
235 235
        if isinstance(data, dict) and last_key in data and data[last_key] is not None:
236 236
            data[last_key + '_text'] = self.get_referential_value(referential_name, data[last_key])
237 237

  
238
    def add_text_value_to_rl_indicator(self, data):
239
        self.add_text_value('RLIndicator', data, ['code'])
240

  
241
    def add_text_value_to_child_indicator(self, data):
242
        self.add_text_value('ChildIndicator', data, ['code'])
243

  
238 244
    def add_text_value_to_child_person(self, data):
239 245
        self.add_text_value('Civility', data, ['personInfo', 'civility'])
240 246
        self.add_text_value('Quality', data, ['personQuality', 'code'])
241 247
        self.add_text_value('Sex', data, ['personInfo', 'sexe'])
242 248
        return data
243 249

  
244 250
    def add_text_value_to_child(self, data):
245 251
        self.add_text_value('Sex', data, ['sexe'])
246 252
        self.add_text_value('DietCode', data, ['dietcode'])
247 253
        self.add_text_value('PAI', data, ['paiInfoBean', 'code'])
248 254
        for person in data['authorizedPersonList']:
249 255
            self.add_text_value_to_child_person(person)
256
        for indicator in data['indicatorList']:
257
            self.add_text_value_to_child_indicator(indicator)
258

  
259
        # sort indicators
260
        if data['indicatorList']:
261
            data['indicatorList'].sort(key=lambda x: x['code'])
250 262
        return data
251 263

  
252 264
    def add_text_value_to_person(self, data):
253 265
        self.add_text_value('Civility', data, ['civility'])
254 266
        self.add_text_value('Quality', data, ['quality'])
255 267
        self.add_text_value('Sex', data, ['sexe'])
256 268

  
257 269
    def add_text_value_to_rl(self, data):
258 270
        self.add_text_value('Civility', data, ['civility'])
259 271
        self.add_text_value('Quality', data, ['quality'])
260 272
        self.add_text_value('Complement', data, ['adresse', 'numComp'])
261 273
        self.add_text_value('CSP', data, ['profession', 'codeCSP'])
262 274
        self.add_text_value('Organ', data, ['CAFInfo', 'organ'])
275
        for indicator in data['indicatorList']:
276
            self.add_text_value_to_rl_indicator(indicator)
277

  
278
        # sort indicators
279
        if data['indicatorList']:
280
            data['indicatorList'].sort(key=lambda x: x['code'])
263 281

  
264 282
    def add_text_value_to_family(self, data):
265 283
        self.add_text_value('Category', data, ['category'])
266 284
        self.add_text_value('Situation', data, ['situation'])
267 285
        for rlg in 'RL1', 'RL2':
268 286
            if data.get(rlg):
269 287
                self.add_text_value_to_rl(data[rlg])
270 288
        for child in data['childList']:
......
321 339
                isinstance(data, dict) and key in data
322 340
            ):
323 341
                break
324 342
            data = data[key]
325 343
        else:
326 344
            key_value = data
327 345
        self.assert_key_in_referential(referential_name, key_value, '/'.join(str(x) for x in keys), required)
328 346

  
347
    def assert_update_indicator_payload_in_referential(self, referential, post_data, parent_keys=None):
348
        keys = parent_keys or []
349
        data = post_data
350
        for key in keys:
351
            data = data[key]
352

  
353
        for i in range(0, len(data.get('indicatorList', []))):
354
            self.assert_post_data_in_referential(
355
                referential, post_data, keys + ['indicatorList', i, 'code'], required=True
356
            )
357

  
329 358
    def assert_child_medical_record_payload_in_referential(self, post_data, parent_keys=None):
330 359
        keys = parent_keys or []
331 360
        data = post_data
332 361
        for key in keys:
333 362
            data = data[key]
334 363

  
335 364
        for i in range(0, len(data.get('vaccinList', []))):
336 365
            self.assert_post_data_in_referential(
......
359 388

  
360 389
        if 'dietcode' in data:
361 390
            self.assert_post_data_in_referential('DietCode', post_data, keys + ['dietcode'], required=False)
362 391
        if 'paiInfoBean' in data:
363 392
            self.assert_child_pai_payoad_in_referential(post_data, keys + ['paiInfoBean'])
364 393
        if 'medicalRecord' in data:
365 394
            # dead code as updateFamily seems not to modify medicalRecord
366 395
            self.assert_child_medical_record_payload_in_referential(post_data, keys + ['medicalRecord'])
396
        self.assert_update_indicator_payload_in_referential('ChildIndicator', post_data, keys)
367 397

  
368 398
    def assert_person_payload_in_referential(self, post_data, parent_keys=None):
369 399
        keys = parent_keys or []
370 400
        self.assert_post_data_in_referential('Civility', post_data, keys + ['civility'], required=False)
371 401
        self.assert_post_data_in_referential('Sex', post_data, keys + ['sexe'], required=False)
372 402
        self.assert_post_data_in_referential('Quality', post_data, keys + ['quality'])
373 403

  
374 404
    def assert_update_coordinate_payload_in_referential(self, post_data, parent_keys=None):
......
381 411
        )
382 412
        self.assert_post_data_in_referential('Organ', post_data, keys + ['CAFInfo', 'organ'], required=False)
383 413

  
384 414
    def assert_rl_payload_in_referential(self, post_data, parent_keys=None):
385 415
        keys = parent_keys or []
386 416
        self.assert_post_data_in_referential('Civility', post_data, keys + ['civility'])
387 417
        self.assert_post_data_in_referential('Quality', post_data, keys + ['quality'])
388 418
        self.assert_update_coordinate_payload_in_referential(post_data, keys)
419
        self.assert_update_indicator_payload_in_referential('RLIndicator', post_data, keys)
389 420

  
390 421
    def assert_create_rl1_payload_in_referential(self, post_data):
391 422
        self.assert_post_data_in_referential('Category', post_data, ['category'])
392 423
        self.assert_post_data_in_referential('Situation', post_data, ['situation'])
393 424
        self.assert_rl_payload_in_referential(post_data, ['rl1'])
394 425

  
395 426
    def assert_family_payload_in_referential(self, post_data):
396 427
        self.assert_post_data_in_referential('Category', post_data, ['category'])
......
1028 1059
    def update_coordinate(self, request, NameID, rl_id, post_data):
1029 1060
        family_id = self.get_link(NameID).family_id
1030 1061
        self.assert_update_coordinate_payload_in_referential(post_data)
1031 1062
        self.replace_null_values(post_data)
1032 1063

  
1033 1064
        self.call('Family', 'updateCoordinate', numDossier=family_id, numPerson=rl_id, **post_data)
1034 1065
        return {'data': 'ok'}
1035 1066

  
1067
    @endpoint(
1068
        display_category='Famille',
1069
        description="Mise à jour des indicateurs d'un responsable légal",
1070
        name='update-rl-indicator',
1071
        perm='can_access',
1072
        parameters={
1073
            'NameID': {'description': 'Publik NameID'},
1074
            'rl_id': {'description': 'Numéro du représentant légal'},
1075
        },
1076
        post={'request_body': {'schema': {'application/json': schemas.UPDATE_INDICATOR_SCHEMA}}},
1077
    )
1078
    def update_rl_indicator(self, request, NameID, rl_id, post_data):
1079
        self.get_link(NameID)
1080
        self.assert_update_indicator_payload_in_referential('RLIndicator', post_data)
1081

  
1082
        self.call('Family', 'updatePersonIndicatorList', numPerson=rl_id, **post_data)
1083
        return {'data': 'ok'}
1084

  
1036 1085
    @endpoint(
1037 1086
        display_category='Famille',
1038 1087
        description="Création d'une personne à prévenir en cas d'urgence",
1039 1088
        name='create-person',
1040 1089
        perm='can_access',
1041 1090
        parameters={
1042 1091
            'NameID': {'description': 'Publik NameID'},
1043 1092
        },
......
1299 1348

  
1300 1349
        payload = {
1301 1350
            'numPerson': child_id,
1302 1351
            'medicalRecord': post_data,
1303 1352
        }
1304 1353
        self.call('Family', 'updateChildMedicalRecord', updateChildMedicalRecordRequest=payload)
1305 1354
        return {'data': 'ok'}
1306 1355

  
1356
    @endpoint(
1357
        display_category='Famille',
1358
        description="Mise à jour des indicateurs d'un enfant",
1359
        name='update-child-indicator',
1360
        perm='can_access',
1361
        parameters={
1362
            'NameID': {'description': 'Publik NameID'},
1363
            'child_id': {'description': "Numéro de l'enfant"},
1364
        },
1365
        post={'request_body': {'schema': {'application/json': schemas.UPDATE_INDICATOR_SCHEMA}}},
1366
    )
1367
    def update_child_indicator(self, request, NameID, child_id, post_data):
1368
        self.get_link(NameID)
1369
        self.assert_update_indicator_payload_in_referential('ChildIndicator', post_data)
1370

  
1371
        self.call('Family', 'updatePersonIndicatorList', numPerson=child_id, **post_data)
1372
        return {'data': 'ok'}
1373

  
1307 1374

  
1308 1375
class Link(models.Model):
1309 1376
    resource = models.ForeignKey(ToulouseMaelis, on_delete=models.CASCADE)
1310 1377
    name_id = models.CharField(blank=False, max_length=256)
1311 1378
    family_id = models.CharField(blank=False, max_length=128)
1312 1379
    created = models.DateTimeField(auto_now_add=True)
1313 1380
    updated = models.DateTimeField(auto_now=True)
1314 1381

  
passerelle/contrib/toulouse_maelis/schemas.py
173 173
        },
174 174
        'countryCode': {
175 175
            'description': 'Pays de naissance (depuis référentiel)',
176 176
            'oneOf': [{'type': 'string'}, {'type': 'null'}],
177 177
        },
178 178
    },
179 179
}
180 180

  
181
INDICATOR_SCHEMA = {
182
    '$schema': 'http://json-schema.org/draft-04/schema#',
183
    'title': 'Address',
184
    'description': 'Indicateurs',
185
    'type': 'object',
186
    'required': ['code', 'isActive'],
187
    'properties': {
188
        'code': {
189
            'description': "Code de l'indicateur (depuis référentiel)",
190
            'type': 'string',
191
            'pattern': '.+',
192
        },
193
        'note': {
194
            'description': "Commentaire pour les indicateurs de type NOTE",
195
            'oneOf': [{'type': 'string'}, {'type': 'null'}],
196
        },
197
        'isActive': {
198
            'description': "True pour ajouter/modifier l'indicateur (défault) ou False pour le retirer",
199
            'oneOf': BOOLEAN_TYPES,
200
        },
201
    },
202
}
203

  
181 204
ID_PROPERTIES = {
182 205
    'firstname': {
183 206
        'description': 'Prénom',
184 207
        'type': 'string',
185 208
    },
186 209
    'lastname': {
187 210
        'description': 'Nom',
188 211
        'type': 'string',
......
345 368
            'description': 'Qualité (depuis référentiel)',
346 369
            'type': 'string',
347 370
            'pattern': '.+',
348 371
        },
349 372
        'adresse': ADDRESS_SCHEMA,
350 373
        'contact': {'oneOf': [CONTACT_SCHEMA, {'type': 'null'}]},
351 374
        'profession': {'oneOf': [PROFESSION_SCHEMA, {'type': 'null'}]},
352 375
        'CAFInfo': {'oneOf': [CAFINFO_SCHEMA, {'type': 'null'}]},
376
        'indicatorList': {
377
            'oneOf': [
378
                {
379
                    'type': 'array',
380
                    'items': INDICATOR_SCHEMA,
381
                },
382
                {'type': 'null'},
383
            ],
384
        },
353 385
    },
354 386
    'unflatten': True,
355 387
    'additionalProperties': False,
356 388
}
357 389
RLINFO_SCHEMA['properties'].update(ID_PROPERTIES)
358 390

  
359 391
DOCTORADDRESS_SCHEMA = {
360 392
    '$schema': 'http://json-schema.org/draft-04/schema#',
......
537 569
            'oneOf': [
538 570
                {
539 571
                    'type': 'array',
540 572
                    'items': AUTHORIZED_PERSON_SCHEMA,
541 573
                },
542 574
                {'type': 'null'},
543 575
            ],
544 576
        },
577
        'indicatorList': {
578
            'oneOf': [
579
                {
580
                    'type': 'array',
581
                    'items': INDICATOR_SCHEMA,
582
                },
583
                {'type': 'null'},
584
            ],
585
        },
545 586
    },
546 587
    'additionalProperties': False,
547 588
}
548 589
CHILD_SCHEMA['properties'].update(ID_PROPERTIES)
549 590

  
550 591
UPDATE_FAMILY_SCHEMA = {
551 592
    '$schema': 'http://json-schema.org/draft-04/schema#',
552 593
    'title': 'Family',
......
617 658
del CREATE_RL1_SCHEMA['properties']['rl1']['properties']['CAFInfo']
618 659

  
619 660
UPDATE_RL1_SCHEMA = copy.deepcopy(RLINFO_SCHEMA)
620 661
UPDATE_RL1_SCHEMA['required'] = ['firstname', 'lastname', 'civility', 'quality', 'birth']
621 662
del UPDATE_RL1_SCHEMA['properties']['adresse']
622 663
del UPDATE_RL1_SCHEMA['properties']['contact']
623 664
del UPDATE_RL1_SCHEMA['properties']['profession']
624 665
del UPDATE_RL1_SCHEMA['properties']['CAFInfo']
666
del UPDATE_RL1_SCHEMA['properties']['indicatorList']
625 667

  
626 668
CREATE_RL2_SCHEMA = copy.deepcopy(RLINFO_SCHEMA)
627 669
CREATE_RL2_SCHEMA['unflatten'] = True
628 670
del CREATE_RL2_SCHEMA['properties']['contact']
629 671
del CREATE_RL2_SCHEMA['properties']['profession']
630 672
del CREATE_RL2_SCHEMA['properties']['CAFInfo']
673
del CREATE_RL2_SCHEMA['properties']['indicatorList']
631 674

  
632 675
UPDATE_RL2_SCHEMA = copy.deepcopy(UPDATE_RL1_SCHEMA)
633 676

  
634 677
CREATE_CHILD_SCHEMA = copy.deepcopy(CHILD_SCHEMA)
635 678
CREATE_CHILD_SCHEMA['unflatten'] = True
636 679
del CREATE_CHILD_SCHEMA['properties']['dietcode']
637 680
del CREATE_CHILD_SCHEMA['properties']['medicalRecord']
638 681
del CREATE_CHILD_SCHEMA['properties']['paiInfoBean']
639 682
del CREATE_CHILD_SCHEMA['properties']['authorizedPersonList']
683
del CREATE_CHILD_SCHEMA['properties']['indicatorList']
640 684

  
641 685
UPDATE_CHILD_SCHEMA = copy.deepcopy(CREATE_CHILD_SCHEMA)
642 686

  
643 687
UPDATE_COORDINATE_SCHEMA = {
644 688
    '$schema': 'http://json-schema.org/draft-04/schema#',
645 689
    'title': 'Update coordinate',
646 690
    'description': "Mise à jour des coordonnées d'un responsable légal",
647 691
    'type': 'object',
......
650 694
        'adresse': ADDRESS_SCHEMA,
651 695
        'contact': {'oneOf': [CONTACT_SCHEMA, {'type': 'null'}]},
652 696
        'profession': {'oneOf': [PROFESSION_SCHEMA, {'type': 'null'}]},
653 697
        'CAFInfo': {'oneOf': [CAFINFO_SCHEMA, {'type': 'null'}]},
654 698
    },
655 699
    'unflatten': True,
656 700
    'additionalProperties': False,
657 701
}
702

  
703
UPDATE_INDICATOR_SCHEMA = {
704
    '$schema': 'http://json-schema.org/draft-04/schema#',
705
    'title': 'Update indicators',
706
    'description': 'Mise à jour des indicateurs',
707
    'type': 'object',
708
    'required': ['indicatorList'],
709
    'properties': {
710
        'indicatorList': {
711
            'type': 'array',
712
            'items': INDICATOR_SCHEMA,
713
            'minItems': 1,
714
        }
715
    },
716
    'additionalProperties': False,
717
    'unflatten': True,
718
}
tests/data/toulouse_maelis/Q_update_child_indicator.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:updatePersonIndicatorList xmlns:ns0="family.ws.maelis.sigec.com">
12
      <numPerson>613880</numPerson>
13
      <indicatorList>
14
        <code>LUNETTE</code>
15
        <isActive>true</isActive>
16
      </indicatorList>
17
      <indicatorList>
18
        <code>AUTRE</code>
19
        <note>rebellious</note>
20
        <isActive>true</isActive>
21
      </indicatorList>
22
    </ns0:updatePersonIndicatorList>
23
  </soap-env:Body>
24
</soap-env:Envelope>
tests/data/toulouse_maelis/Q_update_rl_indicator.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:updatePersonIndicatorList xmlns:ns0="family.ws.maelis.sigec.com">
12
      <numPerson>613878</numPerson>
13
      <indicatorList>
14
        <code>AVL</code>
15
        <isActive>true</isActive>
16
      </indicatorList>
17
      <indicatorList>
18
        <code>ETABSPEC</code>
19
        <note>SNPP</note>
20
        <isActive>true</isActive>
21
      </indicatorList>
22
    </ns0:updatePersonIndicatorList>
23
  </soap-env:Body>
24
</soap-env:Envelope>
tests/data/toulouse_maelis/R_read_family.xml
31 31
            <mail>djhon@example.org</mail>
32 32
            <isContactMail>true</isContactMail>
33 33
            <isContactSms>true</isContactSms>
34 34
            <isInvoicePdf>true</isInvoicePdf>
35 35
          </contact>
36 36
          <profession>
37 37
            <addressPro/>
38 38
          </profession>
39
          <indicatorList>
40
            <code>ETABSPEC</code>
41
            <label>Etablissement sp&#233;cialis&#233;</label>
42
            <note>SNPP</note>
43
          </indicatorList>
44
          <indicatorList>
45
            <code>AVL</code>
46
            <label>Auxiliaire de Vie loisirs</label>
47
          </indicatorList>
39 48
        </RL1>
40 49
        <RL2>
41 50
          <num>613879</num>
42 51
          <lastname>DOE</lastname>
43 52
          <firstname>JANE</firstname>
44 53
          <maidenName>SMITH</maidenName>
45 54
          <quality>MERE</quality>
46 55
          <civility>MME</civility>
......
115 124
                <mail>abent@example.org</mail>
116 125
              </contact>
117 126
            </personInfo>
118 127
            <personQuality>
119 128
              <code>T</code>
120 129
              <libelle>TANTE</libelle>
121 130
            </personQuality>
122 131
          </authorizedPersonList>
132
          <indicatorList>
133
            <code>LUNETTE</code>
134
            <label>Port de lunettes</label>
135
          </indicatorList>
136
          <indicatorList>
137
            <code>AUTRE</code>
138
            <label>Autre</label>
139
            <note>rebellious</note>
140
          </indicatorList>
123 141
          <medicalRecord>
124 142
            <familyDoctor>
125 143
              <name>DRE</name>
126 144
              <phone>0612341234</phone>
127 145
              <address>
128 146
                <street1>Alameda</street1>
129 147
                <zipcode>90220</zipcode>
130 148
                <town>Compton</town>
tests/data/toulouse_maelis/R_read_family_relax.xml
31 31
            <mail>djhon@example.org</mail>
32 32
            <isContactMail>true</isContactMail>
33 33
            <isContactSms>true</isContactSms>
34 34
            <isInvoicePdf>true</isInvoicePdf>
35 35
          </contact>
36 36
          <profession>
37 37
            <addressPro/>
38 38
          </profession>
39
          <indicatorList>
40
            <code>ETABSPEC</code>
41
            <label>Etablissement sp&#233;cialis&#233;</label>
42
            <note>SNPP</note>
43
          </indicatorList>
44
          <indicatorList>
45
            <code>AVL</code>
46
            <label>Auxiliaire de Vie loisirs</label>
47
          </indicatorList>
39 48
        </RL1>
40 49
        <RL2>
41 50
          <num>613879</num>
42 51
          <lastname>DOE</lastname>
43 52
          <firstname>JANE</firstname>
44 53
          <maidenName>SMITH</maidenName>
45 54
          <quality>MERE</quality>
46 55
          <civility>MME</civility>
......
115 124
                <mail>abent@example.org</mail>
116 125
              </contact>
117 126
            </personInfo>
118 127
            <personQuality>
119 128
              <code>T</code>
120 129
              <libelle>TANTE</libelle>
121 130
            </personQuality>
122 131
          </authorizedPersonList>
132
          <indicatorList>
133
            <code>LUNETTE</code>
134
            <label>Port de lunettes</label>
135
          </indicatorList>
136
          <indicatorList>
137
            <code>AUTRE</code>
138
            <label>Autre</label>
139
            <note>rebellious</note>
140
          </indicatorList>
123 141
          <medicalRecord>
124 142
            <familyDoctor>
125 143
              <name>DRE</name>
126 144
              <phone>0612341234</phone>
127 145
              <address>
128 146
                <street1>Alameda</street1>
129 147
                <zipcode>90220</zipcode>
130 148
                <town>Compton</town>
tests/data/toulouse_maelis/R_read_family_reordered.xml
31 31
            <mail>djhon@example.org</mail>
32 32
            <isContactMail>true</isContactMail>
33 33
            <isContactSms>true</isContactSms>
34 34
            <isInvoicePdf>true</isInvoicePdf>
35 35
          </contact>
36 36
          <profession>
37 37
            <addressPro/>
38 38
          </profession>
39
          <indicatorList>
40
            <code>ETABSPEC</code>
41
            <label>Etablissement sp&#233;cialis&#233;</label>
42
            <note>SNPP</note>
43
          </indicatorList>
44
          <indicatorList>
45
            <code>AVL</code>
46
            <label>Auxiliaire de Vie loisirs</label>
47
          </indicatorList>
39 48
        </RL1>
40 49
        <RL2>
41 50
          <num>613879</num>
42 51
          <lastname>DOE</lastname>
43 52
          <firstname>JANE</firstname>
44 53
          <maidenName>SMITH</maidenName>
45 54
          <quality>MERE</quality>
46 55
          <civility>MME</civility>
......
115 124
                <mail>abent@example.org</mail>
116 125
              </contact>
117 126
            </personInfo>
118 127
            <personQuality>
119 128
              <code>T</code>
120 129
              <libelle>TANTE</libelle>
121 130
            </personQuality>
122 131
          </authorizedPersonList>
132
          <indicatorList>
133
            <code>LUNETTE</code>
134
            <label>Port de lunettes</label>
135
          </indicatorList>
136
          <indicatorList>
137
            <code>AUTRE</code>
138
            <label>Autre</label>
139
            <note>rebellious</note>
140
          </indicatorList>
123 141
          <medicalRecord>
124 142
            <familyDoctor>
125 143
              <name>DRE</name>
126 144
              <phone>0612341234</phone>
127 145
              <address>
128 146
                <street1>Alameda</street1>
129 147
                <zipcode>90220</zipcode>
130 148
                <town>Compton</town>
tests/data/toulouse_maelis/R_update_indicator.xml
1
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
2
  <soap:Body>
3
    <ns2:updatePersonIndicatorListResponse
4
        xmlns:ns2="family.ws.maelis.sigec.com"/>
5
  </soap:Body>
6
</soap:Envelope>
tests/test_toulouse_maelis.py
61 61
UPDATE_DIETCODE = FakedResponse(content=get_xml_file('R_update_child_dietcode.xml'), status_code=200)
62 62
UPDATE_PAI = FakedResponse(content=get_xml_file('R_update_child_pai.xml'), status_code=200)
63 63
UPDATE_PAI_500 = FakedResponse(content=get_xml_file('R_update_child_pai_soap_error.xml'), status_code=500)
64 64
UPDATE_MEDICAL = FakedResponse(content=get_xml_file('R_update_child_medical_record.xml'), status_code=200)
65 65
UPDATE_MEDICAL_500 = FakedResponse(
66 66
    content=get_xml_file('R_update_child_medical_record_soap_error.xml'), status_code=500
67 67
)
68 68
UPDATE_CHILD_AUTO = FakedResponse(content=get_xml_file('R_update_child_authorization.xml'), status_code=200)
69
UPDATE_INDICATOR = FakedResponse(content=get_xml_file('R_update_indicator.xml'), status_code=200)
69 70

  
70 71

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

  
76 77

  
......
699 700
            'isContactMail': True,
700 701
            'isContactSms': True,
701 702
            'isInvoicePdf': True,
702 703
        },
703 704
        'CAFInfo': None,
704 705
        'civility_text': 'Monsieur',
705 706
        'quality_text': 'PERE',
706 707
        'quotientList': [],
707
        'indicatorList': [],
708
        'indicatorList': [
709
            {
710
                'choice': None,
711
                'code': 'AVL',
712
                'code_text': 'Auxiliaire de Vie loisirs',
713
                'label': 'Auxiliaire de Vie loisirs',
714
                'note': None,
715
            },
716
            {
717
                'choice': None,
718
                'code': 'ETABSPEC',
719
                'code_text': 'Etablissement spécialisé',
720
                'label': 'Etablissement spécialisé',
721
                'note': 'SNPP',
722
            },
723
        ],
708 724
        'subscribeActivityList': [],
709 725
    }
710 726
    data = resp.json['data']['childList'][0]
711 727
    del data['medicalRecord']
712 728
    del data['authorizedPersonList']
713 729
    del data['paiInfoBean']
730
    del data['indicatorList']
714 731
    assert data == {
715 732
        'num': '613880',
716 733
        'lastname': 'DOE',
717 734
        'firstname': 'JANNIS',
718 735
        'sexe': 'F',
719 736
        'sexe_text': 'Féminin',
720 737
        'birth': {
721 738
            'dateBirth': '1943-01-19T00:00:00+01:00',
......
723 740
            'communeCode': '91122',
724 741
            'countryCode': '99100',
725 742
        },
726 743
        'dietcode': 'RSV',
727 744
        'dietcode_text': '3- RÉGIME SANS VIANDE',
728 745
        'bPhoto': True,
729 746
        'bLeaveAlone': False,
730 747
        'insurance': None,
731
        'indicatorList': [],
732 748
        'subscribeSchoolList': [],
733 749
        'mother': {'num': 613963, 'civility': 'MME', 'firstname': 'JANE', 'lastname': 'DOE'},
734 750
        'father': {'num': 613878, 'civility': 'M.', 'firstname': 'JHON', 'lastname': 'DOE'},
735 751
        'rl': None,
736 752
        'subscribeActivityList': [],
737 753
    }
738 754
    if read_family != READ_FAMILY_LAX:
739 755
        assert resp.json['data']['childList'][0]['paiInfoBean'] == {
......
807 823
            'contact': {'phone': '0123456789', 'mobile': '0623456789', 'mail': 'abent@example.org'},
808 824
        },
809 825
        'personQuality': {
810 826
            'code': 'T',
811 827
            'code_text': 'TANTE',
812 828
            'libelle': 'TANTE',
813 829
        },
814 830
    }
831
    assert resp.json['data']['childList'][0]['indicatorList'] == [
832
        {'choice': None, 'code': 'AUTRE', 'code_text': 'Autre', 'label': 'Autre', 'note': 'rebellious'},
833
        {
834
            'choice': None,
835
            'code': 'LUNETTE',
836
            'code_text': 'Port de lunettes',
837
            'label': 'Port de lunettes',
838
            'note': None,
839
        },
840
    ]
815 841

  
816 842

  
817 843
def test_read_family_not_linked_error(con, app):
818 844
    url = get_endpoint('read-family')
819 845

  
820 846
    resp = app.get(url + '?NameID=')
821 847
    assert resp.json['err'] == 'not-linked'
822 848
    assert resp.json['err_desc'] == 'User not linked to family'
......
2765 2791
        'vaccinList/1/code': 'plop',
2766 2792
        'vaccinList/1/vaccinationDate': '2022-02-22',
2767 2793
    }
2768 2794

  
2769 2795
    Link.objects.create(resource=con, family_id='1312', name_id='local')
2770 2796
    resp = app.post_json(url + '?NameID=local&child_id=613878', params=params)
2771 2797
    assert resp.json['err'] == 'wrong-key'
2772 2798
    assert resp.json['err_desc'] == "vaccinList/1/code key value 'plop' do not belong to 'Vaccin' referential"
2799

  
2800

  
2801
@mock.patch('passerelle.utils.Request.get')
2802
@mock.patch('passerelle.utils.Request.post')
2803
def test_update_rl_indicator(mocked_post, mocked_get, con, app):
2804
    mocked_get.return_value = FAMILY_SERVICE_WSDL
2805
    mocked_post.return_value = UPDATE_INDICATOR
2806
    url = get_endpoint('update-rl-indicator')
2807
    params = {
2808
        'indicatorList': [
2809
            {
2810
                'code': 'AVL',
2811
                'isActive': True,
2812
            },
2813
            {
2814
                'code': 'ETABSPEC',
2815
                'note': 'SNPP',
2816
                'isActive': True,
2817
            },
2818
        ],
2819
    }
2820

  
2821
    Link.objects.create(resource=con, family_id='1312', name_id='local')
2822
    resp = app.post_json(url + '?NameID=local&rl_id=613878', params=params)
2823
    assert_sent_payload(mocked_post, 'Q_update_rl_indicator.xml')
2824
    assert resp.json['err'] == 0
2825
    assert resp.json['data'] == 'ok'
2826

  
2827

  
2828
def test_update_rl_indicator_not_linked_error(con, app):
2829
    url = get_endpoint('update-rl-indicator')
2830
    params = {
2831
        'indicatorList': [
2832
            {
2833
                'code': 'AVL',
2834
                'isActive': True,
2835
            },
2836
        ],
2837
    }
2838

  
2839
    resp = app.post_json(url + '?NameID=local&rl_id=613878', params=params)
2840
    assert resp.json['err'] == 'not-linked'
2841
    assert resp.json['err_desc'] == 'User not linked to family'
2842

  
2843

  
2844
def test_update_rl_indicator_no_indicator_error(con, app):
2845
    url = get_endpoint('update-rl-indicator')
2846
    params = {'indicatorList': []}
2847

  
2848
    Link.objects.create(resource=con, family_id='1312', name_id='local')
2849
    resp = app.post_json(url + '?NameID=local&rl_id=613878', params=params, status=400)
2850
    assert resp.json['err'] == 1
2851
    assert resp.json['err_desc'] == 'indicatorList: [] is too short'
2852

  
2853

  
2854
def test_update_rl_indicator_empty_referential_key_error(con, app):
2855
    url = get_endpoint('update-rl-indicator')
2856
    params = {
2857
        'indicatorList': [
2858
            {
2859
                'code': '',
2860
                'isActive': True,
2861
            },
2862
        ],
2863
    }
2864

  
2865
    Link.objects.create(resource=con, family_id='1312', name_id='local')
2866
    resp = app.post_json(url + '?NameID=local&rl_id=613878', params=params, status=400)
2867
    assert resp.json['err'] == 1
2868
    assert resp.json['err_desc'] == "indicatorList/0/code: '' does not match '.+'"
2869

  
2870

  
2871
def test_update_rl_indicator_wrong_referential_key_error(con, app):
2872
    url = get_endpoint('update-rl-indicator')
2873
    params = {
2874
        'indicatorList': [
2875
            {
2876
                'code': 'plop',
2877
                'isActive': True,
2878
            },
2879
        ],
2880
    }
2881

  
2882
    Link.objects.create(resource=con, family_id='1312', name_id='local')
2883
    resp = app.post_json(url + '?NameID=local&rl_id=613878', params=params)
2884
    assert resp.json['err'] == 'wrong-key'
2885
    assert (
2886
        resp.json['err_desc']
2887
        == "indicatorList/0/code key value 'plop' do not belong to 'RLIndicator' required referential"
2888
    )
2889

  
2890

  
2891
@mock.patch('passerelle.utils.Request.get')
2892
@mock.patch('passerelle.utils.Request.post')
2893
def test_update_child_indicator(mocked_post, mocked_get, con, app):
2894
    mocked_get.return_value = FAMILY_SERVICE_WSDL
2895
    mocked_post.return_value = UPDATE_INDICATOR
2896
    url = get_endpoint('update-child-indicator')
2897
    params = {
2898
        'indicatorList': [
2899
            {
2900
                'code': 'LUNETTE',
2901
                'isActive': True,
2902
            },
2903
            {
2904
                'code': 'AUTRE',
2905
                'note': 'rebellious',
2906
                'isActive': True,
2907
            },
2908
        ],
2909
    }
2910

  
2911
    Link.objects.create(resource=con, family_id='1312', name_id='local')
2912
    resp = app.post_json(url + '?NameID=local&child_id=613880', params=params)
2913
    assert_sent_payload(mocked_post, 'Q_update_child_indicator.xml')
2914
    assert resp.json['err'] == 0
2915
    assert resp.json['data'] == 'ok'
2916

  
2917

  
2918
def test_update_child_indicator_not_linked_error(con, app):
2919
    url = get_endpoint('update-child-indicator')
2920
    params = {
2921
        'indicatorList': [
2922
            {
2923
                'code': 'LUNETTE',
2924
                'isActive': True,
2925
            },
2926
        ],
2927
    }
2928

  
2929
    resp = app.post_json(url + '?NameID=local&child_id=613880', params=params)
2930
    assert resp.json['err'] == 'not-linked'
2931
    assert resp.json['err_desc'] == 'User not linked to family'
2932

  
2933

  
2934
def test_update_child_indicator_no_indicator_error(con, app):
2935
    url = get_endpoint('update-child-indicator')
2936
    params = {'indicatorList': []}
2937

  
2938
    Link.objects.create(resource=con, family_id='1312', name_id='local')
2939
    resp = app.post_json(url + '?NameID=local&child_id=613880', params=params, status=400)
2940
    assert resp.json['err'] == 1
2941
    assert resp.json['err_desc'] == 'indicatorList: [] is too short'
2942

  
2943

  
2944
def test_update_child_indicator_empty_referential_key_error(con, app):
2945
    url = get_endpoint('update-child-indicator')
2946
    params = {
2947
        'indicatorList': [
2948
            {
2949
                'code': '',
2950
                'isActive': True,
2951
            },
2952
        ],
2953
    }
2954

  
2955
    Link.objects.create(resource=con, family_id='1312', name_id='local')
2956
    resp = app.post_json(url + '?NameID=local&child_id=613880', params=params, status=400)
2957
    assert resp.json['err'] == 1
2958
    assert resp.json['err_desc'] == "indicatorList/0/code: '' does not match '.+'"
2959

  
2960

  
2961
def test_update_child_indicator_wrong_referential_key_error(con, app):
2962
    url = get_endpoint('update-child-indicator')
2963
    params = {
2964
        'indicatorList': [
2965
            {
2966
                'code': 'plop',
2967
                'isActive': True,
2968
            },
2969
        ],
2970
    }
2971

  
2972
    Link.objects.create(resource=con, family_id='1312', name_id='local')
2973
    resp = app.post_json(url + '?NameID=local&child_id=613880', params=params)
2974
    assert resp.json['err'] == 'wrong-key'
2975
    assert (
2976
        resp.json['err_desc']
2977
        == "indicatorList/0/code key value 'plop' do not belong to 'ChildIndicator' required referential"
2978
    )
2773
-