Sei sulla pagina 1di 132

Microsoft Dynamics NAV

Sviluppo in NAV 2009

Marco Ferrari
marco.ferrari@cronus.it
Scopo del corso

• Sviluppare una customizzazione partendo


da un’analisi
• Essere in grado di fare un’analisi tecnica
• Sulla base di un documento di analisi essere
in grado di proporre delle soluzioni e di
determinarne l’impatto sul sistema
standard
Microsoft Dynamics NAV

Il progetto
I requisiti essenziali

• Il nostro cliente organizza corsi e seminari destinati a uno o


più clienti
• La maggior parte dei corsi sono a catalogo con un prezzo
specifico, altri hanno un prezzo stabilito al momento
• Ciascun partecipante deve avere un riferimento per la
fatturazione
• L’aula in cui si tiene il corso può essere esterna e quindi
presa in affitto da un fornitore
• L’istruttore può essere un fornitore o una persona interna
• Per ciascun corso possono venire sostenute delle spese
delle quali è necessario tenere traccia
Analisi tecnica

• Quante e quali sono le entità rilevate?


• Quante sono le tabelle che vanno create?
Struttura base

Cliente

Istruttore Risorsa

Partecipanti Corso Edizione Corso Corso

Spese Sostenute Aula Fornitore

Conto C/G
Struttura base

Cliente

Istruttore Risorsa

Partecipanti Corso Edizione Corso Corso

Spese Sostenute Aula Fornitore

Conto C/G
Microsoft Dynamics NAV

Il catalogo dei corsi


Requisiti essenziali

• La società ha un catalogo composto di


diversi corsi
• Il codice del corso è manuale
• Ogni corso ha una durata fissa e un numero
minimo e massimo di partecipanti
• Ogni corso ha un prezzo prefissato
• Alcuni corsi diventano obsoleti e si decide di
non tenerli più
Analisi tecnica

• Identificare i campi e il relativo tipo di dato


• Per ciascun campo indicare le proprietà da
impostare
Tabella Corso

Nr. Nome Tipo Commento


1 Codice Code(10) PK – Non può essere blank

2 Descrizione Text(50)
5 Durata DateFormula
6 Nr. minimo partecipanti Integer MinValue = 0

7 Nr. massimo partecipanti Integer MinValue = 0

9 Bloccato Boolean
15 Prezzo per partecipante Decimal AutoFormatType = 1, MinValue = 0
Business rules

• Il Nr. Massimo di Partecipanti deve essere


maggiore o uguale al Nr. Minimo di Partecipanti
Analisi tecnica

• In quale trigger devo implementare questa regola?


• Quanti trigger sono coinvolti?
Analisi tecnica

• Quante pagine creiamo per la gestione del


catalogo?
Analisi tecnica

• Quando la tabella contiene pochi campi si usa una


sola pagina di tipo tabellare
Microsoft Dynamics NAV

L’aula
Requisiti essenziali

• Ogni corso è tenuto in un aula


• Alcune aule sono interne, altre esterne
• Ogni aula ha un numero massimo di
partecipanti
• Ogni aula esterna ha un costo di affitto
Analisi tecnica

• Identificare i campi e il relativo tipo di dato


• Per ciascun campo indicare le proprietà da
impostare
Tabella aula

Nr. Nome Tipo Commento


1 Codice Code(10) PK – Non può essere blank

2 Descrizione Text(50)
5 Indirizzo Text(50)
6 CAP Code(20) TableRelation Tabella 225 non validata come da standard

7 Città Text(30)
8 Provincia Text(30)
10 Nr. Fornitore Code(20) TableRelation – Tabella 23

15 Costo Unitario Decimal AutoFormatType = 2, MinValue = 0


Giornaliero
20 Nr. Massimo Integer MinValue = 0
Partecipanti
25 Interna/Esterna Option Interna,Esterna
Business rules

• Gestire i CAP e le città come nello standard NAV


Pagine

• Poiché l’aula contiene diversi campi, creare una


pagina a lista e una pagina a scheda legate tra loro
• La pagina a lista verrà usata nelle operazioni di
lookup
Microsoft Dynamics NAV

L’edizione del corso


Requisiti essenziali

• Ogni edizione deve essere numerata. La


numerazione cambia ogni anno ed è
costruita con la logica
CORSO<anno>/<Progressivo>
• Di ogni edizione devo indicare se è in
pianificazione, se si sta svolgendo, se è già
terminato oppure se è già stato fatturato
Analisi tecnica

• Per poter gestire la numerazione


automatica è necessario indicare in una
tabella di setup il codice del numeratore
Analisi tecnica

• Aggiungiamo un campo a una tabella


