Payroll

Payroll is the highest-stakes, least-forgiving process in an ERP. Everything else can be corrected next period. Payroll is people’s rent money, it is legally mandated, and it runs on a fixed date whether you’re ready or not.

Why payroll is different

  1. Zero tolerance for error. An underpayment is a legal breach and a personal crisis. An overpayment is nearly impossible to recover.
  2. Hard deadline. The payment date is fixed. There is no “we’ll ship next sprint.”
  3. Extreme localisation. Every country’s tax, social security, and labour law is different, and changes annually or more often.
  4. Retroactivity. Backdated changes require recalculating closed periods.
  5. Confidentiality. Salary data is the most sensitive data in the company.
  6. Auditability. Every number must be reproducible years later.

This is why most companies buy payroll rather than build it, and why “we’ll just calculate salaries in the ERP” is one of the more expensive sentences in an implementation.

The gross-to-net calculation

GROSS
  Basic salary                          80,000
+ House rent allowance                  32,000
+ Medical allowance                      5,000
+ Conveyance allowance                   3,000
+ Overtime (12h × 625)                   7,500
+ Shift premium                          2,000
+ Bonus / commission                         0
+ Benefit in kind (car, insurance)       4,000
────────────────────────────────────────────────
= GROSS PAY                            133,500

DEDUCTIONS (statutory)
− Income tax (PAYE / TDS)              (14,200)
− Employee social security / PF         (8,000)
− Other statutory levies                  (500)

DEDUCTIONS (voluntary/other)
− Pension contribution                  (4,000)
− Loan repayment                        (5,000)
− Union dues                              (300)
− Salary advance recovery               (2,000)
────────────────────────────────────────────────
= NET PAY                               99,500

EMPLOYER COSTS (not deducted, but a real cost)
+ Employer social security               12,000
+ Employer pension                        6,000
+ Gratuity / end-of-service accrual       6,700
+ Payroll levies                          1,200
────────────────────────────────────────────────
= TOTAL COST TO COMPANY                 159,400

Cost to company ≠ gross pay ≠ net pay. Three different numbers, and business users mix them up constantly. Be precise in every report label.

Wage types (pay elements)

The atomic unit of payroll.

wage_type(
  code, name, category,        -- EARNING | DEDUCTION | EMPLOYER_COST | INFORMATIONAL
  calculation_rule,            -- FIXED | RATE_X_QTY | PERCENTAGE_OF | FORMULA | TABLE_LOOKUP
  base_wage_types[],           -- for percentage/formula types
  taxable, social_security_liable, pensionable,
  prorate_on_partial_period,
  gl_account_debit, gl_account_credit,
  appears_on_payslip, payslip_group, sort_order,
  valid_from, valid_to
)

The flags are where the complexity lives. “Is this allowance taxable?” and “does it count toward the pension base?” and “does it count for overtime rate calculation?” are three independent questions with country-specific answers.

Cumulations are the mechanism: a wage type contributes to one or more cumulation bases (taxable gross, SS base, pension base, overtime base), and calculations reference the base, not individual wage types. Add a new allowance and you flag which bases it feeds — no code change.

The payroll engine

1. RELEASE payroll for the period (locks master data changes)
2. For each employee:
     a. Read master data as of the period
     b. Read time data (worked hours, absences, overtime)
     c. Calculate gross: basic + allowances + variable pay
     d. Apply retroactive adjustments from prior periods
     e. Calculate cumulations (taxable gross, SS base, ...)
     f. Calculate statutory deductions (tax, social security)
     g. Calculate voluntary deductions, respecting priority and protected minimum
     h. Calculate employer costs
     i. Compute net pay
     j. Store the payroll result (immutable)
3. SIMULATE / CHECK — reconcile, compare to last period, review exceptions
4. EXIT payroll (finalise)
5. Post to GL
6. Generate bank payment file
7. Generate payslips
8. Generate statutory filings

Retroactive accounting

The hardest part, and the reason payroll engines are so complex.

March: paid on a salary of 80,000
April: a promotion is approved, effective 1 March, new salary 92,000

April payroll must:
  1. Recalculate March completely with the new salary
  2. Compare new March result to the original March result
  3. Carry the difference forward into April as a retro adjustment
  4. Recalculate March tax and social security on the new figures
  5. Show it on the April payslip as a separate, explained line

The engine keeps every period’s result immutable and computes deltas. It never edits a closed period — it recalculates it in memory and pays the difference now. Your data model must store complete results per period per calculation run, with the run type (original vs retro).

Deduction priority and protected pay

When deductions exceed available net pay, order matters and is legally defined:

