Skip to content

ccnl_engine.inputs

Every fact a caller passes beyond the common path of the root: optional fields of Employment, EmployerProfile and PeriodFacts, tax facts, the calendar, the engine mode, the opening state and imported balances. See Opening state and imported balances for the state types.

Contract type, hours and seniority

ccnl_engine.inputs.Apprentice dataclass

Apprenticeship contract; salary is derived from CCNL apprenticeship rules.

Attributes:

Name Type Description
months_elapsed int

Months of apprenticeship service elapsed so far, >= 0. Used to look up the applicable apprenticeship_pct in the CCNL percentage track, or the under-classification level in under-classification tracks.

track str | None

Name of the CCNL apprenticeship track to apply. Required only when more than one track covers the destination level; None lets the engine select the unique applicable track.

Raises:

Type Description
InvalidInputError

When months_elapsed is not a non-negative int or track is not a non-blank string.

ccnl_engine.inputs.FixedTerm dataclass

Fixed-term contract, which may owe the NASpI surcharge.

Attributes:

Name Type Description
renewals int | None

Renewals of the fixed-term contract with the same employer, this contract being the last, signed from 14 July 2018 (INPS circ. 121/2019 par. 2.3: earlier renewals are not counted). A prorogation of the term is not a renewal. Each renewal raises the surcharge by 0.5 points. None means not known: a run that owes the increase has a missing_fact blocker.

naspi_exclusion NaspiExclusion | None

The exclusion of c. 29 the contract falls in, :attr:NaspiExclusion.NONE when none. None means not known: a run whose sector charges the surcharge has a missing_fact blocker.

Raises:

Type Description
InvalidInputError

When renewals is not a non-negative int or naspi_exclusion names no exclusion.

ccnl_engine.inputs.NaspiExclusion

Bases: StrEnum

Why the NASpI surcharge of a fixed-term contract is not charged.

Sources: L. 92/2012 art. 2 c. 28-29 and D.L. 87/2018 art. 1 c. 3, text in force on Normattiva on 7 October 2026; INPS circ. 121/2019 par. 2.2 and 2.4. Apprentices (c. 29 lett. c) are not a reason here: an apprenticeship is an :class:~ccnl_engine.employment.inputs.Apprentice contract, which never pays the surcharge. Operai agricoli (c. 3) are not a reason either: the bundle marks the categories of the sector the whole article does not apply to.

Attributes:

Name Type Description
NONE

No exclusion: the surcharge and its renewal increase apply.

REPLACEMENT

Hired to replace absent workers (c. 29 lett. a).

SEASONAL

Hired for the seasonal activities of DPR 1525/1963, or for those of the CCNLs of the provincia di Bolzano signed by 31 December 2019 (c. 29 lett. b and b-bis).

PUBLIC_ADMINISTRATION

Employed by a public administration of art. 1 c. 2 D.Lgs. 165/2001 (c. 29 lett. d).

SHORT_SERVICE

Special services of at most three days in tourism and public establishments, D.Lgs. 81/2015 art. 29 c. 2 lett. b (c. 29 lett. d-bis).

RESEARCH

Teaching or research at a private university, a public research institute, a public company promoting research or a private research body: the 1.4% applies, the renewal increase does not (D.L. 87/2018 art. 1 c. 3).

excludes_surcharge property

Whether the whole surcharge of c. 28 is not charged.

excludes_renewal_increase property

Whether the 0.5-point increase per renewal is not charged.

ccnl_engine.inputs.Permanent dataclass

Standard open-ended (permanent) employment contract.

ccnl_engine.inputs.WorkerCategory

Bases: StrEnum

Legal category of an employee under art. 2095 c.c.

The single category vocabulary shared by CCNL data (levels, seniority rules, employer funds), INPS contribution rules and employment facts. Values are the lowercase Italian names used in the bundled JSON.

Attributes:

Name Type Description
OPERAIO

Manual worker.

IMPIEGATO

Clerical or technical employee.

QUADRO

Middle manager (L. 190/1985).

DIRIGENTE

Executive.

ccnl_engine.inputs.EmploymentPeriod dataclass

Start and optional end of the employment relationship.

Attributes:

Name Type Description
started_on date

First day of employment.

ended_on date | None

Last day of employment, or None for an open-ended relationship. Must not precede started_on.

Raises:

Type Description
InvalidInputError

When a date is not a date or ended_on is before started_on.

from_dates(started_on, ended_on) classmethod

Build a period from optional dates, as supplied by callers.

Returns:

Type Description
EmploymentPeriod | None

None when neither date is given, otherwise the validated period.

Raises:

Type Description
InvalidInputError

When only ended_on is given, or when ended_on precedes started_on.

overlaps_month(year, month)

Return whether the employment covers at least one day of a month.

Parameters:

Name Type Description Default
year int

Calendar year of the month.

required
month int

Calendar month, 1-12.

required

Returns:

Type Description
bool

True when the month has at least one employed day.

covers_month(year, month)

Return whether the employment covers every day of a month.

Parameters:

Name Type Description Default
year int

Calendar year of the month.

required
month int

Calendar month, 1-12.

required

Returns:

Type Description
bool

True when the employment starts on or before the first day

bool

and does not end before the last day of the month.

span_in_month(year, month)

Return the first and last employed day of a calendar month.

Parameters:

Name Type Description Default
year int

Calendar year of the month.

required
month int

Calendar month, 1-12.

required

Returns:

Type Description
tuple[date, date] | None

(first, last) employed days of the month, inclusive; None

tuple[date, date] | None

when the employment has no day in it.

clip_start(day)

Return day, or the hire date when day precedes it.

Parameters:

Name Type Description Default
day date

A date, typically the first day of an accrual window.

required

Returns:

Type Description
date

max(day, started_on).

ccnl_engine.inputs.EmploymentSpell dataclass

Days of one employment within a tax year.

Attributes:

Name Type Description
first_day date

First day of the employment in the year.

last_day date

Last day of the employment in the year: its end, or 31 December while the end is not stated.

fixed_term bool

Whether the employment is fixed-term.

unpaid_days tuple[date, ...]

Days of the spell for which no pay at all is due (aspettativa senza assegni), in order: they leave the days of the deductions (AdE circ. 15/E/2007 par. 1.5.1).

Raises:

Type Description
InvalidInputError

When a field is not of its type, or the days are not of one year in order.

with_unpaid(days)

Return the spell with days added to its unpaid days.

Returns:

Type Description
EmploymentSpell

The spell with the days of days that fall within it.

of(period, year, *, fixed_term) classmethod