standard o creiamo una tabella di setup
apposta?
Tabella Setup corsi

Nr. Nome Tipo Commento


1 Chiave Primaria Code(10) PK
2 Nr. Edizioni Corso Code(10) TableRelation Tabella
308
Pagina Setup corsi

• Creare una pagina a scheda che impedisca


l’inserimento e l’eliminazione dei record
• All’apertura della pagina, qualora non ci
fosse alcun record in tabella, il sistema deve
inserire un record con «Chiave primaria»
blank
Tabella Edizione corso

Nr. Nome Tipo Commento


1 Nr. Code(20) PK
5 Codice corso Code(10) TableRelation Tabella Corso

6 Descrizione Text(50)
10 Data inizio corso Date
11 Data fine corso Date Non Editabile
14 Tipo istruttore Option Interno,Esterno

15 Nr. istruttore Code(20) TableRelation su tabella Risorsa (156) o su Fornitori (23) a seconda del
campo «Tipo istruttore»
20 Stato Option Pianificazione,In Corso,Terminato,Fatturato

30 Codice aula Code(10) TableRelation Tabella Aula

45 Nr. serie Code(10) Rel. Tabella 308 – Non Editabile


Business rules

• Gestire la numerazione automatica dell’edizione


• Quando si seleziona un corso, controllare che tale
corso abbia specificati prezzo e durata e copiare il
campo Descrizione
• Quando si inserisce o modifica la Data Inizio Corso,
calcolare la Data Fine Corso sulla base della durata
indicata in catalogo
• Se lo stato è fatturato non deve essere più
possibile cambiarlo
Pagine

• Quante pagine e di quale tipo creiamo per gestire


le edizioni del corso?
Microsoft Dynamics NAV

I partecipanti
Requisiti essenziali

• Ogni partecipante deve essere collegato ad


un cliente
• Il prezzo del corso può variare da
partecipante a partecipante
• Alcuni partecipanti frequentano il corso
gratuitamente
• Si deve tenere traccia della data di
iscrizione
Analisi tecnica
Tabella Partecipante corso

Nr. Nome Tipo Commento


1 Nr. Edizione Code(20) PK – TableRelation Edizione corso
2 Nr. di Riga Integer PK
5 Fatturare a – Nr. Code(20) -> Tabella 18
Cliente
10 Nome Partecipante Text(50)
15 Data Iscrizione Date
17 Fatturare Boolean Default = Sì
18 Importo Decimal AutoFormatType = 1
Business rules

• All’inserimento di un cliente, controllare che


questo non sia bloccato e compilare il
campo Importo con il Prezzo per
Partecipante del corso del catalogo corsi
• All’inserimento del record compilare
automaticamente il campo «Data
Iscrizione» con la workdate
Pagine

• I partecipanti al corso appariranno come


subpagina della scheda edizione corso
Microsoft Dynamics NAV

Le spese
Requisiti essenziali

• Possono essere generiche, come telefono,


fax ecc oppure risorse interne, come i
tecnici
• Possono venire riaddebitate oppure
possono rimanere a carico della società
• Alcune spese vengono addebitate ad un
singolo cliente
Analisi tecnica
Tabella Spesa corso

Nr. Nome Tipo Commento


1 Nr. Edizione Code(20) PK – Rel. Tab. Edizione corso
2 Nr. di Riga Integer PK
5 Tipo Option Blank,Conto C/G,Risorsa
6 Nr. Code(20) -> Variabile con Tipo
10 Descrizione Text(50)
15 Quantità Decimal DecimalPlaces 0:5
16 Cod. Unità di Misura Code(10) -> Variabile con Tipo
17 Costo Unitario Decimal AutoFormatType = 2, MinValue = 0

18 Costo Totale Decimal AutoFormatType = 1, Non Editabile

20 Fatturare a – Nr. Cliente Code(20) -> Tabella 18


21 Fatturare Boolean Default = Sì
Business rules

• All’inserimento del campo «Nr.» copiare il campo


Descrizione dall’anagrafica corrispondente e se Tipo è
uguale a Risorsa, copiare anche l’Unità di Misura e il Costo
Unitario
• Se si cambia il campo Tipo, mettere a blank tutti i campi
della tabella
• All’inserimento o alla modifica del campo Quantità e del
campo Costo Unitario, calcolare il Costo Totale come
Quantità * Costo Unitario, arrotondato come da Setup di
Contabilità
• Se si toglie il flag Fatturare, controllare che il campo
Fatturare a – Nr. Cliente sia blank
Pagine

• Le spese appariranno in una pagina


tabellare da aprirsi dalla scheda e dalla lista
edizione corso
Microsoft Dynamics NAV

