← Back to the hackathon home
Topic 3 of 18

DHIS2 Organisation Units

Step by Step Guide: Building the Hierarchy by Hand and With a CSV Import

Purpose of this guide

Everything else in DHIS2 hangs off the organisation unit hierarchy, so this topic comes first. There are two ways to do it, and this guide covers both. Steps 3 to 8 build the hierarchy inside the platform, one unit at a time, which suits a handful of units and every correction afterwards. Steps 9 to 13 do the same work from a CSV file, which is the only sensible route for a district or a country. Step 14 checks the result, whichever route you took.

Step 1: The Hierarchy and Its Levels

Every value in DHIS2 belongs to an organisation unit, and every organisation unit sits in one hierarchy. Data is entered at the bottom and added up towards the top, so the hierarchy has to be right before anything else is built.

Figure 1. The four levels of the hierarchy. This picture was drawn for the guide. Your screen will show your own names and dates.
  1. 1Level 1, national. One unit, the root. Everything hangs from it.
  2. 2Level 2, district. Data from the chiefdoms under it is added up here.
  3. 3Level 3, chiefdom. The same again, one level down.
  4. 4Level 4, facility. Where data is entered. Nothing is entered above this level.
LevelNameExampleHow many
1NationalSierra Leone1
2DistrictBo16
3ChiefdomBadjia190 or so
4FacilityNgelehun CHC1 300 or so
Step 2: Open the Organisation Unit Section
Click: Maintenance app → ORGANISATION UNIT tab
Figure 2. The ORGANISATION UNIT tab. This picture was drawn for the guide. Your screen will show your own names and dates.
  1. 1The tab. The orange line shows where you are.
  2. 2Side menu. The same items as the cards.
  3. 3Organisation unit. The units and the hierarchy itself.
  4. 4Organisation unit group. Groups of units, such as every CHC.
  5. 5Group set. Holds the groups, for example Facility type.
  6. 6Organisation unit level. Where the levels are named, in Step 6.
Step 3: Create the Root Unit

The first unit has no parent. Everything else will sit under it, so give it the name of the country or the programme area.

Click: Organisation unit → blue plus button
Figure 3. The empty organisation unit form. This picture was drawn for the guide. Your screen will show your own names and dates.
  1. 1Parent. Empty for the root. For every other unit, click its parent in this tree first.
  2. 2Name (*). Sierra Leone.
  3. 3Short name (*). Used in reports and charts.
  4. 4Code. Optional, but useful when data comes from another system.
  5. 5Opening date (*). Must be earlier than any data you will enter.
  6. 6Coordinates. Leave empty for the root.
  7. 7SAVE. Creates the unit.
Figure 4. The root filled in. This picture was drawn for the guide. Your screen will show your own names and dates.
  1. 1Name. Sierra Leone.
  2. 2Short name. The same, since it is already short.
  3. 3Opening date. 1970-01-01 is the usual choice, so no data is ever rejected for being too early.
Step 4: Create a District Under It

Every unit except the root needs a parent. Click the parent in the tree, then fill in the form.

Figure 5. A district under the root. This picture was drawn for the guide. Your screen will show your own names and dates.
  1. 1Parent. Sierra Leone is selected, so Bo will sit under it.
  2. 2Name. Bo.
  3. 3Short name. Bo.
  4. 4Code. SL_BO, so the district is easy to match later.
  5. 5Opening date. The same date as the root, unless the district opened later.
Step 5: Create a Chiefdom and a Facility

Repeat the same two clicks one level down. The facility is where coordinates matter, because a facility without them never appears on a map.

Figure 6. A facility under a chiefdom. This picture was drawn for the guide. Your screen will show your own names and dates.
  1. 1Parent. Badjia, the chiefdom.
  2. 2Name. Ngelehun CHC.
  3. 3Code. A stable code, often the national facility code.
  4. 4Opening date. When the facility opened. Data before this date is rejected.
  5. 5Coordinates. Longitude first, then latitude, in square brackets.
Step 6: Name the Levels