1. Statutory tax                    (always first)
2. Social security
3. Court orders / garnishments      (statutory priority order among these)
4. Child support                    (often above other court orders)
5. Employer loans
6. Voluntary deductions

Most jurisdictions define a protected minimum — an amount that cannot be attached regardless of debts. If deductions would breach it, they’re reduced or deferred to the next period. Getting this wrong is unlawful, not merely embarrassing.

Tax calculation

Every country is different. The main models:

Model Where How
Cumulative / PAYE UK Tax calculated on year-to-date income, so it self-corrects
Non-cumulative Many Each period taxed independently, reconciled at year end
Withholding tables US Prescribed tables by filing status and allowances
Progressive slabs India, Bangladesh, most Bands with increasing rates, with exemptions and rebates
Flat rate Some Simple

Plus: multiple jurisdictions (US federal + state + city, all with different rules), tax codes and personal allowances, benefits-in-kind valuation, salary sacrifice arrangements, and year-end reconciliation forms (P60, W-2, Form 16).

Do not implement tax rules yourself. Use the vendor’s localisation package or a specialist payroll provider. Tax rules change with every budget, sometimes retroactively, and maintaining them for even one country is a full-time job.

Payroll postings

  Salary expense (by cost centre)        Dr 133,500
  Employer SS expense                    Dr  12,000
  Employer pension expense               Dr   6,000
    Net pay clearing (→ bank)               Cr  99,500
    Tax payable                             Cr  14,200
    Social security payable (EE + ER)        Cr  20,000
    Pension payable                         Cr  10,000
    Loan receivable (recovery)              Cr   5,000
    Union dues payable                      Cr     300
    Other payables                          Cr   2,500

Design points:

  • Summarised, not per-employee. Posting individual salaries to the GL exposes confidential data to anyone with GL access. Post by cost centre and wage-type group.
  • The net pay clearing account is cleared when the bank confirms the payment.
  • Liability accounts must be cleared when remittances are made to tax authorities and funds. Aged balances there mean missed statutory payments — a serious problem.
  • Cost centre split: an employee working across departments splits their cost proportionally.

Payroll controls

Control Why
Segregation: HR creates employees, payroll runs, finance approves the payment Ghost employee fraud
Payroll comparison report — this period vs last, by employee, flagging >X% variance Catches nearly every input error
New starters and leavers reconciliation Ghost employees and unterminated leavers
Duplicate bank account detection across employees Classic fraud pattern
Bank detail change requires verification and creates an alert Payroll diversion fraud
Net pay negative or zero exception report Calculation errors
Payment file dual authorisation Last line of defence
Control totals — headcount, gross, net, deductions vs prior period Whole-run sanity check
Access logging on salary data Confidentiality

The period-over-period comparison report is the single highest-value control. Most payroll errors show as an outlier there, and it’s cheap to build.

Statutory reporting

Every country requires periodic filings: monthly/quarterly tax remittance and returns, social security returns, pension contributions, year-end employee certificates (P60/W-2/Form 16), new-hire and leaver notifications, gender pay gap reporting, and equality/workforce statistics.

Increasingly these are real-time: the UK’s RTI requires a submission to HMRC on or before every payment date, not monthly. Several countries have followed. That turns payroll from a batch process into an integration with an availability requirement.

Build vs buy

Situation Recommendation
One country, simple, <200 employees ERP payroll module is viable
One country, complex rules or unions Local specialist payroll provider
Multi-country Never build. Use a global provider (ADP, SD Worx, CloudPay) or country-local providers with an aggregator
Any country you don’t have in-house expertise for Buy

The integration pattern when you buy:

ERP/HR ──▶ payroll provider:  employee master, time data, pay elements
       ◀── payroll provider:  GL posting file, payment file confirmation,
                              cost analysis, payslip references

You still own: master data quality, time data accuracy, the GL posting, and the reconciliation. Outsourcing payroll does not outsource accountability for the numbers.

Developer notes

  1. Payroll results are immutable per period per run. Never update in place.
  2. Retro is calculated as a delta, never by editing history.
  3. Post summarised to the GL. Individual salaries do not belong in a ledger anyone can query.
  4. Wage type configuration, not code, for anything that varies by country or agreement.
  5. Mask or synthesise payroll data in non-production, always.
  6. The comparison report is your best test. Run it on every parallel run during implementation.
  7. Parallel run before go-live: run old and new systems side by side for 2–3 cycles and reconcile to the cent. This is not optional. Payroll go-lives without a parallel run fail publicly.
  8. Payroll has a hard deadline. Build the fallback plan (pay last period’s amounts and correct next period) before you need it.

Next