# Step 24 — Final Documents and Exports — Implementation Report

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

## Overview

Step 24 completes the application's final operational-document and export layer without creating duplicate financial or workflow records.

Documents are generated from the permanent records created by the existing loan, payment, collateral, expense and payroll workflows. PDF and print actions are read-only: opening, printing or downloading a document does not post money, change a loan state, rewrite a payment, alter collateral custody or change an expense/payroll decision.

No database migration or schema change was required for Step 24.

## Final document matrix

### Loan agreements

- The existing generated loan-contract PDF remains available as the permanent generated contract record.
- A new branded printable loan-agreement view is available after the agreement has been generated.
- The print view includes borrower details, configured loan terms, repayment schedule, collateral, guarantor, late-payment terms, borrower obligations and signature areas.

### Loan payment receipts

- Existing receipt print view retained and upgraded with configured business branding.
- Added downloadable PDF generated from the permanent `LoanPayment` record.
- Includes receipt number, customer, loan, payment method/account/reference, amount and principal/interest/fee/penalty allocation.

### Loan/customer statements

- Existing statement print view retained and branded.
- Added downloadable statement PDF.
- Uses the permanent customer-statement ledger plus repayment schedule and current loan balance.

### Collateral receipts

- Existing printable collateral receipt upgraded with configured branding.
- Added downloadable collateral-receipt PDF.
- Uses the permanent collateral code, customer, accepted value, custody details and receiving record.

### Collateral release acknowledgement

- Existing printable release/return acknowledgement upgraded with configured branding.
- Added downloadable release-acknowledgement PDF.
- The PDF is unavailable until a permanent collateral movement to `released` or `returned` exists.
- The acknowledgement records the actual release/return timestamp, responsible staff member and movement note.

### Loan disbursement receipts

- Existing printable disbursement receipt upgraded with configured branding.
- Added downloadable PDF generated from the permanent `LoanDisbursement` record.
- Includes customer, loan, amount, financial account, reference and responsible staff member.

### Expense vouchers

- Added formal printable expense voucher.
- Added downloadable expense-voucher PDF.
- Vouchers are available only when the expense is approved and has both its permanent financial-account transaction and accounting journal reference.
- Pending or rejected/non-posted expenses cannot produce an official voucher.

### Payslips

- Existing printable payslip retained and upgraded with configured logo/stamp support.
- Existing downloadable payslip PDF was standardized onto the shared branded PDF renderer.
- Earnings, deductions, net pay and permanent payment/accounting references remain sourced from the payroll entry snapshot.

## Configured company branding

All Step 24 print/PDF documents use the configured business identity rather than hard-coded system branding where applicable:

- Business name
- Registration number
- TIN
- Address / district / region / country
- Phone
- Email
- Website / postal address when configured
- Currency and currency symbol
- Configured number format

### Private logo and stamp handling

Business logos and stamps remain on the private `local` storage disk.

They are not converted into public storage URLs. Printable authenticated views request them through the new `document-branding.asset` endpoint, which:

- Requires authentication.
- Allows only `logo` or `stamp` assets.
- Confirms the user has access to a branch belonging to that business, except for the existing Super Administrator bypass.
- Returns the private file inline with its detected MIME type.
- Uses private caching and `X-Content-Type-Options: nosniff`.

A user assigned only to another business cannot use the branding endpoint to retrieve the first business's private branding files.

## Shared branded PDF renderer

`App\Services\BrandedPdfService` provides a common lightweight PDF renderer for Step 24 documents and the standardized payslip.

It:

- Produces valid `%PDF-1.4` output without adding a new external PDF dependency.
- Preserves the administrator's configured business-name casing.
- Applies configured currency/number formatting.
- Adds business registration/contact metadata and the permanent document reference.
- Supports multi-page text output.
- Marks the document as generated from the permanent system record.

The existing loan-contract PDF generator remains in place because it is part of the loan contract-generation workflow and its generated private document is already persisted as a loan document.

