Skip to content

D112 — payroll: wage income tax + social contributions

The monthly employer declaration with per-employee detail. This file is a completion guide: what the declaration settles, who files it and when, and how each section maps onto the XSD attributes anafpy authors — followed by the technical XSD/DUK layer. ANAF's validator jar (D112Validator.jar) and the published structure annex + instructions are the authority; this guide is a distilled bridge, not a re-implementation of the rules. The largest classic form (~30 complex types). Live-proven 2026-07-17 with D112Validator.jar J26.0.3 (feed directory D112_209): both a nil employer-only instance and a single-employee instance (identification + asiguratA + asiguratE1/E3) validated clean (ok). The code lists are large enough to live in a companion file — d112-nomenclatoare.md.

D112 is the joint declaration of everything payroll owes the state for one month: the wage income tax withheld at source (impozit pe veniturile din salarii), the social contributions — employee pension CAS (25%), employee health CASS (10%), the employer work-insurance contribution CAM (2.25%), plus employer CAS surcharges on hazardous/special work conditions — and the nominal record (evidența nominală) of every insured person. It is a title de creanță producing legal effects from the filing date. Because it is a joint obligation across four authorities, the wage-tax half goes to ANAF and the contribution halves feed CNPP (pensions), CNAS (health) and ANOFM (unemployment).

  • Current model: approved by joint order OPANAF/OPCNPP/OPCNAS/OPANOFM 2066/248/1377/3103/2025 (20.08.2025), applicable from the August-2025 reporting month. The 01/2026 revision — form version D112_A7.2.6 (v7), structure annex dated 03.02.2026 — refreshes the parameters (minimum wage, the 300/200-lei non-taxable threshold) under OUG 156/2024, OUG 89/2025 and OUG 91/2025, without a new approving order. Legal anchors: art. 147 of the Fiscal Code (Legea 227/2015) for the filing obligation and OUG 158/2005 for sick-leave indemnities.
  • Periodicity: monthly is the default period. A quarterly election exists for small employers (below) — but quarterly filing still means one declaration per month, submitted by the quarter's deadline.

Who files & when

  • Who: employers and assimilated income payers under art. 80 of the Fiscal Code — companies, PFAs with employees, NGOs, public institutions, and the authorities that declare on behalf of non-salaried insured (ANOFM for the unemployed, CNPP, CNAS, MAE) — for every month in which an insured person exists. Filing an "empty" period with no insured persons ends the person's health-insurance coverage and is flagged by the validator (see the gotchas), so an employer with staff always has at least one asigurat.
  • Deadline: the 25th (inclusive) of the month following the reporting month (monthly filers) or following the quarter (quarterly filers). Confirmed by two independent sources: the ANAF filling instructions (Anexa 6/7) and the CECCAR/PortalPFA practitioner guides.
  • Monthly vs quarterly election (art. 147 alin.(4) Fiscal Code): the period is the calendar quarter for associations/foundations and other no-patrimonial entities; for profit-tax payers with prior-year revenue ≤ €100,000 and ≤ 3 average employees; and for micro-enterprise-tax payers with ≤ 3 average employees. Everyone else files monthly. A quarterly filer still authors one D112 per month (luna_r/an_r name the month), and if an employee takes sick leave or loses insured status mid-quarter the declaration for that month is due by the 25th of the next month, not at quarter-end.
  • Corrections: D112 has its own rectificative mechanism on the root — d_rec="1" marks a declarație rectificativă and tip_rec (1–9) states the reason. A rectificative is a complete replacement of the period's declaration (full employer + nominal detail), and it can be filed only if an initial declaration exists; the same period cannot receive an initial and a rectificative on the same day. Correcting a person's CNP fills cnpAnt/ numeAnt/prenAnt (the previous identity). This is distinct from D710, which rectifies declared payment obligations on already filed D100/D112 — the payroll nominal detail itself is corrected through a rectificative D112, not D710.

Filling guide

