Passa al contenuto principale

Dominio reg β€” Panoramica sviluppatore

🎯 Cosa fa​

Il dominio reg (registry) contiene l'anagrafica aziende clienti e fornitori: Γ¨ base dati referenziata da quasi tutti gli altri domini (inv, edu, job, iso, bi). Questa pagina copre tutte le 15 tabelle del dominio raggruppate per area funzionale.

πŸ—ΊοΈ Mappa moduli​

Database β€” TrainingHub.Database/reg/​

Core anagrafica (4):

FileRuolo
Tables/companies.sqlAnagrafica aziende (cliente / fornitore)
Tables/companyContacts.sqlCanali di contatto azienda (email, telefono, PEC)
Tables/companyLocations.sqlSedi del cliente con label descrittiva e locationTag di classificazione
Tables/headquarters.sqlSedi TrainingHub / ente formatore β€” indipendente dalle aziende clienti

Classificazione aziendale (3):

FileRuolo
Tables/companySubcategories.sqlSottocategorie custom per raggruppare aziende
Tables/companyTags.sqlN:N azienda ↔ tag di classificazione
Tables/companiesPreferences.sqlPreferenze configurabili per azienda (flag booleani via tag)

Ruoli esterni (4):

FileRuolo
Tables/externalRspps.sqlAnagrafica RSPP esterni (consulenti compliance)
Tables/companiesExternalRspps.sqlIncarichi azienda ↔ RSPP con periodo validitΓ 
Tables/territorialReferents.sqlAnagrafica RLS territoriali β€” Rappresentanti dei Lavoratori per la Sicurezza designati a livello territoriale (art. 48 D.Lgs. 81/08)
Tables/companiesTerritorialReferents.sqlIncarichi azienda ↔ RLS territoriale con periodo validitΓ 

Anagrafiche lookup (4):

FileRuolo
Tables/organizers.sqlEnti organizzatori di corsi
Tables/ccnl.sqlContratti Collettivi Nazionali di Lavoro
Tables/legalNatures.sqlForme societarie (SRL, SPA, ditta individuale, ecc.)
Tables/academicQualifications.sqlTitoli di studio

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

FileRuolo
QueryModifiers/reg/CompaniesQueryModifier.csHook su CRUD companies: dopo update cascade refresh riskLevel sui workers dell'azienda. Su UpdateSingle setta imported = false.

Non esiste un IRegistryService dedicato: la logica di dominio Γ¨ distribuita fra:

  • Il QueryModifier (hook pre/post su CRUD standard)
  • I code-behind custom .razor.cs dei singoli CRUD

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

15 entitΓ  CRUD auto-generate. Pattern identico al dominio inv (vedi componenti UI inv per il pattern generale). Core di questa spec:

  • Company (con code-behind custom ricco di inject/servizi correlati)
  • CompanyContact
  • CompanyLocation (sede del cliente, classificata via locationTag)
  • Headquarter

