# Step 15 — Loan Write-Off — Implementation Report

**Status:** COMPLETED  
**Verified:** 12 August 2026  
**Pull request:** #27

## Write-off workflow

- Added controlled full-balance loan write-off requests for active loans.
- Only staff with dedicated management permissions can request and approve/reject write-offs.
- Every request requires:
  - loan
  - exact full current outstanding balance
  - reason
  - at least one supporting document
  - management decision
- A submitted request does not modify the active loan until approval.
- Duplicate pending/approved write-offs for the same loan are blocked.
- Write-off requests are blocked while an unresolved restructuring or top-up replacement application exists.
- Supporting evidence is stored privately and downloaded only through branch-scoped authorized routes.
- When maker-checker is enabled, the employee who requested the write-off cannot approve it.
- Approval rechecks the exact current principal, interest, fees and penalties under database locks.
- If the balance changed after request submission, approval is rejected as stale and a fresh request is required.
- Rejection permanently records the decision and leaves the active loan unchanged.

## History preservation

Approved write-off changes the loan status to `written_off` and records `written_off_at` and `written_off_by`.

The write-off does **not** zero, delete or rewrite the original loan history. It permanently preserves:

- customer
- loan number and original loan amount
- original total repayment
- principal outstanding at write-off request
- interest outstanding at write-off request
- fees outstanding at write-off request
- penalties outstanding at write-off request
- total written-off balance
- all normal loan payments
- all installment/payment allocation history
- remaining loan balance fields
- collateral and its custody status/history
- collection follow-up history
- write-off reason and supporting evidence
- requester, approver/rejecter and decision timestamps/comments

A permanent loan status-history event records `active -> written_off`.

Collateral is not automatically released, sold or deleted by a write-off; existing collateral custody controls remain authoritative.

## Accounting treatment

The existing accounting model recognizes the loan principal as a receivable at disbursement, while interest, fees and penalties are recognized when collected.

Therefore approval posts a balanced write-off journal for outstanding principal only:

- Debit: write-off / bad-debt expense
- Credit: principal receivable

Outstanding interest, fees and penalties remain in the permanent write-off recovery snapshot instead of inventing receivables that were never booked in the ledger.

The write-off stores its accounting journal number permanently.

## Written-off loan recovery

- Added a separate written-off-loan recovery workflow.
- Recovery records are never inserted into the normal `loan_payments` table.
- Each recovery records:
  - recovery number
  - write-off
  - loan and customer
  - receiving financial account
  - amount
  - date
  - method
  - reference
  - notes
  - receiving employee
  - linked financial-account transaction
- Recovery increases the selected financial-account balance transactionally.
- Accounting posts:
  - Debit: receiving asset/account
  - Credit: dedicated Written-Off Loan Recovery income
- `recovered_amount` increases and `recoverable_balance` decreases on the write-off record.
- Recovery cannot exceed the remaining recoverable balance.
- A fully recovered written-off loan remains historically `written_off`; the original write-off is never removed or rewritten.
- Customer statements record dedicated `loan_write_off_recovery` entries.
- Daily collection summaries separately track written-off-loan recovery amount and count without treating the recovery as a normal loan payment allocation.

## Database changes

Migration: `2026_08_12_160000_create_loan_write_off_workflow.php`

Created:

- `loan_write_offs`
- `loan_write_off_documents`
- `loan_write_off_recoveries`

Changed:

- `loans`
  - `written_off_at`
  - `written_off_by`
  - lifecycle status `written_off`
- `daily_collections`
  - `write_off_recoveries`
  - `write_off_recoveries_count`
- accounting categories
  - `write_off_recoveries`

## Permissions

Added:

- `loans.writeoff.view`
- `loans.writeoff.request`
- `loans.writeoff.approve`
- `loans.writeoff.recover`

Role assignments separate management write-off authority, recovery posting and read-only audit/operations access.

## User interface

Added a branch-scoped **Loan Write-Offs** workspace with:

- eligible active loans
- permanent pending/rejected/approved write-off history
- recovery history
- write-off request form
- balance snapshot and preserved-history summary
- mandatory evidence upload
- management approval/rejection screen
- private evidence downloads
- recovery posting form
- original payment, collection and collateral preservation indicators
- approval and accounting journal information

The workspace is linked from Operations navigation.

## Audit events

Added:

- `loan_write_off.requested`
- `loan_write_off.approved`
- `loan_write_off.rejected`
- `loan_write_off.recovery_posted`

## Verification

GitHub Actions Foundation CI on pull request #27:

- Fresh migrations: PASS
- Seeders: PASS
- Full Laravel test suite: **118 passed**
- Assertions: **1,091**
- Existing Step 1–14 regression tests: PASS
- Step 15 feature tests: **5 passed**

Step 15 feature tests cover:

1. Full-balance requirement, mandatory evidence and management authorization.
2. Approved write-off accounting, status change and preservation of payments, installments, collateral and collection history.
3. Maker-checker and stale-balance approval protection.
4. Separate written-off recovery accounting, cash posting and over-recovery protection.
5. Rejection, branch isolation and private evidence access.

## Remaining Step 15 work

None.

## Next roadmap module

**Step 16 — Expense Management**.