The document is a real XML tree (unlike D300's single flat element): one <declaratieUnica> root carries the reporting period + declarant, one required <angajator> (employer totals), and zero-or-more <asigurat> (per-insured detail). Employer-level amounts are aggregations the jar recomputes from the per-insured detail — author the detail correctly and the totals must match, or validation fails.

declaratieUnica  (luna_r, an_r, d_rec/tip_rec, declarant name/function)
├─ angajator     (cif, caen, den, casaAng, datCAM, bifa_CAM, totalPlata_A)
│  ├─ angajatorA × (1..41)   creanțe: one per obligation (cod obligație → sumă)
│  ├─ angajatorB             headcounts + total gross wage fund
│  ├─ angajatorC1            aggregated income/base by work condition (required, may be empty)
│  ├─ angajatorC2, C3        sick-leave / accident aggregations (required, may be empty)
│  ├─ angajatorC4, C5        CAM base/amount (present when CAM is owed)
│  ├─ angajatorD, E1..E4     other aggregations (optional)
│  └─ angajatorF1, F2        secondary work-points (optional)
└─ asigurat × (0..n)         (cnpAsig, names, dataAng/dataSf, casaSn, asigCI, asigSO, Timp_E3, …)
   ├─ det1, coAsigurati      detachment / co-insured (optional)
   ├─ asiguratA | B1..B4 | C  ONE of the three contract-shape groups (A xor B xor C)
   ├─ asiguratD × (0..10)    sick-leave certificates
   └─ asiguratE1, E2, E3     income-tax detail (E3 required; E1/E2 for base/extra income)

Parameters (v7, 01/2026 — read them from the structure annex, they change with each revision). Cipens employee CAS = 25%; Cisan employee CASS = 10%; pCAM = 2.25%; employer CAS CacasD (hazardous) = 4%, CacasS (special) = 8%, CacasN (normal) = 0%. Minimum gross wage salMin = 4050 (months 01–06/2026), 4325 (07–12), 4582 (construction). Non-taxable salary top-up Suma300 = 300 (01–06), 200 (07–12). Average gross earning / death-aid castigMed = 8620. All amounts are positive integers; contributions round arithmetically (≥ 0.5 up), with subunit contribution values rounded up to 1 leu.

Employer identification (angajator)

Attribute Form field Notes
cif Cod de identificare fiscală required; check-digit enforced. Also admits a 13-digit CNP-like value for individual employers
cifS CIF succesor optional (art. 90 alin.(4) Cod procedură fiscală)
caen Cod CAEN required; closed enum (Nomenclator 1)
den Denumire required
casaAng Casă de asigurări de sănătate required; 2-char county sigla (nomenclatoare); must match the office county, must ≠ AOPSNAJ
datCAM Datorează CAM required 0/1
bifa_CAM Îndeplinește condițiile facilităților construcții/agricultură required 0/1
bifa_AgCon Bifă activități construcții/agricultură 1 = yes; absent/22 = no
caenC Cod CAEN construcții/agricultură when bifa_AgCon set
cifAf1/cifAf2/pond1 (+ _a) Cifră de afaceri (curent / anterior) construction/agriculture turnover test
totalPlata_A Total obligații de plată required; = Σ A_plata across all creanțe (a control sum)
adrSoc/telSoc/…/mailFisc address & contact optional

Employer creanțe (angajatorA, one element per obligation)

Each obligation the employer owes for the month is a separate angajatorA element (up to 41 of them). A_codOblig picks the obligation and A_codBugetar is its budget code (auto-derived) — the full list is Nomenclator 3. Each element declares four amounts:

Attribute Field Notes
A_codOblig Cod obligație required; unique per declaration (no duplicate codes)
A_codBugetar Cod bugetar required; 5503XXXXXX for most, 20470300XX/20A470600X for CAM
A_datorat 1. Suma datorată required; the jar recomputes it from the per-insured detail (below)
A_deductibil 2. Suma deductibilă optional — absent counts as 0 (the validated instances below omit it); nonzero only for wage tax offset by Law-111 union amounts
A_scutit 2a. Suma scutită/exceptată required; 0 except construction/agriculture/IT exemptions
A_plata 4. Suma de plată required; = A_datorat − A_deductibil − A_scutit ≥ 0

The recomputation the validator enforces (the load-bearing ones):

Obligation A_datorat =
602 wage tax no formula from E3 unless angajatorF1/F2 are present — set it to Σ E3_15 (the tax withheld, = Timp_E3)
412 CAS Σ asigurat(A_14) + Σ B4_8 + Σ B4_20 + Σ C_11 + Σ C_26
432 CASS Σ asigurat(A_12) + Σ B4_6 + Σ C_9
480 CAM Round(C4_baza · 2.25%), where C4_baza = Σ(A_5 + B4_14 + C_29) − C5_baza and the amount is read from angajatorC4/@C4_ct — so angajatorC4 must be present when CAM is owed, else the computed CAM is 0 (a warning)
481/482 employer CAS Round(4%·…) / Round(8%·…) on hazardous/special bases (from section C1)

Employer headcounts (angajatorB, one element)

Attribute Field = count of insured where…
B_cnp Nr. asigurați șomaj baza_AJS is true
B_sanatate Nr. asigurați concedii și indemnizații asigCI=1 and A_1/B1_1 not an exempt type
B_pensie Nr. asigurați care datorează CAS A_14 > 0 (or B4_8/B4_20 > 0)
B_sal Nr. salariați A_1/B1_1 ∈ the salaried set (1, 2, 8, 10, 25, 27, 28, 46, 48, 51, 52, 54)
B_brutSalarii Total fond de salarii brute (C3_13 − C3_14) + Σ A_11 + Σ B4_5
nrSal1_111nrSal3_111, bazaCAS_111, CAS_111 Legea 111/2022 voluntary insured optional

The asigurat (per-insured) block

Identity + insurance flags on the element, then exactly one of the three contract-shape groups: asiguratA (a single ongoing employment), the asiguratB1 family (several contract lines / mid-month changes), or asiguratC (non-salaried insured declared by a third party). asiguratE3 (income-tax detail) is always required for an A/B/C record; asiguratE1/E2 summarise base-function and other income and are required for A/B/C in (1, 19, 25).

Attribute Field Notes
idAsig Nr. crt. record counter
cnpAsig CNP/NIF required; check-digit + year/month/sex + min-age-15 enforced, must be unique in the file
cisAsig CIS (cod la sănătate) for NIF holders (warning if absent)
numeAsig/prenAsig Nume / Prenume required
cnpAnt/numeAnt/prenAnt previous identity only for d_rec=1 corrections
dataAng/dataSf entry / exit into insured category dd.mm.yyyy; dataAng ≤ dataSf ≤ last day of the month
casaSn Casă de sănătate required; usually = casaAng; _N for a zilier or a non-CASS-paying detached
asigCI Asigurat concedii (1/2) required
asigSO Asigurat șomaj (1/2) required
asigScu/asigExc/motivExc income-tax / min-wage-CAS-CASS exemptions see nomenclatoare
Timp_E3 Total impozit reținut required; = Σ E3_15 across the record's E3 sections
plata_CAS/plata_CASS/plata_CAM pays-flags only for detached persons

asiguratA (single employment) — the wage detail. The insured type A_1 (Nomenclator 5) drives which contributions are owed via the dat_CAS/dat_CASS/dat_CAM/ baza_AJS/eSalariat flags:

Attribute Field Notes / formula
A_1 Tip asigurat (contract) required; Nomenclator 5
A_2 Pensionar required; 1/0
A_3 Tip contract (timp de lucru) required; Nomenclator 12 (N, P1P7)
A_4 Ore normă zilnică required; 6/7/8
A_sal1 Salariu de bază brut din CIM required (A_sal1 > 0 and/or A_sal2 > 0)
A_sal2 Venit brut realizat required
A_5 Bază CAM > 0 when dat_CAM true
A_6/A_7/A_8 Ore lucrate / suspendate / zile lucrate A_6 ≤ NZL·A_4 for N; A_8 ≤ NZL
A_9 Bază indemnizație șomaj > 0 when baza_AJS true and A_6 > 0
A_11 Bază CASS 0 when dat_CASS false
A_12 CASS required; = Round(A_11 · 10%)
A_13 Bază CAS = A_11 when dat_CAS true
A_14 CAS required; = Round(A_13 · 25%)
A_13P/A_14P, A_11P/A_12P part-time min-wage CAS/CASS ceilings art. 146(5⁶)/168(6¹)
A_13S Suma de 300 lei netaxabilă (L168/2022) only A_1=51

asiguratE3 (income-tax detail) — required. E3_1 = section (A/B/C), E3_2 = insured type (mirrors A_1), E3_3 = 1 for base-function income, E3_4 = P (reporting period) / A (other period). Then E3_8 gross, E3_9 mandatory social contributions, E3_12/E3_13 deductions, E3_14 = E3_8 − E3_9 − E3_12 − E3_13 (taxable base, 0 ≤ E3_14 ≤ E3_8), E3_15 = Round(E3_14 · 10%) (tax, 0 ≤ E3_15 ≤ E3_14), E3_16 net collected. When E3_3=1, the asiguratE1 summary must equal the E3 sums (E1_1 = Σ E3_8, E1_6 = Σ E3_14, E1_7 = Σ E3_15, …).

Common scenarios

Both instances below validated clean (ok) against D112Validator.jar J26.0.3 on 2026-07-17, authored against the v7 namespace mfp:anaf:dgti:declaratie_unica:declaratie:v7. The synthetic cif="1234565" is check-digit valid; cnpAsig="1850615410019" is a checksum-valid CNP (male, 1985-06-15, Bucharest).

1 — Nil month (an employer with no insured persons). Employer envelope only: one angajatorA for wage tax at zero, an all-zero angajatorB, and the empty angajatorC1/C2/C3 that must be present (below). totalPlata_A="0".

<?xml version="1.0" encoding="UTF-8"?>
<declaratieUnica xmlns="mfp:anaf:dgti:declaratie_unica:declaratie:v7"
  luna_r="6" an_r="2026"
  nume_declar="Popescu" prenume_declar="Ion" functie_declar="Administrator">
  <angajator cif="1234565" caen="6201" den="EXEMPLU TEST SRL"
    casaAng="_B" datCAM="1" bifa_CAM="0" totalPlata_A="0">
    <angajatorA A_codBugetar="5503XXXXXX" A_codOblig="602"
      A_datorat="0" A_scutit="0" A_plata="0"/>
    <angajatorB B_cnp="0" B_sanatate="0" B_pensie="0" B_brutSalarii="0" B_sal="0"/>
    <angajatorC1/>
    <angajatorC2/>
    <angajatorC3/>
  </angajator>
</declaratieUnica>

2 — One full-time employee (normal conditions, gross 8 000 lei, June 2026, no dependents so the personal deduction is 0 above salMin+2000). CAS = 8000·25% = 2000, CASS = 8000·10% = 800, CAM = 8000·2.25% = 180, taxable base = 8000−2800 = 5200, tax = 5200·10% = 520; totalPlata_A = 520+2000+800+180 = 3500. Note the four creanțe, the reconciling angajatorB counts, the filled angajatorC1 (normal-condition income) and angajatorC4 carrying the CAM amount, and the asigurat with asiguratA + asiguratE1 + asiguratE3.

<?xml version="1.0" encoding="UTF-8"?>
<declaratieUnica xmlns="mfp:anaf:dgti:declaratie_unica:declaratie:v7"
  luna_r="6" an_r="2026"
  nume_declar="Popescu" prenume_declar="Ion" functie_declar="Administrator">
  <angajator cif="1234565" caen="6201" den="EXEMPLU TEST SRL"
    casaAng="_B" datCAM="1" bifa_CAM="0" totalPlata_A="3500">
    <angajatorA A_codBugetar="5503XXXXXX" A_codOblig="602" A_datorat="520" A_scutit="0" A_plata="520"/>
    <angajatorA A_codBugetar="5503XXXXXX" A_codOblig="412" A_datorat="2000" A_scutit="0" A_plata="2000"/>
    <angajatorA A_codBugetar="5503XXXXXX" A_codOblig="432" A_datorat="800" A_scutit="0" A_plata="800"/>
    <angajatorA A_codBugetar="20470300XX" A_codOblig="480" A_datorat="180" A_scutit="0" A_plata="180"/>
    <angajatorB B_cnp="1" B_sanatate="1" B_pensie="1" B_brutSalarii="8000" B_sal="1"/>
    <angajatorC1 C1_11="8000" C1_T1="8000"/>
    <angajatorC2/>
    <angajatorC3/>
    <angajatorC4 C4_baza="8000" C4_ct="180"/>
  </angajator>
  <asigurat idAsig="1" cnpAsig="1850615410019" numeAsig="Ionescu" prenAsig="Vasile"
    dataAng="01.03.2020" casaSn="_B" asigCI="1" asigSO="1" Timp_E3="520">
    <asiguratA A_1="1" A_2="0" A_3="N" A_4="8" A_5="8000" A_6="168" A_7="0" A_8="21" A_9="8000"
      A_11="8000" A_12="800" A_13="8000" A_14="2000" A_sal1="8000" A_sal2="8000"/>
    <asiguratE1 E1_1="8000" E1_2="2800" E1_3="0" E1_4="0" E1_41="0" E1_42="0" E1_421="0" E1_422="0"
      E1_5="0" E1_6="5200" E1_7="520"/>
    <asiguratE3 E3_1="A" E3_2="1" E3_3="1" E3_4="P" E3_8="8000" E3_9="2800"
      E3_14="5200" E3_15="520" E3_16="4680" E3_19="0" E3_21="0"/>
  </asigurat>
</declaratieUnica>

3 — Correction (rectificativă). Re-author the complete declaration for the period with d_rec="1" and a tip_rec reason (e.g. tip_rec="1" for an ordinary rectification); if a CNP was wrong, add cnpAnt/numeAnt/prenAnt to the affected asigurat. An initial declaration for that luna_r/an_r must already have been filed. There is no partial "delta" — a rectificative D112 replaces the whole month.

Special attention & gotchas

The pitfalls below trace either to direct XSD/validator verification (the empty-C1–C3 requirement, the angajatorC4-for-CAM rule, the CNP checksum, the computed-totals reconciliation, and the malformed A_sal* XSD tags were each observed against D112Validator.jar J26.0.3) or to an authoritative source (the structure annex and joint order 2066/248/1377/3103/2025 for the parameters, creanțe formulas and deadline; the CECCAR/PortalPFA guides corroborate the deadline and quarterly election). No uncorroborated practitioner claim is carried.

  • The live wire format is v7, but the newest published XSD is v6. Author against namespace mfp:anaf:dgti:declaratie_unica:declaratie:v7 (note the legacy internal name declaratie_unica — D112's historical title, not today's D212). The v6 XSD (d112_10102024.xsd) is the closest schema but lags the wire in several places (below); the structure annex + validator jar win.
  • The published v6 XSD does not even parse strictly. The A_sal1, A_sal2, B1_sal1 and B1_sal2 attribute declarations are malformed (name="A_sal1 type="…" — a missing closing quote). Do not feed the XSD to a strict XSD validator expecting it to load; DUK validates from bytecode, not the XSD, so the jar is authoritative for these fields.
  • angajatorA, angajatorB, angajatorC1, angajatorC2, angajatorC3 must all be present — C1–C3 even as empty elements (all their attributes are optional). The error when they are missing is misleading: "secțiunea 'angajatorD' este greșit poziționată sau lipsesc secțiuni anterioare obligatorii" names whatever section follows, not the missing C1–C3. angajatorD and beyond are optional.
  • angajatorC4 must be present when CAM is owed. A_datorat(480) reads the CAM amount from angajatorC4/@C4_ct; omit angajatorC4 and the jar computes CAM as 0 and raises a mismatch warning (A21.46) against the value you typed on the 480 creanță. Author <angajatorC4 C4_baza="Σ A_5" C4_ct="Round(C4_baza·2.25%)"/>.
  • Employer totals are recomputed from the per-insured detail — they are not free inputs. A_datorat(412)=Σ A_14, A_datorat(432)=Σ A_12, B_pensie/ B_sanatate/B_sal are counts, B_brutSalarii=Σ A_11, C1_11=Σ A_13, and totalPlata_A=Σ A_plata. Get the detail right first; a mismatch is an ERR (or ATT for the count rows). A_plata on every creanță is A_datorat − A_deductibil − A_scutit.
  • Contribution rates are attributes of the value, not the attribute name. A_12=Round(A_11·10%) and A_14=Round(A_13·25%); the employer CAM is 2.25%, employer CAS on hazardous/special conditions 4%/8%. Read the current rates and the minimum wage from the structure annex parameters — they changed at 01/2026 (min wage 4050→4325 mid-year) and again with each OUG.
  • The insured type A_1/B1_1 decides which contributions are owed. The jar derives dat_CAS/dat_CASS/dat_CAM/baza_AJS/eSalariat from A_1 (a military A_1=2 owes no CAS/unemployment; a zilier A_1=3 owes CAS only; construction/agriculture/IT 25/48/54 get reduced CAS and CASS exemptions). Section A cannot coexist with B or C for the same person; types 3/34/36 are section-A-only, 16/17/23/24 are section-B-only. See Nomenclator 5.
  • The CNP is checksum-validated by the jar (weights 2 7 9 1 4 6 3 5 8 2 7 9, mod 11, 10→1), plus year/month/sex coherence and a minimum insurance age of 15, and must be unique in the file ('CNP-ul trebuie să fie unic'). Synthetic test data needs a genuinely valid CNP.
  • Str_A_cod_obligListSType (the XSD's 22-code obligation enum) is stale. The v7 form uses ~37 obligation codes (the structure annex Nomenclator 3); the jar accepts them, and the budget code moved from the XSD's 5502XXXXXX / 20470101XX to 5503XXXXXX (and CAM 20470300XX / 20A470600X). Use the nomenclatoare table, not the XSD enum.
  • angajatorA cardinality: XSD says 29, the structure annex says 41. The v6 XSD caps angajatorA at maxOccurs="29"; the v7 structure annex documents "1‑41 apariții". The jar follows v7 — do not treat 29 as the ceiling.
  • Filing an empty period ends health coverage. The structure annex warns (creanța 19 note) that a declaration with no insured persons closes the insured period at CNAS. An employer with staff must carry the asigurat detail every month; a genuinely nil month is only for an employer with no active insured.
  • Cross-form consistency. The wage-tax half of D112 (Timp_E3, creanța 602) is not re-declared on D100 — D100 carries the other withheld taxes; the two must not double-count wage tax. The nominal detail (names, contracts, entry/exit dates) is expected to reconcile with REGES-Online/REVISAL registrations — a person on the payroll here should have a registered contract. The per-insured CAS/CASS bases feed the individual's future pension/health record, so an under-declared base surfaces later as a benefit gap, not an immediate D112 error.

v7 (live wire format; no standalone XSD published)

  • The live namespace is mfp:anaf:dgti:declaratie_unica:declaratie:v7 (note the internal name declaratie_unica — D112's historical title, not today's D212). The newest XSD ANAF publishes (d112_10102024.xsd) declares v6; every 2025/2026 soft-page row still links that same v6 file, and the validator zip contains no schema (validation is pure bytecode). The structure PDF (structura_D112_0126_030226.pdf) is the only v7 documentation. DUK's namespace error states the expected namespace — trust it (with a current jar) and author v7 against the v6 XSD + structure PDF deltas.
  • Root declaratieUnica: luna_r, an_r, declarant name/function (optional d_rec/tip_rec for rectifications); children angajator (required) + repeating asigurat.
  • angajator required attributes: cif, caen, den, casaAng (health-house code: county sigla, _B = Bucharest, _A/_T = defence/transport houses), datCAM 0/1, bifa_CAM 0/1, totalPlata_A.
  • Mandatory employer sections in v7: angajatorA, angajatorB, angajatorC1, angajatorC2, angajatorC3 — C1–C3 must be present even as empty elements (all their attributes are optional). The error when they are missing is misleading: "sectiunea 'angajatorD' este gresit pozitionata sau lipsesc sectiuni anterioare obligatorii" points at whatever section follows, not at the missing C1–C3. angajatorD itself is optional.
  • angajatorA (the tax-obligation row): A_codOblig + A_codBugetar pairing is jar-enforced, and v7 changed the wage-tax pairing: 602 (wage income tax) now pairs with A_codBugetar="5503XXXXXX" — both v6 enum values (20470101XX, 5502XXXXXX) are rejected ("incorect asociat cu cod obligatie"). Budget codes are X-padded to 10 chars. CAM pairs with 20470300XX. (Recovered from the jar's Parameters_v36 constant pool; the error message does not tell you the expected value, unlike D100's.)
  • angajatorB (headcount/base summary): B_cnp, B_sanatate, B_pensie, B_brutSalarii, B_sal — all required, zero on an employees-less month.
  • cui/cif check digit enforced; CifSType also admits 13-digit CNP-like values ([1-9]\d{12}) for individual employers.
  • Minimal valid instance (employer with no insured persons, June 2026):
<?xml version="1.0" encoding="UTF-8"?>
<declaratieUnica xmlns="mfp:anaf:dgti:declaratie_unica:declaratie:v7"
  luna_r="6" an_r="2026"
  nume_declar="Popescu" prenume_declar="Ion" functie_declar="Administrator">
  <angajator cif="1234565" caen="6201" den="EXEMPLU TEST SRL"
    casaAng="_B" datCAM="1" bifa_CAM="0" totalPlata_A="0">
    <angajatorA A_codBugetar="5503XXXXXX" A_codOblig="602"
      A_datorat="0" A_scutit="0" A_plata="0"/>
    <angajatorB B_cnp="0" B_sanatate="0" B_pensie="0" B_brutSalarii="0" B_sal="0"/>
    <angajatorC1/>
    <angajatorC2/>
    <angajatorC3/>
  </angajator>
</declaratieUnica>

Open items

  • Per-employee (asigurat) authoring is now DUK-verified (2026-07-17): a single full-time asiguratA + asiguratE1/E3 record validated clean (see scenario 2). Not yet exercised: the asiguratB1 multi-contract family, the asiguratC/asiguratD sick-leave path, detachment (det1), and the Law-111/2022 voluntary-contribution fields.
  • The jar's version directories (v28/v32/v6/v1… inside D112Validator.jar) show it keeps validators for many wire generations and dispatches on the declared period — old periods still validate against their era's rules.