Funzionalità aggiuntive
Edizione corso

• Sull’edizione del corso deve essere visibile il


numero totale dei partecipanti
Edizione corso

• Sull’edizione del corso devono essere visibili


il totale delle spese sostenute e l’importo
totale che verrà fatturato
• Le spese totali e l’importo totale devono
poter essere calcolati in funzione del cliente
Tabella Edizione corso – Campi da aggiungere

Nr. Nome Tipo Commento


21 Nr. iscritti Integer FlowField di tipo Count su tabella Partecipanti corso
41 Costi totali Decimal FlowField di tipo Sum sulla tabella Spese

42 Importo totale Decimal FlowField di tipo Sum sulla tabella Partecipanti


50 Filtro cliente Code(20) FlowFilter – TableRelation con tabella 18
Pagina aggiuntiva

• Per far funzionare il DrillDown sui FlowField


è necessario creare una pagina a lista sulla
tabella Partecipante corso
Microsoft Dynamics NAV

Funzioni e procedure
Creazione di una fattura fornitore

• La funzione crea una fattura per la fornitura dell’aula dove si


tiene il corso
• Parte dall’edizione del corso
• La fattura deve essere intestata («Acquistare da – Nr.
Fornitore») al fornitore indicato nel campo «Nr. Fornitore»
nella scheda dell’aula associata all’edizione del corso
• La fattura dovrà contenere due righe: la prima è una
descrizione del tipo ‘Ordine per il corso dal’ «Data Inizio
Corso» al «Data Fine Corso»
• La seconda riga dovrà essere conto COGE con Quantità pari
al numero di giorni di corso e «Costo Unitario Diretto IVA
Escl» = «Costo Unitario Giornaliero»
Analisi tecnica

• Dobbiamo modificare delle tabelle?


• Dobbiamo creare nuovi oggetti?
• Che tipo di oggetti ci servono?
Analisi tecnica

• Se il conto COGE sulle fatture passive è


sempre uguale, dobbiamo aggiungere un
campo alla tabella Setup corsi
• Creiamo una codeunit da richiamare dalla
Scheda edizione corso
Tabella Setup corsi – Campo da aggiungere

Nr. Nome Tipo Commento


5 Nr. Conto C/G Code(20) TableRelation tabella 15

Quando l’utente seleziona il Nr. Conto C/G controllare


che sia un conto analitico, che il conto non sia bloccato
e che abbia Registrazione Diretta a Sì
CONFIRM

• L’istruzione di CONFIRM se usata, deve


sempre essere la prima istruzione di una
transazione
• Non deve mai essere inserita in mezzo ad una
transazione
VALIDATE

• Quando si compila un record in una tabella


standard bisogna sempre far scattare i trigger
OnValidate dei campi nell’ordine in cui li
compilerebbe l’utente
• Vanno comunque compilati per: le chiavi
esterne; i campi di tipo decimale (quantità,
costi, prezzi…) e interi
MESSAGE

• L’istruzione di MESSAGE se usata, deve


sempre essere l’ultima istruzione di una
transazione
• Non deve mai essere inserita in mezzo ad una
transazione
Richieste ulteriori

• Poiché il cliente ha comprato il granulo del CRM di


NAV si vuole che ciascun partecipante sia
associato a un contatto di NAV
• Il contatto deve essere preso dalla lista dei
contatti associati al cliente indicato nel campo
«Fatturare a – Nr. cliente»
• Se il cliente non è specificato, il contatto verrà
lasciato blank
Fatturazione del corso

• La fatturazione può avvenire sia per un singolo


corso che in modo massivo a fine mese
• La fatturazione massiva deve poter essere filtrata
per data inizio corso
Fatturazione del corso

• E’ necessario creare una fattura per ciascun cliente


• Su ciascuna fattura è necessario avere tante righe quanti sono i
partecipanti di quel cliente
• Se un partecipante partecipa a titolo gratuito, deve comunque
apparire nelle righe di fattura con sconto 100%
• Le spese specifiche di un cliente devono apparire in fattura separate
da una riga di descrizione (‘Vostre spese’)
• Le spese condivise tra i clienti devono apparire in fattura separate da
una riga di descrizione (‘Spese condivise’)
• Per una questione di trasparenza, ciascuna voce di spesa deve tradursi
in una riga di fattura con la relativa descrizione
• Le spese condivise devono venire addebitate suddividendo il costo
totale per il totale dei partecipanti al corso, moltiplicato per il numero
di partecipanti del cliente in questione, conteggiando anche i
partecipanti a titolo gratuito
Analisi tecnica

• Sulla base delle esigenze del cliente, preparare


