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 cross-dominio custom (es. ActiveWorker.razor) che caricano elenchi corsi. Un nuovo campo non è automaticamente incluso: se rilevante, aggiornare esplicitamente i code-behind di queste viste.

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.sln
dotnet test TrainingHub.Tests

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 = firstName + ' ' + lastName) 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