Return the spell of period in year.

Parameters:

Name Type Description Default
period EmploymentPeriod | None

The employment period; None when its start is not stated, which covers the whole year.

required
year int

The tax year.

required
fixed_term bool

Whether the employment is fixed-term.

required

Returns:

Type Description
EmploymentSpell | None

The spell, or None when the period has no day in year.

ccnl_engine.inputs.WeeklyHours dataclass

Weekly working hours, contracted or full-time.

Attributes:

Name Type Description
value int

Hours per week, > 0.

Raises:

Type Description
InvalidInputError

When value is not an int or is not positive.

ccnl_engine.inputs.ContributableHours dataclass

Hours worked and paid in a period that are subject to INPS contributions.

Zero is valid (a period with no paid hours).

Attributes:

Name Type Description
value Decimal

Finite :class:~decimal.Decimal number of hours, >= 0.

Raises:

Type Description
InvalidInputError

When value is not a finite Decimal or is negative.

ccnl_engine.inputs.SeniorityFact dataclass

Recognised seniority of the worker, for seniority increments.

The seniority is a fact as of a date: the engine ages it to each run. The increments and the service-gated allowances of a run use the months of service completed by the first day of its competence month, so an increment matured during a month is paid from the next one, and service starting within the month counts zero months (see :meth:months_in_month). A month is complete on the same day of the following month.

Use :meth:since when the caller knows the date the recognised seniority starts from instead of a count of months.

Attributes:

Name Type Description
months int

Completed months of recognised service on as_of, >= 0.

as_of date

Date the months are counted at.

source SenioritySource

Where the seniority was read from; a string value of :class:SenioritySource is accepted and normalized.

Raises:

Type Description
InvalidInputError

When months is not a non-negative int, as_of is not a date or source names no source.

since(recognised_from, source) classmethod

Return the seniority that starts on recognised_from.

Parameters:

Name Type Description Default
recognised_from date

First day of recognised service, which may precede the hire date when the employer recognises earlier service.

required
source SenioritySource

Where the date was read from.

required

Returns:

Type Description
SeniorityFact

Zero months as of recognised_from.

months_at(day)

Return the completed months of recognised service on day.

Parameters:

Name Type Description Default
day date

The date to age the seniority to; it may precede as_of.

required

Returns:

Type Description
int

months plus the whole months from as_of to day,

int

minus them when day precedes as_of.

Raises:

Type Description
InvalidInputError

When day precedes the start of the recognised service.

months_in_month(year, month)

Return the months of service a run of a month counts.

A run counts the months completed by the first day of its month. Service that starts within the month counts zero months: the hire month of a worker whose seniority is recognised from the hire date.

Parameters:

Name Type Description Default
year int

Year of the competence month.

required
month int

Competence month, 1-12.

required

Returns:

Type Description
int

The completed months on the first day of the month, at least 0.

Raises:

Type Description
InvalidInputError

When the recognised service starts after the last day of the month.

ccnl_engine.inputs.SenioritySource

Bases: StrEnum

Where the caller read the recognised seniority from.

Attributes:

Name Type Description
EMPLOYER_RECORDS

The personnel file or the libro unico del lavoro.

PAYSLIP

A previous payslip of the same employment.

EMPLOYMENT_CONTRACT

The letter of hire, for a seniority recognised on hiring (anzianita convenzionale).

ccnl_engine.inputs.ContributionHistory dataclass

The pension history that decides whether the IVS massimale applies.

L. 335/1995 art. 2 c. 18 caps the IVS contribution base at an annual massimale (EUR 122,295 in 2026) for workers without contributions before 1 January 1996 and for those who opted for the contributory system under art. 1 c. 23. Every other worker contributes on the full base. The engine derives the eligibility from these facts; the caller never states it.

The history is the one in force for the run being computed: the engine models no effective date of a change. Pre-1996 periods credited on request to a worker hired after 1995 lift the massimale only from the month after the request (L. 208/2015 art. 1 c. 280), and the option takes effect from when it is exercised: for the runs before those dates, supply the history as it stood then.

Attributes:

Name Type Description
first_enrolled_on date

Date of the first contribution credited to any mandatory pension scheme (prima iscrizione), from the worker's contribution statement.

contributory_option bool

Whether the worker opted for the contributory system (L. 335/1995 art. 1 c. 23). Defaults to False.

Raises:

Type Description
InvalidInputError

When a field is not of its type.

ivs_ceiling_basis property

Why the massimale applies to the worker or not.

ivs_ceiling_applies property

Whether the annual IVS massimale caps the contribution base.

ccnl_engine.inputs.EmploymentSector

Bases: StrEnum

Whether the worker is employed in the private or the public sector.

Attributes:

Name Type Description
PRIVATE

Employer outside the public administrations.

PUBLIC

Public administration employer (D.Lgs. 165/2001 art. 1 c. 2).

ccnl_engine.inputs.PensionFundEnrolment dataclass

The worker's enrolment in a pension fund of the CCNL.

Enrolment is voluntary (D.Lgs. 252/2005 art. 1 c. 2), so it is a fact of the employment, never derived from the CCNL. The employer rate and its base come from the fund in CCNL.parameters.employer_funds.

Attributes:

Name Type Description
fund_code str

Code of the fund in the CCNL data, e.g. "ALIFOND".

employee_rate Decimal

Contribution the worker chose, as a fraction of the same base as the employer rate, e.g. Decimal("0.01"). It cannot be below the minimum of the CCNL when the bundle records one, except zero: a worker who confers the TFR alone, with no contribution of either side (D.Lgs. 252/2005 art. 8 c. 1).

tfr_to_fund bool

Whether the TFR accrued is paid to the fund (D.Lgs. 252/2005 art. 8 c. 1-2). Required: the choice is the worker's, and it moves the TFR out of the company.

young_member bool | None

Whether the worker belongs to the members the CCNL favours for the age at enrolment (Cometa: enrolled after 5 February 2021 before turning 35), read only by a fund with a young_member_rate; None when not stated.

conventional_base Decimal | None

Monthly base the fund applies to the worker, read only by a fund on a conventional base (Previambiente: the base pay of the level at 1 January 1997, its contingenza and one scatto, e.g. 2077.84 for a quadro); None when not stated.

seniority_to_fund bool

Whether the worker opted to convert the seniority increments into fund contributions, read only by a fund with a seniority_conversion (Previambiente art. 65 lett. A) bis): not unless stated.

seniority_converted_on date | None

Date of the request of a worker already in service (lett. A) bis c. 6): the increments matured by then stay in the pay, frozen, and only the later ones are converted; None for a new hire who opted at the hire (c. 1).

