# Payments, Expenses and Payroll Controls Upgrade

Release: 2026-07-24  
Migration: `20260724_011_payments_expenses_payroll_controls.sql`

## Scope review before development

The existing Skulitech package was inspected before adding functions. The following capabilities were already present and were retained rather than duplicated:

- Student fee billing, receipts, statements and M-Pesa/payment records
- Sponsor/HELB parent receipts, student allocations and no-double-receipting controls
- Unallocated receipt management and bank-reconciliation structures
- General ledger, journals, chart of accounts, budgets, commitments and period closing
- Procurement requisitions, sourcing, LPOs, three-way matching, GRNs, creditors and supplier payment vouchers
- Imprest creation, disbursement and clearance/surrender
- Fixed assets and depreciation
- Individual employee payroll calculations, payslips, P9 reports and HR deduction settings

The upgrade therefore adds only missing workflow and control functions.

## New payments and expense controls

### Staff expense claims

A staff member creates a draft claim with itemised expense dates, descriptions, receipt references, expense accounts, cost centre, project and a supporting attachment. General attachments are validated as PDF, JPG/JPEG, PNG, DOC or DOCX on both extension and detected MIME type.

Workflow:

`Draft → Submitted → Approved → Paid`

Alternative outcomes are `Rejected` or `Reversed`.

Controls include:

- A claimant may submit only their own claim
- The submitter cannot approve the same claim
- Approval recognises the expense and accrued liability in the general ledger
- Payment clears the accrued liability against bank
- Bank/payment references are unique
- Issued transactions are reversed through balancing journals; they are not deleted
- Every stage is written to the audit log

### Petty cash

Finance can maintain one or more controlled petty-cash funds with a custodian, asset account and optional maximum float. Replenishments, small expenses and cash returns use a `Draft → Submitted → Approved` maker-checker workflow. Approval posts the balanced journal, available balance is checked while the fund is locked, duplicate references are rejected, a fund cannot be overdrawn or replenished above its configured float, and approved vouchers can only be corrected through a balancing reversal.

### Posted income and expense corrections

The existing Income List and Expense List remain available. Their posted journals are now immutable: choosing the pencil action creates a controlled correction instead of overwriting the original row or deleting its journal. Finance must enter a correction reason; the system reverses the original journal, marks the original register row as reversed, creates a replacement row and posts a new balanced journal. The original value, reversal reason, replacement and both journals remain available in the audit trail.

### Existing supplier and imprest workflows

The control page links to the existing supplier payment-voucher and imprest modules. Supplier invoices and procurement-related payments continue through the existing three-way-match and creditor workflow. Imprest requests and surrenders continue through the existing imprest modules, preventing parallel records for the same process.

### Recurring expenses

Finance can define monthly, weekly, quarterly or annual templates. A due template generates a normal draft expense claim, which then follows the same approval and payment workflow. Generating a template does not automatically post or pay an expense.

### Accruals and prepayments

Finance can create and post:

- Accrual schedules: recognise expense and accrued liability, then settle the liability against bank
- Prepayment schedules: recognise a prepayment asset, then release it to expense over one or more periods

Schedules track total, released/settled and remaining values. Over-processing is blocked.

## New payroll controls

### Payroll batches

Payroll entries are grouped by payroll month and run type:

- Regular
- Off-cycle
- Final

New entries begin in a draft batch. Historical payroll entries remain available and are not rewritten by the migration.

### Maker-checker and payroll locking

Workflow:

`Draft → Prepared → Checked → Approved → Posted → Paid`

- HR prepares and locks the batch
- Finance checks the batch
- An authorised Finance/Admin user approves it
- The preparer cannot check or approve the same batch
- Approved payroll posts automatically to the general ledger
- Salary payment clears the net-salaries liability against bank
- Posted or paid payroll can only be corrected by balancing reversal journals

### Effective-dated statutory rules

