Passa al contenuto principale

Dominio job β€” Panoramica sviluppatore

🎯 Cosa fa​

Il dominio job (workers & risks) gestisce anagrafica lavoratori, mansioni, ruoli aziendali, reparti e rischi. È il ponte logico tra reg (aziende) ed edu (formazione): da reg eredita il contesto azienda/sedi, verso edu determina quali corsi sono obbligatori tramite il cascade rischi.

Dominio di dimensione media: 13 tabelle tutte in scope.

πŸ—ΊοΈ Mappa moduli​

Database β€” TrainingHub.Database/job/​

AreaTabellaRuolo
Lavoratorijob.workersAnagrafica dipendenti
Lavoratorijob.workerJobHistoryStorico mansioni/ruoli/reparti
Mansionijob.jobsMansioni (con riskLevel e inheritsCompanyRisks)
Mansionijob.jobGroupsRaggruppamenti visuali di mansioni
Mansionijob.jobSubcategoriesN:N mansione ↔ sottocategoria azienda
Mansionijob.workersJobsN:N lavoratore ↔ mansione
Ruolijob.rolesRuoli aziendali (lavoratore, preposto, dirigente)
Strutturajob.departmentsReparti gerarchici (parentId)
Rischijob.risksAnagrafica rischi
Rischijob.riskLevelLivelli (1=basso, 2=medio, 3=alto)
Rischijob.atecoCodesCodici ATECO gerarchici (parentCode) con riskLevelId suggerito
Rischijob.companiesRisksRischi aziendali
Rischijob.jobsRisksRischi per mansione
Rischijob.workersRisksOverride/esclusione rischio per lavoratore
Compliancejob.vw_workerComplianceSummaryVista β€” rollup per-lavoratore: worstStatus + conteggi expired/missing/expiring/ok + minDaysRemaining. Filtrabile per companyId. Aggrega edu.vw_workerTrainingStatus

Service layer β€” TrainingHub.Shared/Services/​

FileRuolo
IRiskInheritanceService.cs / RiskInheritanceService.csCascade rischi ATECO β†’ azienda β†’ mansione β†’ lavoratore
ITrainingExpirationService.cs / TrainingExpirationService.csUsa i rischi del lavoratore per calcolare compliance (condiviso con edu)

QueryModifiers β€” TrainingHub.BackOffice/Services/QueryModifiers/job/​

FileScope
CompaniesRisksQueryModifier.csHook su companiesRisks β€” refresh rischi lavoratori dopo cambi rischio azienda

UI CRUD β€” TrainingHub.BackOffice/Components/CRUD/job/​

EntitΓ  CRUD standard:

  • Worker, WorkerJobHistory, WorkersData (vista aggregata)
  • Job, JobGroup, JobSubcategory, JobsData
  • WorkersJob (associazione)
  • Role, Department
  • Risk, RiskLevel, AtecoCode
  • CompaniesRisk, JobsRisk, WorkersRisk
  • WorkerEffectiveRisk β€” vista calcolata dei rischi effettivi del lavoratore (cascade applicato)
  • WorkerComplianceSummary β€” CRUD auto-generato sulla view vw_workerComplianceSummary (read-only). FK manuali su worker/company/role/department, badge stato in colonna worstStatus. Embed nel wizard CompanyFormPopup come step "ConformitΓ  formativa". Pattern descritto in Architettura β€” view β†’ CRUD

πŸ”§ API pubblica​

IRiskInheritanceService​

Propaga il livello di rischio ATECO β†’ azienda β†’ mansione β†’ lavoratore. Invocato da:

  • reg.CompaniesQueryModifier.PostExecutionQuery dopo update aziende β†’ cascade a workers.
  • job.CompaniesRisksQueryModifier dopo cambio rischi aziendali.
  • Extension method worker.UpdateRiskLevel(simpleCRUD, companyId?) per invocazione diretta.

ITrainingExpirationService​

Calcola compliance formativa combinando rischi del lavoratore (dominio job) con formazione ricevuta (dominio edu). Dettaglio in Logica applicativa edu.

🧩 Pattern chiave​

Cascade rischi​

Codice ATECO
└── riskLevelId suggerito
└── azienda.riskLevelId (default)
β”œβ”€β”€ jobs.riskLevelId (opzionale β€” override per mansione)
β”‚ └── jobs.inheritsCompanyRisks
β”‚ └── aggiunge i rischi companiesRisks ai rischi jobsRisks
└── workers.riskLevelId (staticizzato per lavoratore)
└── workersRisks (override singolo rischio + esclusioni)