Raises:

Type Description
InvalidInputError

When a field is not of its type, fund_code is empty, employee_rate is outside [0, 1], or zero with no TFR conferred.

tfr_only property

Whether the worker confers the TFR alone, with no contribution.

ccnl_engine.inputs.NoPensionFund dataclass

The worker is stated not enrolled in a pension fund of the CCNL.

It is the fact Employment.pension_fund left None does not state: on every CCNL but domestic work, an unknown enrolment leaves the contributions to the fund undetermined. Whether the TFR of a worker who expressed no choice goes to the fund (D.Lgs. 252/2005 art. 8 c. 7) is for the caller to establish: the engine does not infer it.

ccnl_engine.inputs.PublicEndOfService

Bases: StrEnum

End-of-service regime of a public employee (DPCM 20 dicembre 1999).

Values

TFS: Trattamento di fine servizio (buonuscita or indennità premio di servizio) of INPS Gestione Dipendenti Pubblici: the worker pays 2.50% of the contribution base, the administration the rest. TFR_INPS: Trattamento di fine rapporto accrued notionally by INPS (art. 1 c. 6): the administration pays the whole contribution and the gross is reduced by the 2.50% the worker no longer pays (c. 3). TFR_EMPLOYER: Trattamento di fine rapporto the employer accrues and pays (art. 1 c. 6 and 8: enti pubblici non economici, enti di ricerca): no contribution to the Gestione, no reduction.

ccnl_engine.inputs.TfrFundBalance dataclass

TFR the worker has accrued with the employer at 31 December of a year.

The fund at 31 December of year, after the revaluation of that date and net of the substitute tax charged to it, less the advances paid: the TFR the next year revalues (art. 2120 c. 4 c.c.: the quota accrued in the year is excluded). It includes the part paid to the Fondo Tesoreria INPS, whose share the Fondo pays out under art. 2120 c.c. (DM 30 gennaio 2007 art. 2 c. 1), and excludes the TFR paid to a complementary pension fund.

Attributes:

Name Type Description
year int

Year at whose 31 December the balance is struck.

amount Decimal

Balance in EUR, non-negative, with at most two decimals.

Raises:

Type Description
InvalidInputError

When year is not an int from 1900 or amount is not a non-negative Decimal in cents.

ccnl_engine.inputs.EmployerActivity

Bases: StrEnum

Activity of the employer, where a regime excludes some activities.

L. 199/2025 art. 1 c. 11 excludes from the night, holiday and shift substitute tax the activities of c. 18: "esercizi di somministrazione di alimenti e bevande, di cui all'articolo 5 della legge 25 agosto 1991, n. 287" and "comparto del turismo, ivi inclusi gli stabilimenti termali". Their workers receive the trattamento integrativo speciale of c. 18 instead.

Attributes:

Name Type Description
FOOD_AND_BEVERAGE_SERVICE

Somministrazione di alimenti e bevande (L. 287/1991 art. 5).

TOURISM

Comparto del turismo, other than thermal establishments.

THERMAL_ESTABLISHMENT

Stabilimenti termali.

OTHER

Any activity not listed above.

ccnl_engine.inputs.AgriculturalZone

Bases: StrEnum

Zone of the agricultural land, for the reduced contributions.

Attributes:

Name Type Description
ORDINARY

No reduction.

DISADVANTAGED

A "zona svantaggiata": 68% less.

MOUNTAIN

A "zona particolarmente svantaggiata (ex montana)": 75% less.

Family and tax facts

ccnl_engine.inputs.FamilyComposition dataclass

Caller-supplied family unit for Art. 12 TUIR deductions.

Used to compute the family deductions the employer applies as sostituto d'imposta, on the reddito complessivo of :class:~ccnl_engine.irpef.other_income.inputs.CurrentYearTaxFacts. Eligibility conditions the engine cannot verify (residency, disability certification, the dependents' own income) are taken as declared; one left unknown grants no deduction (see :class:Dependent). The children also select the fringe-benefit threshold (L. 207/2024 art. 1 c. 390).

Attributes:

Name Type Description
dependents tuple[Dependent, ...]

The dependents; a list is accepted and stored as a tuple.

sole_parent bool

True when the other parent is missing or has not recognized the children, or the children are the worker's alone, and the worker is not married or is legally separated: for the first child the spouse deduction of lett. a applies when more favourable (art. 12 c. 1 lett. c, last period).

has_any_dependent property

True when at least one dependent is declared.

ccnl_engine.inputs.Dependent dataclass

One fiscally dependent family member for Art. 12 TUIR purposes.

The caller declares the dependent and the dated interval in which the conditions it cannot verify hold (marriage, cohabitation, residency, custody); the engine derives from it, month by month, the months the deduction is due (art. 12 c. 3: "rapportate a mese e competono dal mese in cui si sono verificate a quello in cui sono cessate le condizioni richieste") and, for a child, the months of the age band.

A condition left None is unknown, never met by default: when the dependant would give right to a deduction in some month, the family deductions of the run are not determined and the run has a missing_fact blocker naming the field. A condition is read only where art. 12 makes it one: own_income and residency_eligibility for every dependant (c. 2 and c. 2-bis refer to every deduction of c. 1), cohabiting for an ascendant (c. 1 lett. d), allocation_pct for a child and an ascendant (lett. c and lett. d share the deduction; the spouse deduction of lett. a is not shared). The dependency interval has no default: None is an open end the caller states.

Attributes:

Name Type Description
relationship DependentRelationship

Relationship to the worker.

birth_date date | None

Date of birth. Required for a child: the age band of lett. c is evaluated in every month. Ignored for a spouse or an ascendant.

disabled bool

True when a disability is certified under art. 3 L. 104/1992; a child keeps the deduction from the age of 30.

own_income Decimal | None

Dependent's own reddito complessivo of the year (EUR), checked against the limit of art. 12 c. 2; None is unknown.

allocation_pct Decimal | None

Percentage of the deduction allocated to this worker (0-100): the share between the parents of lett. c, or the pro quota share of lett. d. None is unknown for a child or an ascendant; a spouse takes the whole deduction, so only None or 100 is accepted for one.

cohabiting bool | None

True when the ascendant lives with the worker (Art. 12 c. 1 lett. d post L. 207/2024); None is unknown. Not read for a spouse or a child.

residency_eligibility bool | None

True when the condition of Art. 12 c. 2-bis is met: the worker is an Italian, EU or EEA citizen, or the dependant is not resident abroad. Caller-declared, not engine-verified; None is unknown.