un’analisi che spieghi in che modo deve essere
compilata una fattura sulla base delle
informazioni presenti nelle varie tabelle di
gestione dei corsi
Analisi tecnica

• Che oggetti vanno creati?


Analisi tecnica

• Verrà creato il campo «Nr. Conto C/G» sul


catalogo corsi
• Verrà creata una codeunit con una funzione
richiamabile dalla singola edizione del corso
• Verrà creato un batch che richiamerà la funzione
della codeunit
• Il batch verrà richiamato dalla scheda e dalla lista
edizione corso
Tabelle temporanee

• Sono tabelle reali ma referenziate da variabili


record definite come temporary
• Qualsiasi inserimento o modifica del record
avviene solo a livello di client (o di server nel caso
del RTC)
• Non avviene alcuna comunicazione con la base di
dati
• E’ possibile referenziare come temporanea anche
una tabella fuori dal range del cliente
Fatturazione automatica

• La funzione di fatturazione deve permettere


all’utente di registrare automaticamente le fatture
emesse
Richieste ulteriori

• Per alcuni corsi devono venire riconosciute delle


royalty ad un fornitore (es. Microsoft)
• La royalty è una percentuale da riconoscere al
licenziante che varia da corso a corso
• Ogni trimestre viene mandato al licenziante una
lista dei corsi tenuti con il totale delle royalty da
riconoscere nel periodo basato sul fatturato
Microsoft Dynamics NAV

Performance in SQL
Record.ISEMPTY

• Restituisce TRUE se non trova alcun record sulla


base dei criteri applicati (filtri, chiavi)
• Non si posiziona su alcun record e dunque non è
possibile usarla per fare i loop
• Essendo molto veloce è da usare se è necessario
solo verificare l’esistenza o meno di un record con
certe caratteristiche
• In SQL diventa SELECT TOP 1 NULL FROM…
Record.FINDSET

• Trova i primi 50 record sulla base dei filtri applicati e si


posiziona sul primo
• Il numero di record letti è definito nel parametro Set di
Record del database SQL (default = 50)
• Non attiva i cursori in SQL Server.
• Dal 51esimo record vengono attivati i cursori con un
conseguente abbassamento di prestazioni
• Va usata in tutti i loop di lettura con un numero di record
inferiore o uguale al set di record del database (50)
• Non permette il posizionamento sull’ultimo record
• In SQL diventa SELECT TOP 50 * FROM …
Record.FIND(‘-’) e Record.FIND(‘+’)

• Trova i record sulla base dei criteri applicati


(filtri, chiavi e assegnazioni) e si posiziona
sul primo (ultimo)
• Attiva i cursori in SQL Server
• Va usata nei loop di lettura quando il
numero di record da leggere è superiore al
Set di Record (50)
• In SQL diventa SELECT * FROM…
Record.FINDSET(TRUE)

• Trova i primi 50 record sulla base dei filtri


applicati, si posiziona sul primo e li blocca per
consentirne la modifica
• Da usare se il numero di record da leggere e
modificare è superiore a 50
• Se il numero è inferiore a 50, usare LOCKTABLE
prima di FINDSET senza parametro TRUE
Record.FINDSET(TRUE,TRUE)

• Va usata se all’interno del loop modifico i


campi che fanno parte della chiave di
ordinamento dei record
• Se possibile è meglio evitarla, usando una
variabile per ciclare sui record e una per
modificarli
Record.FINDFIRST

• Trova il primo record sulla base dei criteri applicati


(filtri, chiavi)
• Non attiva i cursori in SQL Server.
• Va usata solo quando è necessario ottenere il
primo record sulla base dei criteri applicati
• Non va mai usata nei loop perché alla NEXT attiva
i cursori
• In SQL diventa SELECT TOP 1 * FROM … ORDER BY

Record.FINDLAST

• Trova l’ultimo record sulla base dei criteri applicati


(filtri, chiavi)
• Non attiva i cursori in SQL Server. Da usare
quando è necessario ottenere solo l’ultimo record
sulla base dei criteri applicati
• Non va usata nei loop perché alla NEXT(-1) attiva i
cursori
• In SQL diventa SELECT TOP 1 * FROM … ORDER BY
… DESC
Analisi di FINDSET in un loop

SalesLine.RESET;
SalesLine.SETRANGE("Document Type",SalesHeader."Document Type");
SalesLine.SETRANGE("Document No.",SalesHeader."No.");
SalesLine.FINDSET;
REPEAT
[…]
UNTIL SalesLine.NEXT = 0;
Comportamento della NEXT fino al 51esimo record

Istruzione SQL

