Passa al contenuto principale

Schema DB job

🎯 Cosa fa​

Definisce il persistence layer del dominio lavoratori/rischi: 15 tabelle documentate tutte in questa pagina.

πŸ—ΊοΈ Tabelle (15)​

Anagrafica lavoratori (2)​

TabellaRuolo
job.workersAnagrafica dipendente
job.workerJobHistorySnapshot storico mansione/ruolo/reparto

Mansioni (4)​

TabellaRuolo
job.jobsMansioni (globali)
job.jobGroupsRaggruppamenti visuali
job.jobSubcategoriesN:N mansione ↔ sottocategoria azienda
job.workersJobsN:N lavoratore ↔ mansione

Struttura (2)​

TabellaRuolo
job.rolesRuoli aziendali (lavoratore/preposto/dirigente)
job.departmentsReparti gerarchici

Rischi (7)​

TabellaRuolo
job.risksAnagrafica rischi
job.riskLevelLivelli (int PK)
job.atecoCodesCodici ATECO gerarchici (versione corrente)
job.atecoCodesLegacyCodici ATECO di versioni precedenti con correspondingNewAteco FK verso atecoCodes(code). Usata in import aziende per convertire codici legacy nel codice corrente.
job.companiesRisksRischi per azienda
job.jobsRisksRischi per mansione
job.workersRisksRischi per lavoratore (override/esclusione)

πŸͺŸ Viste​

VistaRuolo
job.vw_workerComplianceSummaryRollup per-lavoratore di compliance formativa: worstStatus (expired > missing > expiring > ok), conteggi per status, minDaysRemaining. Filtra solo lavoratori con endDateWork IS NULL. Aggrega edu.vw_workerTrainingStatus per workerId. PK virtuale = workerId. Esposta come CRUD read-only WorkerComplianceSummary con FK manuali su workerId/companyId/roleId/departmentId.

πŸ”— Relazioni​

Referenze esterne:

  • 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)
  • reg.companies.atecoCode β†’ job.atecoCodes(code) (in uscita da reg)
  • reg.companies.riskLevelId β†’ job.riskLevel(id) (in uscita da reg)

πŸ—‚οΈ Dettaglio tabelle​

job.workers​

  • PK: id
  • FK: companyId, companyLocationId, roleId (obbligatori); departmentId, riskLevelId, academicQualificationId (nullable)
  • Computed column: label = lastName + ' ' + firstName
  • Check: gender IN ('M','F')
  • Indici:
    • IX_workers_fiscalCode filtered su fiscalCode IS NOT NULL con INCLUDE (id, companyId, endDateWork, roleId, riskLevelId, academicQualificationId)
    • IX_workers_active filtered su endDateWork IS NULL con INCLUDE simili β€” ottimizza liste attive

job.workerJobHistory​

  • PK: id
  • FK: workerId, jobId (obbligatori); riskLevelId, roleId, departmentId nullable
  • Campi: startDate, endDate (nullable), insertTimestamp default sysdatetime(), notes

job.jobs​

  • PK: id
  • FK: riskLevelId (nullable = fallback azienda), jobGroupId (nullable)
  • Campo chiave: inheritsCompanyRisks (default 1)

job.workersJobs​

  • PK: id
  • FK: workerId, jobId
  • Nessun campo aggiuntivo (associazione pura; date sono in workerJobHistory)

job.departments​

  • PK: id
  • FK: companyId (obbligatoria), parentId (self, nullable β€” gerarchia)
  • Campo: active (default 1)

job.risks​

  • PK: id
  • Campo: label

job.riskLevel​

  • PK: id (INT, non GUID)
  • Campo: label

job.atecoCodes​

  • PK: code (string β€” natural key)
  • FK: parentCode (self, nullable), riskLevelId
  • Campi: label, selectable, position

job.companiesRisks​

  • PK: non specificata (probabilmente composita (companyId, riskId))
  • FK: companyId, riskId, riskLevelId (nullable)
  • Campo: notes

job.jobsRisks​

  • PK: composita (jobId, riskId)
  • FK: riskLevelId nullable

job.workersRisks​

  • PK: composita (workerId, riskId)
  • FK: riskLevelId nullable
  • Campi: excluded (default 0), notes

job.jobSubcategories​

  • PK: id
  • FK: jobId, companySubcategoryId
  • Associazione N:N senza metadata

job.jobGroups, job.roles​

Anagrafiche semplici: PK + label.

πŸ“ File chiave​

  • TrainingHub.Database/job/Tables/*.sql (13)
  • Indici significativi: IX_workers_fiscalCode, IX_workers_active (entrambi filtered per minimizzare dimensione)

⚠️ Debito tecnico​

  • workers.riskLevelId materializzato. Coerenza richiede refresh dopo cambi ATECO, rischi azienda, cambio mansione. Attualmente gestito da QueryModifier ma non c'Γ¨ test di regressione.
  • atecoCodes.code come natural key. Performance OK, ma modifiche al codice (es. rinomina ATECO) sono bloccate da FK. Se serve rename, procedere via nuovo codice + migrazione.
  • Mansioni globali senza companyId. Condivisione fra aziende crea accoppiamento: modifica a una mansione impatta tutti i clienti che la usano. Valutare pattern mansione template + istanza.
  • Indici mancanti su FK chiave. workerJobHistory.workerId, workersJobs.workerId/jobId, workersRisks.workerId non hanno indici espliciti. Su dataset grandi penalizza query "rischi di un lavoratore" o "storico di un lavoratore".
  • Constraint check su riskLevelId. riskLevel ha PK INT (1, 2, 3) ma qualsiasi intero Γ¨ accettato in FK. Valori fuori range (es. 5) resterebbero orfani se non c'Γ¨ il record. Solo integrity FK li blocca, ma non semantica.
  • workersRisks.excluded = 1 + riskLevelId != NULL. Stato semanticamente ambiguo: lavoratore escluso con livello impostato? Aggiungere check o validazione.

πŸ”— Vedi anche​