Commit to Production
Commit is the irreversible-ish step that turns staging rows into production members, savings accounts, loans, schedules and journal entries. It is the only stage that touches the GL, and it requires Two-Person sign-off for any run above the configured KES threshold.

What Commit does, exactly
Commit walks the staging rows of a Run in dependency order and creates production records in a single database transaction (one savepoint per 1,000 rows for crash recovery). For each row it: (a) creates the production record with the staging hash stamped in x_migration_*, (b) marks the staging row as committed with the production id, (c) writes a Mapping Audit entry. After all rows of a Run are processed, Commit posts the consolidated opening journal in account.move and locks the Run to state committed.
- Member rows -> res.partner (with mfi_member ext) — creates new partners or matches existing by KRA PIN or National ID, never by name.
- Savings rows -> mfi.savings.account — creates a new account, sets opened_on, opens an opening-balance line on account.move.
- Loan rows -> mfi.loan — creates the loan and its product link.
- Schedule rows -> mfi.loan.schedule — creates the amortisation lines and the migrated paid_to_date.
- Transaction rows -> mfi.savings.transaction and mfi.loan.transaction historical records (visible to the member but not posted to current-period GL).
- Collateral rows -> mfi.loan.collateral with attached document metadata.
The Two-Person Rule on large batches

Any Commit whose aggregate KES value (sum of savings balances + loan outstanding + historical transaction absolute values) exceeds the threshold defined in Two-Person Rules requires a countersignature from a user in the Account / Audit group.
| Threshold | Who must countersign | Where configured |
|---|---|---|
| KES 50,000,000 default | Finance Reviewer (Account / Audit group) | Settings -> MFI -> Two-Person Rules -> migration_commit_large_batch |
| KES 250,000,000 (board) | Board-delegated signatory (separate group) | Two-Person Rules -> migration_commit_board |
| Any value at all | Optional 'always countersign' toggle per tenant | Two-Person Rules -> migration_commit_always |
The commit flow, step by step
- On the Run record, click Commit. A wizard shows the pre-commit summary: record counts per table, KES totals, expected opening journal lines.
- If the run exceeds the Two-Person threshold, the wizard pauses and emails the Finance Reviewer a link. Migration Lead cannot proceed alone.
- Finance Reviewer opens the link, reviews the summary, and types their password.
- Background job mfi.migration.commit fires. For a 25,000-member + 60,000-savings + 5,000-loan + 250,000-schedule set, typical runtime is 8-15 minutes.
- Progress bar updates every 1,000 rows. The Run record shows committed_count / total live.
- On completion, the Run moves to state committed. The opening journal is posted but kept in draft if 'Post on commit' is unchecked on the Source.
- The Migration Lead clicks 'Open Reconciliation' to compare the new MFI Suite trial balance against the legacy trial balance provided by Finance. Deltas of less than KES 100 across the whole institution are normal (rounding).
- If reconciliation fails, the Run can be Reverse-Committed within 24 hours. After 24 hours, only a database administrator can unwind.
The opening journal and how it lands in the GL
Commit posts one consolidated opening journal per Run per Source-type. The journal lines follow the chart-of-accounts mapping defined on the Source, with sensible defaults for the SASRA chart.
| Source type | Debit | Credit | Note |
|---|---|---|---|
| Savings opening balances | Cash / Suspense (migration clearing) | Member Savings Liability (by product) | Per-member subledger reflects in mfi_savings reports immediately |
| Loans outstanding | Loan Portfolio Asset (by product) | Cash / Suspense (migration clearing) | ECL stage assigned by IFRS 9 module at first run after commit |
| Accrued interest receivable | Interest Receivable | Cash / Suspense | Optional — only if Source toggle 'Carry accrued interest' is on |
| Member shares / capital | Cash / Suspense | Member Shares Equity | Posts to equity section, not P&L |
| Migration clearing balance | — | — | Must net to zero at end of migration. Any residual is a reconciliation defect. |
Reverse Commit — the 24-hour escape hatch
If reconciliation fails after Commit, the Migration Lead has 24 hours to press Reverse Commit. The wizard requires a typed reason and the Finance Reviewer's password (always, regardless of value).
- Reverse Commit reverses the opening journal (creates a counter-entry, never deletes the original — BridgeERP accounting rule).
- Deletes the production records created by the Run (res.partner, mfi.savings.account, mfi.loan, mfi.loan.schedule, mfi.savings.transaction, mfi.loan.transaction).
- Marks staging rows back to validated.
- Logs everything on the Run chatter and on the Mapping Audit.
- Cannot be reversed if any post-commit downstream activity has touched the records — e.g. a member already logged into iBANK and made a transaction. In that case, Reverse Commit aborts with a list of the conflicting downstream actions.
Worked scenarios
Scenario — Tujikomboe commits members, savings and loans in one weekend
| Character | Role |
|---|---|
| Jane Wambui | Migration Lead |
| Peter Otieno | Data Steward |
| Florence Achieng | Finance Reviewer |
| Samuel Kibet | Tujikomboe CEO (executive sponsor, on standby) |
Timeline
- Sat 22:00: Jane fires final Member Run TJK-MEM-003. Aggregate KES 0 (members are not balances). No countersign needed. (Commit completes in 4m 30s. 8,418 members created. Run state: committed.)
- Sat 22:10: Jane fires Savings Run TJK-SAV-002. Aggregate KES 142,300,000. Two-Person Rule triggers. (Wizard pauses. Email sent to Florence.)
- Sat 22:15: Florence reviews summary: 18,201 accounts across 7 products, top 20 balances shown. Approves; types password. (Background commit job starts. ETA 12 minutes.)
- Sat 22:28: Savings commit completes. 18,201 accounts created, opening journal posted draft for review. (Run state: committed. Migration clearing account: KES 142,300,000 debit pending.)
- Sat 22:35: Jane fires Loans Run TJK-LOAN-003. Aggregate KES 89,700,000. Two-Person Rule triggers again. (Florence countersigns within 5 minutes.)
- Sat 22:55: Loans commit completes. 3,121 loans created, 184,000 schedule lines created. (Run state: committed. Migration clearing now: KES 142,300,000 - KES 89,700,000 = KES 52,600,000 debit.)
- Sat 23:10: Jane fires GL Opening Balances Run for cash, bank, shares, retained earnings. Posts the credit side that nets clearing to zero. (Migration clearing nets to KES 0. Reconciliation green.)
- Sat 23:30: Florence and Jane open the new MFI Suite trial balance, compare line-by-line to Loan Performer printout. (Total assets delta: KES 12 (rounding). Total liabilities delta: KES 12. Acceptable.)
- Sun 06:00: Reconciliation report attached to Cutover record. Florence signs go-ahead. (Cutover stage ready for Monday 06:00.)
Outcome — All four Commits land cleanly inside the planned window. Migration clearing nets to zero. Trial balance reconciles within KES 12. Sunday is used for smoke-testing iBANK and USSD before Monday's branch opening.
Reference
Commit wizard options
Each Commit wizard exposes these options. Defaults are sensible for first-time tenants.
| Option | Default | Description |
|---|---|---|
| Post opening journal | Yes for GL Opening Balances run, draft for others | If unchecked, journal posts in draft and Finance must Post manually. |
| Skip duplicate KRA PIN check | No | If on, members with the same PIN are created as separate partners (only use for genuinely shared corporate PINs). |
| Match members by | id_number > kra_pin > source_key | Order of fallback for matching to an existing partner. |
| Treat dormant as archived | No | If on, members with status=dormant are created with active=False (BridgeERP archive). |
| Carry accrued interest | Per-Source toggle | If on, generates accrued-interest opening journal lines. |
| IFRS 9 stage at commit | Auto (1) | Initial ECL stage. Set to None to defer to first scheduled IFRS 9 run. |
Background job parameters
Commits over 5,000 records run as queue.job entries. Tune these in production.
| Parameter | Default | Description |
|---|---|---|
| batch_size | 1000 | Rows per savepoint. |
| max_runtime_seconds | 3600 | Job auto-pauses (resumable) after this many seconds. |
| channel | root.migration | Dedicated queue channel; max 1 worker by default. |
| retry_on_serialization_error | 3 | Retries on PostgreSQL 40001 (concurrent update). |
| progress_log_every | 1000 | Progress chatter entries every N rows. |
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Commit fails halfway through with 'could not serialize access due to concurrent update'. | Another long-running cron (often the daily IFRS 9 ECL refresh) was touching account.move at the same time. | Pause crons during migration window (Settings -> Technical -> Crons -> deactivate the ECL job temporarily). Resume the failed Run. |
| Two-Person countersign email never arrives. | Reviewer's user does not have a valid email, or the outgoing mail server is throttling. | Verify res.users.email on the reviewer; check outgoing mail queue at Settings -> Technical -> Emails -> Outgoing. |
| Migration clearing account does not net to zero after all commits. | One Source has 'Carry accrued interest' on while its counterpart GL Opening Balances run does not include the offsetting credit. | Compute the delta, post an adjusting journal entry to interest receivable / migration clearing, document on the Cutover record. |
| Reverse Commit aborts with 'downstream activity detected'. | A member already logged in to iBANK or USSD and made a transaction, or a credit officer disbursed a new loan against a migrated member. | Cannot Reverse Commit. Either accept the data and patch errors with manual adjusting journals, or restore from the pre-commit backup taken automatically at commit start. |
| Commit shows green but trial balance is off by a large round number (e.g. KES 100,000). | A legacy GL line was not in the GL Opening Balances source — usually the suspense or 'sundry' account. | Run a small adjusting Migration Run with just that line, or post a manual journal and note it on the Cutover record. |

