Staff Management · Phase 3 · Bulgaria

BG Payroll Reports — Generate ведомост, Декларация 1+6, and bank-transfer files

Compliant report generation for Bulgarian employers — pull hours from clock events, apply the year's official insurance and tax rates, and download files ready for the NRA portal and your bank.

What is BG payroll generation in Ordering.Tools?

BG payroll generation is a country-pluggable layer on top of the Staff module's wage and clock data. For venues with country = 'BG' and a configured bgPayrollProfileId, opening a payroll run for a period materialises one PayrollLine per staff member — gross pay, employer/employee insurance shares, 10% income tax, and net pay — using the rates from the year's BgPayrollProfile (НОИ ceilings, ДОО, ДЗПО, ЗО, ДОД in basis points). From the run, export a salary register XLSX (ведомост), per-employee NRA XML (Декларация образец 1 + 6), and a bank-importable CSV.

We do NOT call ourselves 'compliant payroll software'. We provide reports compatible with NRA portal upload formats — the venue's accountant submits and signs off. The architecture is country-pluggable: BG is the first generator under src/lib/payroll/generators/bg/; future countries (UK PAYE, EL Ergani, RO REVISAL) plug in by registering a new generator. Every payroll line stores its full computation snapshot so any disputed figure can be re-derived months later.

Why this is the BG payroll layer your accountant will use

Year-keyed BgPayrollProfile

Insurance ceilings and rates change every year in Bulgaria. The BgPayrollProfile table is year-keyed (year UNIQUE) — 2026 has its own row, 2027 has its own, the generator picks the right one for the period being processed.

Computation snapshot per line

Every PayrollLine stores its full intermediate computation in computedSnapshot — base gross, overtime, tips, insurable base after clamp, employee/employer insurance shares, taxable base, income tax, net. A disputed figure is re-derivable from the snapshot in seconds.

Native NRA XML output

Декларация образец 1 (per-employee monthly filing) and образец 6 (monthly summary of contributions) are emitted as XML. The accountant uploads to the NRA portal directly — no manual retyping into the portal forms.

Bank-importable CSV for net payments

The bg-net-transfer export is a universal CSV format that imports cleanly into UniCredit, DSK, OBB, Postbank, and Raiffeisen Bulgaria's bulk-payment workflows. Pay 30 employees in one upload instead of typing 30 transfers manually.

How BG payroll generation works

1

Configure the venue

Set venue.country = 'BG', fill in bgEmployerEikBulstat (ЕИК / Булстат) and bgEmployerName (legal name), and bind a BgPayrollProfile via bgPayrollProfileId. Without these, the generator returns 400 with a specific reason so the accountant knows what's missing.

2

Generate the run

Open Staff → Payroll, pick the period (default: last calendar month), click Generate. The generator loads the BgPayrollProfile for the year, aggregates clocked minutes per staff, picks each staff's effective wage at period end, and writes one PayrollLine per (run, user) with full computation snapshots.

3

Export the files

From the run, export bg-vedomost (XLSX salary register), bg-deklaracia-1 (per-employee NRA XML), bg-deklaracia-6 (summary NRA XML), bg-bank-transfer (NRA contributions bank file), bg-net-transfer (employee-net-pay bank CSV).

4

Lock the run

Once the accountant has signed off, lock the run. The status moves DRAFT → LOCKED and no further mutations are allowed. The lines, the snapshots, and the audit log preserve the exact state for any future audit.

BG Payroll — feature deep-dive

Year-keyed BgPayrollProfile rows

Each profile row stores the year's insurance ceilings (min/max insurable income in cents) and rates as basis points (1410 = 14.10%) for ДОО, ДЗПО, ЗО per employer/employee, plus the 10% flat ДОД rate. minimumByCategory captures the per-role minimum brackets.

  • year UNIQUE — exactly one profile per calendar year
  • Basis points (integer) instead of float percentages — no rounding drift
  • Cents (integer) for ceilings — no currency-format ambiguity
  • minimumByCategory JSON for I/II/III labour-category brackets

Step-by-step computation snapshot

Every PayrollLine.computedSnapshot stores: base gross, overtime gross at the OT multiplier, tips, total gross, insurable base after clamp, employee/employer insurance basis points used, all three computed insurance shares, taxable base, income tax, net. A line can be re-derived without the live profile or live wage.

  • Reproducible months later — no need to re-look-up rates
  • Auditable line by line — paste into a spreadsheet to verify
  • Inputs explicit (hours, rate, multiplier) and outputs explicit (insurance, tax, net)
  • JSON shape — easy to query for analytics or debug a specific line

Native NRA XML envelope

