DHIS2 Error Handling

Hi everyone,
We are trying to implement error handling to continue importing dhis2 in the event that there may be a a duplicate individual within a different program. Currently, if there is a duplicate the job stops completely. Attached is the code which worked for importing as well as the error received when a duplicate individual within another program.


I have also attached a screenshot of an attempt of when we attempted to use try catch but we also received an error.


Much appreciated!

Hi @DanglebenC

Funnily enough, I’ve been working on a feature today which would really help you out here. I’m adding a feature where you can do create().catch(error => { ... }) to catch the error and do whatever you want with it.

Sadly it won’t be available for little while so we’ll just have to use what we’ve got.

The dhis2 adaptor actually has an upsert function, which will create the instance if it doesn’t exist, or update it if it does. Does that sound like what you need? Just replace create with upsert in your top example and you should be good to go really.

Regarding your try/catch code block, you’re on the right track for what we would do in your shoes. But a couple of tricky things jump out at me.

When you use create at the “top level” of your code, openfn does a bit of magic for you to make it easier to use. But inside a callback we can’t really do the magic, so you have to make a few extra steps I’m afraid:

  1. create is an asynchronous function, so you need to await it
  2. This means your callback needs to be async
  3. create actually returns a function to you, which you then need to call with state. It’s a little awkward.
  4. When you call create AND await it AND pass state, it’ll return you a state object. So no need to JSON.parse it or anything.

So your callback should look like this:

async (state) => {
   try {
      let response = await create("trackedEntityInstances", state.data)(state)

      console.log(response)

      return response
   } catch(error) {
   // ... as per your code
  }
}

Hope this helps!

-Joe

@jclark
Thanks for the assistance!
I believe in this case it would be better to use the upsert function since an individual may be registered in a different program. While using upsert like recommended above


I did receive the following error:

After going through the documentation I noticed that a filter and org unit variables are used; so I attempted implenting that as well:

However I received an error with the message either program or tracked entity type should be specified. They are mentioned within the event data.

hey @DanglebenC 409 error messages are coming directly from the DHIS2 api (not the OpenFn adaptor). So I think you need to add program or trackedEntityType on the trackedEntity-level (as well as on the event-level).

Check out the example payloads in the DHIS2 api docs for “flat” and “nested” payloads.

  • It looks like if you follow the nested payload approach, when mapping the event, you do not need to reference the id of the parent trackedEntity.
  • However, it does look like you need to repeat fields like trackedEntityType at all levels… so map orgUnit and trackedEntityType at the trackedEntity- AND event-level. (See my screenshot or the below payload for how orgUnit is repeatedly referenced, for example).

Also… if you’re going to reference a specific attribute in the filter, then be sure to include the mapping for that attribute in your payload as well.

Sample payload mentioned above:

{
    "trackedEntities": [
        {
            "enrollments": [
                {
                    "attributes": [
                        {
                            "attribute": "zDhUuAYrxNC",
                            "displayName": "Last name",
                            "value": "Kelly"
                        },
                        {
                            "attribute": "w75KJ2mc4zz",
                            "displayName": "First name",
                            "value": "John"
                        }
                    ],
                    "enrolledAt": "2019-08-19T00:00:00.000",
                    "occurredAt": "2019-08-19T00:00:00.000",
                    "orgUnit": "y77LiPqLMoq",
                    "program": "IpHINAT79UW",
                    "status": "ACTIVE",
                    "trackedEntityType": "nEenWmSyUEp",
                    "events": [
                        {
                            "attributeCategoryOptions": "xYerKDKCefk",
                            "attributeOptionCombo": "HllvX50cXC0",
                            "dataValues": [
                                {
                                    "dataElement": "bx6fsa0t90x",
                                    "value": "true"
                                },
                                {
                                    "dataElement": "UXz7xuGCEhU",
                                    "value": "5.7"
                                }
                            ],
                            "enrollmentStatus": "ACTIVE",
                            "notes": [
                                {
                                    "value": "need to follow up"
                                }
                            ],
                            "occurredAt": "2019-08-01T00:00:00.000",
                            "orgUnit": "y77LiPqLMoq",
                            "program": "IpHINAT79UW",
                            "programStage": "A03MvHHogjR",
                            "scheduledAt": "2019-08-19T13:59:13.688",
                            "status": "ACTIVE"
                        }
                    ]
                }
            ],
            "orgUnit": "y77LiPqLMoq",
            "trackedEntityType": "nEenWmSyUEp"
        }
    ]
}
 
2 Likes

Thanks for the assistance Aleksa!
Will be sure to implement this.

1 Like