Process guide

Italian consulting/IT essentials (HR admin)

Certifications expiry + multi-CCNL + employment type/P.IVA/IBAN for Italian consulting/IT 50-500 FTE.

Italian consulting/IT essentials (HR admin)

Last updated: 2026-05-25 Owner: Product Writer Audience: hr_admin, tenant admin, owner

Purpose

The 3 Horis features designed specifically for the Italian consulting/IT 50-500 FTE segment: certifications with expiry, multi-CCNL versioning, employment type / P.IVA / IBAN. Without these three, an HR app is barely usable for body rental, staff augmentation, and selling consultant profiles to clients.

Key concepts

  • Certification: different from a skill. It has an issuer, a unique credential code (publicly verifiable), issue date and expiry. Examples: AWS Solutions Architect Associate, PMP, ITIL Foundation. In consulting you win or lose tenders for expired or missing certifications.
  • Certification → skill mapping (CV_ENTITY_GRAPH_01 W02): the catalog table hr_certification_skill_map links certification patterns to tenant skills (e.g. CKA → Kubernetes, PMP → Project Management) with a weight. Seeded for ~15 top certs via migration 0086 (resolves ids per tenant, zero orphans); feeds the Talent Partner skill expansion (W03).
  • CCNL (Italian collective labour agreement): the most frequent for Italian consulting/IT are Metalmeccanici Industria, Commercio (Confcommercio), Studi Professionali (Confprofessioni). The Horis catalog is platform-wide (CCNL are national, not per-tenant) seeded with 6 main agreements.
  • Employment type: structured distinction between employee, freelancer with P.IVA, co.co.co., apprentice, intern, extra-curricular intern. Without it, body rental and staff aug cannot separate cost/margin.
  • Italian P.IVA: 11 numeric digits. Required only if employment_type='freelance_p_iva', forbidden otherwise (DB constraint).

Prerequisites

  • role: owner, admin, hr_admin
  • migrations applied on the tenant Supabase project:
  • 0082_hr_user_certifications.sql
  • 0083_hr_ccnl_catalog.sql
  • 0084_organization_user_details_employment.sql

Quick access

  • Employee profile management: /workspace/hr/people → select user
  • API:
  • GET /api/profile/me/certifications (own)
  • GET /api/people/{userId}/certifications (HR scope)
  • GET /api/ccnl-catalog (CCNL catalog readable by all authenticated)
  • PATCH /api/profile/me (self fields: vatNumber, iban, plus identity)
  • PATCH /api/people/{userId}/profile (HR fields: employmentType, ccnlId, ccnlLevel, ccnlClassification, ccnlApprenticeship)

1. Certifications with expiry

Fields

  • name — certification name (e.g. "AWS Solutions Architect Associate")
  • issuer — issuing organization (e.g. "Amazon Web Services")
  • credential_code — unique issuer-side code (verification)
  • credential_url — public verification link (Credly, AWS validation, etc.)
  • issued_at / expires_at — dates (both nullable)
  • statusactive | expired | revoked
  • notes — free text

Status computed UI-side (`deriveExpiryStatus` helper)

  • no_expiry — lifetime certification
  • active — expires in >90 days
  • watch — expires in 30–90 days (yellow)
  • expiring_soon — expires in 0–30 days (orange)
  • expired — expired (red)

Permissions

  • Read / write own: any authenticated user on their own via /api/profile/me/certifications/*
  • Read / write others: HR admin / owner / tenant admin via /api/people/{userId}/certifications/*, with canEditProfile check (reused from identity flow)

Initial out of scope (deferred)

  • Automatic email reminders on expiry (future programme reusing hourly cron)
  • Credly / AWS Credential Manager / LinkedIn Learning integration
  • HR dashboard "expiring certifications by team/company"

2. Multi-CCNL with classification

Catalog

Table hr_ccnl_catalog platform-wide, read open to all authenticated, write only via service-role / SQL Studio.

Initial seed (6 most frequent CCNL for Italian consulting/IT):

| Code | Name | Typical areas | |---|---|---| | metalmeccanici-industria | Metalmeccanici Industria (Federmeccanica + Assistal) | IT services, system integrator | | commercio | Tertiary Distribution Services (Confcommercio) | Management consulting, office | | studi-professionali | Professional Studios (Confprofessioni) | Small body rental companies | | cooperative-sociali | Social Cooperatives | HR/IT cooperatives | | terziario-confesercenti | Tertiary, Distribution and Services (Confesercenti) | Consulting/agencies | | industria-chimica-farmaceutica | Chemical and Pharmaceutical Industry (Federchimica/Farmindustria) | Pharma IT |

Fields on `organization_user_details`

  • ccnl_id — optional FK to catalog
  • ccnl_level — classification level (e.g. "5°", "Quadro A1")
  • ccnl_classification — qualification/role free-text (e.g. "Specialist Technician", "Department Head")
  • ccnl_apprenticeship — boolean flag, apprenticeship regime

Permissions

Editable by HR admin / manager / admin / owner (NOT self — it is contractual management data, not PII).

Initial out of scope (deferred)

  • Catalog CRUD API (Platform owner UI)
  • Historical CCNL versioning (contract renewals)
  • Automatic salary calc by CCNL level

3. Employment type / P.IVA / IBAN

Enum `employment_type` (default `employee`)

| Value | Description | |---|---| | employee | Standard employee | | freelance_p_iva | Freelancer with P.IVA (requires vat_number 11 digits) | | co_co_co | Coordinated and continuous collaboration | | apprendista | Apprenticeship regime (time-limited, reduced pay) | | stagista | Curricular internship (no salary obligation) | | tirocinio_extracurriculare | Extra-curricular internship (regional minimum salary obligation) |

`vat_number` — Italian P.IVA

  • Required ONLY if employment_type='freelance_p_iva', forbidden otherwise (DB check constraint).
  • Format: 11 numeric digits.
  • Self-only: only the employee can enter it from their own profile (financial PII).

`iban`

  • General regex format: ^[A-Z]{2}[0-9A-Z]{13,32}$ (Modulo-97 checksum validation deferred to frontend or future iteration).
  • Self-only: as VAT.

Permissions

  • employment_type editable by HR / manager / admin / owner
  • vat_number + iban editable only by the employee (self) from their own profile

Initial out of scope (deferred)

  • Foreign VAT (EU cross-border B2B)
  • Server-side IBAN Modulo-97 checksum validation
  • Tax regime (forfetario vs ordinario)
  • Automatic company cost calc by employment_type

Security & GDPR

  • hr_user_certifications RLS fully blocked, access only via service-role admin client + applicative canEditProfile check. Audit-tracked (created_by_user_id).
  • hr_ccnl_catalog RLS active with read-for-authenticated policy (internal public catalog). Write only via service-role (Platform owner / SQL).
  • organization_user_details.vat_number and iban are financial self-only PII. HR write attempt → 403 pii_field_restricted.
  • All writes on organization_user_details go through profile-service.upsertProfileBasicsFor with source check (self|hr_admin|manager).

Not (yet) included — successor programme backlog

  • Consolidated UI on /workspace/hr/people + /workspace/profile (APIs work via curl/Postman; dedicated UI in future programme)
  • Email reminders on certification expiry
  • Catalog CCNL editable from Platform owner UI
  • Automatic company cost calc
  • IBAN checksum validation

Origin programme

  • HORIS_CONSULTING_QUICK_WINS_01 (2026-05-25) — 4 waves: W01 certifications backend, W02 multi-CCNL catalog backend, W03 employment_type/P.IVA/IBAN backend, W04 bilingual wiki + closure.

Related guides