Set up branches
Every transaction in the MFI Suite belongs to a branch. Set them up before you create users, products, or members — moving a transaction's branch after the fact requires GL re-mapping and breaks the SOC 2 audit chain.

The branch model
The MFI Suite models branches as res.branch, a child of res.company for a single-company tenant or as siblings for a holding-company tenant. Five levels are supported:
| Level | Code | Example | Cash limit |
|---|---|---|---|
| Head office | HO | Bridge MFI HO | Unlimited |
| Region | RGN | Western Region | KES 50M |
| Branch | BR | Kakamega Branch | KES 5M |
| Sub-branch | SB | Mumias Sub-branch | KES 500K |
| Agent | AG | Mumias Boda-Boda Agent | KES 50K |
Create a branch

From MFI → Configuration → Branches → New the wizard collects:
- Name and code: code is uppercase, 3–6 chars, used in the member-number sequence (KAK-2026-00001).
- Parent branch: drives the hierarchy and the consolidation roll-up.
- Physical address: street, town, county, GPS coordinates (used for the CBK geographical distribution return).
- Operating hours: feeds the dunning calendar and iBANK opening hours.
- Cash policy: daily withdrawal limit, vault threshold, dual-control limit (paired with the two-person rule).
- Bank accounts: at least one operational bank account per branch (KCB or Co-op Bank typically), one M-Pesa paybill if the branch collects via mobile money.
Branch-level chart of accounts
By default the chart of accounts is consolidated at the company level. To get a per-branch P&L you must enable analytic accounting and tag every journal line with the branch's analytic account.
# mfi_base/data/branch_default_accounts.xml — shipped
<record id="branch_analytic_plan" model="account.analytic.plan">
<field name="name">Branches</field>
<field name="applicability_ids" eval="[(0,0,{
'account_prefix': '5,6,7',
'business_domain': 'general',
'applicability': 'mandatory'
})]"/>
</record>
Cash tills and vault
Each branch carries one vault and one or more cash tills. The shipped mfi_cash_policy module enforces:
- Vault opening balance + daily till loadings ≤ branch cash limit.
- Single till withdrawal ≤ KES 100,000 — anything above requires two-person concurrence (handled by mfi_two_person).
- End-of-day till closeout mandatory before 18:00 — branch unable to open the next day without it.
- Vault reconciliation weekly, with internal audit sign-off recorded on
mfi.cash.vault.reconciliation.
Branch bank accounts
Wire each branch to at least one bank journal. The shipped naming convention is BR-<branch-code>-<bank>-<currency> e.g. BR-KAK-KCB-KES.
| Branch | Bank | Account # | Journal code | Use |
|---|---|---|---|---|
| HO | KCB | 1101234567 | HO-KCB-KES | Treasury master |
| Kakamega | KCB | 1102345678 | BR-KAK-KCB-KES | Operational |
| Kakamega | Co-op | 0114567890 | BR-KAK-COOP-KES | Disbursement |
| Mumias | Co-op | 0114567891 | BR-MUM-COOP-KES | Collections |
| Mumias | M-Pesa | Paybill 522522 | BR-MUM-MPESA | C2B |
Branch-restricted users
Once branches exist, every user (loan officer, teller, supervisor) must be assigned a default branch and an allowed-branches set. The record rule on mfi.loan filters by branch_id in allowed_branch_ids — without this assignment, a user can read the system-wide loan list and the SOC 2 evidence collector flags it.
Worked scenarios
Scenario — Opening the Mumias sub-branch
| Character | Role |
|---|---|
| Kimani Mwangi | Finance manager |
| Florence Achieng | System administrator |
| Peter Otieno | Newly-hired Mumias sub-branch officer |
Timeline
- Day 1, 09:00: Kimani sends Florence the board-approved sub-branch parameters: code MUM, parent KAK, daily limit KES 500,000, vault threshold KES 250,000. (Email)
- Day 1, 09:15: Florence opens MFI → Configuration → Branches → New and captures the basics. (res.branch draft)
- Day 1, 09:25: She picks Kakamega as parent and enters GPS coordinates -0.3372, 34.4878. (Hierarchy linked)
- Day 1, 09:35: She creates two bank journals:
BR-MUM-COOP-KESfor collections andBR-MUM-MPESAfor paybill 522522. (account.journal x2) - Day 1, 09:50: She sets the cash policy: daily limit 500K, vault threshold 250K, single till withdrawal limit KES 100,000. (mfi.cash.policy)
- Day 1, 10:00: Two-person rule auto-creates on save (vault open + close requires Peter + a supervisor). (mfi.two.person.rule auto)
- Day 1, 10:15: Peter logs in and confirms his default branch is MUM and his allowed-branches is just MUM. (res.users.x_default_branch_id = MUM)
- Day 14, 08:00: Public launch. First till opens at 08:00. (Branch live)
Outcome — Mumias opens cleanly with full SOC 2 audit chain from day 1; vault is reconciled weekly thereafter.
Reference
Fields on res.branch
| Field | Type | Required | Notes |
|---|---|---|---|
| name | Char | Yes | Display name |
| code | Char | Yes | 3–6 uppercase chars, unique |
| parent_id | Many2one | No | Self-relation |
| level | Selection | Yes | HO / RGN / BR / SB / AG |
| company_id | Many2one | Yes | res.company |
| street | Char | Yes | Physical address |
| county_id | Many2one | Yes | res.country.state |
| gps_lat / gps_lng | Float | No | For CBK geo-dist return |
| analytic_account_id | Many2one | Yes | account.analytic.account auto-created |
| cash_policy_id | Many2one | Yes | mfi.cash.policy |
| bank_journal_ids | One2many | Yes | account.journal |
| operating_hours | Char | Yes | 08:00–17:00 Mon-Fri etc. |
Default cash limits by branch level
| Level | Daily till limit | Vault threshold | Single withdrawal |
|---|---|---|---|
| HO | Unlimited | KES 10M | KES 5M |
| Region | KES 50M | KES 5M | KES 1M |
| Branch | KES 5M | KES 2.5M | KES 250K |
| Sub-branch | KES 500K | KES 250K | KES 100K |
| Agent | KES 50K | KES 25K | KES 25K |
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Cannot save branch — 'analytic plan applicability missing' | Default analytic plan not yet loaded | Re-run -u mfi_base; the plan ships in the data file. |
| User sees loans from all branches | No default branch set on res.users | Settings → Users → Edit → set default branch and allowed-branches set. |
| Cannot close till at 18:00 — 'cash variance not zero' | Float or shortage not declared | Open the till close wizard; capture the variance with the supervisor's two-person confirmation. |
| Branch P&L shows zero revenue | Revenue accounts not tagged with branch analytic | Edit the journal items missing the tag; or re-run the shipped mfi_treasury.tag_unallocated server action. |
| GPS coordinates missing on CBK geo-dist return | Branch saved without lat/lng | Edit branch, capture coords from Google Maps, re-run report. |