Contribution, relief and PAYE tax-band versions have effective-from and optional effective-to dates. A new version closes the preceding open version. The payroll month determines which version is applied, preserving historical calculations.

Before a batch is prepared or paid, the control centre checks calculation consistency and displays missing KRA PIN, NSSF, SHIF and bank details. EFT payment is blocked until every employee with positive net pay has complete bank details.

Payroll entry now records approved overtime, arrears/back pay, final dues, unpaid-leave deductions, staff-loan recovery, salary-advance recovery, pension, SACCO and court-order deductions together with an attendance/overtime approval reference and adjustment notes.

Rules support:

- Percentage, fixed and manual calculation modes
- Gross or taxable-pay basis
- Minimum and maximum amounts
- Relief amounts
- Separate employee and employer rates
- Effective-dated monthly PAYE band widths and rates, including an open final band
- Liability and employer-expense account mappings that are used during payroll posting and remittance settlement

### Statutory remittances

Posting payroll prepares PAYE, NSSF, SHIF, Housing Levy and other-deduction remittances. Each remittance has its own due date, payment reference and balanced general-ledger settlement journal.

### Exports

The Payroll Control Centre exports:

- Bank EFT schedule
- Statutory schedule
- Payroll register

## General-ledger integration

New payroll accounts are seeded only when missing:

- 2120 Net Salaries Payable
- 2130 PAYE Payable
- 2140 NSSF Payable
- 2150 SHIF Payable
- 2160 Housing Levy Payable
- 2170 Other Payroll Deductions
- 5010 Salaries and Wages Expense
- 5020 Employer Payroll Contributions Expense

Expense claims use the existing bank, accrued-liability and configured expense accounts. Accruals and prepayments use the existing `2100 Accrued Liabilities` and `1160 Prepayments` control accounts unless another configured control account is supplied. Petty-cash transactions use `1010 Petty Cash` by default and may use another active asset account selected for the fund.

Taxable gross includes non-cash benefits for tax reporting, but net salary and the payroll cash journal exclude non-cash benefits and value of quarters. This prevents benefits in kind from being paid as cash or causing an unbalanced payroll journal.

## Navigation

- Finance → Payments & Expense Control
- Finance → Petty Cash
- Finance → Payroll Control Centre
- Finance → Effective-Dated Payroll Rules
- Staff & HR → Payroll
- Staff & HR → Payroll Control Centre
- Staff & HR → Effective-Dated Payroll Rules

## Deployment

Back up the application and database, then run:

```bat
cd C:\xampp\htdocs\college_erp
C:\xampp\php\php.exe bin\migrate.php
C:\xampp\php\php.exe bin\check_integrity.php
```

For Linux hosting:

```bash
cd /path/to/college_erp
php bin/migrate.php
php bin/check_integrity.php
```

## Integrity checks added

The CLI checker now reports:

- Expense-claim total/item mismatches
- Approved or paid claims missing journals
- Paid claims missing payment references
- Invalid recurring expense and adjustment balances
- Petty-cash overdrafts, maximum-float breaches and missing journals
- Payroll batch total and net-cash formula mismatches
- Posted or paid payroll missing journals
- Locked batches containing unlocked rows
- Payroll row/batch month or run-type mismatches
- Overlapping active statutory rule or PAYE tax-band versions
- Invalid PAYE band sets, including missing or misplaced open-ended bands
- Paid remittances missing settlement journals
- Posted legacy income/expense rows missing a source journal
- Reversed legacy income/expense rows missing a reason or balancing reversal journal

## Validation completed in the build environment

- All 210 PHP files passed PHP syntax validation
- New and changed navigation targets were checked for existence
- Migration statements were statically checked for balanced quoting and statement termination
- The final ZIP archive was tested for integrity

A live MySQL/MariaDB migration was not run in the build environment. Apply the migration first to a backed-up staging database, run the integrity checker, then perform browser workflow testing before production use.
