Skip to content

Commit

Permalink
Add Entity updates (#2592)
Browse files Browse the repository at this point in the history
* upgrade pyxform version

* downgrade pyxform to previous version

* upgrade pyxform

* upgrade package openpyxl

* downgrade pyxform to v2.0.0

* upgrade pyxform to v2.0.3

* fix import error

fix ImportError: cannot import name 'NSMAP' from 'pyxform.utils'

* fix error ValueError: seek of closed file

* fix lint warning

fix warning line too long

* fix Entities not created on submission

* fix failing tests

* fix failing test

* fix failing tests

* fix failing test

* resolve flaky test

* remove code added for debugging

* fix failing tests

* remove tets cases

tests for entities are catered for in onadata/apps/viewer/models/tests/test_data_dictionary.py

* fix failing tests

* update entity from form

* add test case

* move test case

move onadata.apps.api.tests.viewset.test_xform_submission_viewset.TestXFormSubmissionViewSet.test_create_entity to onadata.apps.logger.tests.models.test_instance.TestInstance.test_create_entity

* add history when updating entity from instance

* rename method names

* add test in test case

* move test case

move onadata.apps.api.tests.viewsets.test_xform_submission_viewset.TestXFormSubmissionViewSet.test_registration_form_inactive to onadata.apps.logger.tests.models.test_instance.TestInstance.test_registration_form_inactive

* handle conditions under which an Entity is updated

* rename variable

* fix lint error redefined-outer-name

* fix lint error redefined-outer-name

* Refactor code

* fix failing test

* refactor test case

* fix failing tests

* fix failing test

* add test case for model EntityHistory

* fix failing test

* refactor tests

* refactor tests

* refactor tests

* refactor tests

* refactor test

* update compose api command

* update CI postgres image

* do not mute Instance signals in tests

* unmute create_registration_form_datadictionary signal

* update Entities via API

* refactor code

* add tests

* update test

* delete Entities via API

* refactor code

* refactor tests

* update entities docs

* add test

* update flaky test max_runs

* update docs

* update docs

* decrement dataset num_entities on delete Entity

* update EntityList last_entity_update_time when Entity is updated

* update method name

* fix url not found

fix url api/v2/entity-lists/<entity_list_id>/entities/<entity_id> not found

* DRY tests

* update docs

* update EntityList last_entity_update_time on Entity delete

* add test

* add field uuid to Entity response

* fix failing tests

* add Entity id, uuid during serialization

* add url to detail view in list of Entities response

* add EntityList object level permissions

* set project permissions to EntityList asynchronously

* add tests

* unassign entitylists permissions when removing user from project

* fix lint error invalid-name

* fix lint warning ungrouped-imports

* fix lint warning redefined-builtin

* fix failing tests

* handle more edge cases for update Entity from form

* DRY code

* update doc string

* add date_created, date_modified to Entities API response

* rename Entity label key

* use chunked iterator in Python migration

* add OwnerRole to creator of form

* prefetch related data for EntityList list

* add tests
  • Loading branch information
kelvin-muchiri authored Jun 24, 2024
1 parent f0cf99b commit e0d1932
Show file tree
Hide file tree
Showing 55 changed files with 3,046 additions and 1,270 deletions.
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ services:
- ./:/srv/onadata
ports:
- 8000:8000
command: /usr/local/bin/uwsgi --ini /srv/onadata/uwsgi.ini
command: python3.10 manage.py runserver --settings=onadata.settings.docker

celery:
build:
Expand Down
176 changes: 149 additions & 27 deletions docs/entities.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,29 @@ Entities allow you to share information between forms, enabling the collection o

The following endpoints provides access to Entities related data: Where:

- _Entity_ - Each item that gets managed by an ODK workflow. Entities are automatically created from submissions receieved from a form that contains entity definitions.
- _EntityList_ - a dataset that contains Entities of the same type.
- `Entity` - Each item that gets managed by an ODK workflow. Entities are automatically created from submissions receieved from a form that contains entity definitions.
- `EntityList` - a dataset that contains Entities of the same type.
- `entity_list_id` - An EntityList's unique identifier
- `entity_id` - An Entity's unique identifier

## Get EntityLists

`GET /api/v2/entity-lists`

**Example**
This endpoint is used to get all EntityList datasets the user permission to view.

**Request**

`curl -X GET https://api.ona.io/api/v2/entity-lists`

**Response**

Status: `200 OK`

Body:

```
[
{
"url":"http://testserver/api/v2/entity-lists/9",
Expand All @@ -39,12 +48,16 @@ To get EntityLists for a specific project

`GET /api/v2/entity-lists?project=<project_id>`

**Example**
**Request**

`curl -X GET https://api.ona.io/api/v2/entity-lists?project=9`

**Response**

Status: `200 OK`

Body:

```
[
{
Expand All @@ -67,12 +80,18 @@ To get EntityLists for a specific project

`GET /api/v2/entity-lists/<entity_list_id>`

**Example**
This endpoint is used to get a single EntityList.

**Request**

`curl -X GET https://api.ona.io/api/v2/entity-lists/1`

**Response**

Status: `200 OK`

Body:

```
{
"id":16,
Expand Down Expand Up @@ -110,38 +129,141 @@ To get EntityLists for a specific project

`GET api/v2/entity-lists/<entity_list_id>/entities`

**Example**
This endpoint is used to get Entities belonging to a single EntityList dataset.

**Request**

`curl -X GET https://api.ona.io/api/v2/entity-lists/1/entities`

**Response**

Status: `200 OK`

Body:

```
[
{
"_id":3,
"species":"purpleheart",
"_version":"2022110901",
"geometry":"-1.286905 36.772845 0 0",
"formhub/uuid":"d156a2dce4c34751af57f21ef5c4e6cc",
"meta/instanceID":"uuid:9d3f042e-cfec-4d2a-8b5b-212e3b04802b",
"_xform_id_string":"trees_registration",
"circumference_cm":300,
"meta/entity/label":"300cm purpleheart",
"meta/instanceName":"300cm purpleheart"
"url":"http://testserver/api/v2/entity-lists/1/entities/3",
"id":3,
"uuid": "dbee4c32-a922-451c-9df7-42f40bf78f48",
"date_created": "2024-06-20T07:37:20.416054Z",
"data": {
"species":"purpleheart",
"geometry":"-1.286905 36.772845 0 0",
"circumference_cm":300,
"label":"300cm purpleheart",
}
},
{
"_id":4,
"species":"wallaba",
"_version":"2022110901",
"geometry":"-1.305796 36.791849 0 0",
"formhub/uuid":"d156a2dce4c34751af57f21ef5c4e6cc",
"intake_notes":"Looks malnourished",
"meta/instanceID":"uuid:648e4106-2224-4bd7-8bf9-859102fc6fae",
"_xform_id_string":"trees_registration",
"circumference_cm":100,
"meta/entity/label":"100cm wallaba",
"meta/instanceName":"100cm wallaba"
"url":"http://testserver/api/v2/entity-lists/1/entities/4",
"id":4,
"uuid": "517185b4-bc06-450c-a6ce-44605dec5480",
"date_created": "2024-06-20T07:38:20.416054Z",
"data": {
"species":"wallaba",
"geometry":"-1.305796 36.791849 0 0",
"intake_notes":"Looks malnourished",
"circumference_cm":100,
"label":"100cm wallaba",
}
}
]
```

## Get a single Entity

`GET api/v2/entity-lists/<entity_list_id>/entities/<entity_id>`

This endpoint is used to get a single Entity.

**Request**

`curl -X GET https://api.ona.io/api/v2/entity-lists/1/entities/3`

**Response**

Status: `200 OK`

Body:

```
{
"id":3,
"uuid": "dbee4c32-a922-451c-9df7-42f40bf78f48",
"date_created": "2024-06-20T07:37:20.416054Z",
"date_modified: "2024-06-20T07:37:20.416054Z",
"data": {
"species":"purpleheart",
"geometry":"-1.286905 36.772845 0 0",
"circumference_cm":300,
"label":"300cm purpleheart",
}
}
```

## Update Entity

`PATCH api/v2/entity-lists/<entity_list_id>/entities/<entity_id>`

This endpoint is used to update the label or the properties (passed as JSON in the request body) of an Entity.

You only need to include the properties you wish to update. To unset the value of any property, you can set it to empty string ("") or null.

A property must exist in the EntityList dataset.

The label must be a non-empty string.

**Request**

```sh
curl -X PATCH https://api.ona.io/api/v2/entity-lists/1/entities/1 \
-H "Authorization: Token ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"label": "30cm mora",
"data": {
"geometry": "-1.286805 36.772845 0 0",
"species": "mora",
"circumference_cm": 30
}
}'
```

**Response**

Status: `200 OK`

Body:

```
{
"id": 1,
"uuid": "dbee4c32-a922-451c-9df7-42f40bf78f48",
"date_created": "2024-06-20T07:37:20.416054Z",
"date_modified: "2024-06-20T08:37:20.416054Z",
"data": {
"geometry": "-1.286805 36.772845 0 0",
"species": "mora",
"circumference_cm": 30,
"label": "30cm mora",
}
}
```

## Delete an Entity

`DELETE api/v2/entity-lists/<entity_list_id>/entities/<entity_id>`

The endpoint is used to delete an Entity

**Request**

```sh
curl -X DELETE https://api.ona.io/api/v2/entity-lists/1/entities/1 \
-H "Authorization: Token ACCESS_TOKEN"
```

**Response**

Status: `204 No Content`
10 changes: 10 additions & 0 deletions onadata/apps/api/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -558,3 +558,13 @@ def has_permission(self, request, view):
return False

return True


class EntityListPermission(DjangoObjectPermissionsAllowAnon):
"""Permission for EntityList"""

def has_permission(self, request, view):
if request.user.is_anonymous:
return True

return super().has_permission(request, view)
Loading

0 comments on commit e0d1932

Please sign in to comment.