Configurazione CRUD β€” _conf/*.dxgrid.conf.json​

Un file JSON per entitΓ  (15 totali). I nomi seguono la convenzione <nomePlural>.dxgrid.conf.json (es. companies.dxgrid.conf.json).

πŸ”§ API pubblica​

CompaniesQueryModifier​

public class CompaniesQueryModifier(ISimpleCRUDService simpleCRUD)
: IQueryModifier<DataLayer.reg.company>
{
public ValueTask PreExecutionQuery(QueryModifierArgs<company> args);
public ValueTask PostExecutionQuery(QueryModifierArgs<company> args, object? result);
public ValueTask ModifyEntity(QueryModifierArgs<company> args);
public ValueTask ModifyQuery(QueryModifierArgs<company> args);
}

Hook registrati in Program.cs. Il pattern IQueryModifier<T> Γ¨ di Brighela.SimpleCRUD: consente di innestare logica pre/post sulle operazioni CRUD standard senza override del service.

Servizi iniettati in Company.razor.cs​

[Inject] private IRiskInheritanceService RiskService { get; set; }
[Inject] private ITrainingExpirationService ExpirationService { get; set; }
[Inject] private ISimpleCRUDService SimpleCRUD { get; set; }

Quando l'utente seleziona un'azienda nella grid, il code-behind carica in parallelo: rischi aziendali, dipartimenti, stats di compliance (dettaglio in Logica applicativa).

🧩 Pattern chiave​

Cascade riskLevel su workers​

Quando si aggiorna un'azienda, CompaniesQueryModifier.PostExecutionQuery invoca worker.UpdateRiskLevel(companyId) per ricalcolare il livello di rischio dei lavoratori collegati. Questo avviene automaticamente su ogni Update via hook del QueryModifier, senza intervento del code-behind UI.

Il comportamento garantisce che il cambio di livello di rischio aziendale (forzato manualmente o conseguente a cambio ATECO) si propaghi ai lavoratori senza ricalcoli espliciti.

imported = false su update​

Il flag imported marca aziende caricate da import massivo. Alla prima modifica manuale (UpdateSingle), il QueryModifier.PreExecutionQuery lo resetta a false: l'azienda perde lo status di "solo importata".

Nessun service dedicato​

Il dominio reg non ha un IRegistryService centrale: la logica applicativa vive in:

  • CompaniesQueryModifier (hook DB)
  • .razor.cs custom (per logica UI di caricamento dettagli, validazioni form)
  • Servizi cross-dominio invocati dai code-behind (IRiskInheritanceService, ITrainingExpirationService)

Se la logica cresce, pattern da considerare: introdurre ICompanyService sul modello di IInvoiceService.

πŸ“¦ Dipendenze​

Runtime:

  • Brighela.SimpleCRUD β€” CRUD base + IQueryModifier<T>
  • Oss.Filters β€” filtri su grid
  • Tabiot.Blazor.* β€” componenti UI (wizard, grid, popup, combo)
  • DevExpress.Blazor β€” controlli UI

Cross-dominio (dipendenze di Company.razor.cs):

  • IRiskInheritanceService (dominio job)
  • ITrainingExpirationService (dominio edu)

DB cross-dominio (FK in uscita da reg):

  • reg.companies.atecoCode β†’ job.atecoCodes(code)
  • reg.companies.riskLevelId β†’ job.riskLevel(id)
  • reg.companies.legalNatureCode β†’ reg.legalNatures(code) (fuori scope)
  • reg.companies.ccnlId β†’ reg.ccnl(id) (fuori scope)
  • reg.companies.companySubcategoryId β†’ reg.companySubcategories(id) (fuori scope)

πŸ“ File chiave​

  • Services/QueryModifiers/reg/CompaniesQueryModifier.cs
  • Components/CRUD/reg/Company.razor.cs β€” code-behind principale
  • Components/CRUD/reg/Forms/CompanyForm.razor (+ .razor.cs) β€” form con validazione VIES e propagazione ATECO β†’ riskLevel
  • Database/reg/Tables/*.sql (16)
  • Database/reg/_conf/*.dxgrid.conf.json (16)

⚠️ Domande aperte / debito tecnico​

  • Nessun ICompanyService. La logica Γ¨ distribuita fra QueryModifier e code-behind. Se cresce β€” e con reg che Γ¨ base di tutto β€” valutare estrazione in un service di dominio per testabilitΓ .
  • imported / originalName flag di migrazione. Entrambi contrassegnati nel DB come "da rimuovere una volta completate le importazioni iniziali". Roadmap di pulizia da concordare. Oggi i flag sono nascosti in UI.
  • CompaniesQueryModifier.UpdateRiskLevel senza entity. Nel caso di UpdateWhere senza entity, il modifier chiama worker.UpdateRiskLevel(simpleCRUD) senza filtro per azienda specifica: ricalcola TUTTI i workers. Performance da monitorare su dataset grandi.
  • headquarters globale senza proprietario. La tabella non ha FK verso reg.companies nΓ© verso un altro "tenant": Γ¨ effettivamente singleton del formatore. Se TrainingHub diventa multi-tenant con piΓΉ enti formatori, la tabella va estesa.

πŸ”— Vedi anche​