Blueprint Incarichi Tecnici - Release 1¶
Obiettivo¶
Release 1 introduce un layer operativo centrale per governare gli incarichi tecnici senza sostituire i verticali esistenti.
Il modulo deve permettere di:
- creare un incarico tecnico manuale;
- assegnare un tecnico;
- distinguere chi gestisce l'incarico da chi lo esegue;
- controllare lo stato con transizioni esplicite;
- tracciare ogni variazione rilevante;
- filtrare gli incarichi per tenant, stato, tecnico, gestore e scadenza.
In Release 1 il calendario viene solo predisposto a livello schema. La sincronizzazione automatica calendario/incarico resta fuori scope.
Perimetro¶
Incluso:
- modelli SQLAlchemy;
- migrazione Alembic;
- service layer transazionale;
- view FAB iniziale;
- menu
Operativo -> Incarichi Tecnici; - permessi base;
- audit log;
- filtri operativi principali.
Fuori scope Release 1:
- automazioni calendario;
- collegamento automatico da ticket/RAS/DVR/checklist;
- rapportini legati direttamente all'incarico;
- kanban;
- dashboard carico tecnici;
- notifiche email.
Tabelle¶
technical_assignment¶
Contenitore principale dell'incarico.
Campi:
idinteger primary keytenant_keystring(64), not null, indexcodestring(40), not nulltipo_incaricostring(40), not nullsource_typestring(80), nullablesource_idinteger, nullablecliente_idinteger, nullablecondominio_idinteger, nullabletitlestring(255), not nulldescriptiontext, nullablestatostring(40), not null, defaultda_assegnareprioritastring(24), not null, defaultmediamanager_user_idinteger, nullable, FKab_user.idassigned_user_idinteger, nullable, FKab_user.idcreated_by_idinteger, nullable, FKab_user.idclosed_by_idinteger, nullable, FKab_user.idplanned_startdatetime, nullableplanned_enddatetime, nullabledue_datedate, nullableopened_atdatetime, nullableassigned_atdatetime, nullablestarted_atdatetime, nullablecompleted_atdatetime, nullablecancelled_atdatetime, nullablenotes_internaltext, nullableclosure_notetext, nullablecreated_atdatetime, not nullupdated_atdatetime, not null
Vincoli e indici:
- unique
(tenant_key, code) - index
(tenant_key, stato) - index
(tenant_key, assigned_user_id, stato) - index
(tenant_key, manager_user_id, stato) - index
(tenant_key, due_date) - index
(tenant_key, tipo_incarico) - index
(tenant_key, source_type, source_id)
technical_assignment_log¶
Storico operativo dell'incarico.
Campi:
idinteger primary keytenant_keystring(64), not null, indexassignment_idinteger, not null, FKtechnical_assignment.idevent_typestring(60), not nullold_valuetext, nullablenew_valuetext, nullablenotetext, nullablecreated_by_idinteger, nullable, FKab_user.idcreated_atdatetime, not null
Indici:
- index
(tenant_key, assignment_id) - index
(tenant_key, event_type) - index
(tenant_key, created_at)
Eventi minimi:
createdstatus_changedassigned_user_changedmanager_changedpriority_changedplanning_changedclosedcancelled
technical_assignment_event¶
Ponte futuro tra incarico ed eventi calendario.
Campi:
idinteger primary keytenant_keystring(64), not null, indexassignment_idinteger, not null, FKtechnical_assignment.idcalendar_event_idinteger, nullableevent_typestring(40), nullablestarts_atdatetime, nullableends_atdatetime, nullablestatusstring(40), not null, defaultplannedcreated_atdatetime, not nullupdated_atdatetime, not null
Indici:
- index
(tenant_key, assignment_id) - index
(tenant_key, calendar_event_id) - index
(tenant_key, starts_at)
Enumerazioni¶
Tipi Incarico¶
Costanti iniziali:
interventorasdvrchecklistsopralluogoformazionealtro
Stati¶
Costanti iniziali:
draftda_assegnareassegnatoda_pianificareprogrammatoin_lavorazionein_attesasospesocompletatoannullato
Priorita¶
Costanti iniziali:
bassamediaaltaurgente
Stato Macchina¶
Transizioni ammesse:
draft -> da_assegnare
da_assegnare -> assegnato
assegnato -> da_pianificare
assegnato -> programmato
da_pianificare -> programmato
programmato -> in_lavorazione
in_lavorazione -> in_attesa
in_lavorazione -> sospeso
in_lavorazione -> completato
in_attesa -> programmato
in_attesa -> in_lavorazione
in_attesa -> annullato
sospeso -> da_pianificare
sospeso -> annullato
Stati terminali:
completatoannullato
Vincoli:
assegnatorichiedeassigned_user_id;programmatorichiedeassigned_user_ideplanned_start;completatorichiedeclosure_noteo outcome minimo;annullatorichiede nota;- ogni transizione deve generare log.
Moduli e File Proposti¶
Percorso modulo:
app/modules/technical_assignments/
File:
app/modules/technical_assignments/__init__.py
app/modules/technical_assignments/models.py
app/modules/technical_assignments/services.py
app/modules/technical_assignments/views.py
app/templates/appbuilder/custom/technical_assignment_show.html
Migrazione:
migrations/versions/<revision>_add_technical_assignments.py
Classi SQLAlchemy¶
Classi:
TechnicalAssignmentTechnicalAssignmentLogTechnicalAssignmentEvent
Relazioni minime:
TechnicalAssignment.logsTechnicalAssignment.eventsTechnicalAssignment.managerTechnicalAssignment.assigned_userTechnicalAssignment.created_byTechnicalAssignment.closed_by
Service Layer¶
Il service layer e obbligatorio. Le view non devono modificare direttamente stato, assegnazioni o pianificazione senza passare dai servizi.
Funzioni iniziali:
create_assignment(...)
assign_technician(...)
change_status(...)
reschedule_assignment(...)
change_manager(...)
change_priority(...)
close_assignment(...)
cancel_assignment(...)
log_assignment_event(...)
Responsabilita:
- validare tenant;
- validare transizioni;
- aggiornare timestamp di processo;
- creare log;
- mantenere atomica ogni operazione.
Regole Service¶
create_assignment¶
Input minimo:
- tenant_key
- title
- tipo_incarico
- manager_user_id opzionale
- assigned_user_id opzionale
- created_by_id
Comportamento:
- genera
code; - imposta
opened_at; - stato iniziale:
assegnatoseassigned_user_idvalorizzato;- altrimenti
da_assegnare; - crea log
created; - crea log
assigned_user_changedse tecnico gia presente.
assign_technician¶
Vincoli:
- tecnico deve essere utente attivo del tenant;
- stati terminali non modificabili.
Comportamento:
- aggiorna
assigned_user_id; - imposta
assigned_atse vuoto; - se stato
da_assegnare, passa aassegnato; - logga cambio tecnico e cambio stato se avviene.
change_status¶
Vincoli:
- transizione presente nella matrice;
- vincoli stato rispettati;
- stati terminali non modificabili.
Comportamento:
- aggiorna stato;
- aggiorna timestamp collegato:
started_atperin_lavorazione;completed_ateclosed_by_idpercompletato;cancelled_atperannullato;- logga
status_changed.
reschedule_assignment¶
Vincoli:
planned_enddeve essere maggiore diplanned_start, se presente;- stati terminali non modificabili.
Comportamento:
- aggiorna pianificazione;
- se stato
assegnato, puo passare aprogrammatoquando esistono tecnico eplanned_start; - logga
planning_changed.
Permessi¶
Profili:
- admin tenant;
- gestore incarichi;
- tecnico.
Ruoli consigliati:
ROLE_PROFILE_ADMIN_TENANTROLE_PROFILE_GESTORE_INCARICHI- profili tecnici esistenti o ruolo tecnico tenant.
Regole:
- admin tenant: piena visibilita tenant;
- gestore incarichi: piena visibilita tenant e gestione operativa;
- tecnico: vede solo
assigned_user_id == current_user.id; - tutti i query scope filtrano sempre
tenant_key.
View FAB¶
Classe:
TechnicalAssignmentView(ModelView)
Route:
/technical-assignments
Menu:
Operativo -> Incarichi Tecnici
Colonne lista:
- code
- tipo_incarico
- title
- cliente_id
- stato
- priorita
- manager_user_id
- assigned_user_id
- planned_start
- due_date
- updated_at
Filtri:
- stato
- tipo_incarico
- priorita
- manager_user_id
- assigned_user_id
- cliente_id
- due_date
Filtri custom da aggiungere:
- senza tecnico;
- da pianificare;
- in ritardo.
Azioni iniziali:
- crea incarico;
- assegna tecnico;
- cambia stato;
- modifica pianificazione;
- chiudi;
- annulla.
Show View¶
La vista dettaglio deve mostrare:
- dati principali;
- responsabilita;
- pianificazione;
- origine;
- note interne;
- chiusura;
- storico log ordinato per data discendente.
Registrazione App¶
In app/__init__.py:
- import
TechnicalAssignmentView; appbuilder.add_view(...);- categoria
Operativo; - menu label
Incarichi Tecnici; - condizione modulo interventi o modulo dedicato
technical_assignments.
Per Release 1 si puo agganciare alla condizione menu_interventi_enabled_current_tenant, poi separare in feature dedicata.
In app/modules/iam/menu_runtime.py:
- aggiungere
incarichi tecnicialle voci operative forzate per tenant abilitati.
Migrazione Alembic¶
La migrazione deve:
- creare le tre tabelle;
- creare indici;
- creare FK verso
ab_user; - usare
tenant_keycoerente con il resto SafeOps; - essere idempotente dove ragionevole, seguendo lo stile delle migrazioni recenti.
Test Smoke Release 1¶
Test minimi:
- crea incarico manuale;
- verifica
codegenerato; - verifica log
created; - assegna tecnico;
- verifica stato
assegnato; - verifica log tecnico;
- prova passaggio a
programmatosenzaplanned_start, deve fallire; - imposta pianificazione;
- passa a
programmato; - passa a
in_lavorazione; - prova completamento senza nota finale, deve fallire;
- completa con nota;
- verifica stato terminale;
- prova modifica stato terminale, deve fallire;
- tecnico vede solo i propri incarichi;
- admin/gestore vede tutto il tenant.
Criteri di Accettazione¶
Release 1 e accettata quando:
- un incarico puo essere creato manualmente;
- ogni incarico e isolato per
tenant_key; - admin e gestore vedono tutto il tenant;
- tecnico vede solo i propri incarichi;
- assegnazione tecnico funziona;
- cambio stato e controllato;
- ogni cambio stato e assegnazione genera log;
- filtri senza tecnico, da pianificare e in ritardo funzionano;
- menu operativo e disponibile;
- nessuna automazione calendario e necessaria per completare il rilascio.
Note di Implementazione¶
- Evitare logica di workflow nelle view.
- Evitare automazioni sui verticali in Release 1.
- Non migrare dati ticket/interventi/RAS nella prima release.
- Tenere
source_typeesource_idnullable per supportare incarichi manuali. - Usare label italiane in UI, valori macchina stabili in DB.