You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
As a breaking change in `8.90` the operator must have the 'Create Events and Alarms' privilege in the division of the source item, if your request specifies a source item. Current versions only require that the operator has that privilege on at least one division.
345
-
346
-
## Error Handling
347
-
348
-
### Exceptions
349
-
350
-
These wrappers raise the following `Exceptions` when they encounter the corresponding HTTP codes:
351
-
352
-
-`gallagher.exception.UnlicensedFeatureException` on `HTTPStatus.FORBIDDEN` when an unlicensed endpoint is accessed (see the discovery section for details)
353
-
-`gallagher.exception.AuthenticationError` on `HTTPStatus.UNAUTHORIZED` if there are issues with authentication
354
-
- gallagher.exception.NotFoundException`on`HTTPStatus.NOT_FOUND`(GET only) - raised if a HTTP endpoint wasn't found e.g A`Detail` object wasn't found
355
-
356
-
### Warnings
357
-
358
-
## Additional Features
359
-
360
-
In addition to a nicely validated wrapper around the data sent by the Command Centre API, we provide provide the following helper interface to keep your interaction `pythonic` wherever possible.
361
-
362
-
## Personal Data Definitions
363
-
364
-
Personal Data Definitions are fields associated to a cardholder and are defined at a Command Centre level. These are dynamically discovered by calling the `/api/personal_data_fields`. When you fetch a cardholder detail, the API returns the `personal_data_fields` as part of the response in the following manner:
365
-
366
-
- children of the `personalDataFields` key in the cardholder detail
367
-
- accessible via key name prefixed with the `@` symbol i.e the personal data field `Email` is accessible via the key `@Email`
368
-
369
-
370
-
!!! tip
371
-
372
-
Note that the `personDataFields` has a `list` of objects, and each object has a single key which is the nae of the personal data field and the value is the related data.
373
-
374
-
To make things more `pythonic` i.e consider the following payload (partially represented):
and we had used the API client to fetch the cardholder detail (partial example):
397
-
398
-
```python title="Personal Data Fields"
399
-
cardholder =await Cardholder.retrieve(340)
400
-
```
401
-
402
-
`cardholder` would have two fields:
403
-
-`personal_data_definitions` which is a list of `CardholderPersonalDataDefinition` objects
404
-
-`pdf` which is a parsed object of the personal data fields
405
-
406
-
`cardholder.personal_data_definitions` is iterable, each instance exposing a `name` and `contents` fields. Use the `value` attribute of `contents` to access the PDF value:
407
-
408
-
```python
409
-
for pdf in cardholder.personal_data_definitions:
410
-
if pdf.name =='@Email':
411
-
print(pdf.name, pdf.contents.value)
412
-
```
413
-
414
-
!!! tip
415
-
416
-
See pyndatic's [Model validator](https://docs.pydantic.dev/latest/concepts/validators/#model-validators) feature in v2, in particular the `@model_validator(mode='after')` constructor.
417
-
418
-
The `cardholder` object will also expose a special attribute called `pdf`. Each instance available in the `personal_data_definitions` field will be mapped to a Pythonic `snake_cased` key, that lets you access the same `CardholderPersonalDataDefinition` object via the `@` prefixed key name. So the above example of accessing the `@Email` field can be done as follows:
419
-
420
-
```python
421
-
cardholder.pdf.email.value
422
-
```
423
-
424
-
The `pdf` attribute is dynamically populated object with dynamically generated keys. Here are some examples of how `PDF` field names are mapped to `snake_case` keys:
425
-
426
-
-`@Cardholder UID` would become `pdf.cardholder_uid`
427
-
-`@City` would become `pdf.city`
428
-
-`@Company Name` would become `pdf.company_name`
429
-
-`@PINNumber` would become `pdf.pin_number`
430
-
431
-
Both approaches have their merits and you should use the one that suits your use case.
0 commit comments