Tabelle: struttura, indici e relazioni

Gli elementi AOT si progettano in Visual Studio con gli strumenti per finance and operations, e la tabella è il mattone di partenza: definisce campi, field group, indici, relazioni, delete action e metodi. Ogni record ha un RecId univoco a livello di tabella: è la surrogate key e il target delle surrogate foreign key, mentre nella UI compaiono i campi del replacement field group. Gli indici non servono solo alle prestazioni — un unique index impone il vincolo sul database ed è il candidato ad alternate key, prerequisito perché una data entity sappia aggiornare per chiave funzionale. Contano anche le proprietà: TableGroup classifica il contenuto (Parameter, Group, Main, Transaction), SaveDataPerCompany decide se il dato è per legal entity o globale, CacheLookup governa il caching. Le delete action (None, Cascade, Restricted, Cascade+Restricted) esprimono l’integrità referenziale in modo dichiarativo, meglio del codice; i metodi di tabella (insert, update, delete, validateWrite, initValue, modifiedField) vanno riservati alla logica che deve valere ovunque, non solo dentro un form.

EDT ed enum: il vocabolario tipizzato del modello

Un EDT incapsula tipo primitivo, lunghezza, label, help text e formattazione in un elemento riusabile. Dichiarare un campo con un EDT significa che una modifica si propaga ovunque e che lookup e relazioni restano coerenti; scrivere un str 20 sparpaglia la stessa decisione su decine di punti. Gli EDT si compongono per ereditarietà e, sullo standard, si toccano con una EDT extension dal margine stretto: label, help text e aumento della string length, non la riduzione né il cambio di tipo base. I base enum rappresentano insiemi chiusi memorizzati come interi: danno controllo a compile time ed etichette tradotte in un solo posto, cosa che un intero magico o una stringa libera non offrono. Aggiungere valori a un enum standard richiede una enum extension, possibile solo se il base enum è dichiarato extensible.

Query e form: dal data source alla UI

La query AOT descrive una lettura in modo riusabile: data source con join (inner, outer, exists, not exists), range, ordinamenti e aggregazioni. Rispetto a una select X++ scritta a mano guadagni componibilità — la stessa query alimenta un report SSRS, un form, una data entity o un processo batch — e range che restano filtrabili dall’utente oppure bloccati a seconda del loro status. Il form dichiara i propri data source su tabelle, view o query e ne governa il comportamento con proprietà come AllowEdit, InsertIfEmpty, JoinSource e LinkType: la validazione dei dati resta sulla tabella, il form aggiunge presentazione e interazione. Ogni form adotta un form pattern (Simple List and Details, Details Master, List Page, Dialog) che ne fissa struttura e controlli attesi; il pattern viene validato e non è un dettaglio estetico, è il modo di restare allineati alla UX standard.

Un elemento non è raggiungibile finché non ha un menu item. I tre tipi coprono tre esigenze: display apre un form, output esegue un report, action lancia una classe (runnable, RunBase o SysOperation service). Il menu item è anche l’entry point della sicurezza: i privilege concedono un access level sul menu item, i duty aggregano i privilege, i role aggregano i duty. Progettare la navigazione significa quindi progettare già la superficie di sicurezza. Le estensioni sono la strada per intervenire sullo standard senza overlayering, che non è più percorribile: una table extension aggiunge campi, field group, indici, relazioni e delete action; una form extension aggiunge controlli e data source; enum extension ed EDT extension seguono le regole viste sopra. Ciò che le estensioni di metadati non fanno è ospitare codice: la logica arriva da event handler (pre/post e gli eventi di tabella, form, data source, controllo) o da Chain of Command, dove l’override deve chiamare next.

Trappole tipiche d’esame

  • Campo nuovo su una tabella standard → table extension, mai overlayering: la extension mantiene il modello aggiornabile e tiene il tuo codice separato dallo standard.
  • Logica all’inserimento di un record standard → event handler o CoC, non un metodo nella table extension: le estensioni di metadati non ospitano metodi; serve una classe di estensione.
  • Valore in più su un enum standard → enum extension, ma solo se il base enum è extensible: se la proprietà non lo consente non esiste scorciatoia lecita lato codice.
  • Cancellare i figli eliminando il padre → delete action Cascade, non delete() riscritto: attenzione però, con delete action attive un delete_from set-based ricade su elaborazione row-by-row.
  • Data entity che deve aggiornare per chiave funzionale → unique index promosso ad alternate key: senza chiave naturale univoca l’entità sa solo inserire e identificare per RecId.
  • Funzionalità da assegnare a un role → display/output/action menu item come entry point: privilege e duty puntano al menu item, non direttamente al form o alla classe.