Opening state and imported balances¶
A run computes the progressive IRPEF of the tax year (art. 23 c. 1 and c. 3 DPR 600/1973) and the INPS base of the competence year toward the IVS massimale (L. 335/1995 art. 2 c. 18) from the state it opens with, and the first run of a tax year withholds what the conguaglio of the year before carried (surtax, installment recoveries, a deferred shortfall). The opening state and the bases of the worker's other employments are therefore facts of the run: a run without them is computed as a simulation and is not payable. The state itself is described in Payroll state and the year change.
History of the employment¶
The engine checks the content of the opening state, not whether the field
was passed. It reports a missing_fact opening_state blocker (issue
opening_state_unknown, status incomplete) when:
- a regular month of the competence year of the run, from January or from
the start of the employment, before the month of the run, is not closed
in the state:
PeriodState.zero()on a June run of an employment begun in January drops January to May, whether passed explicitly or left to the default ofPeriodInput.opening_state; - the employment began before the competence year of the run, or
Employment.employment_periodis not stated, and the state carries nothing of an earlier tax year (no run closed, no tax year bound, no obligation): January from zero would drop the 2025 surtax and recoveries; - the state descends from a run that opened without its history, or from
the conguaglio of a withholding agent computed without
regioneorcomune_belfiore: that conguaglio determines no surtax of the year, so it withholds no saldo, opens no installment and no municipal acconto of the next year, and drops the acconto the year carried.PeriodState.history_knownisFalseon the closing state of such a run and on the stateclose_tax_year()opens from it, so every later run of the chain blocks too, until the chain is recomputed with the missing facts.
A run that a year calculation leaves out because the bundle holds no pay
rules on its date (uncovered_runs, a run_not_computed blocker of the
year) is not counted as missing history: the year reports it once, and the
runs after it do not report it again.
PeriodState.zero() is the fact only for the first run of an employment
whose start is stated and falls in the month of the run. The same rule
applies to the first payment of a CompetenceYearPlan or a TaxYearPlan
whose opening_state is None: a plan of an employment begun in an
earlier year opens with close_tax_year() of the previous year or with
imported balances. A state built by hand (PeriodState(...)) states its
history as the caller built it.
INPS base of other employments¶
The massimale is per worker (INPS circ. 237/2016 par. 3.1): the base of
earlier or simultaneous employments of the competence year counts toward it,
and toward the band of the additional 1% IVS (D.L. 384/1992 art. 3-ter;
INPS circ. 6/2026 note 10). InpsBaseYtd.other_employers is tri-state:
None is not known, Decimal(0) states that there is no other employment,
an amount is the certified (CU) or declared base. It is stated in one of two
places:
CurrentYearTaxFacts.other_employment_inps_base, required next to the other income of the year (CurrentYearTaxFacts.employment_only()states zero). When the tax year of the facts is the competence year of the run, it replaces the base the opening state carries for that year, so the latest declaration wins, and the closing state carries it to the next runs;OpeningBalances.inps_bases, with the base of this employment.
An unknown base has no upper bound, so some value of it moves any run with
a positive INPS base across the massimale or the 1% threshold. The engine
encodes no estimate: the run computes on this employment alone and, when
its INPS rules carry a massimale the worker may be subject to (the
contribution history is unknown or within the contributory cohort) or a 1%
threshold, reports a missing_fact other_employers blocker (issue
other_employment_inps_base_unknown). Domestic work, contributed per hour
without either, reads no base of other employments.
Sickness history¶
OpeningBalances.sickness_episodes lists the sickness of the employment up
to the import, and OpeningBalances.sickness_known_from the first day from
which that list is complete: the start of the employment when it lists
every episode. Left None, the list covers the tax year only, from
1 January. A CCNL that counts the sickness of earlier years
(Metalmeccanici Federmeccanica: comporto over three years, treatment chain
across episodes, see
Sickness counted over several episodes)
cannot count the days before it. As many sick days as calendar days
between the start of the window (or of the employment, if stated and
later) and that day could be missing, so a mid-employment import without
it gives a sick run of such a CCNL a missing_fact sickness_known_from
blocker (issue sickness_history_unknown) whenever those days could pass
a threshold: for an employment begun more than about six months before,
always.
Balances from a previous provider¶
OpeningBalances takes the progressive totals of a previous payroll
provider for one tax year, with the recoveries still running, and
PayrollEngine.import_opening_balances(balances) turns them into the
PeriodState of the first run the engine computes: the one entry point for
totals the engine did not compute. inps_bases, recoveries and
surtax_obligations have no default: what the previous provider
determined is stated, () when there is nothing, and every competence year
of payments and competence_runs needs its InpsBaseYtd. They are
validated with the rules of the state the engine produces: every amount non-negative with at most two
decimals, credit recovered not above recognized (trattamento_*,
somma_esente_*), taxed fringe not above fringe value, payments
(payments, a tuple of PaymentId) of the tax year in payment order, each
of a different run, YTD totals only with the payments that produced them,
competence runs closed in earlier tax years (competence_runs, e.g. the
2026 runs paid in 2026 before a December paid in 2027), the INPS base per
competence year with the base of other employers (inps_bases), the surtax
already settled at an earlier termination (regional_settled,
municipal_settled), the shortfalls not yet withheld (irpef_shortfall,
surtax_shortfall, credit_recovery_shortfall), no recovery opened after
the tax year, surtax
obligations (surtax_obligations) determined by the conguaglio of an
earlier year, an acconto withheld (municipal_advance_withheld) not
above the surtax withheld, and IRPEF deferred on written request
(deferred_shortfall) by the conguaglio of tax_year - 1 only. A violation raises
InvalidInputError with feature opening_balances.
When the totals hold an earlier employment of the year with the same
employer (a rehire), state its days in employment_spells, one
EmploymentSpell(first_day, last_day, fixed_term) per employment: the
art. 13 deduction of the next runs counts the days of the income they
project (see Fiscal rules). () states none, and the next run
adds the spell of its own employment.
from decimal import Decimal
from ccnl_engine.inputs import (
InpsBaseYtd,
OpeningBalances,
RecoveryObligation,
RecoveryPlan,
)
opening = engine.import_opening_balances(OpeningBalances(
tax_year=2027,
recoveries=(
RecoveryObligation(
tax_year=2026,
plan=RecoveryPlan(
kind="trattamento_integrativo",
original_amount=Decimal(160),
installment_amount=Decimal(20),
installments_total=8,
installments_posted=4,
),
),
),
# No payment of 2027 yet and no other employment of the worker in 2027.
inps_bases=(InpsBaseYtd(2027, Decimal(0), Decimal(0)),),
surtax_obligations=(),
))