# Phase 3 exit evidence: branch modules I

Brief section 13, Phase 3 exit criteria: **maker-checker works; the reconciliation statement balances;
reports tie to the ledger.** Scope: brief 7.2 Cash Book, 7.3 Bank Book, 7.4 Income, 7.5 Expenditure,
7.6 General Journal. Each line says how the rule is enforced and which automated test proves it. All tests
run on MySQL/MariaDB (the default since 3A) and on SQLite, locally and in CI.

The whole-church proof is `BranchModulesProofTest`: the demo church is built by the seeder, put through a
month of Phase 3 work (petty cash and a top-up, a reviewed requisition paid by cheque and presented, a
reversal by hand, a reconciliation signed off), and every rule below is then read back from the database.

## Maker-checker works

| Where | Rule | Proved by |
|---|---|---|
| Manual journals | Posted by someone other than the preparer | `LedgerIntegrityTest`; `BranchModulesProofTest` (every hand-made journal in the church) |
| Reversals by hand | Drafted, posted by a second person; posting links the two; only one waiting at a time; refused if already reversed another way | `GeneralJournalTest::test_a_reversal_asked_for_by_hand_is_a_draft_that_a_second_person_posts`, `…cannot_post_once_the_journal_was_reversed_another_way` |
| Recurring journals, accrual reversals | Only drafts, in the name of whoever set them up | `GeneralJournalTest::test_recurring_journals_…`, `…an_accrual_drafts_its_own_reversal…` |
| Imprest top-ups | Approved by neither the requester nor the custodian | `CashBookTest::test_top_up_is_approved_by_someone_else_and_restores_each_fund` |
| Cash counts | Two different people sign | `CashBookTest::test_cash_count_needs_two_signatures_and_posts_the_difference` |
| Requisitions | Prepared, reviewed, approved, paid by different people | `IncomeExpenditureTest::test_a_requisition_is_reviewed_then_approved_and_nobody_does_two_steps`; `GivingAndExpenseTest` |
| Bank reconciliations | Signed off by someone other than the preparer | `BankBookTest::test_a_reconciliation_is_signed_off_by_someone_else_and_then_locked` |
| Giving batches | Two counters sign before posting (since the MVP) | `GivingAndExpenseTest::test_batch_posts_per_fund_with_cash_shortage_after_two_signoffs` |

## The reconciliation statement balances

| Rule | Proved by |
|---|---|
| A reconciliation is saved only with a difference of ₦0.00: statement + uncleared receipts − uncleared payments = book + unbooked statement items | `BankBookTest`; `BranchModulesProofTest` (every reconciliation in the church, and its saved items add up to its totals) |
| The printed statement comes from the items saved at completion, so it never changes | `BankBookTest::test_imports_leave_out_lines_in_a_locked_period_and_the_statement_prints` |
| After sign-off the period is locked: no unmatching, no older lines imported, no earlier reconciliation | `BankBookTest::test_a_reconciliation_is_signed_off_by_someone_else_and_then_locked` |

## Reports tie to the ledger

| Report | Ties to | Proved by |
|---|---|---|
| Cash Book | Each cash account's ledger balance (with branch floats under 11020) | `CashBookTest::test_cash_book_ties_to_the_ledger…`; `BranchModulesProofTest` (every cash account) |
| Bank Book | Each bank account's book balance; "Cleared" from statement matches | `BankBookTest::test_bank_book_marks_cleared_lines_and_ties_to_the_ledger`; `BranchModulesProofTest` (every bank account) |
| Receipt Register | Gifts behind the receipts and the giving posted in the period | `IncomeExpenditureTest::test_posting_a_batch_issues_numbered_receipts…`; `BranchModulesProofTest` |
| Payment Voucher Register | Net paid = what left cash and bank in the vouchers' journals | `BranchModulesProofTest` |
| Cheque Register | Each cheque = its payment journal's credit to that bank account; presented on matching | `IncomeExpenditureTest::test_cheques_come_from_the_book_in_order…`; `BranchModulesProofTest` |
| Pledge Status | Gifts recorded against pledges in posted batches | `IncomeExpenditureTest::test_pledges_follow_instalments…` |
| The whole ledger | Nightly `ledger:verify` passes on the seeded church after all Phase 3 activity | `BranchModulesProofTest`; `WholeLedgerProofTest` |

## Brief 7.2 to 7.6 against what was built

| Brief | Built (decision) | Left for later |
|---|---|---|
| 7.2 Cash book | Imprest floats with limits, petty cash vouchers, top-ups, count sheets by denomination with over/short, Cash Book (D-040) | |
| 7.3 Bank book | Account kinds, minimum-balance alerts, transfers, CSV/Excel import with remembered columns, reference matching, unmatched lists, sign-off and lock, printable statement, fixed deposits with interest drafts, Bank Book (D-041) | Excel/PDF export of every report (Phase 4) |
| 7.4 Income | Numbered receipts (PDF, emailed with consent), two-person counts, pledge campaigns, instalments, reminders, fulfilment and status reports (D-042) | Receipts for other income posted by journal |
| 7.5 Expenditure | Review step, approval limits, separation of duties, printable payment voucher, payee register (existing), cheque books and register, WHT/VAT (existing) (D-042) | Cancelling an issued cheque is done by reversing its payment |
| 7.6 General journal | Checker for every journal including reversals, reversal wizard with corrected copy, recurring templates, auto-reversing accruals (D-043) | |

## Found and fixed while proving Phase 3

- A parent branch's bank page and ledger reports failed on lines from a branch's remittance journal (3B).
- A receipt for a member of another branch, posted at Headquarters, was filed as unidentified (3C).
- About twenty module postings (bills, fixed assets, business units, payroll, statement booking, year-end…)
  recorded their source module as "manual"; they now name the service that made them (3D, brief section 5).
