Add support for Location as person attribute

Hey, i recently worked on → RESTWS-955: Add support for person attribute of type Location by mherman22 · Pull Request #620 · openmrs/openmrs-module-webservices.rest · GitHub with an attempt to add suport for org.openmrs.Location to person attributes. The challenge is that when we create or update a patient while adding a location as a person attribute, the attributed is created as can be seen below.

Click to see request body
{
	"person": {
		"addresses": [
			{
				"address1": "Address10737",
				"cityVillage": "City0737",
				"country": "Country0737",
				"postalCode": "95293",
				"stateProvince": "State0737"
			}
		],
		"attributes": [
			{
				"attributeType": "8d87236c-c2cc-11de-8d13-0010c6dffd0f", --------> uuid for attributetype i.e health centre
				"value": "8d9045ad-50f0-45b8-93c8-3ed4bce19dbf" ------->  uuid for the person attribute / location i.e unknown location
			}
		],
		"birthdate": "1963-4-10",
		"birthdateEstimated": false,
		"dead": false,
		"gender": "M",
		"names": [
			{
				"familyName": "Martinez",
				"givenName": "James",
				"preferred": true,
				"uuid": "b4ece550-dc90-4409-ba91-91aa4a650f92"
			}
		],
		"uuid": "cfef612c-ceb1-4d43-858f-26b0717e8527"
	}
}
Click to see response
{
    "uuid": "cfef612c-ceb1-4d43-858f-26b0717e8527",
    "display": "100005L - James Martinez",
    "identifiers": [
        {
            "uuid": "9198b51a-9f4b-4152-af76-594b5c92b3bd",
            "display": "OpenMRS ID = 100005L",
            "links": [
                {
                    "rel": "self",
                    "uri": "http://dev3.openmrs.org/openmrs/ws/rest/v1/patient/cfef612c-ceb1-4d43-858f-26b0717e8527/identifier/9198b51a-9f4b-4152-af76-594b5c92b3bd",
                    "resourceAlias": "identifier"
                }
            ]
        }
    ],
    "person": {
        "uuid": "cfef612c-ceb1-4d43-858f-26b0717e8527",
        "display": "James Martinez",
        "gender": "M",
        "age": 61,
        "birthdate": "1963-04-10T00:00:00.000+0000",
        "birthdateEstimated": false,
        "dead": false,
        "deathDate": null,
        "causeOfDeath": null,
        "preferredName": {
            "uuid": "b4ece550-dc90-4409-ba91-91aa4a650f92",
            "display": "James Martinez",
            "links": [
                {
                    "rel": "self",
                    "uri": "http://dev3.openmrs.org/openmrs/ws/rest/v1/person/cfef612c-ceb1-4d43-858f-26b0717e8527/name/b4ece550-dc90-4409-ba91-91aa4a650f92",
                    "resourceAlias": "name"
                }
            ]
        },
        "preferredAddress": {
            "uuid": "47f58c7a-ca8d-423c-bdbd-99b223b8fb8f",
            "display": "Address10737",
            "links": [
                {
                    "rel": "self",
                    "uri": "http://dev3.openmrs.org/openmrs/ws/rest/v1/person/cfef612c-ceb1-4d43-858f-26b0717e8527/address/47f58c7a-ca8d-423c-bdbd-99b223b8fb8f",
                    "resourceAlias": "address"
                }
            ]
        },
        "attributes": [
            {
                "uuid": "fe015ab0-70ae-44c0-b319-c4408052d072",
                "display": "",
                "links": [
                    {
                        "rel": "self",
                        "uri": "http://dev3.openmrs.org/openmrs/ws/rest/v1/person/cfef612c-ceb1-4d43-858f-26b0717e8527/attribute/fe015ab0-70ae-44c0-b319-c4408052d072",
                        "resourceAlias": "attribute"
                    }
                ]
            }
        ],
        "voided": false,
        "birthtime": null,
        "deathdateEstimated": false,
        "links": [
            {
                "rel": "self",
                "uri": "http://dev3.openmrs.org/openmrs/ws/rest/v1/person/cfef612c-ceb1-4d43-858f-26b0717e8527",
                "resourceAlias": "person"
            },
            {
                "rel": "full",
                "uri": "http://dev3.openmrs.org/openmrs/ws/rest/v1/person/cfef612c-ceb1-4d43-858f-26b0717e8527?v=full",
                "resourceAlias": "person"
            }
        ],
        "resourceVersion": "1.11"
    },
    "voided": false,
    "links": [
        {
            "rel": "self",
            "uri": "http://dev3.openmrs.org/openmrs/ws/rest/v1/patient/cfef612c-ceb1-4d43-858f-26b0717e8527",
            "resourceAlias": "patient"
        },
        {
            "rel": "full",
            "uri": "http://dev3.openmrs.org/openmrs/ws/rest/v1/patient/cfef612c-ceb1-4d43-858f-26b0717e8527?v=full",
            "resourceAlias": "patient"
        }
    ],
    "resourceVersion": "1.8"
}

However the challenge is when i click to make a GET request using http://dev3.openmrs.org/openmrs/ws/rest/v1/person/cfef612c-ceb1-4d43-858f-26b0717e8527/attribute/fe015ab0-70ae-44c0-b319-c4408052d072 which is a link to the person attribute we created, it returns the response below:

