HR Analytics
Versione documentazione: 1.0beta
Data: 7 ottobre 2026
Questo manuale descrive la struttura del database HR Analytics. L’obiettivo è spiegare in modo operativo cosa rappresentano le tabelle, quale sia il livello di dettaglio di ciascuna riga, come interpretare i campi e come collegare correttamente le tabelle tra loro.
Le query possono utilizzare le funzionalità standard di PostgreSQL, inclusi operatori e funzioni JSON/JSONB, LATERAL, funzioni di aggregazione e Window Functions.
Modulo HR Analytics
Le funzionalità descritte in questa sezione sono disponibili esclusivamente per i clienti che hanno attivato il modulo HR Analytics. Il modulo consente di utilizzare i dati dell’applicativo a fini di analisi e Business Intelligence, offrendo:
- Accesso diretto al database (in sola lettura) da parte di strumenti di Business Intelligence (BI).
- Database denormalizzato, con una struttura stabile nel tempo e ottimizzata per l’analisi dei dati.
- Disponibilità dello storico dei dati su un ampio intervallo temporale.
- Aggiornamento giornaliero dei dati, per mantenere le informazioni disponibili per l’analisi costantemente aggiornate.
Indicazioni generali per le query
Durate
Le colonne che rappresentano una durata sono da considerarsi in minuti, per ottenere le ore usare una unità operativa decimale, ad esempio duration / 60.0. Evitare la unità operativa intera se servono frazioni di ora.
Date e timestamp
- Le colonne di tipo
dateusano il formato logicoYYYY-MM-DD. - Le colonne di tipo
timestampcontengono data e ora. - Le colonne
starteenddikpisono di tipotime, quindi rappresentano solo l’orario.
Campi JSONB
Diverse informazioni sono memorizzate in jsonb, soprattutto gli attributi storicizzati dei dipendenti. In PostgreSQL sono utili in particolare:
->per estrarre un valore JSON;->>per estrarre un valore come testo;@>per verificare il contenimento JSONB;jsonb_array_elements(...)per espandere un array JSONB in righe;CROSS JOIN LATERALquando l’espansione JSONB dipende dalla riga corrente.
Pattern tipico per espandere le unità operative di un dipendente:
SELECT
e.id,
d.costcenter,
d.name
FROM public.employee AS e
CROSS JOIN LATERAL jsonb_array_elements(e.divisions) AS ed(division_item)
JOIN public.division AS d ON d.costcenter = ed.division_item ->> 'id';
Window Functions
Le Window Functions sono adatte a confronti tra giornate, ranking e valori progressivi senza perdere il dettaglio delle righe. Ad esempio, LAG, LEAD, ROW_NUMBER e SUM(...) OVER (...) possono essere usate direttamente sulle tabelle di questo schema.
Attenzione ai join uno-a-molti
Per esempio shift contiene normalmente una riga giornaliera per dipendente, mentre justification, clocking, breakdown e activity possono contenere più righe per lo stesso dipendente e giorno. Un join diretto può quindi duplicare le misure di shift. Se la query deve sommare minuti o ore, pre-aggregare le tabelle di dettaglio oppure calcolare separatamente le misure di shift.
Mappa tabelle
| Tabella | Ruolo | Livello di dettaglio |
|---|---|---|
shift | Dettaglio turni | Una riga per turno lavorativo per dipendente per giorno. Rappresenta il consuntivo giornaliero di un dipendente: ore ordinarie, assenze, straordinari. È la fact table principale del sistema. |
kpi | KPI | Una riga per KPI per centro di costo per giorno. Rappresenta il valore giornaliero di un indicatore configurato per uno specifico centro di costo, eventualmente associato a un intervallo orario. |
justification | Dettaglio giustificativi | Una riga per giustificativo. Ogni riga rappresenta una singola istanza di assenza o presenza per un dipendente in un orario specifico. Un dipendente può avere più giustificativi nello stesso giorno. |
employee | Dipendenti | Una riga per dipendente (addetto). Ogni riga rappresenta un singolo lavoratore registrato nel sistema. |
division | Struttura Aziendale | Una riga per unità operativa organizzativa. Ogni riga rappresenta un nodo della gerarchia aziendale a tre livelli: azienda radice, unità produttiva, area operativa. |
clocking | Timbrature | Una riga per timbratura. Ogni riga rappresenta un singolo evento di timbratura di un dipendente: entrata, uscita, inizio pausa o fine pausa. Un dipendente ha più timbrature per giorno. |
breakdown | Componenti Orarie | Una riga per componente di breakdown giornaliero per dipendente. Rappresenta la scomposizione delle ore di una giornata lavorativa nelle sue componenti: ore ordinarie, assenze, aggiunte, anomalie. Un dipendente può avere più righe per lo stesso giorno. |
balance | Dettaglio Pianificazione | Una riga per combinazione di costcenter, division, shift, giorno, step (fascia oraria), skill e position, che rappresenta il fabbisogno e la disponibilità di personale in quell'intervallo. |
activity | Attività | Una riga per attività svolta da un dipendente in un giorno. Ogni riga rappresenta una singola attività con fascia oraria precisa. Un dipendente può avere più attività nello stesso giorno. |
Relazioni principali
| Da | A | Condizione | Note |
|---|---|---|---|
shift | employee | shift.employee = employee.id | Dipendente a cui appartiene il turno. |
shift | division | shift.division = division.costcenter | unità operativa associata al turno. |
shift | justification | shift.employee = justification.employee AND shift.day = justification.day | Giustificativi dello stesso dipendente e giorno; relazione potenzialmente uno-a-molti. |
shift | breakdown | shift.employee = breakdown.employee AND shift.day = breakdown.day | Componenti di dettaglio dello stesso dipendente e giorno; relazione potenzialmente uno-a-molti. |
shift | clocking | shift.employee = clocking.employee AND shift.day = clocking.day | Timbrature dello stesso dipendente e giorno; relazione potenzialmente uno-a-molti. |
shift | activity | activity.employee = shift.employee AND activity.day = shift.day | Attività dello stesso dipendente e giorno; relazione potenzialmente uno-a-molti. |
kpi | division | kpi.costcenter = division.costcenter | unità operativa/centro di costo a cui appartiene il KPI. |
justification | division | justification.costcenter @> to_jsonb(division.costcenter) | Centro di costo contenuto nel JSONB del giustificativo. |
employee.divisions | division | jsonb_array_elements(employee.divisions)->>'id' = division.costcenter | Storico delle unità operative del dipendente. |
employee.sections | division.sections | jsonb_array_elements(employee.sections)->>'id' = jsonb_array_elements(division.sections)->>'costCenter' | Collegamento tra sezione del dipendente e sezione della unità operativa. |
breakdown | justification | breakdown.employee = justification.employee AND breakdown.day = justification.day AND breakdown.cause = justification.cause | Giustificativo con la stessa causale. |
balance | division | balance.costcenter = division.costcenter | unità operativa/centro di costo del dato di bilanciamento. |
Nei casi JSONB il join può richiedere l’espansione dell’array con jsonb_array_elements(...) o un operatore di contenimento come @>.
shift
Consuntivo giornaliero del lavoro per dipendente. Riassume, per giornata, il turno effettivo e le principali quantità di tempo: ore ordinarie pianificate, assenze, straordinari e componenti produttive.
Granularità: Una riga per turno lavorativo per dipendente per giorno. Rappresenta il consuntivo giornaliero di un dipendente: ore ordinarie, assenze, straordinari. È la fact table principale del sistema.
Quando usarla: È la tabella di riferimento per analisi aggregate su ore pianificate, assenze, straordinari e produttività giornaliera. Le misure di durata sono espresse in minuti.
Relazioni
| Tabella collegata | Condizione di join | Significato |
|---|---|---|
employee | shift.employee = employee.id | Dipendente a cui appartiene il turno |
justification | shift.employee = justification.employee AND shift.day = justification.day | Giustificativi del dipendente nello stesso giorno |
breakdown | shift.employee = breakdown.employee AND shift.day = breakdown.day | Breakdown del dipendente nello stesso giorno |
clocking | shift.employee = clocking.employee AND shift.day = clocking.day | Timbrature del dipendente nello stesso giorno |
division | shift.division = division.costcenter | unità operativa/costcenter del turno |
Campi
| Campo | Tipo | Nullable | Descrizione | Dettagli |
|---|---|---|---|---|
employee | varchar | Sì | Matricola del dipendente a cui appartiene il consuntivo giornaliero. Si collega a employee.id. Può contenere anche identificativi di lavoratori esterni. | — |
day | date | Sì | Data della giornata lavorativa a cui si riferisce il turno. È il riferimento temporale principale per filtri e aggregazioni. | Formato: YYYY-MM-DD |
name | varchar | Sì | Codice che descrive il tipo di giornata. Tra i Valori: WRK per giornata lavorativa e L per giornata libera/riposo. | Valori: WRK — giornata lavorativaL — giornata libera / riposo |
division | varchar | Sì | Identificativo della unità operativa associata al turno. La relazione con l’anagrafica organizzativa è shift.division = division.costcenter. | — |
costcenter | varchar | Sì | Centro di costo riportato direttamente sul turno come stringa. È distinto dal campo JSONB omonimo presente in alcune tabelle di dettaglio. | Esempio: 128, 1726 |
start | timestamp | Sì | Timestamp di inizio effettivo del turno. | Formato: YYYY-MM-DD HH:MM:SS.000 |
end | timestamp | Sì | Timestamp di fine effettivo del turno. | Formato: YYYY-MM-DD HH:MM:SS.000 |
bstart | timestamp | Sì | Timestamp di inizio della pausa registrata nel turno. | Formato: YYYY-MM-DD HH:MM:SS.000 |
bend | timestamp | Sì | Timestamp di fine della pausa registrata nel turno. | Formato: YYYY-MM-DD HH:MM:SS.000 |
bduration | int2 | Sì | Durata della pausa, espressa in minuti. | Unità: minuti |
bpaid | bool | Sì | Indica se la pausa è retribuita (true) oppure no (false). | — |
ord | int2 | Sì | Minuti ordinari pianificati per la giornata, cioè il monte ore contrattuale previsto. Esempio: 480 corrisponde a 8 ore. | Unità: minuti Esempio: 0 (giorno libero), 480 (8 ore) |
abs | int2 | Sì | Minuti di assenza registrati nella giornata. | Unità: minuti |
ovt | int2 | Sì | Minuti di straordinario registrati nella giornata. | Unità: minuti |
ovtprod | int2 | Sì | Quota di straordinario considerata produttiva, in minuti. È un sottoinsieme di ovt. | Unità: minuti |
ordprod | int2 | Sì | Minuti ordinari considerati produttivi nella giornata. | Unità: minuti |
totprod | int2 | Sì | Totale dei minuti produttivi della giornata. | Unità: minuti |
ext | boolean | Sì | Indica se il turno è classificato come esterno. | — |
Note operative
Quando viene collegata a tabelle con più righe per dipendente e giorno, come justification, breakdown o clocking, le righe di shift possono essere replicate dal join. Per sommare misure di shift, aggregare prima le tabelle di dettaglio oppure calcolare i totali di shift separatamente.
- Le misure
ord,abs,ovt,ovtprod,ordprodetotprodsono espresse in minuti. - Per analisi su periodi, aggregare le misure in base al livello desiderato, ad esempio per
day,employee,divisionocostcenter. - La relazione con
divisionusashift.division, nonshift.costcenterche può far riferimento anche a una sezione.
kpi
Valori giornalieri degli indicatori configurati dal cliente, associati a un centro di costo. Un KPI può riferirsi all’intera giornata oppure a una fascia oraria tramite start ed end.
Granularità: Una riga per KPI per centro di costo per giorno. Rappresenta il valore giornaliero di un indicatore configurato per uno specifico centro di costo, eventualmente associato a un intervallo orario.
Quando usarla: Usare questa tabella per analizzare indicatori di business o operativi configurati nell’installazione. Il significato di value dipende dal KPI indicato in name.
Relazioni
| Tabella collegata | Condizione di join | Significato |
|---|---|---|
division | kpi.costcenter = division.costcenter | Centro di costo della unità operativa a cui è associato il KPI |
Campi
| Campo | Tipo | Nullable | Descrizione | Dettagli |
|---|---|---|---|---|
costcenter | varchar | Sì | Centro di costo a cui è associato il KPI. Si collega a division.costcenter. | Esempio: 128, 1726 |
name | varchar | Sì | Nome o codice del KPI. È configurabile per cliente e identifica il significato del valore memorizzato nella riga. | — |
day | date | Sì | Data a cui si riferisce il valore del KPI. | Formato: YYYY-MM-DD |
start | time | Sì | Ora di inizio dell’eventuale intervallo temporale associato al KPI. | Formato: HH:MM:SS |
end | time | Sì | Ora di fine dell’eventuale intervallo temporale associato al KPI. | Formato: HH:MM:SS |
value | float8 | Sì | Valore numerico dell’indicatore. L’unità di misura e la corretta aggregazione dipendono dalla configurazione del KPI. | — |
Note operative
I nomi dei KPI e la semantica dei valori non sono standard: verificare i valori presenti in name e la configurazione del cliente prima di scegliere funzioni di aggregazione come SUM, AVG, MIN o MAX.
nameè configurabile: prima di costruire query specifiche è utile esaminare i valori disponibili conSELECT DISTINCT name FROM public.kpi ORDER BY name.- L’aggregazione corretta di
valuedipende dal significato del KPI; non tutti gli indicatori sono necessariamente sommabili.
justification
Registro dei giustificativi del personale. Ogni riga descrive una singola assenza, uno straordinario o un’informazione statistica riferita a un dipendente, con causale, durata, fascia oraria e stato di autorizzazione.
Granularità: Una riga per giustificativo. Ogni riga rappresenta una singola istanza di assenza o presenza per un dipendente in un orario specifico. Un dipendente può avere più giustificativi nello stesso giorno.
Quando usarla: È la tabella da usare per analisi di dettaglio su assenze, straordinari, permessi, causali e relativo workflow autorizzativo.
Relazioni
| Tabella collegata | Condizione di join | Significato |
|---|---|---|
employee | justification.employee = employee.id | Dipendente a cui appartiene il giustificativo |
shift | justification.employee = shift.employee AND justification.day = shift.day | Giustificativi del dipendente nello stesso giorno |
division | justification.costcenter @> to_jsonb(division.costcenter) | I giustificativi possono essere associati a un centro di costo corrispondente a una unità operativa |
Campi
| Campo | Tipo | Nullable | Descrizione | Dettagli |
|---|---|---|---|---|
employee | varchar | Sì | Matricola del dipendente a cui appartiene il giustificativo. Si collega a employee.id. | — |
day | date | Sì | Data a cui si riferisce il giustificativo. | Formato: YYYY-MM-DD |
start | timestamp | Sì | Timestamp di inizio della fascia coperta dal giustificativo. | Formato: YYYY-MM-DD HH:MM:SS.000 |
end | timestamp | Sì | Timestamp di fine della fascia coperta dal giustificativo. | Formato: YYYY-MM-DD HH:MM:SS.000 |
duration | int2 | Sì | Durata del giustificativo, in minuti. | Unità: minuti |
type | varchar | Sì | Categoria generale del giustificativo: ABSENCE, OVERTIME oppure STAT secondo i Valori. | Valori: ABSENCE — assenzaOVERTIME — straordinarioSTAT — Statistico: qualifica che non modifica il conteggio delle ore lavorate del dipendente, ma fornisce un'informazione aggiuntiva (es. che le ore sono state lavorate da remoto). |
cause | varchar | Sì | Causale di dettaglio. I codici disponibili sono configurabili e possono cambiare da cliente a cliente. | — |
hourly | boolean | Sì | Indica se il giustificativo è orario (true) o giornaliero (false). | — |
prod | boolean | Sì | Indica se le ore del giustificativo sono considerate produttive. | Valori: truefalse |
zm | boolean | Sì | Flag “zero minute”. Quando è true, il giustificativo non modifica il conteggio delle ore, anche se duration può essere maggiore di zero. | — |
created | timestamp | Sì | Timestamp di creazione del record nel sistema. | Formato: YYYY-MM-DD HH:MM:SS.0000 |
status | varchar(32) | Sì | Stato del processo di autorizzazione: AUTHORIZED, PENDING o REJECTED secondo i Valori. | Valori: AUTHORIZED — autorizzatoPENDING — in attesa di autorizzazioneREJECTED — rifiutato |
last_manager | varchar | Sì | Identificativo dell’ultimo responsabile o servizio che ha gestito il giustificativo, ad esempio per autorizzazione o modifica. | — |
costcenter | jsonb | Sì | Array JSONB di codici di centro di costo associati al giustificativo. | — |
minutes | jsonb | Sì | Oggetto JSONB con una coppia chiave/valore. Il valore numerico rappresenta la durata in minuti e corrisponde a duration. | Esempio: {"803": 360} |
Struttura dei campi JSONB
Struttura di costcenter
Array di stringhe. Centri di costo associati al giustificativo.
Stringa identificativa del centro di costo
Struttura di minutes
Oggetto con una singola coppia chiave-valore: il secondo valore corrisponde alla durata in minuti (uguale al campo duration).
| Proprietà | Significato |
|---|---|
chiave | Centro di costo |
valore | Durata in minuti (intero) |
Esempio:
{
"803": 360
}
Note operative
Un dipendente può avere più giustificativi nello stesso giorno. Un join diretto con shift su dipendente e data può quindi produrre più righe per lo stesso turno.
type = 'STAT'rappresenta un’informazione statistica che non modifica il conteggio delle ore.causecausale.costcenterè un array JSONB; la relazione condivisionusajustification.costcenter @> to_jsonb(division.costcenter).
employee
Anagrafica dei dipendenti. Contiene i dati identificativi di base e diversi attributi storicizzati in JSONB: unità operative, unità operative esterne, posizioni, competenze, sezioni e contratti.
Granularità: Una riga per dipendente (addetto). Ogni riga rappresenta un singolo lavoratore registrato nel sistema.
Quando usarla: Usare questa tabella come dimensione anagrafica per arricchire turni, giustificativi, timbrature, breakdown e attività. Per gli attributi storicizzati, considerare sempre l’intervallo di validità start/end.
Relazioni
| Tabella collegata | Condizione di join | Significato |
|---|---|---|
shift | employee.id = shift.employee | Tutti i turni lavorati da un dipendente |
activity | employee.id = activity.employee | Attività associate al dipendente |
justification | employee.id = justification.employee | Giustificativi di assenza o straordinario |
breakdown | employee.id = breakdown.employee | Dipendente a cui appartiene il breakdown |
clocking | employee.id = clocking.employee | Dipendente che ha effettuato la timbratura |
division | jsonb_array_elements(employee.divisions)->>'id' = division.costcenter | Le unità operative di appartenenza dei dipendenti in employee.divisions referenziano costcenter |
division | jsonb_array_elements(employee.sections)->>'id' = jsonb_array_elements(division.sections)->>'costCenter' | Le sezioni dei dipendenti referenziano le unità operative tramite employee.sections.id = division.sections.costCenter |
Campi
| Campo | Tipo | Nullable | Descrizione | Dettagli |
|---|---|---|---|---|
id | varchar | No | Matricola univoca del dipendente. È la chiave primaria dell’anagrafica e il riferimento usato dalle principali tabelle operative. | Chiave primaria |
first_name | varchar | Sì | Nome del dipendente. | — |
last_name | varchar | Sì | Cognome del dipendente. | — |
birth | date | Sì | Data di nascita del dipendente. | Formato: YYYY-MM-DD |
pic | varchar | Sì | Codice fiscale del dipendente (Personal Identification Code). | — |
sex | varchar | Sì | Valore anagrafico del sesso. I Valori sono m e f. | Valori: m — maschiof — femmina |
acl | varchar | Sì | Ruolo/livello di accesso dell’utente nel sistema. Tra gli esempi documentati: Addetto e Responsabile. | Esempi: Addetto, Responsabile |
supervisor | boolean | Sì | Indica se il dipendente ha il ruolo di supervisore. | Valori: truefalse |
enabled | boolean | Sì | Indica se il dipendente è abilitato nel sistema. | Valori: true — attivofalse — disattivo |
properties | jsonb | Sì | Oggetto JSONB con attributi aggiuntivi configurati per il cliente. Chiavi e significato non sono standard. | — |
divisions | jsonb | Sì | Array JSONB con lo storico delle unità operative di appartenenza. Ogni elemento contiene id, start, end e data; end = "" indica un’appartenenza attiva. | Esempio: [{"id": "87", "end": "2023-09-18", "start": "2020-07-20", "data": {}}] |
external_divisions | jsonb | Sì | Array JSONB con lo storico delle unità operative esterne. La struttura è analoga a divisions e lo stesso id può ricomparire in periodi diversi. | Esempio: [{"id": "41", "end": "2022-11-01", "start": "2022-06-01", "data": {}}] |
positions | jsonb | Sì | Array JSONB con lo storico delle posizioni o ruoli lavorativi del dipendente. end = "" indica una posizione attiva. | — |
skills | jsonb | Sì | Array JSONB con competenze, abilitazioni o gruppi associati al dipendente nel tempo. Più skill possono essere attive contemporaneamente. | — |
sections | jsonb | Sì | Array JSONB con lo storico delle sezioni di appartenenza del dipendente. | — |
contracts | jsonb | Sì | Array JSONB con lo storico dei contratti. Oltre alle date di validità, data può contenere costo orario, giorni lavorativi settimanali, minuti settimanali e percentuale part-time. | Esempio: [{"id": "C_40.00h_5gg", "end": "", "start": "2020-02-14", "data": {"hourly_cost": null, "working_days": 5, "minutes_per_week": 2400, "parttime_percentage": null}}] |
Struttura dei campi JSONB
properties
Oggetto con proprietà custom configurate per cliente. Le chiavi principali variano in base alla configurazione del cliente.
Struttura di divisions
Array di oggetti. unità operative di appartenenza del dipendente nel tempo. end = '' indica appartenenza attiva.
| Proprietà | Significato |
|---|---|
id | ID della unità operativa (riferimento alla tabella division) |
start | Data inizio appartenenza (YYYY-MM-DD) |
end | Data fine. Stringa vuota '' indica attivo. |
data | Oggetto dati aggiuntivi (può essere vuoto ) |
Esempio:
[
{
"id": "87",
"end": "2023-09-18",
"start": "2020-07-20",
"data": {}
}
]
Struttura di external_divisions
Array di oggetti. unità operative esterne di appartenenza del dipendente. Struttura identica a divisions. Può contenere più record con lo stesso id in periodi diversi.
| Proprietà | Significato |
|---|---|
id | ID della unità operativa esterna |
start | Data inizio (YYYY-MM-DD) |
end | Data fine. Stringa vuota '' indica attivo. |
data | Oggetto dati aggiuntivi (può essere vuoto ) |
Esempio:
[
{
"id": "41",
"end": "2022-11-01",
"start": "2022-06-01",
"data": {}
}
]
Struttura di positions
Array di oggetti. Posizioni o ruoli lavorativi ricoperti dal dipendente nel tempo. end = '' indica posizione attiva.
| Proprietà | Significato |
|---|---|
id | Nome della posizione |
start | Data inizio (YYYY-MM-DD) |
end | Data fine. Stringa vuota '' indica attivo. |
Struttura di skills
Array di oggetti. Competenze, abilitazioni o gruppi di appartenenza del dipendente. end = '' indica skill attiva. Un dipendente può avere più skill attive contemporaneamente.
| Proprietà | Significato |
|---|---|
id | Nome della skill o gruppo |
start | Data inizio (YYYY-MM-DD) |
end | Data fine. Stringa vuota '' indica attivo. |
Struttura di sections
Array di oggetti. Sezioni di appartenenza del dipendente.
| Proprietà | Significato |
|---|---|
id | Codice sezione |
start | Data inizio (YYYY-MM-DD) |
end | Data fine. Stringa vuota '' indica attivo. |
Struttura di contracts
Array di oggetti. Storico dei contratti del dipendente nel tempo.
| Proprietà | Significato |
|---|---|
id | Identificativo/codice del contratto (es. 'C_40.00h_5gg') |
start | Data inizio (YYYY-MM-DD) |
end | Data fine (stringa vuota oppure '7999-01-01' se indeterminato) |
data.hourly_cost | Costo orario associato al contratto |
data.working_days | Giorni lavorativi settimanali previsti |
data.minutes_per_week | Minuti settimanali previsti dal contratto |
data.parttime_percentage | Percentuale di part-time (null se full-time o non specificato, può essere null anche se il contratto è part time.) |
Esempio:
[
{
"id": "C_40.00h_5gg",
"end": "",
"start": "2020-02-14",
"data": {
"hourly_cost": null,
"working_days": 5,
"minutes_per_week": 2400,
"parttime_percentage": null
}
}
]
Note operative
I campi JSONB contengono storico. Se una query estrae tutti gli elementi senza filtrare l’intervallo di validità, lo stesso dipendente può comparire più volte.
divisions,external_divisions,positions,skills,sectionsecontractssono storicizzati all’interno di array JSONB.- Per
divisions,external_divisions,positions,skillsesections,si usaend = ''per indicare un’associazione attiva. - Per
contracts, una data finale vuota oppure7999-01-01può rappresentare un contratto senza una fine ordinaria, dipende dal sistema con cui StaffRoster è integrato. propertiese i valori delle skill sono client-specific.
division
Anagrafica della struttura organizzativa. Ogni riga rappresenta una unità operativa identificata dal proprio centro di costo e collegabile alla unità operativa madre tramite parent.
Granularità: Una riga per unità operativa organizzativa. Ogni riga rappresenta un nodo della gerarchia aziendale a tre livelli: azienda radice, unità produttiva, area operativa.
Quando usarla: Usare questa tabella per tradurre i codici di unità operativa/centro di costo in nomi e per ricostruire la gerarchia organizzativa. Le sezioni interne sono memorizzate nel campo JSONB sections.
Relazioni
| Tabella collegata | Condizione di join | Significato |
|---|---|---|
employee (divisions JSONB) | jsonb_array_elements(employee.divisions)->>'id' = division.costcenter | Le unità operative di appartenenza dei dipendenti in employee.divisions referenziano costcenter |
employee (sections JSONB) | jsonb_array_elements(division.sections)->>'costCenter' = jsonb_array_elements(employee.sections)->>'id' | Le sezioni dei dipendenti referenziano le unità operative tramite employee.sections.id = division.sections.costCenter |
shift | shift.division = division.costcenter | I turni sono associati a una unità operativa tramite costcenter |
justification | justification.costcenter @> to_jsonb(division.costcenter) | I giustificativi possono essere associati a un centro di costo corrispondente a una unità operativa |
Campi
| Campo | Tipo | Nullable | Descrizione | Dettagli |
|---|---|---|---|---|
costcenter | varchar | Sì | Identificativo della unità operativa e chiave primaria. È il codice richiamato da diversi campi di unità operativa/centro di costo nelle altre tabelle. | Chiave primaria |
name | varchar | Sì | Nome leggibile della unità operativa. | — |
parent | varchar | Sì | Codice costcenter della unità operativa padre nella gerarchia organizzativa. | — |
properties | jsonb | Sì | Oggetto JSONB con informazioni aggiuntive della unità operativa. Le proprietà dipendono dalla configurazione del cliente. | — |
tags | jsonb | Sì | Array JSONB di etichette che classificano la unità operativa. | — |
sections | jsonb | Sì | Array JSONB di sezioni interne alla unità operativa. Ogni elemento contiene nome, stato di abilitazione e centro di costo della sezione. | — |
Struttura dei campi JSONB
properties
Oggetto contenente informazioni aggiuntive relative alla unità operativa, come area e identificativi del punto vendita.
tags
Array di stringhe. Etichette che identificano il tipo operativo della unità operativa.
Struttura di sections
Array di oggetti. Ogni oggetto rappresenta una sezione appartenente a questa unità operativa, con nome, flag di abilitazione e centro di costo associato.
| Proprietà | Significato |
|---|---|
name | Nome della sezione |
enabled | Booleano, indica se la sezione è attiva |
costCenter | Id/centro di costo della sezione (stringa) |
Note operative
parentconsente di risalire alla unità operativa madre tramite un self-join sudivision.costcenter.- Le sezioni interne sono nel JSONB
sections;sections[].costCenterè il codice usato per collegare le sezioni del dipendente.
clocking
Registro delle singole timbrature. Ogni riga corrisponde a un evento rilevato o inserito manualmente, con timestamp preciso, dispositivo e flag di validità.
Granularità: Una riga per timbratura. Ogni riga rappresenta un singolo evento di timbratura di un dipendente: entrata, uscita, inizio pausa o fine pausa. Un dipendente ha più timbrature per giorno.
Quando usarla: Usare clocking per analizzare il dettaglio degli eventi di presenza: sequenza delle timbrature, inserimenti manuali, eventi invalidati o anomalie. Per i totali giornalieri già calcolati è normalmente più semplice usare shift.
Relazioni
| Tabella collegata | Condizione di join | Significato |
|---|---|---|
employee | clocking.employee = employee.id | Dipendente che ha effettuato la timbratura |
shift | clocking.employee = shift.employee AND clocking.day = shift.day | Turno del dipendente nello stesso giorno |
Campi
| Campo | Tipo | Nullable | Descrizione | Dettagli |
|---|---|---|---|---|
employee | varchar | Sì | Matricola del dipendente che ha effettuato la timbratura. Si collega a employee.id. | — |
day | date | Sì | Data della timbratura; è il riferimento pratico per filtri per periodo. | Formato: YYYY-MM-DD |
ts | timestamp | Sì | Timestamp esatto dell’evento di timbratura. | Formato: YYYY-MM-DD HH:MM:SS.000 |
action | varchar | Sì | Codice/tipo dell’evento di timbratura. | — |
clock | varchar | Sì | Identificativo del dispositivo o terminale usato per la timbratura. | Esempio: SR-07022152, SR-07088236 |
manual | boolean | Sì | Indica se la timbratura è stata inserita manualmente (true) invece di essere acquisita automaticamente (false). | Valori: true — manualefalse — automatica |
enabled | boolean | Sì | Indica se la timbratura è attiva/valida. Un valore false può rappresentare un evento annullato o invalidato. | Valori: true — attivafalse — disattivata |
ingress | boolean | Sì | Flag che distingue gli eventi di ingresso in turno (true) dagli eventi non classificati come ingresso (false). | Valori: true — ingressofalse — uscita |
Note operative
Un dipendente può avere molte timbrature nello stesso giorno. Non sommare misure provenienti da shift dopo un join diretto con clocking senza gestire la moltiplicazione delle righe.
- Usare
enabledper distinguere le timbrature attive da quelle annullate/invalidate, quando l’analisi richiede solo eventi validi.
breakdown
Scomposizione analitica delle ore giornaliere del dipendente. Ogni riga rappresenta una singola componente della giornata, con causale, fascia oraria, durata ed eventuale indicazione di anomalia.
Granularità: Una riga per componente di breakdown giornaliero per dipendente. Rappresenta la scomposizione delle ore di una giornata lavorativa nelle sue componenti: ore ordinarie, assenze, aggiunte, anomalie. Un dipendente può avere più righe per lo stesso giorno.
Quando usarla: Usare breakdown quando serve capire da quali componenti è formato il totale giornaliero. Per i soli totali di ore ordinarie, assenze e straordinari è preferibile shift.
Relazioni
| Tabella collegata | Condizione di join | Significato |
|---|---|---|
employee | breakdown.employee = employee.id | Dipendente a cui appartiene il breakdown |
shift | breakdown.employee = shift.employee AND breakdown.day = shift.day | Turno del dipendente nello stesso giorno |
justification | breakdown.employee = justification.employee AND breakdown.day = justification.day AND breakdown.cause = justification.cause | Giustificativo corrispondente per la stessa causale |
Campi
| Campo | Tipo | Nullable | Descrizione | Dettagli |
|---|---|---|---|---|
employee | varchar | Sì | Matricola del dipendente a cui appartiene la componente di breakdown. Si collega a employee.id. | — |
day | date | Sì | Data effettiva della giornata lavorativa a cui appartiene la componente. | Formato: YYYY-MM-DD |
relday | date | Sì | Data contrattuale di riferimento a cui viene imputata la componente. Di solito coincide con day, ma può differire, ad esempio per turni a cavallo della mezzanotte o registrazioni imputate a una diversa giornata contrattuale. | Formato: YYYY-MM-DD |
type | varchar | Sì | Categoria generale della componente di breakdown. | — |
cause | varchar | Sì | Causale di dettaglio che identifica la natura della componente oraria. | — |
start | timestamp | Sì | Timestamp di inizio della componente. | Formato: YYYY-MM-DD HH:MM:SS.000 |
end | timestamp | Sì | Timestamp di fine della componente. | Formato: YYYY-MM-DD HH:MM:SS.000 |
duration | int2 | Sì | Durata della componente, in minuti. | Unità: minuti |
anomalous | boolean | Sì | Indica se la componente è considerata anomala e richiede verifica o intervento. | Valori: true — anomalofalse — normale |
costcenter | jsonb | Sì | Array JSONB dei centri di costo associati alla componente; può contenerne più di uno. | — |
Struttura dei campi JSONB
costcenter
Array di stringhe. Centri di costo associati al breakdown. Può contenere più centri di costo.
Note operative
Sono possibili più righe per dipendente e giorno. La colonna relday può differire da day in casi particolari; scegliere esplicitamente quale data rappresenta il criterio temporale dell’analisi.
durationè in minuti.- Per collegare un breakdown a un giustificativo con maggiore precisione si usano condizioni su
employee,dayecause. costcenterpuò contenere più centri di costo nello stesso array JSONB.
balance
Dati di pianificazione e bilanciamento del personale. Ogni riga confronta fabbisogno e disponibilità per centro di costo, giorno, fascia oraria, skill, posizione e riferimento al turno.
Granularità: Una riga per combinazione di costcenter, division, shift, giorno, step (fascia oraria), skill e position, che rappresenta il fabbisogno e la disponibilità di personale in quell'intervallo.
Quando usarla: Usare questa tabella per analisi di copertura del fabbisogno: personale richiesto, minimo, previsto e disponibile nelle diverse fasce orarie.
Relazioni
| Tabella collegata | Condizione di join | Significato |
|---|---|---|
division | balance.costcenter = division.costcenter |
Campi
| Campo | Tipo | Nullable | Descrizione | Dettagli |
|---|---|---|---|---|
costcenter | varchar | Sì | Centro di costo a cui si riferisce il dato di bilanciamento. Si collega a division.costcenter. | — |
division | varchar | Sì | Codice o descrizione di unità operativa riportato nella riga. | — |
shift | varchar | Sì | Riferimento al turno usato nel dato di pianificazione (shift-driven). | — |
day | date | Sì | Data di riferimento del fabbisogno/disponibilità. | Formato: YYYY-MM-DD |
step | timestamp | Sì | Timestamp della fascia o dello slot orario all’interno della giornata. | — |
skill | varchar | Sì | Competenza richiesta o associata alla riga. Fa riferimento ai valori usati in employee.skills[].id. | — |
position | varchar | Sì | Posizione o ruolo richiesto per la fascia considerata. | Esempio: Addetto |
request | int4 | Sì | Numero di persone richieste/necessarie nello slot indicato da step. | — |
request_min | int4 | Sì | Soglia minima di personale richiesta nello slot. | — |
request_forecast | int4 | Sì | Previsione del fabbisogno di personale, distinta dalla richiesta pianificata in request. | — |
available | int4 | Sì | Numero di persone disponibili nello slot. | — |
Note operative
requestrappresenta il fabbisogno pianificato/effettivo;request_minla soglia minima;request_forecastla previsione;availablela disponibilità.skillrichiama i valori usati negli elementiemployee.skills[].id.
activity
Registro delle attività operative svolte dai dipendenti. Ogni riga descrive una singola attività con fascia oraria, durata, centro di costo, eventuale risorsa associata e flag di produttività.
Granularità: Una riga per attività svolta da un dipendente in un giorno. Ogni riga rappresenta una singola attività con fascia oraria precisa. Un dipendente può avere più attività nello stesso giorno.
Quando usarla: Usare questa tabella per analizzare cosa è stato svolto durante il turno e per quanto tempo. I nomi delle attività e molte proprietà sono specifici per cliente.
Relazioni
| Tabella collegata | Condizione di join | Significato |
|---|---|---|
employee | activity.employee = employee.id | Dipendente che ha svolto l'attività |
shift | activity.employee = shift.employee AND activity.day = shift.day | Turno del dipendente nello stesso giorno |
Campi
| Campo | Tipo | Nullable | Descrizione | Dettagli |
|---|---|---|---|---|
employee | varchar | Sì | Matricola del dipendente che ha svolto l’attività. Si collega a employee.id. | Esempio: 1745, 60030, 1555, 1188, 362, 51 |
day | date | Sì | Data in cui è stata svolta l’attività. | Formato: YYYY-MM-DD |
name | varchar | Sì | Nome dell’attività svolta. I valori sono definiti dal cliente e possono cambiare tra installazioni. | — |
costcenter | jsonb | Sì | Centro di costo associato all’attività, memorizzato come JSONB. Può essere un'unità operativa oppure una sezione. | — |
activitycostcenter | varchar | Sì | Il centro di costo associato direttamente all'attività. | — |
start | timestamp | Sì | Timestamp di inizio dell’attività. | Formato: YYYY-MM-DD HH:MM:SS.000 |
end | timestamp | Sì | Timestamp di fine dell’attività. | Formato: YYYY-MM-DD HH:MM:SS.000 |
duration | int2 | Sì | Durata dell’attività in minuti, calcolata a monte e concettualmente equivalente alla differenza tra end e start. | Unità: minuti |
resource | varchar | Sì | Risorsa associata all’attività. | — |
resource_type | varchar | Sì | Categoria generale della risorsa associata all’attività. | — |
properties | jsonb | Sì | Oggetto JSONB con proprietà aggiuntive dell’attività. La struttura è variabile e specifica per cliente. | — |
prod | bool | Sì | Indica se l’attività è considerata produttiva. | Valori: truefalse |
Note operative
nameepropertiessono specifici per cliente; verificare i valori reali prima di costruire classificazioni rigide.durationè in minuti.
Pattern PostgreSQL utili
Filtrare un elemento in un array JSONB
Per verificare la presenza di un valore in un campo JSONB usare gli operatori JSONB appropriati. Quando serve accedere agli attributi interni di ogni elemento, espandere l’array:
SELECT
e.id,
skill_item ->> 'id' AS skill,
skill_item
FROM public.employee AS e
CROSS JOIN LATERAL jsonb_array_elements(e.skills) AS s(skill_item);
Recuperare solo gli elementi storici validi in una data
Gli array storicizzati contengono date come testo nel JSONB. Il filtro deve considerare sia start sia end, convertendo esplicitamente in date quando necessario. La regola precisa dipende dal campo; una stringa vuota rappresenta fine aperta.
Confrontare una riga con la precedente
Le Window Functions permettono confronti temporali senza self-join. Pattern generico:
SELECT
employee,
day,
ord,
LAG(ord) OVER (PARTITION BY employee ORDER BY day) AS previous_ord
FROM public.shift;
Esempi
Esempio 1
Descrizione
Contratti dei dipendenti che hanno fatto pause più lunghe di un'ora
Query SQL
SELECT
e.id AS employee_id,
e.first_name,
e.last_name,
c.contract->>'id' AS contract_id
FROM shift s
JOIN employee e
ON e.id = s.employee
LEFT JOIN LATERAL (
SELECT contract
FROM jsonb_array_elements(COALESCE(e.contracts, '[]'::jsonb)) AS contract
WHERE contract->>'start' <= s.day::text
AND (
COALESCE(contract->>'end', '') = ''
OR contract->>'end' >= s.day::text
)
) AS c(contract)
ON TRUE
WHERE s.bduration > 60
GROUP BY
e.id,
e.first_name,
e.last_name,
c.contract->>'id'
ORDER BY
e.id;
Estratto del risultato
| employee_id | first_name | last_name | contract_id |
|---|---|---|---|
| 100 | GIANNI | ROSSI | C_40.00h_6gg |
| 156 | JOHN D | PATERNO | C_40.00h_6gg |
| 1568 | JEAN MARC | SIMONETTI | C_24.00h_3gg |
Esempio 2
Descrizione
Dipendenti che, al 3 Settembre 2026, ricoprono la posizione di addetto da almeno 10 anni.
Query SQL
SELECT
e.id,
e.first_name,
e.last_name,
(p->>'start')::date AS position_start
FROM employee AS e
CROSS JOIN LATERAL jsonb_array_elements(e.positions) AS p
WHERE e.enabled IS TRUE
AND p->>'id' = 'Addetto'
AND p->>'end' = ''
AND (p->>'start')::date <= DATE '2026-09-03' - INTERVAL '10 years';
Estratto del risultato
| id | first_name | last_name | position_start |
|---|---|---|---|
| 111 | GINO | GAROFALO | 2011-07-11 |
| 222 | FRANCESCA | FAGGIN | 2012-03-01 |
| 13 | ALICE | DE MARCHI | 2009-04-01 |
| 888 | MARIA LUISA | ANTONI | 2008-05-12 |
Esempio 3
Descrizione
Costo orario medio dei responsabili.
Query SQL
SELECT AVG(REPLACE(e.properties->'Costo Orario'->0->>'value', ',', '.')::numeric) AS average_hourly_cost
FROM employee e
WHERE e.supervisor IS TRUE;
Estratto del risultato
| average_hourly_cost |
|---|
| 11.0855555555555556 |
Esempio 4
Descrizione
Dipendenti hanno effettuato almeno 10 ore di straordinario raggruppati per mese nel 2026
Query SQL
WITH months AS (
SELECT generate_series(
'2026-01-01',
'2026-12-01',
INTERVAL '1 month'
)::date AS month
),
overtime AS (
SELECT
date_trunc('month', s.day::date)::date AS month,
s.employee,
SUM(s.ovt) AS overtime_minutes
FROM shift AS s
WHERE s.day::date >= '2026-01-01'
AND s.day::date < '2027-01-01'
GROUP BY date_trunc('month', s.day::date)::date, s.employee
HAVING SUM(s.ovt) >= 300
)
SELECT
m.month,
COUNT(DISTINCT st.employee) AS employee_count
FROM months m
LEFT JOIN overtime st
ON st.month = m.month
GROUP BY m.month
ORDER BY m.month;
Estratto del risultato
| month | employee_count |
|---|---|
| 2026-08-01 | 6 |
| 2026-09-01 | 1 |
Esempio 5
Descrizione
Per ogni unità operativa, mostrami il rank di 3 dipendenti in base al totale di ore lavorate nel 2026.
Query SQL
WITH employee_hours AS (
SELECT
s.division AS division_costcenter,
d.name AS division_name,
s.employee AS employee_id,
e.first_name,
e.last_name,
SUM(COALESCE(s.ord, 0) + COALESCE(s.ovt, 0) - COALESCE(s.abs, 0)) / 60.0 AS total_hours
FROM shift s
JOIN employee e
ON e.id = s.employee
LEFT JOIN division d
ON d.costcenter = s.division
WHERE s.day::date >= '2026-01-01'
AND s.day::date < '2027-01-01'
GROUP BY
s.division,
d.name,
s.employee,
e.first_name,
e.last_name
),
ranked_employees AS (
SELECT
division_costcenter,
division_name,
employee_id,
first_name,
last_name,
total_hours,
ROW_NUMBER() OVER (
PARTITION BY division_costcenter
ORDER BY total_hours DESC, employee_id
) AS employee_rank
FROM employee_hours
)
SELECT
division_costcenter,
division_name,
employee_rank,
employee_id,
first_name,
last_name,
total_hours
FROM ranked_employees
WHERE employee_rank <= 3
ORDER BY division_costcenter, employee_rank;
Estratto del risultato
| division_costcenter | division_name | employee_rank | employee_id | first_name | last_name | total_hours |
|---|---|---|---|---|---|---|
| 126 | Reparto A | 1 | 1628 | MARIO | DE CINTI | 389.00 |
| 126 | Reparto A | 2 | 1193 | MARIA | CABAS | 355.50 |
| 126 | Reparto A | 3 | 1597 | ROBERTA | PIRELLI | 353.50 |
| 128 | Reparto B | 1 | 845 | ANNA | NONI | 57.50 |
| 128 | Reparto B | 2 | 1811 | JEAN | CHINZA | 36.00 |
| 128 | Reparto B | 3 | 1383 | GIANNI | COSI | 12.00 |
| 154 | Reparto C | 1 | 704 | GIULIO | DELLOA | 430.50 |
| 154 | Reparto C | 2 | 1313 | DAVID | COSTRA | 405.00 |
| 154 | Reparto C | 3 | 1500 | BEN | GELLI | 328.00 |
Esempio 6
Descrizione
Le 5 skill più comuni tra i dipendenti
Query SQL
SELECT
skill->>'id' AS skill,
COUNT(DISTINCT e.id) AS employee_count
FROM employee e
CROSS JOIN LATERAL jsonb_array_elements(e.skills) AS skill
WHERE skill->>'end' = ''
GROUP BY skill->>'id'
ORDER BY employee_count DESC, skill
LIMIT 5;
Estratto del risultato
| skill | employee_count |
|---|---|
| Chiavi | 52 |
| Cassa | 45 |
| Taglio | 22 |
| Fresatura | 20 |
| Pulizia | 15 |
Esempio 7
Descrizione
Dipendenti con contratto full-time con più di 50h di assenza nel mese di Settembre 2026
Query SQL
SELECT
e.id AS employee_id,
e.first_name,
e.last_name,
SUM(s.abs) / 60.0 AS absence_hours
FROM employee e
JOIN shift s
ON s.employee = e.id
WHERE EXISTS (
SELECT 1
FROM jsonb_array_elements(e.contracts) AS c
WHERE (c->>'id' ILIKE 'C_40.00h%' OR (c->'data'->>'minutes_per_week')::int = 2400)
AND c->>'start' <= '2026-09-01'
AND (
c->>'end' = ''
OR c->>'end' >= '2026-09-30'
)
)
GROUP BY e.id, e.first_name, e.last_name
HAVING SUM(s.abs) > 3000
ORDER BY absence_hours DESC, e.last_name, e.first_name;
Estratto del risultato
| employee_id | first_name | last_name | absence_hours |
|---|---|---|---|
| 592 | ROB | ROGITU | 325.00 |
| 122 | SAN | PERRI | 277.00 |
| 895 | ANNA | IONICI | 253.00 |
Esempio 8
Descrizione
Dipendenti con contratto full-time con più di 50h di assenza nel mese di Settembre 2026
Query SQL
SELECT
b.day,
concat(to_char(b.step, 'HH24:MI'),'-',to_char(b.step + INTERVAL '30 minutes', 'HH24:MI')),
b.request - b.available as "offset"
FROM balance b
WHERE b.division = '2'
AND b."day" BETWEEN '2026-10-01' AND '2026-10-07'
AND b.request > b.available;
Estratto del risultato
| day | concat | offset |
|---|---|---|
| 2026-10-01 | 11:00-11:30 | 1 |
| 2026-10-01 | 09:30-10:00 | 1 |
| 2026-10-01 | 14:00-14:30 | 2 |
| 2026-10-01 | 10:00-10:30 | 1 |
| 2026-10-01 | 12:30-13:00 | 2 |
| 2026-10-01 | 13:30-14:00 | 2 |
HR Analytics da StaffRoster
È possibile eseguire estrazioni direttamente da StaffRoster tramite la pagina Console Analytics e esportare i dati in PDF/XLS.
Se il Modulo AI Report è attivo è anche possibile definire reportistica utilizzando il database di HR Analytics.
AI Report su HR Analytics
Tipi di report possibili:
JSON da AnalyticsPDF da AnalyticsXLS da Analytics
I report derivanti dal database di Analytics saranno disponibile per i soli utenti che possono vedere dati fuori dal proprio cono di visibilità.
Report parametrizzati
I placeholder sono valori racchiusi tra doppie parentesi graffe e vengono sostituiti prima dell'esecuzione dello script del report. Le chiavi distinguono maiuscole e minuscole e possono contenere soltanto lettere, numeri e _.
Usare un parametro obbligatorio con la sintassi {{CHIAVE}}:
WHERE stato = '{{STATO}}'
Per rendere il parametro facoltativo, dichiarare il valore di default dopo ::
WHERE tipo = '{{TIPO:ORDINARIO}}'
Quando si salva il report, l'editor rileva i placeholder e mostra i parametri nella sezione Parametri. Per ogni parametro si possono indicare valori possibili, separandoli con una virgola. In fase di esecuzione l'utente trova un selettore se sono stati configurati valori possibili; altrimenti può digitare il valore. I parametri senza default sono obbligatori, mentre lasciando vuoto un parametro con default viene usato il valore dichiarato nello script.
La stessa chiave può comparire più volte, ma deve avere sempre la stessa forma: non è possibile alternare {{CHIAVE}} e {{CHIAVE:default}}, né dichiarare default diversi. Se sono presenti valori possibili, il default deve appartenere alla lista.
Il valore di un parametro utente è un valore semplice, non una lista SQL: nel codice SQL le virgolette e gli altri elementi di sintassi restano a carico dello script, come nell'esempio precedente. I valori accettati contengono lettere, numeri, spazi e i caratteri _, ., /, :, -.
Parametri speciali
I parametri speciali sono riconosciuti automaticamente dall'editor e popolati dal backend. Non appaiono tra i normali campi parametro.
| Placeholder | Valore sostituito | Interfaccia di esecuzione | Uso previsto |
|---|---|---|---|
{{FROM}} | Data iniziale del periodo in formato yyyy-MM-dd. | Selettore periodo. | Usarlo insieme a {{TO}}. |
{{TO}} | Data finale del periodo in formato yyyy-MM-dd. | Selettore periodo. | Usarlo insieme a {{FROM}}. |
{{DIVISIONS}} | Centri di costo dei reparti selezionati, ad esempio ('CDC1','CDC2'). | Selettore reparti. | Usarlo direttamente in una clausola IN. |
{{EMPLOYEES}} | Matricole degli addetti trovati con i filtri, ad esempio ('123','AS2'). | Selettore reparti e filtri addetti. | Usarlo direttamente in una clausola IN. |
DIVISIONS ed EMPLOYEES non ammettono un default: usare esclusivamente {{DIVISIONS}} e {{EMPLOYEES}}.
Anche FROM e TO vanno dichiarati nella forma senza default e sempre in coppia.
Nei report normali rimangono disponibili i filtri ordinari già previsti. Nei report BI, invece, il periodo è visibile se sono presenti entrambi FROM e TO; il selettore reparti è visibile con DIVISIONS oppure EMPLOYEES; i filtri addetti sono visibili con EMPLOYEES.
Esempio
Il seguente frammento usa il periodo, il reparto, gli addetti e un parametro definito dall'autore:
SELECT matricola, data, centro_costo
FROM presenze
WHERE data >= '{{FROM}}'
AND data < '{{TO}}'
AND centro_costo IN {{DIVISIONS}}
AND matricola IN {{EMPLOYEES}}
AND stato = '{{STATO:ATTIVO}}'
I valori di DIVISIONS ed EMPLOYEES sono già serializzati dal backend come insiemi SQL, comprese le virgolette e l'escape degli apostrofi: non devono essere aggiunte altre virgolette né parentesi attorno al placeholder. L'esecuzione viene rifiutata se non è selezionato alcun reparto per DIVISIONS oppure se la ricerca di EMPLOYEES non restituisce addetti con matricola valida.