SalesLine.FINDSET; SELECT TOP 51 * FROM


“Sales Line" WITH
(READUNCOMMITTED) WHERE
(("Document Type"=1)) AND
(("Document No_"='1020'))
ORDER BY "Document
Type","Document No_","Line
No_" OPTION (OPTIMIZE FOR
UNKNOWN)
UNTIL SalesLine.NEXT = 0; Cached (no cursori)
Comportamento della NEXT fino dopo il 51esimo record

Istruzione SQL

UNTIL SalesLine.NEXT = 0; SELECT * FROM “Sales Line"


WITH (READUNCOMMITTED)
WHERE (("Document
Type"=1)) AND (("Document
No_"='1020')) AND
"Document Type"=1 AND
"Document No_"='1020' AND
"Line No_">510000 ORDER BY
"Document Type","Document
No_","Line No
Dopo Cached o FETCH (cursori)
Analisi di FIND(‘-’) in un loop

SalesLine.RESET;
SalesLine.SETRANGE("Document Type",SalesHeader."Document Type");
SalesLine.SETRANGE("Document No.",SalesHeader."No.");
SalesLine.FIND(‘-’);
REPEAT
[…]
UNTIL SalesLine.NEXT = 0;
Comportamento della NEXT su tutti i record

Istruzione SQL

SalesLine.FIND(‘-’); SELECT * FROM "Sales Line"


WITH (READUNCOMMITTED)
WHERE (("Document
Type"=1)) AND (("Document
No_"='1021')) ORDER BY
"Document Type","Document
No_","Line No_" OPTION
(OPTIMIZE FOR UNKNOWN)
UNTIL SalesLine.NEXT = 0; Cached oppure FETCH
(cursori)
Analisi di FINDSET(TRUE) in un loop

SalesLine.RESET;
SalesLine.SETRANGE("Document Type",SalesHeader."Document Type");
SalesLine.SETRANGE("Document No.",SalesHeader."No.");
SalesLine.FINDSET(TRUE);
REPEAT
[…]
UNTIL SalesLine.NEXT = 0;
Comportamento della NEXT su tutti i record

Istruzione SQL

SalesLine.FINDSET(TRUE); SELECT * FROM "Sales Line"


WITH (UPDLOCK) WHERE
(("Document Type"=1)) AND
(("Document No_"='1022'))
ORDER BY "Document
Type","Document No_","Line
No_" OPTION (OPTIMIZE FOR
UNKNOWN)
UNTIL SalesLine.NEXT = 0; Cached oppure FETCH
(cursori)
Analisi di LOCKTABLE e FINDSET in un loop

SalesLine.RESET;
SalesLine.SETRANGE("Document Type",SalesHeader."Document Type");
SalesLine.SETRANGE("Document No.",SalesHeader."No.");
SalesLine.LOCKTABLE;
SalesLine.FINDSET;
REPEAT
[…]
UNTIL SalesLine.NEXT = 0;
Comportamento della NEXT fino al 51esimo record

Istruzione SQL

SalesLine.FINDSET; SELECT TOP 51 * FROM


"Sales Line" WITH
(UPDLOCK) WHERE
(("Document Type"=1)) AND
(("Document No_"='1023'))
ORDER BY "Document
Type","Document No_","Line
No_" OPTION (OPTIMIZE FOR
UNKNOWN)
UNTIL SalesLine.NEXT = 0; Cached (no cursori)
Comportamento della NEXT fino dopo il 51esimo record

Istruzione SQL

UNTIL SalesLine.NEXT = 0; SELECT * FROM "Sales Line"


WITH (UPDLOCK) WHERE
(("Document Type"=1)) AND
(("Document No_"='1023'))
AND "Document Type"=1 AND
"Document No_"='1023' AND
"Line No_">510000 ORDER BY
"Document Type","Document
No_","Line No_" OPTIO
Dopo Cached o FETCH (cursori)
Analisi di LOCKTABLE e FIND(‘-’) in un loop

SalesLine.RESET;
SalesLine.SETRANGE("Document Type",SalesHeader."Document Type");
SalesLine.SETRANGE("Document No.",SalesHeader."No.");
SalseLine.LOCKTABLE;
SalesLine.FIND(‘-’);
REPEAT
[…]
UNTIL SalesLine.NEXT = 0;
Comportamento della NEXT su tutti i record

Istruzione SQL

SalesLine.FIND(‘-’); SELECT * FROM "Sales Line"


WITH (UPDLOCK) WHERE
(("Document Type"=1)) AND
(("Document No_"='1024'))
ORDER BY "Document
Type","Document No_","Line
No_" OPTION (OPTIMIZE FOR
UNKNOWN)
UNTIL SalesLine.NEXT = 0; Cached oppure FETCH
(cursori)
Analisi di FINDSET(TRUE,TRUE) in un loop

SalesLine.RESET;
SalesLine.SETRANGE("Document Type",SalesHeader."Document Type");
SalesLine.SETRANGE("Document No.",SalesHeader."No.");
SalesLine.FINDSET(TRUE,TRUE);
REPEAT
[…]
UNTIL SalesLine.NEXT = 0;
Comportamento della NEXT su tutti i record

Istruzione SQL

SalesLine.FINDSET(TRUE,TRUE); SELECT * FROM "Sales Line"


WITH (UPDLOCK) WHERE
(("Document Type"=1)) AND
(("Document No_"='1024'))
ORDER BY "Document
Type","Document No_","Line
No_" OPTION (OPTIMIZE FOR
UNKNOWN)
UNTIL SalesLine.NEXT = 0; FETCH 1 (cursori)
Riassunto