dependent_from date | None

First day the conditions hold; None states that they held before the tax year. Keyword only, required.

dependent_until date | None

Last day the conditions hold; None states that they have not ceased. Keyword only, required.

Raises:

Type Description
InvalidInputError

When a field is not of its type or is outside its range, a child has no birth date, a spouse is allocated less than the whole deduction, or the interval ends before it starts.

share property

Percentage of the deduction to this worker; 100 when not stated.

A child or an ascendant without a stated share has a missing fact (:attr:missing_facts) and no deduction, so the 100 is never applied to one.

missing_facts property

Conditions of art. 12 this dependant leaves unknown.

Returns:

Type Description
str

The names of the fields left None that art. 12 reads for

...

the relationship, in field order.

may_qualify(income_limit)

Return whether no stated condition excludes the deduction.

An unknown condition does not exclude it: the dependant may qualify once the fact is stated.

Parameters:

Name Type Description Default
income_limit Decimal

Own-income limit of art. 12 c. 2 for this dependant.

required

Returns:

Type Description
bool

False when residency or, for an ascendant, cohabitation is

bool

stated as not met, or the stated own income exceeds the limit.

dependency_months(year)

Return the months of year the conditions hold on some day.

Returns:

Type Description
frozenset[int]

Months 1-12 the interval touches, both ends included (c. 3).

ccnl_engine.inputs.DependentRelationship

Bases: StrEnum

Relationship category of a fiscally dependent family member.

ccnl_engine.inputs.PriorYearTaxFacts dataclass

Prior-year income, written waivers and requests of the tax year.

The single source of the requirements the preferential regimes check: the premio di risultato (L. 208/2015 art. 1 c. 182, prior-year income up to 80,000 EUR), the renewal increments (L. 199/2025 art. 1 c. 7, 2025 income up to 33,000 EUR) and the night, holiday and shift supplements (L. 199/2025 art. 1 cc. 10-11, 2025 income up to 40,000 EUR). For a 2026 payment the prior year is 2025, the reference year of both L. 199/2025 regimes.

Attributes:

Name Type Description
employment_income Decimal | None

Employment income (reddito di lavoro dipendente) of the year before the tax year, in EUR, >= 0. None means not known: the PdR substitute rate is not applied and the L. 199/2025 regimes are unknown, so the result is provisional.

waived_regimes frozenset[SubstituteTaxRegime]

Regimes the worker renounced in writing; their amounts are taxed as ordinary income. String values are accepted and normalized.

shortfall_deferral ShortfallDeferralRequest | None

The worker's written request to have the IRPEF the conguaglio cannot withhold for lack of pay withheld on the payslips of the next year, with interest (art. 23 c. 3 DPR 600/1973). None: what is not withheld is communicated to the worker. Read on the conguaglio only.

foreign_taxes tuple[ForeignTaxPaid, ...]

Foreign tax paid on employment income of the tax year, one entry per State, credited at the conguaglio (art. 165 TUIR, art. 23 c. 3 DPR 600/1973). A list is accepted and stored as a tuple.

Raises:

Type Description
InvalidInputError

When employment_income is not a finite, non-negative Decimal, a waiver names no regime, shortfall_deferral is not a request, or two foreign taxes name the same State.

ccnl_engine.inputs.CurrentYearTaxFacts dataclass

Income of the tax year that enters the reddito complessivo.

The family deductions of art. 12 TUIR depend on the reddito complessivo of the worker, not on the income of this employment alone. The engine adds to its own projection of the employment income of the year:

reddito complessivo = this employment + other_employment_income
    + other_income - main_dwelling_income

The somma esente of L. 207/2024 art. 1 c. 4 adds the exempt share of the impatriati and researcher regimes (c. 9), exempt_regime_income.

Every amount is required: declaring no other income is a fact, stated with zeros (see :meth:employment_only). Without these facts the reddito complessivo is unknown, and a run whose family deductions depend on it is not payable; so is a run whose contributions could depend on the INPS base of other employments, unless the opening state states it.

Attributes:

Name Type Description
tax_year int

The tax year the income belongs to. Facts of another tax year are not used.

other_employment_income Decimal

Employment and pension income of the tax year from other employers or payers (e.g. a previous employer of the year), net of their exclusions, >= 0.

other_employment_inps_base Decimal

INPS base of the worker's other employments of :attr:tax_year, earlier or simultaneous, >= 0. It counts toward the IVS massimale and the additional 1% threshold of the runs whose competence year is :attr:tax_year, and is carried in their closing state (:class:~ccnl_engine.contribution.base.models.InpsBaseYtd).

other_income Decimal

Every other income of the tax year in the reddito complessivo (land and buildings, self-employment, rents under cedolare secca, art. 3 c. 7 D.Lgs. 23/2011), >= 0.

main_dwelling_income Decimal

Income of the main dwelling and its appurtenances included in other_income, excluded from the reddito complessivo of art. 12 (c. 4-bis), >= 0 and not above other_income.

exempt_regime_income Decimal

Exempt share of the income of the tax year under art. 44 c. 1 D.L. 78/2010 (researchers), art. 16 D.Lgs. 147/2015 or art. 5 D.Lgs. 209/2023 (impatriati), >= 0. It counts only in the reddito complessivo of the somma esente (L. 207/2024 art. 1 c. 9), not in that of the family deductions.

estimated_on date

Date the amounts were stated.

quality IncomeEstimateQuality

How the amounts are known.

Raises:

Type Description
InvalidInputError

When a field is not of its type or in its range.

external_income property

Reddito complessivo of the year beyond this employment.

somma_esente_income property

Reddito complessivo beyond this employment for the somma esente.

L. 207/2024 art. 1 c. 9 adds the exempt share of the impatriati and researcher regimes to :attr:external_income.

employment_only(tax_year, estimated_on, quality=IncomeEstimateQuality.DECLARED) classmethod

Return the facts of a worker whose only income is this employment.

Returns:

Type Description
CurrentYearTaxFacts

Facts with every other income and the INPS base of other

CurrentYearTaxFacts

employments stated as zero.

ccnl_engine.inputs.IncomeEstimateQuality

Bases: StrEnum

How the income of :class:CurrentYearTaxFacts is known.

Attributes:

Name Type Description
CERTIFIED

Final amounts from a certification (Certificazione Unica of another employer) or from the worker's tax return.

DECLARED

The worker's declaration to the employer of the income expected in the year.

ESTIMATED

The employer's own estimate: enough for the runs of the year, not for the conguaglio, which then stays provisional.

