Passa al contenuto principale

Tutorial - aggiungere un campo a edu.courses

Esempio edu-specific del pattern generale di estensione CRUD. Per i passi comuni (sync DB, MCP generator, rigenerazione) vedi Aggiungere un campo su inv.invoices.

Questa pagina mostra le specificità del dominio edu.

🎯 Cosa fa​

Esempio: aggiungere un campo prerequisiteText (descrizione testuale dei prerequisiti del corso) alla tabella edu.courses.

⚠️ Prerequisiti​

Stessi del tutorial inv/reg:

  • Ambiente sviluppo con TrainingHub.Database
  • DB locale sync
  • MCP 3sd-generator
  • Branch dedicato

👣 Passi​

1. Modifica edu.courses​

File: TrainingHub.Database/edu/Tables/courses.sql

CREATE TABLE [edu].[courses] (
[id] UNIQUEIDENTIFIER DEFAULT (newid()) NOT NULL,
[trainingVariantId] UNIQUEIDENTIFIER NOT NULL,
[organizerSlug] NVARCHAR (128) NOT NULL,
[code] NVARCHAR (128) NOT NULL,
[label] NVARCHAR (512) NOT NULL,
[description] NVARCHAR (MAX) NULL,
[prerequisiteText] NVARCHAR (MAX) NULL,
-- ... altri campi esistenti ...
);

GO
EXECUTE sp_addextendedproperty @name = N'MS_Description',
@value = N'Descrizione testuale dei prerequisiti di partecipazione al corso',
@level0type = N'SCHEMA', @level0name = N'edu',
@level1type = N'TABLE', @level1name = N'courses',
@level2type = N'COLUMN', @level2name = N'prerequisiteText';
GO

Considerazioni edu-specifiche:

  • Posiziona il nuovo campo dopo description per coerenza visiva nel form.
  • Non violare le CHECK constraint esistenti (CK_courses_maxPeople, CK_courses_extraInstructorThreshold).

2. Sincronizza il DB e rigenera​

Uguale a inv/reg: sqlpackage + mcp__3sd-generator__generator_run per courses.

3. conf.json - considerazioni edu​

File: TrainingHub.BackOffice/Components/CRUD/edu/_conf/courses.dxgrid.conf.json

Per un campo di testo lungo come prerequisiteText:

{
"Columns": {
"prerequisiteText": {
"Visible": false,
"FormInsertVisibility": "editable",
"FormUpdateVisibility": "editable",
"EditorType": "TextArea"
}
},
"FormOrder": [
// ... altri campi ...
"description",
"prerequisiteText",
"maxPeople"
]
}

Note:

  • EditorType TextArea per testo multilinea (se supportato dalla generazione; altrimenti sarà singolo textbox).
  • Nascondi in grid di default (campo lungo).

4. Impatto sulle viste analitiche​

Il dominio edu ha viste analitiche generate su vista SQL - per esempio AppointmentsData.razor su edu.vw_appointmentsData. Un nuovo campo non vi compare da solo: va aggiunto alla vista SQL e poi si rigenera con l'MCP. Non modificare i .razor, sono clobberati al primo generator_run.

5. Impatto sulla vista calendario​

Se il campo va mostrato nel pannello dettaglio del calendario, modifica Pages/AppointmentsCalendar/AppointmentDetailPanel.razor (rendering laterale) o eventualmente la query in AppointmentsCalendarService.GetAppointmentsAsync / GetSessionContextAsync se il campo serve a livello di scheda sessione. La vista è scritta a mano, non CRUD-generata.

6. Impatto su ITrainingExpirationService​

Se il campo influenza la compliance (es. un prerequisito impatta expiring vs ok), aggiornare la logica del service. Nel caso di prerequisiteText puramente descrittivo, nessun impatto.

7. Build, test, commit​

dotnet build TrainingHub.slnx
dotnet test TrainingHub.UnitTests

git add TrainingHub.Database/edu/Tables/courses.sql
git commit -m "feat(db): add prerequisiteText to edu.courses"

git add TrainingHub.BackOffice/Components/CRUD/edu/_conf/courses.dxgrid.conf.json
git commit -m "feat(edu): show prerequisiteText in course form"

git add TrainingHub.BackOffice/Components/CRUD/edu/Course.razor \
TrainingHub.BackOffice/Components/CRUD/edu/Course.razor.tt.cs \
TrainingHub.BackOffice/Components/CRUD/edu/Forms/CourseForm.razor \
TrainingHub.BackOffice/Components/CRUD/edu/Forms/CourseForm.razor.tt.cs
git commit -m "regen edu.courses"

⚡ Casi particolari edu​

  • Campo che richiede cascade variante normativa. Se il nuovo campo deve essere pre-popolato al cambio di trainingVariantId, estendere il metodo cascade in CourseForm.razor.cs.
  • Campo calcolato da altri (es. durata totale). I computed column (come teachers.label = lastName + ' ' + firstName) sono sintassi SQL specifica. Seguire pattern esistente: dichiarare AS (expression) nella CREATE TABLE.
  • Campo con impatto su workerCompletionsCache. Se il campo cambia la logica di calcolo compliance (es. influenza scadenza), serve refresh del cache dopo update. Aggiungere hook in un QueryModifier dedicato.
  • Campo visualizzato in vista calendario. Il pannello Pages/AppointmentsCalendar/AppointmentDetailPanel.razor e le query del data provider AppointmentsCalendarService vanno aggiornati esplicitamente.
  • Nuova lookup table. Se il campo è FK verso una nuova tabella, crea anche il CRUD completo per la nuova entità (genera in cascata il combobox nel form courses).

⚠️ Domande aperte​

  • Rigenerazione parziale. Il generatore rigenera tutta l'entità: se il form ha markup custom inline nel conf.json (rare in edu), verificare che non si rompa.
  • Impatto su 38 tabelle. Aggiungere un campo a una tabella centrale (es. courses) può richiedere aggiornamenti in più punti: form, viste analitiche, cache. Checklist standard da stilare.
  • Testing post-regen. Nessun test UI automatico: modifiche come questa vanno validate manualmente.

🔗 Vedi anche​