The levels exist as soon as units are created, but they have no names until you give them some. Those names appear in every analysis app, so do it now.

Click: ORGANISATION UNIT tab → Organisation unit level
Figure 7. The four levels, named. This picture was drawn for the guide. Your screen will show your own names and dates.
  1. 1Organisation unit level. The side menu item.
  2. 2The list. One row per level that exists.
  3. 3Level number. 1 at the top, counting down the hierarchy.
  4. 4Name. National, District, Chiefdom, Facility.
  5. 5Offline levels. How many levels the tree loads at once. 1 is fine.
Step 7: Create the Groups

A group holds units of the same kind, for example every CHC. Groups are what let a chart show only health centres, or only hospitals.

Click: Organisation unit group → blue plus button
Figure 8. An organisation unit group. This picture was drawn for the guide. Your screen will show your own names and dates.
  1. 1Name. CHC.
  2. 2Short name. CHC.
  3. 3Code. OUG_CHC.
  4. 4Available units. Everything not yet in the group.
  5. 5Selected units. The facilities of this type.
  6. 6SAVE. Creates the group.
GroupWhat it holds
CHCCommunity health centres
CHPCommunity health posts
MCHPMaternal and child health posts
HospitalDistrict and referral hospitals
Step 8: Put the Groups in a Group Set

A group set is the question the groups answer. Facility type is one question, ownership is another. A unit belongs to one group per group set.

Figure 9. The group set that holds the four groups. This picture was drawn for the guide. Your screen will show your own names and dates.
  1. 1Name. Facility type.
  2. 2Short name. The same.
  3. 3Compulsory. Ticked, so every facility must belong to one of the groups.
  4. 4Data dimension. Ticked, so charts can be split by facility type.
  5. 5The groups. CHC, CHP, MCHP and Hospital.
  6. 6SAVE. Creates the group set.
Step 9: When to Use a CSV Instead

Creating units by hand is fine for a handful. For a district with two hundred facilities it is not, so the rest of this guide imports them from a file.

How many unitsUse
A few, or a correctionThe form, as in Steps 3 to 5
A whole district or countryA CSV import
Units that already exist elsewhereA CSV import, using their codes
Whichever route you take: the hierarchy is the same. A CSV simply creates the same units faster, and it still needs a parent for every row.
Step 10: Prepare the CSV File

The importer reads the columns by position, so the order matters and the first row is ignored. Only name is required, but parent is what builds the hierarchy.

Figure 10. The file, opened in a spreadsheet. This picture was drawn for the guide. Your screen will show your own names and dates.
  1. 1name. The full name of the unit.
  2. 2parent. The UID of the unit above it.
  3. 3coordinates. Longitude first, in square brackets, for facilities.
  4. 4The header row. Ignored on import, but keep it so the columns stay in order.
  5. 5One row per unit. And one file per level, which is the next step.
