Country Variants
The HCPI source repo holds one branch per country deployment. The c:/hcpi checkout you've been working with is one country's worldview (Uganda); the same shared core lives in every other country's branch with a different overlay on top.
This page maps the branch zoo and the concrete differences between country overlays — what each country adds, where the location hierarchies differ, and why some countries need a xx_data_collection overlay while others don't.
Source: github.com/kola-tech/HCPI-full (the canonical multi-branch repo). All findings below come from git ls-tree/git show against that repo.
The branch zoo
Sixteen branches in current use. Read the suffixes:
| Suffix pattern | Meaning |
|---|---|
18.0 |
The shared upstream — Odoo 18 base, no country overlay |
xx_18 |
Country xx deployment, currently on Odoo 18 |
xx_18_mtnce |
Maintenance branch for xx_18 (release candidates / hotfixes that merge back into xx_18). Note: the ke_18_mtnce/tz_18_mtnce instances are stale (frozen July 2025) — work on ke_18/tz_18 instead |
xx (no number) |
Legacy — pre-Odoo 18 deployment, single-folder architecture, frozen since March 2024 |
xx-18 |
Old intermediate naming — superseded by xx_18 |
ft-... |
Feature branches (e.g. ft-imputations_ug, ft-ug-outliers) |
secretariat |
EAC Secretariat regional aggregator (a completely different application) |
main |
Historical default — superseded by 18.0 as the upstream |
Country branches in use
| Country | Active branch | Last commit | Status |
|---|---|---|---|
| Upstream | 18.0 |
2026-04-14 | Shared base |
| Uganda | ug_18 |
2026-05-12 | Active |
| Kenya | ke_18 |
2026-04-13 | Active |
| Tanzania | tz_18 |
2026-04-13 | Active |
| Zanzibar | zar_18 |
2026-04-14 | Active |
| EAC Secretariat | secretariat |
2026-05-25 | Active (separate aggregator app) |
Use ke_18/tz_18, not the _mtnce branches
An earlier version of this page listed ke_18_mtnce/tz_18_mtnce as the active
Kenya/Tanzania branches. They are not — both have been frozen since July 2025
and sit ~95 commits behind 18.0. The live deployment branches are the plain
ke_18 (last commit 2026-04-13, 1 behind 18.0) and tz_18 (2026-04-13, 1
behind). The _mtnce branches hold nothing unique — ke_18_mtnce's only commit
not in ke_18 is a merge node, and tz_18_mtnce is fully contained in tz_18.
Restored production databases match ke_18/tz_18, not _mtnce.
zar = Zanzibar, not South Africa
Despite "ZAR" being the ISO currency code for South African Rand, in this repo zar/zar_18 is Zanzibar (semi-autonomous part of Tanzania). The zar_data_collection manifest is explicit: "Customize and manage Zanzibar data collections". South Africa isn't part of the HCPI deployment family.
Legacy branches (rw, ss, bi)
Rwanda, South Sudan, and Burundi each have a branch (rw, ss, bi) using an older single-folder architecture (hcpi-xx/ containing country-prefixed modules with no shared core). All three have been frozen since March 2024 and aren't representative of current HCPI. If you're working on these countries, plan to migrate them to the modern overlay pattern below rather than extending the old structure.
The modern overlay pattern
Every active country (UG, KE, TZ, ZAR) layers on top of the shared 18.0 upstream by adding xx_* modules — never modifying the core.
18.0 (upstream) Country branch (e.g. ug_18)
───────────────── ────────────────────────────
hcpi_coicop hcpi_coicop ◀── inherited verbatim
hcpi_item hcpi_item ◀── inherited verbatim
hcpi_outlet hcpi_outlet ◀── inherited verbatim
hcpi_data_collection hcpi_data_collection ◀── inherited verbatim
hcpi_index hcpi_index ◀── inherited verbatim
hcpi_dashboard hcpi_dashboard ◀── inherited verbatim
... (all core modules) ... (all core modules)
┌─────────────────────────┐
│ ug_location ◀── ADDED │
│ ug_outlet ◀── ADDED │
│ ug_base_import ◀── ADDED│
└─────────────────────────┘
Core modules pull in verbatim via regular git merges (visible as Merge pull request #129 from kola-tech/18.0 in branch history). When upstream changes — a bug fix in hcpi_outlet, say — every country branch can merge it without losing their overlay. This is the pattern the Module Reference describes, and the one to use for new countries.
Country overlays compared
Every active country (modern branches) ships the same template: a xx_location module defining the geographic hierarchy, a xx_outlet module linking outlets to that geography, and optionally xx_data_collection and xx_base_import modules.
But the hierarchies are different, and not every country needs every overlay.
Geographic hierarchies
| Country | Levels | Models |
|---|---|---|
| Uganda | 5 | ug.region → ug.district → ug.county → ug.sub.county → ug.parish |
| Kenya | 3 | ke.region → ke.county → ke.zone |
| Tanzania | 2 | tz.region → tz.district |
| Zanzibar | 3 | zar.region → zar.district → zar.collection.center |
Hierarchy depth follows each country's administrative structure. Uganda is the deepest (parish-level data collection); Tanzania is the flattest (district-level).
Outlet anchor
Each xx_outlet module extends hcpi.outlet with the deepest geographic FK; the higher levels are stored-related fields that cascade up the chain for fast filtering.
| Country | _inherit anchor field |
|---|---|
| Uganda | parish_id (the leaf); sub_county_id/county_id/district_id/region_id are related-stored |
| Kenya | zone_id (the leaf); county_id/region_id are related-stored |
| Tanzania | district_id (the leaf); region_id is related-stored |
| Zanzibar | collection_center_id (the leaf); district_id/region_id are related-stored |
So filtering "all outlets in Kampala" works the same way in every country — just substitute the right field name.
Which extra modules each country needs
Not every country has every overlay. Some countries needed extra workflow customization (bulk questionnaire wizards, specific validation flows); others use the core HCPI behaviour as-is.
| Module pattern | Uganda | Kenya | Tanzania | Zanzibar |
|---|---|---|---|---|
xx_location |
✅ | ✅ | ✅ | ✅ |
xx_outlet |
✅ | ✅ | ✅ | ✅ |
xx_data_collection |
❌ | ✅ | ✅ | ✅ |
xx_base_import |
✅ | ✅ | ✅ | ❌ |
Why Uganda has no ug_data_collection: the core hcpi_data_collection module was largely written against Uganda's workflow, so Uganda's needs are covered by the base behaviour. Other countries added their own variants where their workflow diverges.
What xx_data_collection typically adds:
| Country | Models added |
|---|---|
ke_data_collection |
bulk_questionnaire_wizard, extends hcpi.data.collection, extends hcpi.data.validation |
tz_data_collection |
bulk_questionnaire_wizard, assign_questionnaire_wizard, extends hcpi.data.collection, extends hcpi.data.validation |
zar_data_collection |
bulk + assign questionnaire wizards (in wizards/), extends hcpi.data.collection |
Common themes: bulk-creation wizards for spinning up many questionnaires at once, and assignment wizards for batching surveys to enumerators.
Has the core drifted across branches?
In a perfect world, the core HCPI modules (hcpi_outlet, hcpi_data_collection, hcpi_index, etc.) would be identical between 18.0 and every country branch — country deltas would live entirely in the xx_* overlay modules.
In practice the drift is now small — the active branches all track 18.0 closely:
| Branch | Behind 18.0 |
Diff in hcpi_data_collection vs. 18.0 |
|---|---|---|
ug_18 |
0 | 1 file changed |
ke_18 |
1 | None — fully in sync |
tz_18 |
1 | None — fully in sync |
zar_18 |
0 | None — fully in sync |
The earlier large drift (Kenya 28 files, Tanzania 9 files) was on the now-abandoned
ke_18_mtnce/tz_18_mtnce branches, which were ~95 commits behind 18.0. Moving
Kenya and Tanzania onto ke_18/tz_18 closed it — those branches have merged the
latest 18.0, so hcpi_data_collection is identical to upstream again. The country
deltas now live entirely in the xx_* overlay modules, which is the intended state.
The EAC Secretariat — separate application
The secretariat branch is not a country deployment. It's a regional aggregator: one Odoo instance that pulls CPI snapshots from each country's HCPI database over XML-RPC and presents a consolidated dashboard.
Folder layout:
secretariat/
└── hcpi_secretariat_hub/
├── __manifest__.py
├── models/
│ ├── remote_instance.py
│ ├── snapshot.py
│ ├── dashboard.py
│ └── res_users.py
├── data/
│ └── ir_cron.xml ← scheduled syncs
├── views/
├── security/
└── static/ ← OWL dashboard
Only one HCPI-aware module: hcpi_secretariat_hub. It depends only on Odoo's base and web — none of the country modules — because it doesn't share data tables with them; it talks to them as remote clients.
Key models
| Model | Purpose |
|---|---|
hcpi.secretariat.instance |
One per country deployment. Fields: name, code (KE/TZ/UG/ZAR), base_url, database_name, username, api_key, sync_month_window (default 12), state (draft/connected/error), last_sync_at, last_sync_status. Unique on code. |
hcpi.secretariat.sync.log |
One row per sync attempt. Fields: instance_id, status (running/success/failed), started_at, finished_at, records_synced, message. |
hcpi.secretariat.country.snapshot |
The actual aggregated data. One row per (country, month). Fields: instance_id, country_code (stored-related), snapshot_month, current_cpi, min_cpi, max_cpi, total_outlets, total_items, total_outlet_items, total_observations, last_sync_at. |
How it works
- An admin creates
hcpi.secretariat.instancerecords — one per country, with that country's Odoo URL and an API key for an integration user. - An
ir.cronjob runs periodically (defined indata/ir_cron.xml), iterates instances, opens an XML-RPC connection to each, and pulls the latest N months of indicators. - Each pull writes a
sync.logand (on success) one or morecountry.snapshotrows. - The OWL dashboard (
static/src/js/secretariat_dashboard.js) reads fromcountry.snapshotto render the regional view.
Why XML-RPC and not direct DB access?
Two reasons. Each country runs its HCPI in its own data centre under its own authority — the secretariat has no business connecting to their PostgreSQL directly. And the indicators are derived from queries that already exist in hcpi_index; calling them via RPC reuses that logic, rather than re-implementing index computation in the aggregator.
The integration user on each country instance is granted read access to the relevant index models only. If you're standing up a new country and integrating it with the secretariat, you'll need to create that user and share the API key.
Adopting HCPI for a new country
The recipe, distilled from how UG/KE/TZ/ZAR are structured:
- Create a branch off
18.0namedxx_18(e.g.gh_18for Ghana). - Create
xx_location/— define your country's administrative hierarchy as a chain of models. Match the existing pattern: one model per level,codeandnamefields,mail.activity.mixinfor tracking. - Create
xx_outlet/—_inherit = 'hcpi.outlet', add a Many2one to the leaf level of your geography, and stored-related fields up the chain. - (Optional) Create
xx_data_collection/— only if your country's workflow diverges from the core. Typical adds: bulk-creation wizards, country-specific validation rules. - (Optional) Create
xx_base_import/— only if your country has unusual import formats or validation rules. - Update
hcpi.confon the deployment server: add the new module folders toaddons_path. - For secretariat integration: create an integration user on the new instance with read access to indices; share base URL + database name + API key with the secretariat team.
Avoid:
- ❌ Modifying core
hcpi_*modules in your country branch — the drift will haunt you at merge time. - ❌ Naming a new branch
xx(no number, no_18suffix) — that pattern is used for older retired branches and is confusing.
Quick reference
| If you want to... | Look in... |
|---|---|
| See what's specific about Uganda's outlets | ug_18:ug_outlet/models/hcpi_outlet.py |
| Compare Kenya's vs Tanzania's geography depth | ke_location/models/ vs tz_location/models/ |
| Find Zanzibar's bulk-questionnaire wizard | zar_18:zar_data_collection/wizards/ |
| See what the secretariat aggregates | secretariat:hcpi_secretariat_hub/models/snapshot.py |
| See how country branches merge from upstream | git log --merges 18.0..ug_18 (etc.) |