Initial situation
Payroll processing in several internal ICC companies was done in a combination of Excel + manual SEPA file upload to internet banking. With 5–15 employees per company it was manageable, but:
- Recurring errors in transcription of hours or deductions.
- Time overhead of 4–6 hours per person every month.
- No audit trail — on retroactive changes (correction of worked hours) the old calculations were lost.
- SEPA files were assembled manually per bank-specific format, frequent rejections at inconsistent IBAN/SWIFT.
Goal
Build an own payroll system that:
- performs the full gross-to-net calculation with Slovak social and health contributions,
- generates a SEPA XML pain.001 payment order directly,
- preserves the audit trail of every change,
- securely integrates with banking APIs (ČSOB pilot, others via SEPA XML upload).
Solution
Gross-to-net pipeline:
- Input — hours worked, bonuses, overtime, deductions.
- Gross wage calculation per contract (monthly / hourly / combination).
- Social contributions (employee + employer) — table per year, automatically updated when legislation changes.
- Health contributions — analogously.
- Tax bonus, non-taxable allowance — per-employee config.
- Net wage + employee statement (PDF, branded).
SEPA XML generation:
- Standard pain.001.001.03 format (Slovak banking guideline).
- Pre-validation of IBAN via MOD-97 checksum + BIC lookup against the SWIFT registry.
- Hash check of the resulting XML against the input batch — ensures it does not change between generation and bank upload.
Bank integrations:
- ČSOB Open API (pilot) — direct submission of pain.001 via OAuth + further authorization steps.
- Universal SEPA XML export for other banks — manual upload to internet banking.
Audit trail:
- Every change in the records (correction of hours, retroactive bonus) is insert-only with a reference to the original version.
- The monthly close “freezes” calculations — later corrections are separate delta adjustments, not history rewrites.
Results
- Monthly processing dropped from 4–6 hours to 15–20 minutes of result review.
- Zero rejections of SEPA files since deployment (previously 2–3 monthly).
- Tax bonus and edge cases (parental leave, longer sick leave) are handled by per-person configuration without code changes.
- GDPR-friendly — payroll data stays exclusively in the EU on ANDROS hardware.
Stack and infrastructure
Self-hosted FastAPI backend, PostgreSQL with row-level security per employer. Frontend React 19 + Tailwind v4 per D-008. Backup via restic + Backblaze B2 dual repo for disaster recovery.