Istruzione SQL Commento

SalesLine.FINDSET SELECT TOP 51 * FROM “Sales Al 51esimo record esegue una seconda
Line" WITH (READUNCOMMITTED) SELECT * FROM WITH
(READUNCOMMITED)
SalesLine.FIND(‘-’) SELECT * FROM "Sales Line"
WITH (READUNCOMMITTED)
SalesLine.FINDSET(TRUE) SELECT * FROM "Sales Line"
WITH (UPDLOCK)
SalesLine.LOCKTABLE; SELECT TOP 51 * FROM "Sales Al 51esimo record esegue una seconda
SalesLine.FINDSET; Line" WITH (UPDLOCK) SELECT * FROM WITH (UPDLOCK)
SalesLine.LOCKTABLE; SELECT * FROM "Sales Line"
SalesLine.FIND(‘-’); WITH (UPDLOCK)
SalesLine.FINDSET(TRUE,TRUE) SELECT * FROM "Sales Line" Alla NEXT corrisponde l’istruzione di FETCH
WITH (UPDLOCK) 1
Riassunto

Istruzione Da usare Da non usare

In tutti i loop di lettura in cui il numero di


Nei loop di lettura in cui il numero di record
SalesLine.FINDSET record è inferiore al set di record del
supera il set di record nel database
database
In tutti i loop di lettura in cui il numero di In tutti i loop di lettura in cui il numero di
SalesLine.FIND(‘-’) record è superiore al set di record del record è inferiore al set di record del
database database
In tutti i loop di modifica dei record in cui il Nei loop di modifica in cui il numero di
SalesLine.FINDSET(TRUE) numero di record è superiore al set di record record è inferiore al set di record del
del database database
In tutti i loop di modifica in cui il numero di In tutti i loop di modifica in cui il numero di
SalesLine.LOCKTABLE;
record è inferiore al set di record del record è superiore al set di record del
SalesLine.FINDSET;
database database
SalesLine.LOCKTABLE;
Equivalente alla FINDSET(TRUE) Equivalente alla FINDSET(TRUE)
SalesLine.FIND(‘-’);
Nei loop in cui uno dei campi della chiave di
SalesLine.FINDSET(TRUE,TRUE) Sempre…
ordinamento cambia nel loop
Cose da evitare

• Usare l’istruzione COUNT per verificare la


presenza di record in tabella
• Usare i loop WHILE-END per ciclare sui record
• Usare l’istruzione IF NOT Record.INSERT THEN
Record.MODIFY
• Usare l’istruzione MARKEDONLY in luogo di una
tabella temporanea in cui memorizzare i record
Impostazioni dell’applicativo «delicate»

• «Registrazione sconti» = Tutti gli sconti


• «Avvisi di credito» = Entr. avvisi
• «Avviso esaurimento scorte» attivato
Impostazioni dei campi BLOB

• Quando si crea un campo BLOB è consigliabile


mettere la proprietà Compressed al valore No
• In questo modo SQL necessita di meno istruzioni
per calcolarlo
Impostazioni del database

• Il parametro Set di record va impostato al numero


medio delle righe di un ordine di vendita
• Il flag «Abilita Trova durante digitazione»
andrebbe disabilitato, perché ad ogni pressione di
un tasto SQL genera una query, abbassando le
prestazioni
Chiavi e SIFT

• Se si aggiunge una chiave di solo ordinamento


dati, disabilitare la proprietà MaintainSQLIndex
• Nelle chiavi i campi boolean e option non vanno
mai messi in cima all’indice
• I campi data vanno sempre messi in fondo
all’indice
• I sumindex creati su una tabella con pochi dati
devono avere disabilitata la proprietà
MaintainSIFTIndex
Microsoft Dynamics NAV