{
    "display": "",
    "uuid": "fe015ab0-70ae-44c0-b319-c4408052d072",
    "value": {
        "uuid": "2d097920-d992-4605-8d4f-2643ef5a1be8",
        "display": "",
        "links": [
            {
                "rel": "self",
                "uri": "http://dev3.openmrs.org/openmrs/ws/rest/v1/location/2d097920-d992-4605-8d4f-2643ef5a1be8",
                "resourceAlias": "location"
            }
        ]
    },
    "attributeType": {
        "uuid": "8d87236c-c2cc-11de-8d13-0010c6dffd0f",
        "display": "Health Center",
        "links": [
            {
                "rel": "self",
                "uri": "http://dev3.openmrs.org/openmrs/ws/rest/v1/personattributetype/8d87236c-c2cc-11de-8d13-0010c6dffd0f",
                "resourceAlias": "personattributetype"
            }
        ]
    },
    "voided": false,
    "links": [
        {
            "rel": "self",
            "uri": "http://dev3.openmrs.org/openmrs/ws/rest/v1/person/cfef612c-ceb1-4d43-858f-26b0717e8527/attribute/fe015ab0-70ae-44c0-b319-c4408052d072",
            "resourceAlias": "attribute"
        },
        {
            "rel": "full",
            "uri": "http://dev3.openmrs.org/openmrs/ws/rest/v1/person/cfef612c-ceb1-4d43-858f-26b0717e8527/attribute/fe015ab0-70ae-44c0-b319-c4408052d072?v=full",
            "resourceAlias": "attribute"
        }
    ],
    "resourceVersion": "1.8"
}

This is problematic because the uuid within the value object which is supposed to be the uuid to the location we created as a person attribute earlier which is not the case. It is a new uuid each time we fetch the person attribute we created for a person.

@usamakakumba can you talk more about this?

Any pointers on where i could be going wrong? cc: @dev5 @dev4 @dev3

3 Likes

To my notice @mherman22 u set the location to person attribute

public void setValue(PersonAttribute personAttribute, String value) {
		if (RestUtil.isValidUuid(value)) {
			Location location = Context.getLocationService().getLocationByUuid(value);
			if (location != null) {
				personAttribute.setValue(location.getUuid());
				return;
			}
		}

However seems like the patient identifier changes on each request from the rest api that could be the issue maybe investigating how the patient identier is set could be the solution

Thats the whole idea of trying to support locations as person attributes.

However the issue is why does it return a new uuid for the person attribute each time we fetch attributes for the given person?!.

However, i am exploring the avenue of setting the id instead.

personAttribute.setValue(location.getId());

1 Like

Can you add a controller test for this somewhere like in PersonAttributeController1_9Test or any other appropriate controller test?

1 Like

I have added this test in PersonAttributeController1_9Test class which clearly shows what i was talking of earlier

	@Test
	public void shouldSupportLocationPersonAttributeBySettingUuidAsValue() throws Exception {
		String personAttributeTypeJson = "{\"name\": \"location\", \"description\": \"Points to a location\", \"format\": \"org.openmrs.Location\"}";
		SimpleObject personAttributeType = deserialize(handle(newPostRequest("personattributetype", personAttributeTypeJson)));
		String personAttributeTypeUuid = (String) personAttributeType.get("uuid");
		assertThat(personAttributeTypeUuid, is(notNullValue()));

		Location location = locationService.getLocation(1);

		String personAttributeJson = "{ \"attributeType\":\"" + personAttributeTypeUuid + "\", \"value\":\"" + location.getUuid() + "\"}";
		SimpleObject personAttribute = deserialize(handle(newPostRequest(getURI(), personAttributeJson)));

		Map<String, Object> value = personAttribute.get("value");

		assertThat(value.get("uuid"), is(notNullValue()));
		Assert.assertEquals(value.get("uuid"), location.getUuid());
		assertThat((String) value.get("display"), is("Unknown Location"));
		assertThat(value.get("links"), is(notNullValue()));
	}

It fails at Assert.assertEquals(value.get(“uuid”), location.getUuid());

When i look at this:

It fails to parse the uuid as an integer and returns a new location object which will obviously have a randomly generated uuid. So before we fix that code, you are left with using personAttribute.setValue(location.getId()); as you suggested above.

2 Likes

Good catch!, now the controller test passes. I will now test on an instance before i send in a PR. Thanks!

1 Like

Tested and i can confirm the fix, find pull request at RESTWS-955: Fix adding support for locations as person attributes by mherman22 · Pull Request #628 · openmrs/openmrs-module-webservices.rest · GitHub

cc: @dkayiwa @usamakakumba

2 Likes

@dkayiwa Looks like the issue persists on dev3 but i suspect it could be related to the failed build on bamboo which fails with

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-install-plugin:2.4:install (default-install) on project webservices.rest: Failed to install artifact org.openmrs.module:webservices.rest:pom:2.45.0-SNAPSHOT: /home/bamboo-agent/.m2/repository/org/openmrs/module/webservices.rest/2.45.0-SNAPSHOT/webservices.rest-2.45.0-SNAPSHOT.pom (Permission denied) → [Help 1

Scratch that, after a rebuild the artifact was successfully uploaded