Setup & Configuration — Detailed Requirements
What an operator configures before the first pay run: the payroll item catalogue (what an earning or deduction is), reusable item groups for bulk assignment, contribution groups holding the statutory scheme rates, per-year tax brackets (PAYE bands + reliefs), and the GL accounts in company configuration.
Item catalogue
Allowance / deduction / overtime / tax-relief definitions with taxability, statutory bases and GL account.
Item groups
Named bundles of items + default amounts, applied to many employees in one action.
Contribution groups
Statutory policies — schemes, rates, who pays, GL payable accounts.
Tax brackets
Per-year PAYE bands and relief values; bands auto-seeded, reliefs operator-set.
Setup · Detailed
Data model
item catalogue| Field | Type | Notes |
|---|---|---|
name | string | Required. Display name, e.g. "Housing Allowance". |
type key | enum | ALLOWANCE / DEDUCTION / OVERTIME / TAX_RELIEF. |
statutoryTypes key | reference list | Which statutory bases (pension/NHF/…) this item's amount joins. Empty → default base. |
accountId | reference → GL account | Journal account for deduction items; unmapped deductions block posting. |
isBasicSalary key | boolean | Marks the basic-salary item — only one may carry it (auto-cleared elsewhere). |
isTaxable | boolean | Non-taxable items act as PAYE relief (amount ×12 reduces chargeable income). |
taxReliefType, taxRelief, maxTaxRelief | enum + numbers | AMOUNT / PERCENTAGE relief with cap, for tax-relief items. |
frequency | enum | MONTHLY (default) / ANNUALLY (÷12-smoothed). |
There is no bonus/one-off flag and no annual-form category on items — a one-time payment is an ordinary item scoped to a single-month window, taxed as ordinary pay.
bulk-assignment bundle| Field | Type | Notes |
|---|---|---|
name, description | strings | Group label, e.g. "Junior Staff Package". |
items[] | {itemSettingId, amount} | Catalogue items with default amounts; no duplicates; at least one entry. |
statutory policy| Field | Type | Notes |
|---|---|---|
name | string | e.g. "NG Statutory — Pension + NHF + NSITF". |
types[].statutoryTypeId key | reference | The scheme (seeded masters: paye, pension, nhf, nhis, nsitf). |
types[].accountId | reference → GL account | Payable account credited for the employee share in the journal. |
types[].paidBy | enum | EMPLOYEE / EMPLOYER / BOTH. |
types[].frequency | enum | MONTHLY (default) / ANNUALLY. |
types[].employeePayment / employerPayment | {mandatory, voluntary, valueType} | PERCENTAGE (default) / FIXED / TABLE (computes zero for Nigerian schemes — avoid). |
per-year PAYE configuration| Field | Type | Notes |
|---|---|---|
taxYear key | number | Matched on the run's pay-date year. |
name | string | Seeded as Nigeria PAYE {year}. |
bands[] | {minAmount, maxAmount?, baseTax, ratePercentage} | Progressive cumulative bands. |
individualRelief, spouseRelief, perChildRelief | numbers (default 0) | Personal reliefs — not seeded; operator-set. |
statutoryReliefs[] | {statutoryTypeId, annualLimit} | unused Cap structure stored but never consumed. |
Setup · Detailed
Item catalogue CFG-I
- Flagging an item basic-salary automatically clears the flag from every other item.
- Statutory bases are expressed by tagging seeded statutory types, not booleans.
- A non-taxable allowance both joins gross and adds an equal relief — net-neutral to taxable income by design.
- A deduction item without a GL account blocks journal posting, reported by name.
Setup · Detailed
Item groups — bulk assignment CFG-B
A named bundle of catalogue items with default amounts (a "pay package"). Applying a group materialises one standing assignment per item per employee — the group is a template, not a live link.
- Apply is skip-and-report, never all-or-nothing: entries whose item was deleted, or that would overlap an employee's existing active assignment of the same item, are skipped and itemised in the result (created / skipped counts + reasons).
- End date before start date is rejected.
- Editing a group later does not change already-materialised assignments.
Setup · Detailed
Contribution groups CFG-G
- Import validation requires an employee rate when paid-by includes the employee, and an employer rate when it includes the employer.
- An employee links to exactly one group on their master record.
Setup · Detailed
Tax brackets CFG-T
- Seeded name:
Nigeria PAYE {year}; seeding never overwrites an existing bracket. - A year with no bracket computes zero PAYE silently (see PAYE gaps).
Setup · Detailed
GL accounts CFG-A
| Config key | Purpose |
|---|---|
payrollExpenseAccountId | Salary Expense — the journal's single debit line. |
payrollLiabilityAccountId | Net-salary payable — credited per employee (overridable at post time). |
payrollTaxAccountId | PAYE payable — credited per employee's tax. |
payrollEmployerExpenseAccountId | unused Read but never posted — employer costs are not journalled. |
- The liability account chosen at post time is remembered on the run.
- Per-scheme payable accounts come from the contribution group; per-deduction accounts from the item catalogue.
Setup · Detailed
Bulk import CFG-M
- Confirmation re-validates and reports success and error counts per row.
- Item groups have no import flow — they are defined on screen.
Setup · Detailed
Business rules
- Catalogue owns behaviour; assignments own amounts; groups are one-shot templates.
- Statutory types are seeded master data referenced by configuration, never redefined.
- Rates and reliefs are tenant data — the engine ships bands only; pension/NHF rates and personal reliefs must be configured before the first run.
- All setup entities are company-scoped, soft-deleted and audited.
Setup · Detailed