Logica applicativa β dominio job
π― Cosa faβ
La logica applicativa del dominio job gira intorno al cascade dei
rischi β meccanismo che propaga il livello di rischio da ATECO β
azienda β mansione β lavoratore, con possibilitΓ di override a ogni
livello. Tre punti di ancoraggio:
IRiskInheritanceService+worker.UpdateRiskLevelextension (inTrainingHub.Shared) β logica di calcoloCompaniesRisksQueryModifier(inBackOffice) β hook su cambi rischio azienda- Code-behind
WorkerForm.razor.csβ auto-calcolo da CF, cascade combobox WorkerEffectiveRisk.razorβ vista calcolata
π§ IRiskInheritanceService + extension methodsβ
// In TrainingHub.Shared.Services
public interface IRiskInheritanceService
{
// (API pubblica β signature dettagliata da verificare nel file)
}
// Extension methods in TrainingHub.DataLayer.job.worker (static)
public static async Task UpdateRiskLevel(
ISimpleCRUDService db,
Guid? companyId = null);
Uso tipico:
reg.CompaniesQueryModifier.PostExecutionQuerydopo update azienda βworker.UpdateRiskLevel(db, companyId).job.CompaniesRisksQueryModifierdopo update rischi aziendali.- Potenzialmente anche hook su
job.jobs,job.jobsRisks,job.workersRisksper coerenza β da ispezionare.
Cosa fa internamente:
- Legge ATECO azienda β livello suggerito
- Legge override livello azienda (
companies.riskLevelId) - Per ogni lavoratore collegato, determina:
- Mansioni attive (via
workersJobs) - Livello mansione (
jobs.riskLevelId) o fallback azienda - Override lavoratore (
workersRiskscon esclusioni)
- Mansioni attive (via
- Materializza il risultato in
workers.riskLevelId
π§© CompaniesRisksQueryModifierβ
Path: TrainingHub.BackOffice/Services/QueryModifiers/job/CompaniesRisksQueryModifier.cs.
Hook su operazioni CRUD di companiesRisks:
- Insert / update / delete di un rischio aziendale β refresh rischi effettivi dei lavoratori delle aziende coinvolte.
Effetto: modificare i rischi di un'azienda propaga coerentemente a tutti i lavoratori di quell'azienda, senza intervento esplicito dell'utente.
π§© Code-behind WorkerForm.razor.csβ
Contiene logica UI-specifica non centralizzata nel service:
Cascade FK filterβ
Al cambio companyId, filtra:
companyLocationsdisponibili (solo quelle dell'azienda selezionata)departmentsdisponibili (solo quelli dell'azienda selezionata)
Auto-calcolo da codice fiscaleβ
Se il CF Γ¨ valido (16 caratteri, checksum OK):
- Calcola data di nascita e sesso dal CF
- Eventualmente luogo di nascita (se il codice catastale Γ¨ riconosciuto nel catalogo italiano)
Implementazione tipica in un helper statico condiviso.
Validazione CFβ
Checksum del codice fiscale italiano Γ¨ deterministico. Implementato lato C# con regex e algoritmo Luhn-like. Da verificare se il form valida in tempo reale o solo al salvataggio.
π§© Vista WorkerEffectiveRiskβ
Componente Razor che mostra la lista dei rischi finali del lavoratore applicando il cascade. Architettura tipica:
// Pseudocodice
List<EffectiveRisk> ComputeEffectiveRisks(Guid workerId)
{
var worker = LoadWorker(workerId);
var company = LoadCompany(worker.companyId);
var jobs = LoadWorkerJobs(workerId);
var companyRisks = LoadCompanyRisks(company.id);
var jobsRisks = jobs.SelectMany(j => LoadJobRisks(j.id));
var workerOverrides = LoadWorkerRisks(workerId);
// Accumula rischi con provenienza
var effective = new Dictionary<Guid, EffectiveRisk>();
foreach (var cr in companyRisks)
effective[cr.riskId] = new(cr.riskId, cr.riskLevelId, "azienda");
foreach (var jr in jobsRisks)
if (!effective.ContainsKey(jr.riskId))
effective[jr.riskId] = new(jr.riskId, jr.riskLevelId, "mansione");
foreach (var wr in workerOverrides)
{
if (wr.excluded)
effective.Remove(wr.riskId);
else
effective[wr.riskId] = new(wr.riskId, wr.riskLevelId, "override");
}
return effective.Values.ToList();
}
(Implementazione reale: vedi WorkerEffectiveRisk.razor +
code-behind).
π§© Staticizzazione workers.riskLevelIdβ
Il campo riskLevelId su workers Γ¨ materializzato: viene
calcolato e scritto al posto di essere derivato a ogni query. Trade-off:
Pro:
- Query su "lavoratori con rischio alto" sono immediate (filtro su colonna, index-friendly).
- Join con formazione/compliance piΓΉ efficienti.
Contro:
- Coerenza dipende da puntualitΓ dei refresh.
- Se un refresh viene saltato (errore, path non coperto dal QueryModifier), il dato Γ¨ fuori sync.
Mitigazioni:
- QueryModifier chiave invocati da piΓΉ percorsi (azienda, rischi azienda).
- Possibile batch job di rebuild massivo su
endDateWork IS NULL.
π¦ Dipendenzeβ
Brighela.SimpleCRUDβ CRUD base e hookTrainingHub.Shared.Services.IRiskInheritanceService+TrainingHub.Shared.Services.ITrainingExpirationService(quest'ultimo consuma output job)- Cross-dominio:
reg.companies,reg.companyLocations,reg.academicQualificationsβ FK in uscita daworkersreg.companySubcategoriesβ FK in uscita dajobSubcategoriesedu.*β consumatori diworkers.riskLevelId(viaITrainingExpirationService)
π File chiaveβ
TrainingHub.Shared/Services/IRiskInheritanceService.cs+RiskInheritanceService.csTrainingHub.DataLayer/job/worker.Extensions.cs(o simile) βUpdateRiskLevelstatic methodTrainingHub.BackOffice/Services/QueryModifiers/job/CompaniesRisksQueryModifier.csTrainingHub.BackOffice/Components/CRUD/job/Forms/WorkerForm.razor.csTrainingHub.BackOffice/Components/CRUD/job/WorkerEffectiveRisk.razor(+ eventuale code-behind)
β οΈ Debito tecnicoβ
- Staticizzazione
riskLevelIdβ coerenza. Non esiste job di rebuild massivo documentato. Se un bug del QueryModifier lascia dati fuori sync, non c'Γ¨ strumento diagnostico rapido. - Regola calcolo rischio finale lavoratore. Quando esistono piΓΉ mansioni con livelli diversi: quale prevale? (Max? Ultimo inserito? Manuale?) Non documentato β logica da ispezionare nel codice.
- Validazione CF italiano. Se implementata solo lato UI, import da Excel o API bypassano il check. Valutare validazione a livello DB (check constraint con UDF) o service centrale.
- Cascade combobox in
WorkerForm. Logica cascade FK Γ¨ duplicata tra form (qui, e incompaniesreg). Helper condiviso farebbe bene. -
workerJobHistoryβ trigger autmatico. Al cambio mansione, chi inserisce il record inworkerJobHistory? Form custom? Hook DB? Da chiarire. - Performance
UpdateRiskLevelglobale. Chiamata senzacompanyIdricalcola TUTTI i workers: costoso su dataset multi-tenant grande.
π Vedi ancheβ
- Panoramica dominio
- Schema DB
- Componenti UI β vista
WorkerEffectiveRisk - Dominio
reg: logica applicativa β cascade chiamata daCompaniesQueryModifier - Dominio
edu: logica applicativa βITrainingExpirationServiceconsuma rischi job