ccnl_engine.inputs.ForeignTaxPaid dataclass

Tax paid in one foreign State on income taxed in Italy this year.

Attributes:

Name Type Description
country str

ISO 3166-1 alpha-2 code of the State, not "IT".

income Decimal

Foreign-source employment income as it entered the Italian taxable income of the tax year (the conventional pay when art. 51 c. 8-bis TUIR applies), in EUR, positive.

tax Decimal

Foreign tax paid on it "a titolo definitivo", in EUR, >= 0, within the rate of a tax treaty. Pass it already reduced as art. 165 c. 10 TUIR requires when the income entered the taxable income only in part: on the conventional pay, by the ratio of that pay to the income that would be taxable under art. 51 without c. 8-bis (circ. AdE 9/E/2015 par. 5).

Raises:

Type Description
InvalidInputError

When country is not an ISO code of a foreign State, or an amount is not a finite Decimal in its range.

ccnl_engine.inputs.ShortfallDeferralRequest dataclass

The worker's written authorization to defer the year-end shortfall.

Attributes:

Name Type Description
signed_on date

Date of the written request. It must fall between 1 January of the tax year and the end of February of the next one, the deadline of the conguaglio.

Raises:

Type Description
InvalidInputError

When signed_on is not a date.

check_for(tax_year)

Check that the request can defer the conguaglio of tax_year.

Raises:

Type Description
InvalidInputError

When signed_on is before the tax year or after the end of February of the next year.

ccnl_engine.inputs.SubstituteTaxRegime

Bases: StrEnum

Preferential regimes a worker can renounce in writing.

Each value is the regime_id of a bundled :class:PreferentialTaxRegime.

Attributes:

Name Type Description
RINNOVO

Contract-renewal increments (L. 199/2025 art. 1 c. 7).

NOTTE_FESTIVI_TURNI

Night, holiday and shift supplements (L. 199/2025 art. 1 cc. 10-11).

Calendar and engine mode

ccnl_engine.inputs.WorkCalendar dataclass

Year-level payroll calendar with extra-month schedule.

Attributes:

Name Type Description
year int

The tax year this calendar applies to.

extra_months tuple[ExtraMonthSchedule, ...]

Ordered tuple of extra-month payment schedules. A list is accepted and stored as a tuple.

Raises:

Type Description
InvalidInputError

When year is not an int from 1970, an extra month is not an :class:ExtraMonthSchedule, a kind appears twice, or a fourteenth month comes without a thirteenth.

entitlement property

Equivalent months of pay granted by this calendar.

Twelve regular months plus the max_fraction of each extra month, so a full tredicesima and half a quattordicesima give 13.5.

from_additional_months(year, additional_months, *, thirteenth_payment_month=12, fourteenth_payment_month=6) classmethod

Build a calendar from a CCNL additional_months parameter.

Accepts fractional values (e.g. Decimal("13.5")). A fractional fourteenth month is added with :attr:ExtraMonthSchedule.max_fraction set to the fractional part so the caller receives the correct partial entitlement without discarding it.

For additional_months=13 (12 regular + 1 tredicesima) this produces one :class:ExtraMonthSchedule paid in December. For additional_months=14 it produces tredicesima (December) and quattordicesima in fourteenth_payment_month (default June). For additional_months=13.5 it produces tredicesima (full) and a half quattordicesima (max_fraction=Decimal("0.5")).

Parameters:

Name Type Description Default
year int

Tax year.

required
additional_months int | Decimal | ExtraMonthEntitlement

Value from CCNL parameters (13, 13.5 or 14), as :class:ExtraMonthEntitlement, int or Decimal. Fractional parts are preserved.

required
thirteenth_payment_month int

Calendar month for the tredicesima. Defaults to December (12).

12
fourteenth_payment_month int

Calendar month for the quattordicesima. Defaults to June (6).

6

Returns:

Type Description
WorkCalendar

class:WorkCalendar with up to two extra schedules.

Raises:

Type Description
InvalidInputError

When additional_months is outside the range [12, 14], or strictly between 12 and 13: a partial tredicesima is not a supported calendar and would otherwise be dropped silently.

ccnl_engine.inputs.CalendarOverride dataclass

A calendar that replaces the CCNL standard one, with its reason.

Attributes:

Name Type Description
calendar WorkCalendar

The calendar to run instead of the standard one.

reason CalendarOverrideReason

Why the standard calendar does not apply.

note str

Free-text justification kept for audit, e.g. the CCNL article or the agreement that sets the payment month. Must not be blank.

Raises:

Type Description
InvalidInputError

When calendar is not a :class:WorkCalendar, reason is not a :class:CalendarOverrideReason or note is blank.

resolve(standard)

Validate the override against the standard calendar and return it.

Rules, compared per :class:ExtraMonthKind on max_fraction (names are free):

  • the override is for the same year as standard;
  • every extra month accrues over the 12 months ending in its payment month (accrual_window_start_month == payment_month % 12 + 1), so it pays its full fraction; a tredicesima is therefore paid in December;
  • every extra month of standard is kept with at least its fraction, whatever the reason;
  • :attr:CalendarOverrideReason.PAYMENT_MONTH: the fractions equal the standard ones, no extra month is added;
  • :attr:CalendarOverrideReason.MORE_FAVOURABLE_TREATMENT: at least one extra month is added or has a larger fraction.

Parameters:

Name Type Description Default
standard WorkCalendar

Calendar derived from the CCNL for the same year.

required

Returns:

Type Description
WorkCalendar

attr:calendar, the effective calendar of the year.

Raises:

Type Description
InvalidInputError

When any rule is broken.

ccnl_engine.inputs.CalendarOverrideReason

Bases: StrEnum

Domain reason for replacing the standard calendar of a CCNL.

The list is deliberately short. Paying the ratei monthly inside the regular pay (mensilizzazione) is real practice, but the engine does not pay ratei in regular runs, so an override that drops extra-month runs would underpay the worker; no reason allows it.

Members

PAYMENT_MONTH: The CCNL article or the employer's practice pays an extra month in a different month than the engine default (quattordicesima in June), e.g. a quattordicesima paid with the July salary. The extra months and their fractions must equal the ones the CCNL grants. MORE_FAVOURABLE_TREATMENT: An individual or company agreement grants more than the CCNL (trattamento di miglior favore, art. 2077 c.c.): an extra month the CCNL does not grant, or a larger fraction of one it grants. Every CCNL extra month must be kept at least at its CCNL fraction, and at least one must be larger or added.

ccnl_engine.inputs.EngineMode

Bases: StrEnum