## Financial report CSV/spreadsheet export

All eight Step 19 financial reports now support CSV download:

1. Profit & Loss
2. Cash Flow
3. Account Statement
4. Capital Report
5. Expense Report
6. Payroll Report
7. Collection Report
8. Disbursement Report

The financial-report toolbar exposes **Download CSV** next to **Print Report**.

Exports reuse `FinancialReportService::generate()` and the same scope resolver as the HTML report. Therefore the screen and exported file use the same:

- Date validation
- Assigned-branch restrictions
- Single/multiple branch selection
- Company-wide accessible scope
- Account-statement account restriction
- Reconciled report formulas and underlying records

Step 20 loan/branch reports already supported CSV and remain unchanged.

### Spreadsheet safety

CSV values beginning with spreadsheet formula trigger characters (`=`, `+`, `-`, `@`) are prefixed before export so user-entered descriptions/references are treated as text when opened in spreadsheet software.

CSV output includes a UTF-8 BOM for spreadsheet compatibility.

## Authorization and branch isolation

Document routes reuse the existing module permissions and also enforce branch access inside the document controller.

Examples:

- Loan/payment/disbursement/statement documents require `loans.view` plus branch access.
- Collateral documents require `collateral.view` plus branch access.
- Expense vouchers require `expenses.view` plus branch access and a completed financial posting.
- Financial CSV exports require `reports.view` and the same allowed-branch validation as the HTML reports.

Knowing a document identifier from another branch does not bypass branch isolation.

## Read-only guarantee

Step 24 tests snapshot payment, expense and financial-account transaction state before PDF generation and verify it is unchanged afterwards.

Generating or downloading a document does not:

- Add a financial transaction.
- Alter a loan payment allocation.
- Change an expense status/posting reference.
- Create a collateral movement.
- Change a loan balance.

Official event-specific documents are gated by the permanent source event rather than creating the event themselves.

## Main files created

- `app/Http/Controllers/DocumentExportController.php`
- `app/Services/BrandedPdfService.php`
- `routes/documents.php`
- `resources/views/documents/loan-agreement.blade.php`
- `resources/views/documents/expense-voucher.blade.php`
- `tests/Feature/FinalDocumentsExportsTest.php`

## Main files modified

- `app/Http/Controllers/FinancialReportController.php`
- `app/Services/PayrollPayslipPdfService.php`
- `routes/accounting.php`
- `routes/reports.php`
- `resources/views/reports/index.blade.php`
- `resources/views/payments/receipt.blade.php`
- `resources/views/payments/statement.blade.php`
- `resources/views/disbursements/receipt.blade.php`
- `resources/views/collateral/receipt.blade.php`
- `resources/views/expenses/show.blade.php`
- `resources/views/payroll/payslip.blade.php`

## Database changes

None.

Step 24 adds document/export presentation and read-only generation over the existing authoritative records.

## Automated tests

Step 24 adds 6 feature tests covering:

1. PDF integrity, configured business identity and read-only behavior across payment, statement, collateral, disbursement and expense documents.
2. Private logo/stamp rendering plus branch-scoped document access.
3. Cross-business denial for private branding files.
4. Expense-voucher and collateral-release event-completion guards.
5. All eight financial CSV exports, report branch scope and spreadsheet-formula neutralization.
6. Document actions exposed from the existing operational workflow pages.

## Verification

GitHub Actions Foundation CI on pull request #36:

- Fresh migrations: PASS
- All seeders: PASS
- Full Laravel test suite: **171 passed**
- Assertions: **1,853**
- Step 24 feature tests: **6 passed**
- Existing Step 1–23 regression tests: PASS
- Final implementation-and-toolbar head: PASS
- Final documentation-inclusive exact-head CI: PASS before merge

## Remaining Step 24 work

None.

## Next roadmap module

**Step 25 — Security and Backup Review**.