Декларация образец 1 + 6 emit as schema-friendly XML. We pin the NRA schema version year by year (XSDs ship with the generator under schemas/) and re-validate before each yearly release. The XML is what the accountant uploads to the NRA portal.

  • Per-employee monthly Декларация образец 1 with EGN, position code, days insured, gross, insurance, tax
  • Monthly summary Декларация образец 6 with totals per fund (ДОО, ДЗПО, ЗО, ДОД)
  • XSD pinned year by year — re-validated each yearly release
  • UTF-8 encoded, properly escaped attributes, NRA-portal compatible

Bank-importable CSV exports

Two bank-targeted CSVs: bg-bank-transfer for the NRA central-account contributions (one row per fund: ДОО, ДЗПО, ЗО, ДОД); bg-net-transfer for the employee net pay (one row per staff member with their IBAN from StaffEmploymentBg). Both import into the major BG bank bulk-payment workflows.

  • Universal CSV that works across UniCredit, DSK, OBB, Postbank, Raiffeisen
  • Bank-specific dialects can be added later without touching the core generator
  • Pulls IBAN from StaffEmploymentBg.bankIban (per-venue staff record)
  • Reference field includes 'Salary {period}' for clean bank-statement readability

Where BG payroll generation earns its keep

Monthly NRA filing without a separate payroll vendor

End of March: open Staff → Payroll, generate run for March, download bg-deklaracia-1 + 6, hand to the accountant. They upload to NRA portal Friday afternoon. Total time: 5 minutes. The previous flow with a separate payroll vendor took 4 days of back-and-forth.

Mid-month hire

A new staff member joins on the 17th. The generator picks up only their hours from the 17th onward, applies the wage in effect at period end, and writes a partial-month PayrollLine. The Декларация образец 1 row reports the correct daysInsured.

Cat-I labour rates

A waiter with insuranceCategory = 'I' (heavy labour) gets a higher minimum insurable base from the profile's minimumByCategory. The generator applies the right minimum per staff; the snapshot records which category was used.

Tip income subject to insurance

Tip-pool distributions for the period flow into PayrollLine.tipsCents and are added to gross. The insurance and tax math runs against the higher base, exactly as the NRA expects for tipped income.

Auditing a past payslip

An employee disputes their May payslip. Open Staff → Payroll, find the May run, click the line, see the full computedSnapshot — exact hours, exact wage rate, exact insurance shares, exact net. Re-derive in 30 seconds; show the employee.

Yearly profile update

January 2027: NRA publishes new rates. The Ordering.Tools team adds a 2027 BgPayrollProfile row with the updated basis points and ceilings. Every run for periods in 2027 picks the new row automatically; runs for 2026 periods continue to use the 2026 row. Year boundaries handled transparently.

BG payroll done right — generated, not retyped

BG payroll has three painful artefacts: the salary register (ведомост), the NRA monthly filings (Декларация образец 1 per employee + образец 6 summary), and the bank-transfer files for NRA contributions and employee net pay. Most restaurants outsource this to a vendor and pay 50-100 BGN per employee per month. Ordering.Tools generates all three from the wage and clock data the platform already has — the venue's accountant gets a portal-ready XML, an XLSX salary register, and a bank-importable CSV in one click. The vendor cost evaporates; the audit trail is built in.

Why year-keyed profiles are the only way

BG insurance ceilings and rates change almost every January. A naive payroll system stores the current rates as constants and silently breaks every January when the rates change. A year-keyed profile table indexed by year solves this: 2026 has its row, 2027 has its row, the generator picks based on the period's year. Older periods always use their original rates; new periods pick up new rates at the year boundary; no manual code change at midnight on Dec 31.

The computedSnapshot is the audit trail

When an employee disputes a payslip from 6 months ago, you don't want to be re-looking-up the BgPayrollProfile row for that period and trying to reproduce the math from scratch. Every PayrollLine stores its full computedSnapshot — exact hours, exact wage rate, exact insurance shares, exact net — at generation time. The snapshot is a JSON column; querying it is one SQL row read; explaining a payslip is reading the JSON aloud. No re-derivation, no maths errors, no 'sorry, the system can't tell us why'.

The disclaimer that earns trust, not weakens it

We say plainly in the admin UI: 'This module generates ready-to-submit files, but the final responsibility for accuracy and regulatory compliance is the employer's. We recommend periodic review by a licensed accountant.' That language doesn't say 'use at your own risk' — it says 'the system computes; the accountant audits'. The split of responsibilities is healthy: software is fast and never misses a row; humans catch the cases the software wasn't taught about (a salary advance, a one-off bonus, a category-change mid-year).

BG payroll, generated in 5 minutes

Set the year's profile, generate the run, download the XML + XLSX + bank CSV. Premium feature, available for venues with country = 'BG'.