Posting function
Posting function

• Sono le procedure di registrazione


• Si dividono in Single Table Posting Function e
Multiple Table Posting Function
• Le Single Table sono le procedure di base, le
Multiple Table si appoggiano sulle altre
Microsoft Dynamics NAV

Single Table Posting Function


Single Table Posting Function

• Sono le procedure «base» di registrazione


presenti in tutti i granuli di NAV
• Sono le uniche procedure che scrivono nelle
tabelle finali «ledger entry»
• Si basano su un «journal» il cui contenuto viene
trasferito nel «ledger» dalla procedura stessa
• Il «journal» e il «ledger» sono tabelle pressoché
identiche
Differenze tra journal e ledger

Journal:
• E’ un’area di lavoro transitoria
• Il suo contenuto viene svuotato al termine della
registrazione (tranne che per le registrazioni
periodiche)
Ledger:
• Sono tabelle protette
• Solo le procedure di posting possono scrivere in
quelle tabelle
Architettura delle Single Table Posting Function

• Ci sono delle codeunit definite «di partenza» e tre


codeunit preposte alla registrazione vera e
propria
Architettura delle Single Table Posting Function

0 Journal Management
1 Journal Post
2 Journal Post+Print • Routine di gestione
3 Journal Batch Post e di “partenza”
4 Journal Batch Post+Print
5 Show Ledger

1 Journal Check Line


2 Journal Post Line • Routine di posting
3 Journal Post Batch
Architettura delle Single Table Posting Function

Codeunit di partenza
• Fanno solo la domanda all’utente poi «partono»

Codeunit di posting
• Non devono fare alcuna domanda
• Devono solo fare la registrazione
Architettura delle Single Table Posting Function

XX Journal Line

Post

Codeunit *2
XX Jnl.-Post Line

XX Ledger Entry
Microsoft Dynamics NAV

Journal tables
Journal tables

Gen. Journal Line (81) Registrazioni Contabili

Item Journal Line (83) Registrazioni Magazzino

Res.Journal Line (207) Registrazioni Risorse

Job Journal Line (210) Registrazioni Commesse

FA Journal Line (5621) Registrazioni Cespiti


Corrispondenze tra journal e ledger

Gen. Journal Line (81) G/L Entry (17)

Item Journal Line (83) Item Ledger Entry (32)

Res. Journal Line (207) Res. Ledger Entry (203)

Job Journal Line (210) Job Ledger Entry (169)


G/L Posting
Architettura del G/L Posting

Gen. Journal Line (81) n righe

Gen. Jnl.-Post
Codeunit 231 Gen. Jnl.-Check Line
Loop Controllo Codeunit 11
(n volte)

Gen. Jnl.-Post Batch G/L Entry (17)


Codeunit 13

Loop Registrazione Gen. Jnl.-Post Line


(n volte) Codeunit 12
G/L Posting

• La codeunit 12 è l’unica codeunit in NAV che


scrive nella tabella 17
• Qualsiasi scrittura contabile passa (e deve
passare) dalla codeunit 12
• La codeunit 11 non deve scrivere nel database
ma solo effettuare controlli sui dati
Struttura della codeunit 12

Detailed Cust.
Gen. Jnl.-Check Line Ledg. Entry
Codeunit 11
VAT Entry Customer
Ledger
Entry
Gen. Jnl. -
G/L Register Post Line
Codeunit 12
Vendor
Ledger Bank
Entry Acc.
G/L Entry
Ledg. Entry

Detailed
Check Ledger Entry Vendor Ledg.
VAT Entry
Book Entry G/L
Book Entry
Item Posting
Architettura dell’Item Posting

Item Journal Line (83) n righe

Item Jnl.-Post
Codeunit 241 Item Jnl.-Check Line
Loop Controllo Codeunit 21
(n volte)

Item Ledger
Item Jnl.-Post Batch Entry (32)
Codeunit 23

Loop Registrazione Item Jnl.-Post Line


(n volte) Codeunit 22
Item Posting

• La codeunit 22 è l’unica codeunit in NAV che


scrive nella tabella 32
• Qualsiasi procedura di movimentazione del
magazzino passa dalla codeunit 22
• La codeunit 21 non deve scrivere nel database
ma solo effettuare controlli sui dati
Struttura della codeunit 22

Item Jnl.-Check Line


Codeunit 21
Cap.
Ledger Entry Value
Entry
Item Jnl.
Item Register -Post Line
Codeunit 22
Item
Ledger
Entry Item Appl.
Phys. Invt.
Entry
Ledger Entry
Microsoft Dynamics NAV

Multiple Table Posting