Payability policy of a payroll engine.

Attributes:

Name Type Description
SIMULATION

Amounts with their assurance; readiness is reported only.

OPERATIONAL

Amounts are payable only from production rulesets.

Opening state and imported balances

ccnl_engine.inputs.PeriodState dataclass

State entering a payroll run: what is accrued and what is paid.

Pass :meth:zero for the first run of an employment. Between runs, pass the closing_state of the previous run. To open the next tax year, pass the closing state of the last run of the year to :func:~ccnl_engine.year.tax_year.closing.rules.close_tax_year: it restarts :attr:cash with its obligations and keeps :attr:accrual.

A run that opens without the history of the employment before it (a zero state after the start of the employment, or a state descending from such a run) is computed as a simulation with a missing_fact opening_state blocker, and its closing state has :attr:history_known False, so every later run of the chain blocks too. The same holds for the closing state of a conguaglio of a withholding agent computed without the worker's residence: it determines no surtax of the year and opens none of the obligations of the next. Import the balances of the previous provider, or recompute the chain with the missing facts, to restart from a known history.

A run closes once (its competence run in :attr:accrual) and is paid once (its payment in :attr:cash). The same request on the same opening state yields the same closing state; a state that already closed the run rejects it, so a retry never counts a payment twice.

Attributes:

Name Type Description
accrual EmploymentAccrualState

Competence runs closed over the employment; carried across tax years.

cash TaxCashState

Payments, YTD accounts and carried obligations of the current tax year; the payments and accounts restart every tax year.

history_known bool

Whether the state accounts for every run of the employment before it. The engine sets it False on the closing state of a run that opened without that history, or of a conguaglio without the residence; a state the caller builds states it.

Raises:

Type Description
InvalidInputError

When a field is not of its type, or a payment of :attr:cash settles a run :attr:accrual has not closed.

tax_year property

Tax year of :attr:cash; None when not yet bound to a year.

check_next(payment)

Check that payment and the run it settles can close next.

A run already closed or out of order in its competence year, or a payment that cannot close in the tax year, raises InvalidInputError.

zero() classmethod

Return the state of a new employment: no run closed, no obligation.

Returns:

Name Type Description
A PeriodState

class:PeriodState with all counters and accumulators at zero.

ccnl_engine.inputs.period_state_from_json(text)

Return the state written by :func:period_state_to_json.

A text that is not such JSON, written by another schema, engine or knowledge-bundle version, or that names a type outside the persisted state raises :class:~ccnl_engine.errors.InvalidInputError: recompute the runs, or import the balances with :class:~ccnl_engine.balance.opening.provider.services.OpeningBalances.

Returns:

Type Description
PeriodState

The state, its invariants checked by its constructors.

ccnl_engine.inputs.period_state_to_json(state)

Return state as JSON text, with its schema, engine and bundle versions.

Returns:

Type Description
str

The JSON text of the state.

ccnl_engine.inputs.OpeningBalances dataclass

Progressive totals of a tax year computed outside the engine.

Every amount is in EUR, non-negative and with at most two decimals; an amount left None (a *_due) is not known. The totals are validated by the same rules as the state the engine produces (:class:~ccnl_engine.balance.models.PeriodState); a violation is raised as InvalidInputError. A tax-year total without the payments that produced it is rejected: it could not be told apart from the payments the engine would compute again. The INPS bases and the obligations carried from an earlier run have no default: what the previous provider determined is a fact the import states, () when there is none.

Attributes:

Name Type Description
tax_year int

Tax year of the totals.

payments tuple[PaymentId, ...]

The payments already made this tax year, in payment order (:meth:~ccnl_engine.calendar.payment.models.PaymentId.parse reads "2026-12-regular@2027-01-13"), whatever their competence year. Each must belong to tax_year; its run is closed, so it is rejected if computed again, and each takes a slot of the withholding schedule of the year but an adjustment.

competence_runs tuple[PayrollRunId, ...]

Runs closed in earlier tax years that a run still to compute must follow: with December 2026 paid on 13 January 2027, the other 2026 runs paid in 2026. Payments of tax_year go in payments, not here.

inps_bases tuple[InpsBaseYtd, ...]

