Skip to main content

Motore di forecasting e ricalcolo

Input canonici​

Per ogni mese/giorno nell'orizzonte il motore usa:

  • periodo e domanda ore dei progetti;
  • risorse associate e validità dell'associazione;
  • compatibilità tra città della sede del progetto e sede della risorsa valida nel periodo;
  • calendario lavorativo, orario e periodi di impiego;
  • monte ferie e piano ferie, distinguendo ferie possibili e già pianificate/approvate;
  • allocazioni su tutti i progetti dell'organizzazione;
  • limite ore progetto-risorsa (default 1720) e ore contrattuali dei freelancer;
  • costi reali o standard validi nel periodo;
  • consuntivi fino al relativo cursore e mesi consegnati immutabili.

Vincoli hard​

  1. Ore assegnate a una risorsa nel periodo ≤ capacità lavorativa disponibile meno ferie pianificate/approvate e altri impegni.
  2. Somma delle allocazioni della risorsa su tutti i progetti ≤ capacità: nessuna over-allocation.
  3. Ore di una risorsa su un progetto in un anno solare ≤ max_hours_per_resource. Corretto il 18 agosto 2026: questa riga diceva «ore cumulative risorsa-progetto», cioè sull'intera vita del progetto. Il committente ha confermato che 1720 sono ore/anno/risorsa, e che il valore è un default sovrascrivibile per progetto — su un progetto triennale le due letture davano risultati molto diversi.
  4. Allocazioni solo dentro periodo progetto, rapporto di lavoro e associazione.
  5. Per un progetto con sede, allocazioni solo a risorse assegnate a una sede della stessa città nel periodo; un progetto senza sede non applica il vincolo geografico.
  6. Mesi consegnati non modificabili.
  7. Per costo standard deve esistere una tariffa univoca ente + macro-livello + data; per costo reale una tariffa dipendente univoca. Se manca o è ambigua il calcolo si ferma e riporta un warning: non ricade sul costo reale e non mette zero. Oggi fa entrambe le cose, in silenzio — vedi Difetti noti.
  8. Freelancer: usare ore contrattuali, senza applicare il normale calcolo predittivo e consuntivo automatico.

Obiettivi​

Ordine consigliato, da confermare con il committente:

  1. massimizzare la copertura della domanda dei progetti;
  2. evitare over-allocation e violazioni dei limiti;
  3. minimizzare scostamenti rispetto al piano precedente per stabilità;
  4. rispettare priorità/scadenze progetto;
  5. distribuire il carico in modo uniforme, preservando una riserva ferie configurabile;
  6. minimizzare sforamenti di budget come obiettivo secondario, senza nascondere domanda non coperta.

Se non esiste una soluzione completa, il motore non deve produrre silenziosamente numeri falsamente validi: salva uno scenario INFEASIBLE/PARTIAL con ore scoperte, risorse sature e vincoli responsabili.

Monte ferie e piano ferie​

  • Ferie pianificate/approvate: riducono direttamente la capacità nei periodi indicati.
  • Ferie disponibili ma non pianificate: alimentano una riserva prudenziale distribuita sull'orizzonte secondo policy configurabile.
  • Il forecast mostra capacità lorda, ferie pianificate, riserva ferie, capacità netta e allocazione.
  • Se il piano ferie cambia, si ricalcola dal primo periodo interessato.

Cosa se ne realizza in Fase 2 — solo il primo punto: il piano mensile riduce la capacità dei mesi indicati. Non esistono stati di approvazione, quindi «pianificate» e «approvate» qui sono la stessa cosa. La riserva per le ferie disponibili ma non pianificate dipende dal modello di capacità, che è rimandato: vedi Fase 2.

Trigger e dirty range​

EventoInizio intervallo da ricalcolare
Nuovo/chiuso/modificato progettoPrima data modificata non consegnata
Assunzione/cessazione o cambio orarioData di efficacia
Associazione/rimozione risorsa-progettoInizio/fine associazione modificata
Estensione/riduzione progettoPrima data coinvolta
Costo o tariffa standardvalid_from
Ferie/balance/calendarioPrima giornata interessata
Modifica retroattiva consuntivoMese modificato
Limite ore risorsa-progettoPrimo mese futuro/non consegnato
Cambio sede progetto o sede storica risorsaPrima data in cui cambia la compatibilità città

Gli eventi vengono aggregati nel minimo intervallo dirty. Il job acquisisce un lock per organizzazione/scenario, legge uno snapshot coerente, calcola e pubblica atomicamente una nuova versione. Un evento arrivato durante il calcolo programma una nuova run, senza perdere invalidazioni.

Cosa di questa tabella esiste davvero, al 18 agosto 2026​

La tabella qui sopra descrive il disegno di arrivo, non ciò che gira. Leggerla come stato dei fatti porta a credere che una modifica scateni un ricalcolo, e a guardare numeri vecchi convinti che siano freschi.

I trigger reali sono due:

cosa scatenacosa ricalcola
import del foglio presenzeil consuntivo di quel mese, poi il forecast del periodo successivo
POST /employees/reconcilei mesi impattati dalla riconciliazione di un nominativo

Tutto il resto è manuale, per decisione del committente: un bottone nella scheda del progetto rifà il consuntivo di quel progetto dal suo cursore di consegna al mese consuntivato. Cambiare un'assegnazione o spostare una persona non ricalcola niente da solo, e niente segnala che quei numeri siano vecchi — è il limite noto di questa scelta, e il posto dove il dirty range servirà.

Il primo mese previsto​

Il forecast non parte dal mese corrente ma dal mese successivo al cursore del consuntivo. La differenza si vede quando l'import è in ritardo: con il consuntivo a maggio e oggi 18 agosto, giugno e luglio non sono consuntivati — quindi sono previsione, anche se stanno nel passato. Partendo da oggi, il ricalcolo cancellava le loro righe e non le riscriveva: due mesi spariti, senza una riga a dirlo.

Solo in assenza di qualunque import si ricade sul mese corrente, che è l'unico riferimento disponibile.

Versionamento e spiegabilità​

Ogni forecast_run conserva:

  • versione algoritmo e parametri;
  • intervallo, trigger/eventi e utente correlato;
  • hash/snapshot logico degli input;
  • stato, tempi e metriche;
  • risultati per progetto/risorsa/periodo;
  • warning, vincoli violati e domanda scoperta;
  • riferimento alla versione precedente sostituita.

Sviluppo incrementale​

  1. V1 deterministica: capacità mensile, ferie approvate, vincoli hard e ricalcolo manuale/automatico idempotente.
  2. V2 globale: ottimizzazione su tutti i progetti, domanda scoperta e stabilità rispetto al piano precedente.
  3. V3 scenari: simulazioni what-if, priorità, riserva ferie evoluta e confronto/approvazione scenari.

Prima della scelta della libreria/solver creare dataset sintetici “golden” con casi fattibili, impossibili, variazioni retroattive, costi temporali e freelancer.