Function
Multiple Table Posting Function

• Sono le procedure di registrazione dei granuli


aggiuntivi a quelli «base» (es. ciclo attivo e
passivo, gestione degli ordini di produzione)
• Si appoggiano e richiamano le single table posting
function
• Si chiamano così perché una stessa procedura può
richiamare N procedure di tipo «single table» a
seconda di cosa deve registrare
Esempi di Multiple Table Posting Function

• Registrazione di una spedizione (carico) da ordine


di vendita (acquisto)
• Registrazione di una fattura attiva (passiva) dal
granulo del ciclo attivo (passivo) e non dalle
registrazioni vendite (acquisti)
Registrazione di una spedizione da ordine
Registrazione di una spedizione da ordine

Page 42
Sales Order

Record 36
Sales Header
F9
Post

Codeunit 81 Record 83
Sales-Post (Yes/No) Item Journal Line

Record 32
Item Ledger Entry

Codeunit 80 Codeunit 22
Sales-Post Item Jnl.-Post Line

Record 37 Codeunit 21
Sales Line Item Jnl.-Check Line
Loop
Registrazione di una spedizione da ordine

• Viene compilato un record di appoggio nella


journal di magazzino (tabella 83) per ogni riga
ordine di tipo Articolo
• Il record non viene memorizzato nella tabella
perché sarebbe un inserimento inutile
• Il record viene mandato direttamente alla
codeunit 22
• Non serve richiamare la codeunit 23
• La codeunit 21 viene richiamata automaticamente
dalla codeunit 22
Struttura della codeunit 80

Sales
Header
Gen. Jnl.-Post Line
Codeunit 12
Sales
Line(s)
Item Jnl.-Post Line
Codeunit 22
Sales - Post
Codeunit 80 Posted
Res. Jnl.-Post Line Shipment Posted
Codeunit 212 Header Shipment
Line(s)

Job Jnl.-Post Line


Codeunit 202 Posted
Invoice Posted
Header Invoice
Line(s)
Registrazione di una fattura attiva/passiva

Sales Line (37) n righe Purchase Line (39)

Raggruppamento delle righe in un


m righe Inv. Post. Buffer (49) buffer

m righe Gen. Journal Line (81) Compilazione prima nota dal buffer

To Codeunit
12
Compilazione di un documento registrato

Sales Shipment
Sales Header (36) Codeunit 80
Header (110)
1 1

TRANSFERFIELDS

N
N

Sales Shipment
Sales Line (37) Codeunit 80
Line (111)
Funzionamento della TRANSFERFIELDS

SalesShptHeader.TRANSFERFIELDS(SalesHeader)
Uso della TRANSFERFIELDS

Sales Shipment
Header
(112)

Sales Invoice
Header
(114)
TRANSFERFIELDS
Sales Header Sales Cr. Memo
(36) Header
(116)

Sales Header
Archive
(5107)

Return Receipt
Header (6660)
Cosa non devo mai fare

• Le codeunit delle single table posting function


e quelle delle multiple table posting function
non devono mai contenere istruzioni di
CONFIRM, MESSAGE o EXIT
Cosa non devo mai fare

• Non bisogna mai scrivere procedure che


scrivano o modifichino i dati nelle tabelle
«ledger entry»
Microsoft Dynamics NAV

Esercizi di modifica dello


standard
Esercizio

• Si ha la necessità di gestire una data di incasso


previsto sui movimenti contabili del cliente,
eventualmente modificabile anche dopo la
registrazione
• Tale data viene calcolata come la data di
scadenza del pagamento più un certo numero
di giorni che dipendono da cliente a cliente
Esercizio

• Esporre una soluzione possibile al problema,


una lista degli oggetti e delle eventuali
funzioni che andranno modificati e una stima
del tempo previsto per la personalizzazione
Esercizio

• Un cliente compra e vende barre di acciaio


• Le barre vengono gestite a magazzino a pezzi
• Ogni barra può avere un peso completamente
diverso dall’altra
• Ad ogni movimentazione del magazzino l’utente pesa
le barre da spedire (o quelle in entrata) e ha la
necessità di segnare il peso totale (in Kg) delle barre
movimentate
• Il cliente deve poter vedere sull’anagrafica articoli il
peso totale a magazzino delle barre
Esercizio

• Il peso deve essere obbligatorio nelle registrazioni di


un certo magazzino (es. nel BLU deve essere
obbligatorio, nel ROSSO no)
Esercizio

• La fatturazione delle barre di acciaio avviene dagli


ordini di vendita contestualmente alla spedizione
• Quando spedisco e fatturo le barre ad un cliente,
nella fattura deve apparire il peso