Column orderMeaning
nameRequired. Max 230 characters, unique
uidLeave empty and DHIS2 generates one
codeYour own stable code
parentThe UID of the parent unit
shortNameFalls back to the first 50 characters of the name
description, openingDate, closedDate, commentDates as YYYY-MM-DD
featureType, coordinatesPOINT with [longitude, latitude], or NONE
url, contactPerson, address, email, phoneNumberOptional contact details
There is no level column: the level is worked out from the parent chain. A row with no parent is level 1, its children are level 2, their children level 3, and so on. You never type a level number anywhere in the file.
Leaving uid empty: DHIS2 then generates an 11 character UID for you, which is fine for the last level. The catch is that you cannot use a generated UID as a parent in the same file, because it does not exist until the import finishes, so you would import one level, read the new UIDs, and only then import the level below.
What goes in the parent column: the root row leaves it empty, and every other row must name its parent before the dry run. Leave it blank on a district and the importer either rejects the row or creates a second root. There are three ways to fill it.
WayWhat you type in parentImport option
Parent already existsIts UID, 11 characters, copied from DHIS2Identifier: UID
You prefer your own codesThe parent code, such as SL_BOIdentifier: Code
One file for every levelThe UID you wrote yourself in the uid column of the parent rowIdentifier: UID
Writing your own UIDs: a UID is 11 characters, starts with a letter, and uses only letters and digits, for example SLBO0000001. Put it in the uid column of the district row and in the parent column of its chiefdoms, and the whole hierarchy imports in one go, with no copying between steps.
The file to use is beside this guide: csv/orgunits_import.csv. It creates a root, two districts, three chiefdoms and four facilities in one import, with the UIDs written in, so nothing has to exist first. csv/orgunit_groups_template.csv creates the groups.
Step 11: Import It as a Dry Run First
Click: Apps menu → Import/Export → Metadata import → choose the file
SettingSet it toWhat happens if it is wrong
FormatCSVThe file is read as JSON and fails
First row is headerTickedYour first unit is swallowed, and the row count is one too many
Class keyORGANISATION_UNITThe report reads 0 created, 0 ignored, 0 total
IdentifierUIDParents are looked up as codes and every row is ignored
Import report modeFull while testingOnly the first error is shown
Import strategyMergeAppend refuses to update a unit that already exists
Dry runTicked for the first runMistakes reach the database
Figure 11. The metadata import screen. This picture was drawn for the guide. Your screen will show your own names and dates.
  1. 1Format. CSV.
  2. 2Import type. Metadata.
  3. 3CSV object type. Organisation unit. Getting this wrong is the most common mistake.
  4. 4Identifier. UID, because the parent column holds UIDs.
  5. 5Dry run. Ticked. Nothing is written, but everything is checked.
  6. 6The file. One level at a time: districts, then chiefdoms, then facilities.
  7. 7IMPORT. Runs the check.
Step 12: Read the Report

A dry run either passes or tells you exactly what is wrong.

Figure 12. A dry run that passed. This picture was drawn for the guide. Your screen will show your own names and dates.
  1. 1Status. OK, dry run. Nothing was written yet.
  2. 2Created. How many units would be created.
  3. 3Total. It should match the number of rows in your file.
Figure 13. A dry run that failed. This picture was drawn for the guide. Your screen will show your own names and dates.
  1. 1Status. ERROR. Nothing was written.
  2. 2Ignored. The rows that could not be used.
  3. 3The messages. A missing parent UID, or a missing opening date. Fix the file and run it again.
MessageWhat it meansFix
Invalid reference for parentThe parent UID does not exist yetImport the level above first, then copy its UIDs
Missing required property openingDateThe date column is empty or in the wrong placeCheck the column order, and use YYYY-MM-DD
Duplicate nameA unit with that name existsRename, or update the existing unit instead
Nothing imported, no errorThe class key was wrongSet it to Organisation unit
Invalid reference for the rootYou used a UID from another instanceOn a new instance, leave the parent of the root empty, as in the file provided
Step 13: Import Level by Level

A parent must exist before its children, so the files go in from the top down. After each import, copy the new UIDs into the parent column of the next file.

Districts → copy UIDs → chiefdoms → copy UIDs → facilities
Figure 14. The real import, with the dry run unticked. This picture was drawn for the guide. Your screen will show your own names and dates.
  1. 1Dry run. Untick it only after the dry run passed.
  2. 2The file. The next level down.
  3. 3IMPORT. Writes the units.
Where to find the new UIDs: export the same units as CSV from the Import/Export app, or open a unit and read the UID in Show details.
Step 14: Check the Hierarchy, Then Use It

The tree is the proof. Every facility should sit under a chiefdom, and every chiefdom under a district.

Figure 15. The finished hierarchy. This picture was drawn for the guide. Your screen will show your own names and dates.
  1. 1The root. One only.
  2. 2Districts. Directly under the root.
  3. 3Chiefdoms. Under their district.
  4. 4Facilities. Under their chiefdom, where data is entered.
  5. 5What next. Assign the data set to these facilities, as in the data set topic.
Expected result: A hierarchy with named levels, groups and group sets, built by hand where it was small and by CSV where it was not.

Final Checklist