Skip to main content

ccnl-engine

PyPI version Python CI Coverage License: MIT

A Python library for modeling Italian collective labor agreements (CCNL) as structured, versioned data and computing gross-to-net salary and employer cost from first principles.

Documentation · Demo

Motivation

I never really understood employment contracts or pay slips. The whole system strikes me as needlessly complicated. On top of that, finding reliable CCNL information online feels like an uphill battle: conflicting figures are everywhere, and identifying authoritative sources is harder than it should be. This project grew out of a desire to understand a little more. I make no claim to becoming an expert, but I hope to make this information more accessible and comprehensible for everyone.

The Problem

Italian payroll is governed by collective agreements (CCNL) that define base salaries, seniority increments, and allowances as time-series values — they change at negotiated renewal dates. Existing tools either lock this data inside proprietary systems or require a full HRMS. This library treats each CCNL as a validated JSON file and the computation as a pure function:

compute(PayrollScenario) → Calculation

The returned Calculation is self-describing: along with the PayrollResult (.result) it records the engine version, the exact CCNL / tax / INPS / surtax ruleset revisions used (.ruleset_version), and a snapshot of the inputs (.input_snapshot) — so any figure can be traced back to the engine and data that produced it.

Quickstart

from datetime import date
from ccnl_engine import (
    Employee, Employer, Employment,
    PayrollScenario, Permanent, compute,
)

calculation = compute(PayrollScenario(
    employee=Employee(level_code="4"),
    employment=Employment(
        ccnl="commercio-confcommercio.json",
        contract=Permanent(),
        employer=Employer(num_employees=50),
        calculation_date=date(2026, 9, 1),
    ),
))

payroll = calculation.result  # attributes are also forwarded onto the calculation
print(payroll.net_annual)              # → Decimal('...')
print(payroll.trattamento_integrativo) # → Decimal('...') — Art. 1 D.L. 3/2020 bonus
print(payroll.fiscal_simplifications)  # → frozenset of items not computed by the engine
print(payroll.employer_cost_annual)    # → Decimal('...')

print(calculation.engine_version)      # → '0.5.0'
print(calculation.ruleset_version)     # → {'ccnl': '…', 'tax': '…', 'inps': '…', 'surtax': '…'}

CCNL coverage

Over 100 contracts covering approximately 16 million employees across private and public sectors.

  • L1 — Gross: base salary, seniority, fixed allowances, additional months, hourly rate.
  • L2 — Net: INPS contributions, TFR, IRPEF, regional/municipal surtax.
  • L3 — Work rules: overtime and night/holiday premiums, absence deduction, leave accrual, sick-pay integration, performance bonuses, welfare/benefits.

Coverage % = (L1 × 50% + L2 × 35% + L3 × 15%) − 5% per missing data note (max −20%).

→ CCNL coverage table — per-contract coverage, verification status, and feature breakdown

Scope boundaries

Feature In net_annual? How to activate
L3 work rules — overtime, absence, sick pay, bonus, welfare No — reported separately Pass OvertimeHours, AbsenceDays, etc. to PayrollScenario
Family-dependent deductions (Art. 12 TUIR) Yes Pass FamilyComposition to PayrollScenario.family
Art. 15 mortgage-interest deduction Yes Pass Art15Deductions to PayrollScenario.art15_deductions
PdR flat tax on premio di risultato Reported separately Set BonusInput.eligible_for_pdr=True
Bilateral fund contributions (EST, Fon.Te, …) — Not modelled

See API docs for full detail.

Disclaimer

This library is not legal or tax advice. Figures are computed from publicly available CCNL tables and statutory rates as of the dates indicated in the data files. Always verify results against official sources or a qualified payroll professional.

Metadata

Release files for ccnl-engine 0.5.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ccnl-engine 0.5.1
File Size Uploaded
ccnl_engine-0.5.1.tar.gz 757.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ccnl-engine 0.5.1
File Interpreter ABI Platform
ccnl_engine-0.5.1-py3-none-any.whl Python 3 none any Details

Total release size: 1.4 MB

Release files / ccnl_engine-0.5.1.tar.gz

Download URL ccnl_engine-0.5.1.tar.gz
Size 757.0 kB
Tags Source
SHA-256 checksum
How to use checksums
8b8a34ebcb502785fcf291a6752562aa7c5cde83d26556ab2a9669c86ed116ae
BLAKE2b-256 checksum
How to use checksums
6233e1cec1159ed3d87cb573e479c7683a33ff463485111990a7c2df8b9e8a19
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.

Transparency log

Release files / ccnl_engine-0.5.1-py3-none-any.whl

Download URL ccnl_engine-0.5.1-py3-none-any.whl
Size 681.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b4c4cd044a7d3e7d4e9d8479a21e7d3f2b41a6a66abdc664719b71320aef4ba6
BLAKE2b-256 checksum
How to use checksums
67140e4faef4c3f4dbf800a7a8bc3d1ca82589a716de8ffc4b95e1a617a271e3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.5.1 This release

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page