Propagazione automatica:

  • Cambio ATECO azienda β†’ CompaniesQueryModifier β†’ UpdateRiskLevel
  • Cambio riskLevel azienda β†’ idem
  • Cambio companiesRisks β†’ CompaniesRisksQueryModifier β†’ ricalcolo
  • Cambio mansione lavoratore β†’ staticizzazione workers.riskLevelId

Storico mansioni​

workerJobHistory Γ¨ un snapshot storico: al cambio di mansione / ruolo / reparto di un lavoratore, un record viene inserito con startDate/endDate e i valori correnti di riskLevelId, roleId, departmentId. Permette audit temporale.

Vista WorkerEffectiveRisk​

Componente UI non-CRUD che mostra i rischi finali del lavoratore applicando il cascade (rischi azienda + mansione + override lavoratore, meno esclusioni). Utile per DVR e per determinare formazione richiesta.

Gerarchia departments​

Tabella auto-referenziante: departments.parentId crea un albero reparti (es. "Produzione" β†’ "Linea A" β†’ "Turno notte"). UI deve supportare visualizzazione ad albero.

Codici ATECO gerarchici​

atecoCodes.parentCode simile ai reparti: ATECO hanno gerarchia (es. "F - Costruzioni" β†’ "F.41 - Costruzione di edifici" β†’ "F.41.1 - Sviluppo di progetti immobiliari"). Flag selectable indica quali codici possono essere assegnati direttamente alle aziende (foglie o nodi selezionabili).

πŸ“¦ Dipendenze​

  • Brighela.SimpleCRUD β€” CRUD base + QueryModifier
  • Stack UI comune (DevExpress, Tabiot, Oss)

Cross-dominio in entrata (FK da altri domini a job):

  • reg.companies.riskLevelId β†’ job.riskLevel(id)
  • reg.companies.atecoCode β†’ job.atecoCodes(code)
  • edu.courses.trainingVariantId non tocca job, ma varianti formative (fuori scope edu) mappano verso rischi

Cross-dominio in uscita (FK da job):

  • job.workers.companyId β†’ reg.companies(id)
  • job.workers.companyLocationId β†’ reg.companyLocations(id)
  • job.workers.academicQualificationId β†’ reg.academicQualifications(id)
  • job.departments.companyId β†’ reg.companies(id)
  • job.jobSubcategories.companySubcategoryId β†’ reg.companySubcategories(id)

πŸ“ File chiave​

  • Database/job/Tables/*.sql (13)
  • BackOffice/Services/QueryModifiers/job/CompaniesRisksQueryModifier.cs
  • BackOffice/Components/CRUD/job/Worker.razor{,.cs,.tt.cs} + Forms/WorkerForm.razor
  • BackOffice/Components/CRUD/job/WorkerEffectiveRisk.razor β€” vista rischi effettivi calcolati
  • Shared/Services/IRiskInheritanceService.cs + impl

⚠️ Domande aperte / debito tecnico​

  • Regola calcolo rischio finale del lavoratore. Con piΓΉ mansioni con livelli diversi e override personali, non Γ¨ documentata la formula esatta (max? ultimo? merge?).
  • Storico mansioni β€” trigger automatico. Al cambio mansione, il sistema crea automaticamente il record in workerJobHistory o lo fa solo dopo azione esplicita?
  • workers.riskLevelId staticizzato. Commento DB: "calcolato e staticizzato in base alla mansione". Staticizzato = materializzato. Quando viene refreshato? Coerenza con i rischi attuali?
  • Refresh massivo workers.UpdateRiskLevel senza companyId. Path UpdateWhere senza entity ricalcola TUTTI i workers. Costoso su DB grande. GiΓ  segnalato nel dominio reg.
  • Validazione codice fiscale. Checksum non validato lato DB. Regex/Luhn lato UI? Verificare.
  • Mansioni globali vs per-azienda. Oggi jobs Γ¨ tabella globale: non ha companyId. Un'azienda "Acme" e "Beta" che hanno un "Saldatore" condividono lo stesso record. Se una vuole personalizzare rischi solo per la propria "Saldatore" deve creare una mansione custom. Pattern da documentare.
  • atecoCodes.selectable β€” semantica. Chi puΓ² deselezionare? Sono ATECO pre-popolati dal sistema o l'utente puΓ² aggiungerne?

πŸ”— Vedi anche​