Required. INPS base toward the IVS massimale per competence year: this employment's (own) and the worker's other employments of the same year (other_employers, from their CU or the worker's declaration; INPS circ. 237/2016 par. 3.1; None when not known, which blocks the runs whose contributions could depend on it), with the additional 1% IVS each withheld on it (additional_ivs, other_employers_additional_ivs). Every competence year of payments and competence_runs needs its base; import the year before too when its December is paid in tax_year.

sickness_episodes tuple[SicknessEpisode, ...]

Sickness episodes of the employment up to the last processed day, in start order: they set the waiting period, INPS days and CCNL tier of later episodes.

sickness_known_from date | None

First day from which sickness_episodes list every sick day of the employment: the first day of the employment when they list all of them. None states the episodes of tax_year only (from 1 January). A CCNL that counts the sickness of earlier years (Federmeccanica: the comporto over three years) has a missing_fact blocker when the days before it could change a sick day it pays.

gross Decimal

Contractual gross earnings paid.

taxable Decimal

IRPEF taxable income.

inps_employee Decimal

Employee INPS contributions withheld.

pension_deducted Decimal

Pension fund contributions already deducted from the taxable income (D.Lgs. 252/2005 art. 8 c. 4).

irpef_withheld Decimal

IRPEF withheld.

surtax_withheld Decimal

Regional and municipal surtax withheld.

municipal_advance_withheld Decimal

Part of surtax_withheld withheld as the municipal acconto of tax_year (D.Lgs. 360/1998 art. 1 c. 5); the conguaglio deducts it from the municipal surtax.

regional_settled Decimal

Regional surtax of tax_year a conguaglio at the end of an earlier employment of the year already withheld.

municipal_settled Decimal

Municipal saldo of tax_year withheld the same way.

fringe_value Decimal

Fringe benefit value granted (Art. 51 c. 3 TUIR).

fringe_taxed Decimal

Part of fringe_value already taxed.

pdr Decimal

Premio di Risultato taxed at the substitute rate.

trattamento_recognized Decimal

Trattamento integrativo paid.

trattamento_recovered Decimal

Trattamento integrativo already recovered.

trattamento_due Decimal | None

Annual trattamento integrativo last computed by the previous provider, None when not known.

trattamento_reason str | None

Lower snake case reason of that amount, e.g. "full_amount", None when not known.

somma_esente_recognized Decimal

Somma esente (L. 207/2024) paid.

somma_esente_recovered Decimal

Somma esente already recovered.

somma_esente_due Decimal | None

Annual somma esente last computed, or None.

somma_esente_reason str | None

Reason of that amount, or None.

ulteriore_recognized Decimal

Ulteriore detrazione (L. 207/2024 art. 1 c. 6) already applied by the withholding.

ulteriore_recovered Decimal

Ulteriore detrazione already taken back.

ulteriore_due Decimal | None

Annual ulteriore detrazione last computed, or None.

ulteriore_reason str | None

Reason of that amount, or None.

irpef_shortfall Decimal

IRPEF due on earlier runs and not yet withheld for lack of pay.

surtax_shortfall Decimal

Surtax due on earlier runs and not yet withheld.

credit_recovery_shortfall Decimal

Credit recoveries (trattamento integrativo, somma esente, installments) due on earlier runs and not yet withheld for lack of pay.

work_time_regime_used Decimal

Night, holiday and shift supplements already taxed at the substitute rate (L. 199/2025 art. 1 cc. 10-11).

recoveries tuple[RecoveryObligation, ...]

Required. Installment recoveries still running, from this tax year or an earlier one; () states that there is none.

surtax_obligations tuple[SurtaxObligation, ...]

Surtax determined by the conguaglio of an earlier tax year and not yet withheld: the regional surtax and municipal saldo of tax_year - 1 and the municipal acconto of tax_year, by the installments still to post. Required: the engine withholds no surtax the previous provider determined unless it is stated here; () states that there is none.

deferred_shortfall DeferredShortfall | None

IRPEF the conguaglio of tax_year - 1 deferred on the worker's written request (art. 23 c. 3 DPR 600/1973) and not yet withheld, None without one.

employment_spells tuple[EmploymentSpell, ...]

Days in tax_year of the employments whose income the totals hold, when they hold an earlier employment with this employer (a rehire): the art. 13 TUIR deduction counts their union. () states none: the next run adds the days of its own employment.

ccnl_engine.inputs.InpsBaseYtd dataclass

INPS base of one competence year, toward the massimale and the 1% band.

Attributes:

Name Type Description
year int

The competence year.

own Decimal

INPS base of the runs of this employment of :attr:year.

other_employers Decimal | None

INPS base of the worker's other employments of :attr:year, earlier or simultaneous, as certified (CU) or declared by the worker. It counts toward the massimale and the band of the additional 1% IVS and is never contributed by this employer. None means not known: a run whose contributions could depend on it has a missing_fact blocker; 0 states that there is none.

additional_ivs Decimal

Additional 1% IVS (D.L. 384/1992 art. 3-ter) this employment withheld on the pay of :attr:year, net of what its conguagli gave back. Negative only when a conguaglio refunded more than this employment withheld, giving back what other employers withheld (INPS circ. 156/2025 par. 5).

other_employers_additional_ivs Decimal | None

Additional 1% IVS the other employments withheld on :attr:other_employers, as certified; the conguaglio deducts it from the 1% due on the year. None when not stated: with a base of other employers the conguaglio then cannot be settled (:attr:other_employers_withheld_unknown).

month int | None

Competence month of the latest run of this employment, None before the first run of :attr:year.

month_base Decimal

INPS base of the runs of this employment of :attr:month: the runs of one month share its threshold of the additional 1% IVS.

Raises:

Type Description
InvalidInputError

When a field is not of its type, an amount other than :attr:additional_ivs is negative, an amount is not finite, or :attr:month_base is not zero without a month.

other_employers_known property

Whether the base of the other employments is stated.

total property

Base of the year toward the massimale: own and other employers.

An unknown base of other employers counts as zero: the run computes on this employment alone and reports the missing fact.

additional_ivs_withheld property

Additional 1% IVS withheld on the year by every employment.

An unstated 1% of other employers counts as zero here; see :attr:other_employers_withheld_unknown.

other_employers_withheld_unknown property

Whether other employers have a base but their 1% is not stated.

stating_other_employers(amount)

Return the base with the other employers' base stated as amount.

Returns:

Type Description
InpsBaseYtd

A new base with other_employers set and every other field

InpsBaseYtd

unchanged.

base_of_month(month)

Return the INPS base this employment already declared for month.

Returns:

Type Description
Decimal

attr:month_base when month is :attr:month, else zero.

plus(amount, month, additional_ivs=_ZERO)

Return the base after a run of this employment of month.

Parameters:

Name Type Description Default
amount Decimal

INPS base of the run.

required
month int

Competence month of the run.

required
additional_ivs Decimal

Additional 1% IVS the run withheld, negative when its conguaglio gave some back.

_ZERO

Returns:

Type Description
InpsBaseYtd

A new base with own raised by amount and the base of

InpsBaseYtd

month by the same amount.

ccnl_engine.inputs.PaymentId dataclass

Identifier of one payment: the run it pays and its payment date.

The text form is "{run_id}@{payment_date}", e.g. "2026-12-regular@2027-01-13". A run is paid once, so the run id alone identifies the payment within an employment; the date fixes the tax year the payment belongs to.

Attributes:

Name Type Description
run_id PayrollRunId

The competence run the payment settles.

payment_date date

Day the run is paid, not before the first day of the run month.

Raises:

Type Description
InvalidInputError

When a field is not of its type or the payment precedes the run month.

competence property

First day of the run month.

tax_year property

Tax year of the payment (TUIR art. 51 c. 1, cassa allargata).

is_prior_competence property

Whether the payment settles a run of a year before its tax year.

parse(text) classmethod

Parse the text form "{run_id}@{payment_date}".

Parameters:

Name Type Description Default
text str

A payment id such as "2026-12-regular@2027-01-13".

required

Returns:

Type Description
PaymentId

The typed identifier. A text that is not a well-formed

PaymentId

payment id raises

PaymentId

class:~ccnl_engine.errors.InvalidInputError.

ccnl_engine.inputs.PayrollRunId dataclass

Typed identifier of a payroll run: year, month, kind and sequence.

The text form is "{year}-{month:02d}-{kind}", e.g. "2026-12-thirteenth", as in :attr:PayrollRun.run_id. A month has at most one run of each kind, except adjustment runs: the second and later adjustments of a month carry their sequence number as a suffix, e.g. "2026-12-adjustment-2".

Attributes:

Name Type Description
year int

Year of the run month (the competence year). The tax year of the run follows from its payment date and can be later.

month int

Run month, 1-12.

kind RunKind

Kind of the run.

sequence int

Number of the run among the runs of its kind and month, from 1. Above 1 only for an adjustment run.

order_key property

Key ordering the runs as they are paid: year, month, kind rank, sequence.

payment_key property

Key of what the run pays, closed once per employment.

A regular, termination or adjustment run pays its month, an adjustment once per sequence number; a tredicesima or quattordicesima pays the extra month of its year, whatever month it is paid in: the quattordicesima of 2027 is the same entitlement paid in June or in July.

parse(text) classmethod

Parse the text form of :meth:__str__.

Parameters:

Name Type Description Default
text str

A run id such as "2026-06-fourteenth" or "2026-12-adjustment-2".

required

Returns:

Type Description
PayrollRunId

The typed identifier. A text that is not a well-formed run

PayrollRunId

id, or not in its canonical form (a "-1" or "-02"

PayrollRunId

suffix), raises

PayrollRunId

class:~ccnl_engine.errors.InvalidInputError.

ccnl_engine.inputs.RecoveryObligation dataclass

An installment recovery and the tax year of the credit it recovers.

Attributes:

Name Type Description
tax_year int

Tax year whose conguaglio found the credit not due. The installments posted in that year enter the recovered total of its :class:~ccnl_engine.balance.cash.account.models.CreditAccount; those posted in a later year are carried: they are deducted on the payslip but belong to no account of the later year.

plan RecoveryPlan

The installment plan, with the installments still to post.

post(run)

Return what run recovers and the obligation after it.

Returns:

Type Description
PostedInstallment

meth:RecoveryPlan.post of the plan and the obligation still

RecoveryObligation | None

running, None once the plan is settled.

ccnl_engine.inputs.RecoveryPlan dataclass

Structured installment plan for recovering an over-paid tax credit.

Created when the amount to recover exceeds 60 EUR, to spread the recovery over equal installments: eight for the trattamento integrativo (D.L. 3/2020 art. 1 co. 3), ten for the somma esente (L. 207/2024 art. 1 c. 7). The last installment absorbs any rounding residual so the sum is always exactly original_amount.

Attributes:

Name Type Description
kind str

Identifier for the credit being recovered, e.g. "trattamento_integrativo" or "somma_esente".

original_amount Decimal

Total amount to recover (positive).

installment_amount Decimal

Uniform per-period deduction (positive, rounded).

installments_total int

Number of periods over which the recovery runs.

installments_posted int

Number of installments already deducted.

residual property

Amount not yet recovered.

next_installment property

Amount to deduct this period.

The last installment uses the residual to absorb rounding.

post(run)

Return what run recovers of the plan.

The single rule shared by every recovered credit: the next installment on an ordinary or adjustment run, the whole residual on the final run of the employment.

Parameters:

Name Type Description Default
run InstallmentRun

The run the installment is posted on.

required

Returns:

Type Description
PostedInstallment

The amount recovered, its reason and the plan still running.

advance()

Return a plan with installments_posted incremented by one.

Returns:

Type Description
RecoveryPlan

A new :class:RecoveryPlan one period further along.

create(kind, original_amount, installments_total) classmethod

Create a fresh plan from the original recovery amount.

Parameters:

Name Type Description Default
kind str

Credit identifier.

required
original_amount Decimal

Total amount to recover (positive).

required
installments_total int

Number of periods to spread across.

required

Returns:

Name Type Description
A RecoveryPlan

class:RecoveryPlan with installments_posted=0 and

RecoveryPlan

installment_amount set to original_amount / installments_total

RecoveryPlan

rounded to two decimal places.

ccnl_engine.inputs.SurtaxComponent

Bases: StrEnum

Part of the surtax a conguaglio determines.

REGIONAL_BALANCE = 'regional_balance' class-attribute instance-attribute

Regional surtax of the tax year (it has no acconto).

MUNICIPAL_BALANCE = 'municipal_balance' class-attribute instance-attribute

Municipal surtax of the tax year less the acconto withheld in it.

MUNICIPAL_ADVANCE = 'municipal_advance' class-attribute instance-attribute

Municipal acconto of the next tax year.

ccnl_engine.inputs.SurtaxObligation dataclass

Surtax a conguaglio determined, still to withhold in the next year.

Attributes:

Name Type Description
component SurtaxComponent

What the amount is.

tax_year int

Tax year whose conguaglio determined it; it is withheld in tax_year + 1.

jurisdiction str

Region code (ISO 3166-2:IT) or Belfiore code of the municipality it is due to: the one of the tax year of the conguaglio, not of the year it is withheld in.

plan RecoveryPlan

The installments still to post; plan.kind is the component value.

window property

Installment window of the component.

withheld_in property

Tax year whose payslips withhold the installments.

reference_year property

Tax year the surtax is due for: the next one for the acconto.

open(component, tax_year, jurisdiction, amount) classmethod

Return the obligation of amount over the window.

An amount below one cent per installment runs over fewer installments, so that none is zero.

Returns:

Type Description
SurtaxObligation

The obligation with no installment posted.

Raises:

Type Description
ValueError

When amount is below one cent.

part(amount)

Return amount withheld of this obligation as a run part.

Returns:

Type Description
SurtaxPart

The part of the component and reference year.

post(run, *, year, month, regular)

Return what a run of year and month withholds of it.

The last run of the employment withholds the residual. Otherwise a regular run of the window withholds the next installment, and the one of the last month, or any regular run after the window, the residual; nothing is withheld before the window, on another kind of run, or before :attr:withheld_in.

Returns:

Type Description
PostedInstallment | None

What the run withholds, None when nothing, and the

SurtaxObligation | None

obligation after it, None once settled.

ccnl_engine.inputs.DeferredShortfall dataclass

IRPEF of a conguaglio deferred on the worker's written request.

Attributes:

Name Type Description
tax_year int

Tax year whose conguaglio found the shortfall; it is withheld in tax_year + 1.

signed_on date

Date of the written request.

deferred_from date

First day of the pay period of the conguaglio: the interest runs from its month.

irpef Decimal

IRPEF still to withhold, positive.

withheld_in property

Tax year whose payslips withhold the deferred IRPEF.

months_to(year, month)

Whole months from the conguaglio month to year and month.

Returns:

Type Description
int

The number of months, at least zero.

due_in(year, month)

Whether a payslip of year and month may withhold it.

Returns:

Type Description
bool

True from March of :attr:withheld_in to its December.

post(available, year, month)

Return what a payslip leaving available pay withholds of it.

The principal is the largest amount whose interest still fits in available, at most the residual.

Returns:

Type Description
DeferredInstallment | None

The installment, None when nothing fits, and the shortfall

DeferredShortfall | None

left after it, None once exhausted.