Skip to content

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

  1. An admin creates hcpi.secretariat.instance records — one per country, with that country's Odoo URL and an API key for an integration user.
  2. An ir.cron job runs periodically (defined in data/ir_cron.xml), iterates instances, opens an XML-RPC connection to each, and pulls the latest N months of indicators.
  3. Each pull writes a sync.log and (on success) one or more country.snapshot rows.
  4. The OWL dashboard (static/src/js/secretariat_dashboard.js) reads from country.snapshot to 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:

  1. Create a branch off 18.0 named xx_18 (e.g. gh_18 for Ghana).
  2. Create xx_location/ — define your country's administrative hierarchy as a chain of models. Match the existing pattern: one model per level, code and name fields, mail.activity.mixin for tracking.
  3. Create xx_outlet/ — _inherit = 'hcpi.outlet', add a Many2one to the leaf level of your geography, and stored-related fields up the chain.
  4. (Optional) Create xx_data_collection/ — only if your country's workflow diverges from the core. Typical adds: bulk-creation wizards, country-specific validation rules.
  5. (Optional) Create xx_base_import/ — only if your country has unusual import formats or validation rules.
  6. Update hcpi.conf on the deployment server: add the new module folders to addons_path.
  7. 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 _18 suffix) — 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.)