FACOLTÀ DI INGEGNERIA
Corso di Laurea in Ingegneria Informatica
Laureando: Relatore:
Daniele De Gan Chiar.mo Prof. Ing. Fermeglia
3
Introduzione
4
Analisi
1.1 Introduzione
Si espone in questo capitolo la fase iniziale del ciclo di vita del software, ossia l’analisi. Questo
momento, contrariamente a quanto si potrebbe pensare, risulta essere il più importante
dell’intera fase di produzione dell’applicativo. Si è erroneamente portati a credere infatti, che sia
la fase di codifica il punto critico, ma basti pensare che un errore di valutazione al momento
dell’analisi si ripercuoterà su tutte le fasi successive (benché queste siano svolte correttamente),
quindi sull’intero progetto. È quindi l’errore in fase di definizione dei requisiti il più grave che si
possa commettere, in quanto esso potrà essere rilevato solo al momento del collaudo
dell’applicativo con immaginabili conseguenze negative, soprattutto in progetti di grandi
dimensioni. Ecco perché nei casi di produzioni importanti si è soliti utilizzare modelli di sviluppo
misti, magari con l’aggiunta del ciclo di prototipizzazione, al fine di evitare in modo assoluto
grossolani errori in questo primo avanzamento della produzione. Nel nostro caso, vista la
limitatezza del lavoro, si è ritenuto sufficiente adottare un modello di sviluppo standard a cascata.
In generale un modello segue lo schema a blocchi proposto in Fig. 1.1 in cui l’output di ogni blocco
rappresenta l’input per il blocco successivo.
Nel dettaglio, il modello a cascata prevede le fasi di analisi, progetto, sviluppo, collaudo,
integrazione e manutenzione. Come è possibile notare in Fig. 1.2. il modello segue lo schema
generale appena descritto in cui ogni fase produce un ben determinato output che viene utilizzato
come input per la fase successiva.
5
Figura 1.2: Modello di sviluppo a cascata.
Va detto che non è stato necessario eseguire tutte le fasi del modello da zero. Essendo questo un
lavoro che si fonda su una progettazione già collaudata, alcune fasi, come la raccolta dei requisiti
mediante intervista e la realizzazione della base di dati non sono state affrontate e si è utilizzato il
materiale già presente, raccolto in precedenza.
6
1.2 I requisiti
I requisiti forniscono le linee guida sulle funzionalità e le operazioni che il sistema finale dovrà
essere in grado di svolgere. Si ottengono in vari modi, come interviste dirette agli utenti e
committenti, oppure utilizzando materiali quali documentazioni raccolte in momenti precedenti.
Nel nostro caso si seguirà questa seconda modalità. In particolar modo riportiamo l’intervista
effettuata all’impiegato della segreteria amministrativa del dipartimento, da cui è possibile
ricavare le caratteristiche che l’utente finale desidera vedere implementate nel sistema.
Nell’ordine che devo compilare devo inserire innanzitutto il codice del fornitore.
Questo è il mio elenco dei fornitori (un foglio appeso al muro davanti alla scrivania con il nome del
fornitore e il codice associato ad esso). Io inserisco il codice in Excel e mi da direttamente il nome,
l’indirizzo e i recapiti telefonici del fornitore, così non mi sbaglio. Poi devo inserire i dati relativi al
fondo. Sotto la voce “ESERCIZIO” vorrei che fosse già presente l’anno corrente. Qui, in “POS.FIN.”
vorrei che ci fossero una decina di elementi, quelli che vengono utilizzati più spesso, ma con la
possibilità di poterne aggiungere qualcuno ‘a mano’.
Sono i numeri dei conti correnti dai quali verranno prelevati i soldi per pagare la merce. In base al
tipo di acquisto, si sceglie a quale conto addebitarlo. È legata all’oggetto, l’ordine che noi facciamo
va inserito in un capitolo di spesa di bilancio. In “COMMESSA” scrivo ‘a mano’ il codice della
commessa, che mi viene dato di volta in volta dal responsabile della commessa. Si tratta
generalmente di acquisti per dei fondi di ricerca.
È una sigla che diamo noi. Per esempio supponiamo che si ottenga un finanziamento, mettiamo
5000 €, si chiama direttiva ministero, come premio, mettono una certa quota di fondi. È una
abbreviazione che decidiamo noi, con al massimo 8 caratteri. Per esempio “PRE05COL” significa
premio dell’anno 2005 di Colussi. In alternativa a “COMMESSA” bisogna compilare il campo
“C.D.C.”
7
-Cosa significa C.D.C.?
C.D.C. è il Centro Di Costo. Si inseriscono dei valori in questo campo nel caso di acquisti non
personali, ma che servono all’intero dipartimento. Questo campo può avere tre possibili valori:
120110 se è un ordine che serve al dipartimento in generale, 110111 se è un ordine per il
laboratorio, 120112 se invece si tratta di ordinare del materiale per la biblioteca. Quando al posto
della commessa c’è il C.D.C. non firma nessuno, solo il direttore del dipartimento. Il campo
“FORNITORE” vorrei che si riempisse automaticamente una volta inserito il fornitore nella parte
alta dell’ordine. La fase successiva consiste nell’inserire la descrizione del prodotto all’interno
dell’ordine.
No, non abbiamo un elenco di prodotti. Li inseriamo ‘a mano’ di volta in volta, perché non c’è un
elenco predefinito. Alcuni prodotti vengono acquistati più volte, ma ci sono anche acquisti che non
si ripeteranno mai come per esempio qualche macchinario. Poi c’è il prezzo da inserire in base al
preventivo che mi manda il fornitore.
Fino ad una certa cifra basta anche solo una telefonata, quando sono cifre grandi si fa un’indagine
di mercato. Dipende anche dal numero di ditte che forniscono un certo prodotto: se un prodotto ha
un unico fornitore, anche in questo caso basta una telefonata, altrimenti si procede chiedendo alle
ditte fornitrici di spedire via fax i vari preventivi. Poi si valuta qual è quello più conveniente e si
procede con l’ordine di acquisto. La maggior parte delle volte il preventivo è inteso IVA esclusa,
quindi nell’ordine bisogna aggiungere l’IVA al 20%. Alcune volte capita però che i prezzi dei
preventivi siano già ivati, in tal caso non serve aggiungere l’IVA nell’ordine. C’è ancora un terzo
caso in cui i preventivi sono senza IVA perché il prodotto dell’ordine è esente dall’IVA. Per questo
vorrei che nell’intestazione dell’ordine ci fosse la possibilità di nascondere il codice fiscale e la
partita IVA del nostro dipartimento, in quanto non sempre servono alla ditta fornitrice. Questo nel
caso di ordini all’estero in cui l’IVA la pagano loro e quindi non devono caricarla a noi, cioè nei casi
di commercio elettronico e di fornitura di servizi, non di beni materiali quindi. Mentre in Italia la
fattura è già gravata da IVA, per gli acquisti CE si pone un problema: l’IVA va a quale paese? Italia
o Estero? Si distinguono due casi: l’acquisto di beni materiali, in cui l’IVA va allo stato acquirente,
quindi la paghiamo noi; nel caso di servizio o commercio elettronico l’IVA va al paese fornitore,
dovrebbero metterla loro nella fattura. Quindi quando si toglie il codice fiscale e la partita IVA
dall’ordine significa che è la ditta fornitrice che deve pagare l’IVA.
Un ordine viene creato non necessariamente perché qualcosa finisce, come ad esempio la carta. Se
la carta finisce la ordiniamo noi senza problemi, ma un ordine può avvenire anche perché un
professore richiede una nuova apparecchiatura oppure perché si rompe un macchinario oppure
bisogna spedire qualcosa. Ci sono motivi molto diversi fra loro. Ad ogni ordine è poi necessario
assegnare un numero e una data. Alla creazione di un nuovo ordine vorrei che fosse proposta una
8
data, che possa però essere cambiata per eseguire ordini postdatati. Vorrei inoltre che ci fosse la
possibilità di modificare un ordine già effettuato, sia per poter correggere eventuali errori, sia per
evitare di ripetere tutta la procedura nel caso in cui, a distanza di tempo, bisognasse eseguire un
ordine già effettuato in precedenza. In questo caso basterebbe cambiare solamente la data e il
numero dell’ordine. Una volta completato l’ordine, il passo successivo è prendere l’impegno nel
sistema SAP. L’impegno non è vincolante per l’acquisto della merce, è una cosa interna al
dipartimento. Serve a bloccare i soldi di un certo fondo. Se poi l’acquisto non viene effettuato basta
azzerare l’impegno.
Procedura standard:
Si esegue l’ordine al fornitore (si invia subito via Fax alla ditta);
Prendiamo l’impegno di spesa nel sistema SAP (registrazione dell’operazione);
Arriva la merce e di conseguenza la fattura (solitamente la merce arriva dopo la fattura);
Registrazione della fattura in SAP;
Mandato di pagamento: ordine alla banca di effettuare il pagamento.
Il pagamento in genere viene effettuato 30 giorni dopo il ricevimento della fattura. Riguardo
all’impegno: di distingue in attività commerciale o attività istituzionale. Nel caso di attività
commerciale, bisogna inserire a fianco al numero dell’ordine la sigla “LE”, che identifica all’interno
del SAP questo tipo di attività. Attività commerciale: attività conto terzi, all’interno della quale ci
sono delle spese. Per le attività istituzionali bisognerebbe scrivere la sigla “DE”, che però non viene
messa. Vorrei che tutti gli ordini venissero salvati in un archivio che può essere interrogato secondo
diversi parametri. Bisogna prevedere un flag per ogni ordine che dovrà essere settato in caso di
ricezione della fattura. La consegna della merce equivale ad evadere un ordine, in questo modo
sarà possibile tenere traccia degli ordini non evasi.
Si deve produrre un applicativo per la gestione degli ordini ai fornitori. Lo scopo dell’applicazione è
di fornire un’interfaccia user-friendly per facilitare l’elaborazione del documento dell’ordine e in
particolar modo utilizzando una base di dati per l’archiviazione degli ordinativi. Il documento da
elaborare consisterà in un riepilogo dei dati dell’ordine, in particolar modo l’intestazione del
fornitore, l’elenco dei prodotti da ordinare e altri dati come ad esempio le date di ordine e offerta
ecc. La data che dell’ordine nel sistema deve avere come default la data odierna ma con la
9
possibilità di modificarla per effettuare ordini postdatati. In caso di attività commerciali va posto a
fianco del numero dell’ordine (calcolato in automatico ma con possibilità di modifica) la sigla “LE”,
per l’identificazione all’interno del SAP. Per le attività istituzionali vien omessa la sigla “DE” che
viene sottointesa.
Riguardo al fornitore della merce-servizio deve essere presente il nome, l’indirizzo e il numero di
Fax a cui poter eventualmente inviare l’ordine. La parte successiva all’intestazione è il corpo
dell’ordine. Devono comparire le quantità e le descrizioni delle merci, nonché i prezzi unitari e
l’IVA da applicare all’ordine. Non risulta necessario avere una tabella relativa ai prodotti, in quanto
questi non si ripetono così frequentemente. Particolare attenzione va prestata all’IVA. Vi sono tre
casi possibili: il più frequente è quello in cui il preventivo è inteso senza IVA. Nell’ordine andrà
aggiunta quindi il 20% di IVA. Vi è il caso poi in cui i preventivi sono già ivati, quindi non è
necessario aggiungerla al prezzo del preventivo ed infine si può presentare il caso in cui i
preventivi sono senza IVA poiché i prodotti richiesti ne sono esenti. Proprio in quest’ultimo caso
sarà necessario prevedere la possibilità di escludere dal resoconto dell’ordine sia il codice fiscale
che la partita IVA del dipartimento, in modo da far capire al fornitore che l’IVA è a suo carico.
Infine la parte bassa del documento dell’ordine dovrà contenere vari campi quali l’esercizio, la
posizione finanziaria, l’impegno, il centro di costo e il fornitore.
L’esercizio come già detto rappresenta l’anno finanziario corrente, utile per inserire l’ordine
all’interno del bilancio annuale. È un campo automatico, anche se potrà essere modificato al
momento dell’inserimento dell’ordine con valori a piacere.
La posizione finanziaria contiene il numero di conto corrente da cui verranno prelevati i soldi per
pagare la merce.
La commessa invece, è un codice alfanumerico di 8 cifre, scelto arbitrariamente dall’utente per
descrivere il tipo di commessa (utilizzato soprattutto per acquisti per dei fondi di ricerca).
Il campo relativo al centro di costo è alternativo alla commessa e si utilizza in caso di acquisti che
interessano l’intero dipartimento. Vi saranno vari codici per mappare i vari centri di costo (ad es.
120110 rappresenta un ordine per il dipartimento in generale).
Nel campo fornitore, verrà inserito il codice che all’interno del dipartimento rappresenta il relativo
fornitore in modo univoco.
Il campo impegno potrà essere compilato (eventualmente a mano) solo dopo aver preso
l’impegno di spesa all’interno del sistema SAP.
Una volta compilato l’ordine questo va salvato in archivio con possibilità di essere ripreso per
visualizzarlo o per modificarlo. Dovrebbe essere possibile interrogare l’archivio sotto vari
parametri. Dovrà infine essere previsto un flag per ogni ordine relativo al ricevimento della relativa
fattura.
10
La Base di Dati
2.1 Introduzione
Come già anticipato si è partiti, nella realizzazione dell’applicativo, da una banca dati preesistente.
Daremo, in questo capitolo, una breve descrizione della struttura del Data Base e in particolar
modo evidenzieremo le modifiche (aggiunte) apportate alle tabelle dello stesso, per poter
implementare alcune funzionalità utili. Una su tutte, l’invio automatico del documento
dell’ordine, generato dall’applicativo, direttamente alla casella di posta elettronica del fornitore.
In questa tabella sono (e possono essere) memorizzati i Centri di Costo con i relativi codici univoci
di identificazione.
Tutti i singoli prodotti ordinati vengono salvati in questa tabella. Grazie al campo [OrdineID] è
possibile correlare ogni record della tabella ad un ordine in particolare, che sarà memorizzato nella
11
relativa tabella. In sostanza in questa raccolta di record compaiono i dettagli dell’ordine (ossia la
descrizione, la quantità, il prezzo unitario e l’IVA).
TABELLA ‘FONDI’
TABELLA ‘ ORDINI’:
Gli ordini immessi e confermati nel sistema sono salvati in questa tabella. La tabella ‘Ordini’
assieme alla tabella ‘Dettaglio Ordini’ permette di “ricostruire” tutti i dati dei singoli ordini per
essere poi visualizzati e rivisti dall’utente.
TABELLA ‘MASTER’:
12
Questa è forse la più importante tabella dell’intero sistema. È stata creata per contenere
informazioni relative all’applicativo e permetterne il corretto funzionamento. Si nota subito che
essa è costituita da un unico record contenente numerosi campi eterogenei (24 per la precisione).
Di particolare rilevanza risulta essere l’aggiunta alla tabella originale di 7 nuovi campi (evidenziati
in rosso in Fig. 2.6). Sono campi contenenti svariate informazioni necessarie alla gestione della
connessione SMTP utilizzata per l’invio automatico dell’ordine al fornitore via posta elettronica, su
richiesta dell’utente. A differenza della versione precedente dell’applicativo, in cui era necessario
l’utilizzo di Microsoft Outlook, questa versione in .NET permette di gestire la connessione per
l’invio di posta elettronica (SMPT) direttamente con il server SMTP indicato nel campo
[ServerSMTP]. Sarà cura dell’utente compilare correttamente i campi mediante l’apposita finestra
“Manutenzione” che descriveremo più avanti.
TABELLA ‘IMPIEGATI’:
Permette la memorizzazione di tutti gli utenti che useranno il sistema e che quindi potranno
effettuare gli ordini delle merci. Possibili aggiunte future potrebbero prevedere un nuovo campo
*Password+ per l’implementazione di un sistema di Login personale all’avvio dell’applicativo.
TABELLA ‘FORNITORI’:
Tutti i dati relativi ai fornitori delle merci/servizi son qui memorizzati. In particolare i recapiti
telefonici e gli indirizzi delle società fornitrici. Il campo [Email] se richiesto dall’utente viene
sfruttato in automatico dal sistema al momento dell’invio dell’ordine via posta elettronica.
13
2.3 Struttura e schema del Data Base
Presentiamo in Fig. 2.9 lo schema fisico della Base di Dati, risultato delle fasi di progettazione
concettuale, logica e fisica, nell’ambito della normale creazione di un Data Base. Lo schema
comprende solo le sei tabelle che presentano correlazioni tra loro. È stata quindi esclusa la tabella
“Master” in quanto non risulta interessante ai fini della comprensione della struttura fisica del
Data Base.
Il fulcro, come si nota, è rappresentato dalla tabella “Ordini” relazionata con tutte le restanti
tabelle. Un’ulteriore modifica apportata al DataBase Originale è stata l’impostazione della
relazione tra la tabella “Ordini” e quella “DettaglioOrdini”. Una volta eliminato un ordine, infatti si
poteva presentare un errore in quanto il sistema (il database) non sapeva come comportarsi con i
record della tabella “DettaglioOrdini”. Tra le varie scelte ci sono: no fare nulla (verrà sollevata
però un’eccezione qualora si provi ad eliminare un record della tabella “Ordini”), impostare a NULL
i riferimenti nella tabella dei dettagli oppure eliminare anche i record collegati (Cascata). È
possibile scegliere il secondo o terzo intervento. Nel caso di questo applicativo, si è scelto di
eliminare anche i dettagli in cascata ritenendoli parte integrante dell’ordine e non riscontrando
particolari motivi per cui dovessero risiedere nel DB senza riferimento. Qualora si voglia sarà
comunque possibile modificare tale funzionamento direttamente nelle opzioni del motore data
base.
14
L’applicativo
3.1 Introduzione
Vista una panoramica sulle necessità e scopi del lavoro affrontato, e fornita una veloce descrizione
della Base di Dati su cui si fonda il nostro sistema, passiamo ora ad occuparci dello sviluppo vero e
proprio dell’applicativo. Si presenterà in questo capitolo una sintesi del percorso di progettazione
e codifica del software, mettendo in luce le tecniche e gli strumenti utilizzati per ottenere il
funzionamento desiderato.
Come delineato nella fase di analisi, il nostro applicativo deve essere in grado di gestire
l’inserimento degli ordini di un dipartimento universitario, al fine di produrre un documento
d’ordine da poter inviare alla ditta fornitrice della merce o dei servizi. L’aspetto importante sarà
dunque l’output dell’applicativo, rappresentato da un documento (in formato PDF e XLSX)
riassuntivo della merce ordinata e contenente tutte le informazioni che sono necessarie per poter
eseguire correttamente la richiesta e l’evasione dell’ordine. Tra questi dati troviamo quindi le
‘generalità’ della ditta fornitrice (indirizzo e recapiti), le date degli ordini e il loro numero
identificativo, nonché altri campi che descriveremo più in dettaglio al momento opportuno.
Come detto la qualità non è un parametro unico e assoluto, è bensì un insieme di caratteristiche e
parametri in cui lo sviluppatore deve trovare un compromesso accettabile, sempre tenendo conto
delle caratteristiche che l’utente vuole e comunque dal target dell’applicativo. Perché un software
sia definito “di qualità” dovrà seguire i parametri che di seguito elenchiamo:
15
Correttezza: esecuzione corretta dei suoi compiti (secondo le specifiche). Il prodotto
software è visto come una funzione computabile f(i): è corretto se ad ogni input (che sia
ammissibile per f) fornisce l’output appropriato (ossia quello desiderato dal cliente).
Efficienza: utilizzo economico e razionale delle risorse di calcolo. Deve essere efficiente dal
punto di vista spaziale e temporale, cioè utilizzare poca memoria di massa e centrale, non
intasare i canali di comunicazione e svolgere le funzionalità in poco tempo.
Robustezza: funzionamento anche in condizioni anomale. Un software è robusto se non
succede nulla di male quando l’input non è ammissibile per f(i). Bisogna quindi definire un
comportamento per la funzione quando l’input non è corretto: estensione del dominio e
gestione delle eccezioni.
Affidabilità: stabilità che comporta rari guasti. È la probabilità che non succedano errori
non dipendenti da input scorretti. Dipende da HW e SW ed è misurabile in tempo medio
tra due guasti o con la frequenza media dei guasti. Il livello di affidabilità richiesto dipende
dal sistema stesso e dall’uso finale.
Usabilità: facilità di apprendimento del suo utilizzo da parte dell’utente. Il sistema è usabile
se l’utente si trova a proprio agio con esso, fa pochi errori, lo trova gradevole e user-
friendly. Va calibrata sulla specializzazione dell’utenza e determina spesso il successo del
sistema.
Sicurezza: la possibilità di negare l’accesso ad utilizzi non autorizzati, ad esempio con
sistemi di login personali.
Mantenibilità: è una funzione della facilità di gestione dei problemi durante la fase di
utilizzo. Data da:
o Modificabilità: facilità di modifica a seguito della scoperta di un errore o di una
variazione delle necessità applicative; dipende dalla modularità, dalla leggibilità e
comprensibilità del codice e della documentazione allegata.
o Portabilità: facilità nel trasferimento in ambienti di hardware e software diversi.
Estendibilità: facilità di adattamento a modifiche (nelle specifiche).
Riusabilità: possibilità di utilizzare il software (tutto o in parte) per diverse applicazioni.
Strutturazione: grado di organizzazione interna in parti con funzioni specifiche ed
interagenti.
Leggibilità: capacità di presentare esplicitamente le scelte fatte dal progettista.
Compatibilità: facilità di combinare differenti prodotti software (necessità di standard).
Costo: deve essere adeguato e proporzionato rispetto ai benefici offerti.
16
Sicurezza Usabilità
Efficienza Portabilità
Affrontiamo qui la descrizione delle scelte progettuali, in particolar modo mettendo in risalto le
tecnologie scelte per l’implementazione del nostro sistema. Si fornisce una panoramica del
progetto .NET di Microsoft e del linguaggio C# scelto come linguaggio di sviluppo. Si passerà poi a
trattare le modalità di accesso ai dati dalle Form dell’applicativo, descrivendo come sia possibile
associare svariati controlli alle tabelle del nostro Data Base.
Per la creazione dell’applicativo di gestione degli ordini si è scelto di migrare da una tecnologia
fondata su un progetto ADP (Access Data Project) a .NET appunto, che rappresenta la più evoluta
visione Microsoft per lo sviluppo di applicazioni (desktop e Server) incentrate su un’ottica del
“linguaggio comune”.
.NET può essere definito in vari modi, ma fondamentalmente è un progetto, costituito da una suite
di prodotti, all’interno del quale Microsoft ha creato una piattaforma di sviluppo software, che
rappresenta una versatile tecnologia di programmazione ad oggetti. La strategia Microsoft ha
previsto lo sviluppo di .NET come contrapposizione al linguaggio JAVA (open source) e mira ad
attribuire alla propria creazione un ruolo strategico come piattaforma di sviluppo per applicazioni
desktop e server, nel prossimo decennio, per le architetture client/server, internet ed intranet. A
differenza del concorrente open source, .NET è uno standard ISO riconosciuto, quindi non è
possibile, da parte della casa madre, modificarne la sintassi, a meno che non si discosti dal suo
stesso standard.
La prima versione risale ormai al 2002 e la sua peculiarità è quella di essere indipendente dal
sistema operativo Windows su cui è istallato, nonché di includere molte funzionalità progettate
espressamente per integrarsi in ambiente internet e garantire il massimo grado di sicurezza e
integrità dei dati. Utilizza in modo esteso il concetto di modularità dei componenti software
17
(Component Oriented Programming), proponendosi così come evoluzione dell'esistente modello
COM (Component Object Model).
La CLR (Common Language Runtime) è un insieme di librerie che, insieme alla classe di librerie di
base denominata FCL (Framework Class Library), è progettata per poter funzionare con qualsiasi
sistema operativo. Il compilatore Just-In-Time esegue un codice assembly denominato CIL
(Common Intermediate Language). È inoltre possibile:
accedere a componenti scritti in altri linguaggi;
quando il sistema operativo sottostante è Microsoft Windows, accedere ai suoi servizi e
alle sue API;
accedere ai servizi web utilizzando il protocollo SOAP.
.NET è quindi corredato da una serie di strumenti di sviluppo delle applicazioni, progettati in modo
da essere integrati con la piattaforma .NET. Lo strumento più importante è rappresentato dall’IDE
(Integrated Development Environment ossia Ambiente di Sviluppo Integrato) denominato Visual
Studio, utilizzato per il nostro lavoro nella versione 2010. La CLI (Common Language
Infrastructure) è concepita per essere compatibile con qualsiasi linguaggio di alto livello orientato
agli oggetti, fornendo un unico modello a oggetti ed una vasta libreria di classi condivisibili.
3.3.2 Il linguaggio: C#
18
descritto: la prima seguendo appunto le procedure di binding automatico, la seconda istanziando
via codice gli oggetti necessari all’accesso.
19
Figura 3.3: Oggetti creati in automatico.
Come anticipato il Data Set permette di avere una copia delle tabelle costitutive del Data Base
originario, per gli usi che più desideriamo. Questa copia però prevede inizialmente solo la
struttura delle tabelle. All’avvio dell’applicativo, questi contenitori creati ad immagine e
somiglianza delle effettive tabelle del DB, devono essere riempiti, ossia popolati con i record reali,
sempre secondo le nostre direttive. Le operazioni di popolamento (FILL) e le altre funzionalità
come da esempio il salvataggio delle modifiche, non avvengono però direttamente sul Data Base
originale. A livello di applicazione prima di tutto si eseguono le modifiche alle tabelle dei Data Set;
per fare in modo che le modifiche si propaghino anche al livello inferiore è necessario l’oggetto
Table Adapter che fornisce vari metodi, tra cui l’UPDATE e che permette di collegare il Data Set
con le tabelle fisiche del DB.
Con l’operazione di trascinamento, abbiamo creato inoltre anche un altro controllo: il
DataGridView. Di per se questo controllo non è unicamente indirizzato alla visualizzazione di dati
con sorgente collegata ad un Data Base. È infatti un elemento che fornisce una tabella generica in
cui possiamo effettuare le più svariate operazioni, come per esempio inserire una nuova riga,
operare su colonne calcolate oppure ispezionare e modificare le singole celle. Però è appunto uno
strumento eccezionale se collegato ad una tabella di una base di dati, in quanto ci permette di
avere una visione immediata dell’insieme dei record che compongono la tabella associata. Sarà poi
possibile modificare, eliminare, semplicemente scorrere i record e i relativi campi, ed infine salvare
le modifiche apportate. L’oggetto che permette di associare ad un controllo (in questo caso il
DataGridView, ma vedremo che le potenzialità sono più ampie) un’origine dati è l’oggetto Binding
Source.
Nell’applicativo tale modalità è stata utilizzata soprattutto per gestire la visualizzazione e la
modifica di dati già presenti nel Data Base, mentre per le operazioni di inserimento di nuovi record
si è preferito, anche a scopo di apprendimento individuale, gestire via codice la creazione di tutti
gli oggetti necessari al collegamento dei controlli con il DB.
IL CONTROLLO DATAGRIDVIEW:
Il controllo DataGridView fornisce un sistema efficiente e flessibile per visualizzare i dati in formato
tabulare. È possibile utilizzare il controllo DataGridView per la visualizzazione in sola lettura di una
piccola quantità di dati oppure è possibile scalarlo per consentire di modificare la visualizzazione di
insiemi di dati di dimensioni maggiori.
20
Per creare comportamenti personalizzati nelle applicazioni, il controllo DataGridView può essere
esteso in numerosi modi. È possibile specificare ad esempio propri algoritmi di ordinamento a
livello di codice e creare tipi personalizzati di celle. L'aspetto del controllo DataGridView può
inoltre essere personalizzato facilmente scegliendo diverse proprietà. È possibile utilizzare come
origine dati molti tipi di archivi dati; il controllo DataGridView è tuttavia in grado di funzionare
senza alcuna origine dati associata, come già accennato. Nel nostro caso, dunque, abbiamo
impostato (in realtà noi non abbiamo fatto nulla, ci ha pensato Visual Studio) la proprietà
*DataSource+ sull’oggetto Data Binding (Fig. 3.4) relativo alla tabella da visualizzare. Impostando
poi le proprietà delle singole colonne abbiamo infinite possibilità di personalizzare il nostro
controllo, scegliendo ad esempio di nascondere alcune colonne, di renderle disponibili in sola
lettura ecc.
L’utilizzo precedente, è utile qualora sia necessario visualizzare i dati in forma tabellare ma la
personalizzazione è ulteriormente amplificata dalla possibilità di associare, con la medesima
operazione di “drag and drop”, anche i singoli campi delle tabelle a svariati controlli (Fig 3.5),
fornendo quindi numerose possibilità di creare form orientati ai dati secondo le nostre esigenze. È
possibile inoltre utilizzare sia la visione attraverso DataGridView associata ai controlli di dettaglio.
Quando si selezionerà un record tra quelli della tabella, automaticamente il BindingSource
provvederà ad aggiornare anche le TextBox (o i controlli da noi scelti) con i valori relativi allo
stesso record (Fig. 3.6). Questo consente di creare numerose varianti di maschere lista-dettaglio,
facendo in modo che nel DataGridView compaiano solamente alcuni campi indicativi e i restanti
21
valori vadano a formare il dettaglio della selezione, presentando e visualizzando il resto dei
controlli secondo il nostro piacimento.
In questo caso sono state utilizzate due TextBox ma i controlli disponibili vanno dalle Label alle
ComboBox e così via. Vedremo nella descrizione dei vari Form che costituiscono l’applicativo
sviluppato, come si sia sfruttata tale caratteristica per ottenere una maschera Lista-Dettaglio, per
esempio per la visualizzazione dell’archivio degli ordini o della lista dei fornitori memorizzati.
Solitamente viene creato, assieme al DataGridView anche il Binding Navigator (Fig. 3.7), ossia una
barra di pulsanti per ‘navigare’ all’interno dei record. Nel nostro caso è stata eliminata risultando
inutile, infatti le operazioni di salvataggio e di creazione di nuovi record è stata gestita unicamente
via codice con controlli Button personalizzati.
22
ACCESSO ‘VIA CODICE’:
L’alternativa all’uso del semplice drag & drop e delle procedure automatiche è quella di procedere
via codice alla definizione di tutti gli oggetti necessari per il collegamento con il data base. Si è
optato per questa scelta quando esigenze particolari di personalizzazione dei controlli l’hanno
richiesto, nonché per personale scelta volta alla miglior comprensione del funzionamento di
questo meccanismo alternativo.
Si procede definendo tre oggetti, come mostrato in Fig. 3.8 da questo stralcio di codice.
La connessione SQL permetterà di effettuare il collegamento con il Data Base da noi scelto. Per far
ciò sarà necessario impostare la proprietà [ConnectionString] con la stringa di connessione che
identifica la Base di Dati con cui creare la connessione. Per ottenerla, un modo rapido consiste nel
ripetere la “Configurazione guidata origine dati” fino alla schermata in cui viene proposta la
Connection String (Fig. 3.9). Copiamo la stringa (con il tasto destro del mouse>copia) e chiudiamo
la procedura guidata. Istanziamo quindi la connessione ed incolliamo la stringa nel nostro file di
codice impostandola come valore corrente per la proprietà “Connection String” della connessione
creata (Fig. 3.10).
23
Figura 3.10: Apertura della Connessione
Ora abbiamo la nostra connessione aperta ed il Data Set è pronto per ricevere i dati dal Data Base
sottostante. Per le operazioni che interessano le tabelle del DB e quelle del Data Set, come già
detto, è
necessario un
adattatore
Arrivati a questo punto il nostro Data Set è stato popolato con i record richiesti secondo la
direttiva SQL da noi scritta e, in pratica, abbiamo un’esatta copia dei dati del DB originale. Su
questi dati possiamo effettuare tutte le modifiche che desideriamo e queste non si estenderanno
in tempo reale alla Base di Dati sottostante, ma solo richiamando il metodo UPDATE
24
dell’adattatore SQL, in cui specifichiamo la tabella del Data Set che vogliamo sia aggiornata nel
Data Base.
L’uso di questa modalità di accesso ai dati è stato preferito nei casi in cui fosse necessario
aggiungere nuovi record alle tabelle del nostro DB. Tutte le tabelle del Data Set sono infatti
facilmente accessibili per le operazioni di inserimento nuova riga ecc. Mostriamo di seguito (Fig.
3.14) la serie di istruzioni per creare un nuovo record nella tabella “Impiegati” prendendo i valori
dei campi da delle TextBox compilate dall’utente:
Creando una nuova DataRow come nuova riga della tabella “Impiegati” del DataSet, prepariamo
un nuovo record che presenta la stessa struttura (numero campi e tipi) della tabella originale.
Successivamente è sufficiente accedere ai vari campi della nuova riga, come si farebbe con un
array di valori, per impostare il contenuto delle celle secondo le nostre esigenze. Qui si è fatto
coincidere tale valore con la proprietà Text delle TextBox, realizzando cosi una prima interfaccia di
inserimento dati da parte dell’utente.
Una volta riempita la riga, è il momento di aggiungerla al DataSet mediante il metodo Add()
relativo alla tabella e all’insieme delle righe di essa. In questo modo si ha un DataSet aggiornato
col nuovo record appena creato. Da notare, però, che le modifiche ancora non si sono propagate
al livello inferiore, ossia alla tabella “Impiegati” sul nostro Data Base SQL.
L’ultima operazione da eseguire, quindi, sarà quella di aggiornare la Base Dati con i nuovi record
immessi. È grossomodo l’operazione inversa della FILL. Mentre prima abbiamo copiato i valori dal
DB al DataSet ora facciamo il contrario, copiando le modifiche nelle tabelle originali. Questa
sequenza di operazioni va eseguita per ogni record nuovo da creare.
Quando tutte le operazioni di aggiornamento, modifica ed inserimento (o anche semplici letture di
valori) sono completate è buona norma ricordarsi di terminare la connessione SQL mediante la
chiusura (metodo Close()) e la liberazione delle risorse allocate, con il metodo Dispose() (Fig. 3.15).
La fase di codifica è la fase in cui le idee sviluppate nella progettazione vengono implementate
concretamente attraverso la creazione dei moduli funzionali e la loro progressiva integrazione. Si
riporteranno di seguito degli stralci di codice che descrivono le principali funzionalità
dell’applicativo.
Gran parte del codice è stato scritto per implementare il Form per l’inserimento di un nuovo
ordine in archivio. Innanzitutto presentiamo lo stralcio per il salvataggio di un nuovo record nella
tabella “Ordini” (Fig. 3.15).
try{nuovaRiga[1] = txtNumeroOrdine.Text;}
catch { }
try{nuovaRiga[2] = dtpDataOrdine.Text;}
catch { }
try{nuovaRiga[3] = cmbFornitore.SelectedValue.ToString();}
catch { }
try{nuovaRiga[4] = cmbFondo.SelectedValue.ToString();}
catch { }
try{nuovaRiga[5] = cmbImpiegato.SelectedValue.ToString();}
catch { }
try{nuovaRiga[6] = txtEsercizio.Text;}
catch { }
try{nuovaRiga[7] = txtCommessa.Text;}
catch { }
try{nuovaRiga[8] = cmbCentroDiCosto.SelectedValue.ToString();}
catch { }
try{nuovaRiga[9] = txtNumeroOfferta.Text;}
catch { }
try{nuovaRiga[10] = dtpDataOfferta.Text;}
catch { }
try{nuovaRiga[11] = ckbFattura.Checked.ToString();}
catch { }
try{nuovaRiga[12] = ckbCommerciale.Checked.ToString();}
catch { }
try{nuovaRiga[13] = txtNote.Text; }
catch { }
26
Per prima cosa, come già sintetizzato in precedenza, creiamo una nuova DataRow, con la struttura
dei record della tabella interessata (in questo caso la tabella “Ordini”). Ogni campo della nuova
riga viene poi riempita con il valore, relativo all’input dell’utente nei rispettivi controlli. Si noti
come si è scelto di inserire ogni salvataggio in un blocco try-catch. Questo permette, in caso di
qualche errore non previsto, di poter continuare l’esecuzione del programma senza crolli
irreparabili. Le eccezioni servono proprio per istruire il nostro applicativo su cosa fare in caso di
qualche malfunzionamento nell’esecuzione del codice contenuto nel blocco try,-. In questo caso il
blocco catch,- è stato lasciato vuoto, in quanto l’errore che si voleva gestire era il caso in cui la
TextBox, o ogni altro controllo, presentasse un valore indefinito, NULL. Provando a salvare infatti
in un campo un valore, prelevandolo dalla proprietà [Text] di una TextBox ad esempio , qualora
questa fosse nulla non restituirebbe una stringa valida e verrebbe sollevata un’eccezione. Il blocco
catch serve proprio a intercettare questo tipo di eccezione e permette dunque di non salvare nulla
nel campo interessato, come se si fosse saltata totalmente quella operazione. Si sarebbero potuti
mettere altri controlli sulla coerenza dei tipi di dati, per esempio, ma si è preferito eseguire queste
verifiche prima di passare al salvataggio vero e proprio, per poter eventualmente informare
l’utente, prima delle operazioni di archiviazione, che qualche campo non è stato compilato
correttamente, oppure che qualche valore obbligatorio non è stato inserito (Fig. 3.16).
Nell’esempio sottostante si verifica che il campo contenga una valore numerico. Per fare ciò si
prova a convertire la stringa contenuta nelle TextBox in interi con la funzione int.Parse(). Qualora
non sia presente una stringa che rappresenta un valore numerico valido, tale funzione solleva
un’eccezione. Questa viene catturata dal blocco catch,- e in questo caso viene colorato lo sfondo
della TextBox con un colore rosso per evidenziare e attirare l’attenzione sul controllo. In caso di
errore viene anche settata a False la variabile booleana okCheck che serve a segnalare a livello di
codice se sono stati rilevati errori. In caso affermativo, una volta terminate le operazioni di
verifica, si chiama una RETURN che permette di uscire dalla funzione corrente, in quanto non è
consigliabile continuare col salvataggio. Tutte queste operazioni saranno, come vederemo,
associate all’evento *Click+ di un pulsante del nostro Form.
27
Un’altra parte importante di codice, è quella che permette di creare e compilare il documento
dell’ordine. Utilizzando la versione 2010 di Visual Studio, purtroppo ci si è trovati di fronte al
problema della creazione dei report. Fino alla versione precedente infatti, Microsoft distribuiva,
già integrato nell’ambiente di sviluppo, lo strumento Crystal Report, duttile funzionalità per la
creazione ed esportazione dei report. Dall’ultimo aggiornamento del prodotto però, è stato scelta
la strada della distribuzione separata. Il Crystal Report compatibile con la versione 2010 però
ancora non è stato rilasciato e non ce ne siamo potuti servire nello svolgimento del lavoro qui
descritto. Per aggirare l’inconveniente si è trovata una soluzione accettabile che comporta come
unico requisito, che nel sistema in cui sarà eseguito l’applicativo, sia installata la versione 2007 di
Microsoft Excel. L’idea è quella di sfruttare un modello predefinito in cui compilare solo le celle di
interesse come l’intestazione e altri dati (quantità, descrizione e prezzo dei prodotti). Tale
modello, una volta compilato a nostro piacimento sarà salvato in una directory scelta dall’utente
sia in formato .Xlsx che in formato .Pdf. Questo per permettere di apportare modifiche manuali al
documento. Il documento in formato .Pdf invece può, su richiesta essere inviato automaticamente
via posta elettronica all’indirizzo predefinito del fornitore (recuperato dal Data Base) oppure ad un
indirizzo inserito dall’utente al momento della conferma dell’ordine.
Inoltre è stata implementata la possibilità di richiedere una stampa dell’ordine nel numero di
copie desiderato, agendo su dei controlli appositi che saranno descritti quando si affronterà la
discussione dell’interfaccia grafica.
Le operazioni implementate via codice, seguono la successione e la logica descritti nel seguente
schema a blocchi (Fig. 3.17).
Apertura File
Modifica celle del
Creazione EXCEL da Salvataggio del
modello secondo
Oggetti EXCEL. percorso nuovo documento.
input dell’utente.
predefinito.
Chiusura file e SI
liberazione delle Stampa? Eseguo stampa.
risorse allocate.
NO
SI
Mail? Invio Mail.
NO
TERMINE
OPERAZIONI.
28
A monte di tutto questo però, è stato necessario impostare i riferimenti alle librerie di Microsoft
Excel (Fig. 3.18) operazione indispensabile per poter automatizzare via codice Microsoft Excel.
Questa libreria ci permette di compiere tutte le azioni che potremmo svolgere se ci trovassimo
effettivamente di fronte ad un foglio di lavoro Excel: dall’apertura di un file, alla modifica del
contenuto delle celle e della loro formattazione, nonché il salvataggio e l’esportazione in svariati
formati disponibili.
Inoltre, per poter usare lo spazio dei nomi relativo alle classi di Excel, si è aggiunta la direttiva
“using”(Fig. 3.19).
Questo permette di rendere le dichiarazioni degli oggetti più sintetiche, senza l’obbligo di
specificare l’intero percorso dei nomi ogni volta (Microsoft.Office.Interop.Excel). La procedura
appena descritta, inoltre, è uguale per qualsiasi applicativo del pacchetto Microsoft Office noi
volessimo utilizzare nei nostri sistemi. L’integrazione risulta molto facile da implementare: è
sufficiente importare i riferimenti e si è immediatamente in grado di sfruttare numerose funzioni
che ci permettono di automatizzare l’esecuzione di operazioni complesse come quella di apertura,
modifica e salvataggio dei dati o addirittura di stampa dei documenti, aprendo numerose porte
alla realizzazione di software completi e alla risoluzione di problemi come nel nostro caso.
29
Dopo la descrizione delle operazioni ‘preliminari’ passiamo alla descrizione e al commento del
codice creato per svolgere i processi e la logica preannunciati in Fig. 3.17.
System.Reflection.Missing o = System.Reflection.Missing.Value;
Excel._Application MyApp;
Excel.Workbook MyWb;
Excel._Worksheet MyWs;
MyWs = (Excel.Worksheet)MyWb.Worksheets.get_Item(1);
In Fig. 3.20 sono mostrate le istruzioni per la prima fase delle operazioni per la creazione del
report: l’apertura del file. Sono necessari i tre oggetti che vediamo, ossia un’Application, un
Workbook e un Worksheet. Il Workbook è una classe che permette di istanziare dei contenitori
per i nostri fogli di Excel, ossia i Worksheet. Da notare anche che il percorso di apertura del file
viene composto a run-time a seconda della scelta dell’utente. Nell’interfaccia grafica, selezionando
il tipo di IVA da applicare, automaticamente si indirizzerà l’applicativo ad aprire uno dei tre modelli
predefiniti, differenti proprio per le diverse caratteristiche che devono avere gli ordini. Particolare
interessante è la funzione per aprire un Workbook, unica e con 15 parametri!
Il Path di origine dei modelli inoltre, viene reperito mediante ispezione della tabella “Master” del
nostro DataSet; si vedrà in seguito che tale percorso è modificabile dall’utente mediante l’apposito
menù di configurazione dell’applicativo. È fondamentale però che i modelli seguano la struttura di
quelli proposti, in quanto la modifica delle celle avviene con riferimento alle celle dei suddetti.
Detto ciò, pur dovendo utilizzare tali modelli, che comunque già vengono forniti con l’applicativo,
questi possono risiedere in qualunque directory del nostro sistema. Basterà solo avere l’accortezza
di specificare tale percorso nella voce di menù apposita.
Dopo queste operazioni, il nostro foglio Excel è aperto e pronto per essere modificato a nostro
piacimento. Il passo seguente è reperire i valori dall’interfaccia e caricarli nel file che diventerà poi
il nuovo file d’ordine compilato (Fig. 3.21).
30
try
{
//Riempio le celle con i valori dell'ordine (Quantità, Descrizioe e Prezzo Unitario).
Le successive istruzioni, invece prendono i dati dai restanti controlli del Form. Notare come la
commessa e il codice del Centro di Costo siano utilizzati solo dopo un test. In sostanza questi due
valori sono uno alternativo all’altro, quindi si verifica prima di inserire il valore se è stato scelto di
utilizzare la Commessa oppure il Centro di Costo, come richiesto e annotato nel documento dei
requisiti. Anche il numero dell’ordine deve tenere conto dell’indicazione se l’ordine sia di tipo
‘commerciale’ o meno, in caso affermativo viene aggiunta la sigla LE al numero d’ordine generato.
L’intera serie di istruzioni è racchiusa in un blocco try{} e il relativo catch{} cattura eventuali errori
che dovessero presentarsi durante le operazioni di modifica del WorkSheet. In questi casi di
anomalia, l’applicazione e il WorkBook vengono chiusi (ovviamente senza salvare le modifiche) e
inoltre viene mostrato un Messaggio che informa l’utente dell’impossibilità a creare il report.
Successivamente, sempre se l’utente lo desidera verrà eseguita la stampa del documento appena
creato, (Fig. 3.22) in un numero di copie dipendente da un controllo dell’interfaccia, ovviamente
modificabile dall’utilizzatore.
if (ckbStampa.Checked == true)
{
try
{
MyWb.PrintOutEx(o, o, nudCopie.Value, o, o, o, o, o, o);
}
catch { MessageBox.Show("Impossibile effettuare la stampa",null,MessageBoxButtons.OK);}
}
32
MessageBox con la scritta “Impossibile effettuare la stampa.”. Non avendo specificato nulla, verrà
utilizzata la stampante di default del sistema.
Finito di apportare le modifiche al modello, si provvede al salvataggio del documento.
//Chiudo il File salvandone una copia con il nome del fornitore e la data dell'ordine
//Salvo il file sia in PDF che in formato Excel per eventuali modifiche manuali.
MyWb.ExportAsFixedFormat(Excel.XlFixedFormatType.xlTypePDF, Percorso + "\\" +
cmbFornitore.Text.TrimEnd() + "_" + DateTime.Today.Day.ToString() + "_" +
DateTime.Today.Month.ToString() + "_" + DateTime.Today.Year.ToString()+ "_" +
txtNumeroOrdine.Text);
MyApp.Quit();
In Fig. 3.23 vengono mostrate le istruzioni per la chiusura e il salvataggio del documento d’ordine
creato. Si effettuano due salvataggi: il primo è un export del modello in formato PDF e ci permette
di creare un file, non modificabile, in formato PDF appunto. Sarà questo che verrà inviato via mail
al fornitore. Per la creazione dei nomi dei file si è scelto il seguente formato: ogni file sarà
costituito dal nome del fornitore seguito dal giorno, dal mese e dall’anno in cui è stato effettuato
l’ordine stesso più il numero dell’ordine. Se per esempio dovessimo effettuare un ordine al
fornitore “x” il 04/08/2010, il relativo file di riepilogo avrà nome: x_04_08_2010_y.pdf con y il
numero dell’ordine creato. Questo modo di nominare i file permette innanzitutto l’eventuale
inserimento (seppur improbabile) di più ordini verso lo stesso fornitore nello stesso giorno e
inoltre permette di creare un certo ordine nell’archiviazione dei file ottenuti dalle varie procedure
di inserimento.
Oltre al file PDF si è deciso anche di mettere a disposizione degli utenti anche la copia Excel
dell’ordine, questo per eventuali necessità di modifiche al foglio dell’ordine che saranno applicabili
manualmente aprendo separatamente il file desiderato, con la possibilità successiva di salvarlo o
esportarlo in PDF una volta ottenuti i risultati desiderati.
In entrambi i casi la directory di destinazione viene recuperata dal DataSet e in particolare nel
campo “DirectoryOrdini” della tabella master, con la seguente riga di codice mostrata in Fig. 3.24.
33
Figura 3.24: Recupero percorso di salvataggio
Alla stringa percorso, come visibile nelle figure precedenti viene concatenato il nome del file
appropriato andando così a ricreare il percorso assoluto di salvataggio del documento d’ordine.
A seguito della chiusura e del salvataggio del documento nei due formati, l’applicativo passa ad
esaminare se vi è la necessità o meno di inviare copia dell’ordina al fornitore. La logica viene
implementata con il codice riportato in Fig. 3.25. Viene testato il valore della checkbox relativa alla
scelta di invio. Se è impostata (valore = true) allora procede con le operazioni di creazione ed
inoltro della mail.
try
{
MailMessage email = new MailMessage();
email.From = new MailAddress(dataSet1.Tables["Master"].Rows[0]["ClientSMTP"].ToString(), "DanieleDeGan");
email.To.Add(new MailAddress(emailTextBox.Text));
email.Subject = dataSet1.Tables["Master"].Rows[0]["Oggetto"].ToString();
email.Body = dataSet1.Tables["Master"].Rows[0]["Corpo"].ToString();
email.Attachments.Add(new Attachment(Allegato));
SmtpClient Smpt = new SmtpClient(dataSet1.Tables["Master"].Rows[0]["ServerSMTP"].ToString(), 587);
Smpt.Credentials=new System.Net.
NetworkCredential(dataSet1.Tables["Master"].Rows[0]["NomeUtente"].ToString(),
dataSet1.Tables["Master"].Rows[0]["Password"].ToString());
Smpt.EnableSsl = true;
Smpt.Send(email);
MessageBox.Show("Mail Inviata", "", MessageBoxButtons.OK);
}
catch(System.Exception erroree){
MessageBox.Show("Non è stato possibile inviare la mail al Fornitore"+erroree.ToString(),
"Attenzione",MessageBoxButtons.OK);
}
L’invio di una mail da codice prevede la creazione di un istanza della classe “MailMessage”. Si
vanno poi ad impostare tutta una serie di proprietà che definiscono il messaggio da inviare.
Nell’ordine abbiamo dapprima settato il mittente, prelevando il nome del Client SMTP dalla ormai
nota tabella master. Sempre dalla stessa tabella si sono reperite altre informazioni: l’indirizzo del
destinatario, l’oggetto e il corpo della mail, il nome utente e la password per accedere al server
SMTP sempre impostato nella tabella “Master”. Nel caso riportato in figura la prova è stata
effettuata con il server di Gmail e l’account del sottoscritto. Quindi il server deve essere contattato
34
alla porta 587 (superfluo dire, anche questo valore impostabile da menù) ed è richiesta
l’attivazione della modalità di sicurezza SSL.
Alla mail è stato associato quindi l’allegato, cioè il file creato dalla procedura descritta in
precedenza. Una volta terminate le operazioni di preparazione del messaggio, mediante la
connessione SMTP è stato inviata la mail con il metodo Send().
Quando la mail è stata inviata l’applicativo mostra a video un messaggio che informa l’avvenuta
spedizione dell’ordine e restituisce il controllo all’utente.
In caso contrario il messaggio visualizzato permetterà di informare l’utilizzatore che qualcosa è
andato storto e che la mail non è stata inoltrata al destinatario. Per completezza, riportiamo il
semplice meccanismo che permette di rendere i campi “Commessa” e “Centro di Costo” uno
alternativo all’altro. Si è utilizzata una coppia di RadioButton, uno per selezionare l’uso del campo
relativo alla commessa e uno per scegliere il centro di costo.
In Fig. 3.26 la semplice logica che permette si selezionare uno dei due utilizzi escludendo l’altro,
impedendo così l’utilizzo nello stesso ordine di entrambi i valori.
Per ogni RadioButton si è gestito l’evento *CheckedChanged+, scatenato quando lo stato del
bottone cambia, passando da selezionato a deselezionato o viceversa. Si è provveduto quindi a
settare le proprietà ‘Enabled’ dei controlli relativi alla commessa e al centro di costo. In questo
modo, selezionando uno dei due RadioButton, l’evento permette di rendere i controlli associati
attivi e invece disattivare i restanti, implementando così l’alternanza dell’uso dei due ambiti.
Riportiamo infine la sequenza di istruzioni che viene eseguita al fine di aggiornare la Tabella in cui
vengono inseriti i dettagli dell’ordine (quantità, descrizione e prezzo del prodotto). Lo scopo è
quello di aggiornare i campi relativi al totale parziale e al gran totale dell’ordine durante
l’inserimento di nuovi prodotti, tenendo conto anche del tipo di IVA da applicare all’ordine. Ecco
perché le seguenti operazioni sono svolte sull’evento *CellEndEdit+ relativo alle celle della
35
DataGridView, ossia quando viene lasciata una cella della griglia l’evento esegue queste operazioni
(Fig. 3.27) che ora descriveremo.
//Codice per aggiornare la colonna calcolata relativa al totale parziale del prodotto.
int riga = dgwDettaglio.CurrentCell.RowIndex;
int colonna = dgwDettaglio.CurrentCell.ColumnIndex;
dgwDettaglio.Rows[riga].Cells[4].Value = parziale;
}
catch{
MessageBox.Show("Attenzione ai campi numerici!", "", MessageBoxButtons.OK);
}
//Ricavo il numero di righe inserite.
int numeroRighe = dgwDettaglio.Rows.Count;
double somma = 0;
try{
for (int i = 0; i < numeroRighe - 1; i++){
somma = somma + double.Parse(dgwDettaglio.Rows[i].Cells[4].Value.ToString());}
txtTotale.Text = "€ " + somma.ToString();
}
catch { }
}
}
Si reperiscono innanzitutto i valori della riga corrente ed in base alla selezione dell’iva si compila in
automatico il campo relativo. Infine, con un ciclo, si esegue un’operazione di somma di tutti i totali
parziali utilizzando come indice massimo il numero righe – 1 (istanziate) che si può ottenere con il
membro Rows.Count() della classe DataGridView. Infine si aggiorna il campo txtTotale con la
somma corrente dell’ordine, preceduto dal simbolo della valuta. Nel caso di input non corretti,
come ad esempio valori alfanumerici nelle celle di tipo numerico, il sistema gestisce le relative
eccezioni senza causare il blocco dell’applicativo.
Operazioni analoghe sono svolte ogni volta che si cambia la selezione dell’IVA nell’interfaccia.
Riportiamo il codice relativo all’impostazione dell’IVA al 20% (Fig. 3.28). Gli altri due casi sono
analoghi, infatti cambia solo il valore da impostare nella colonna “IVA” della tabella che sarà 0
invece che 0,2 (20%).
36
private void radioButton1_CheckedChanged(object sender, EventArgs e){
//Iposto l'IVA al 20%
if (rdbIva20.Checked == true){
int numeroRighe = dgwDettaglio.Rows.Count;
try{
for (int i = 0; i < numeroRighe - 1; i++){
dgwDettaglio.Rows[i].Cells["IVA"].Value = 0.2;
try{
double quantità = double.Parse(dgwDettaglio.Rows[i].Cells[0].Value.ToString());
double prezzo = double.Parse(dgwDettaglio.Rows[i].Cells[2].Value.ToString());
double iva = double.Parse(dgwDettaglio.Rows[i].Cells[3].Value.ToString());
dgwDettaglio.Rows[i].Cells[4].Value = parziale;
}
catch { }
}
double somma = 0;
try{
for (int i = 0; i < numeroRighe - 1; i++){
somma = somma + double.Parse(dgwDettaglio.Rows[i].Cells[4].Value.ToString());}
txtTotale.Text = "€ " + somma.ToString();
}
catch { }
}
catch { }
}
}
Come richiesto dal committente, inoltre, all’inserimento di un nuovo ordine viene creato il numero
d’ordine più appropriato con l’algoritmo mostrato un Fig. 3.29.
Ciò che viene fatto è il recupero dell’ultimo numero d’ordine archiviato. Si verifica prima quanti
ordini sono inseriti nella tabella, al fine di trovare l’indice del record a cui accedere. Poi si legge il
valore del numero d’ordine e dell’anno in cui è stato eseguito l’ultimo ordinativo. Se l’anno è
quello corrente si incrementa di un’unità l’ultimo codice noto, altrimenti vuol dire che si è in un
nuovo anno e si assegna il valore 0 all’ordine, come primo ordine dell’anno corrente.
37
Riportiamo infine, per completezza, anche il codice che permette il salvataggio dei record relativi
al dettaglio degli ordini (Fig. 3.30). Grazie ad un ciclo, si scorrono tutte le righe inserite nella
tabella, recuperando i vari campi e salvandoli, ad ogni iterazione, in un nuovo record che viene
inserito nel dataset. Il numero di iterazioni da eseguire viene calcolato grazie al reperimento del
numero di righe che costituiscono la tabella, mediante il metodo Count().
Al termine delle iterazioni, il DataSet contiene tutti i nuovi record relativi ai prodotti da ordinare.
Per estendere e salvare le modifiche al Database sottostante viene chiamato il metodo Update()
dell’adattatore associato alla tabella “Dettaglio Ordini”.
DataRow n1 = dataSet1.Tables["DettaglioOrdini"].NewRow();
n1[1] = LastId;
n1[2] = int.Parse(dgwDettaglio.Rows[i].Cells["Quantità"].Value.ToString());
n1[3] = dgwDettaglio.Rows[i].Cells["Descrizione"].Value;
n1[4] = double.Parse(dgwDettaglio.Rows[i].Cells["Prezzo"].Value.ToString());
n1[5] = double.Parse(dgwDettaglio.Rows[i].Cells["IVA"].Value.ToString());
//Aggiorno il dataAdapter.
dataAdapter2.Update(dataSet1, "DettaglioOrdini");
38
3.5 Test
Al termine della codifica, il ciclo di produzione del software deve prevedere una fase di Testing.
La fase di test e collaudo serve a verificare che il prodotto software sia corretto. Normalmente
nell’industria del software, si tratta di una fase lunga e costosa, che può incidere anche per il 50%
sul costo del prodotto finito. Questa fase si divide usualmente in:
Verifica (verification): viene svolta all’interno dell’azienda del fornitore del software; il
prodotto viene confrontato col documento delle specifiche e con il cosiddetto progetto di
dettaglio.
Certificazione (validation): viene svolta nell’ambiente finale, nell’azienda del cliente, in
presenza di utenti e committente; si confronta il prodotto software con il documento dei
requisiti e si controlla che il prodotto ottenuto sia quello richiesto.
Come per la progettazione, anche il testing può essere effettuato con direzione top-down o
bottom-up, ma normalmente si sceglie un compromesso tra le due tecniche. In generale si osserva
che è più conveniente effettuare test frequenti e brevi.
Esistono diverse tecniche per questa importante fase:
Va sottolineato che in ambito industriale il prodotto, per la fase di testing, viene fatto provare ad
un team diverso da quello che l’ha sviluppato. Vediamo ora i diversi livelli:
Test di unità: l’unità è il più piccolo blocco di codice che ha senso collaudare;
Test di modulo: insieme di unità interdipendenti;
Test di sottosistema: il sottosistema è un aggregato significativo di moduli, spesso
progettati da team diversi (problemi di interfaccia);
Test di sistema o integrazione: test del prodotto completo;
α-test: se il sistema è progettato per un unico cliente, viene portato nel luogo in cui dovrà
lavorare e collaudato con i dati con cui dovrà operare;
β-test: se il sistema è distribuito ad una comunità di utenti, viene dato in prova a più utenti
che lo utilizzano e forniscono al produttore osservazioni ed errori rilevati;
Benchmark: il sistema viene testato su dati standardizzati e di pubblico dominio per il
confronto con prodotti già esistenti sul mercato. Può essere incluso nel contratto.
Stress-testing si verifica il comportamento del sistema quando è sovraccarico di lavoro,
portandolo al limite e verificando che il sistema fallisca in modo accettabile (fail-soft).
Al termine del debugging, si esegue il cosiddetto “Test di regressione”, cioè la verifica del
comportamento del modulo corretto nei confronti degli altri moduli con cui coopera, per vedere
se sono stati introdotti nuovi errori.
Appurato infatti che è impossibile creare un software privo di errori, lo scopo di questa fase è
quello dunque di rilevarne e correggerne il più possibile, avendo l’accortezza di verificare che tali
correzioni non si rivelino controproducenti, inserendo ulteriori errori nel sistema.
Consideriamo i seguenti grafici per farci un’idea di quello che si intende.
40
Figura 3.31: Distribuzione errori - A Figura 3.32: Distribuzione errori - B
Nelle precedenti figure (Fig. 3.31 e Fig. 3.32) si vuole mostrare l’andamento della distribuzione
degli errori. Nel primo caso si mettono in relazione gli errori già riscontrati (ascisse) e la probabilità
di esistenza di ulteriori errori (ordinate).
Nel secondo grafico, invece, sono posti a confronto il tempo di manutenzione (ascisse) e il numero
di errori presenti nel software (ordinate).
In sostanza ciò denota il rischio a cui si accennava prima: ossia l’introduzione di nuovi errori
durante la correzione di altri. È necessario quindi porre molta attenzione alle modalità e alle
tempistiche della fase di testing.
41
L’interfaccia grafica
4.1 Introduzione
In questo capitolo verrà presentato l’applicativo dal punto di vista dell’interfaccia utente.
Verranno proposte le immagini dei Form sviluppati e descritte le scelte grafiche e funzionali che li
caratterizzano. Verrà dapprima proposta un breve excursus sull’interfaccia utente, sottolineando
l’aspetto fondamentale che ricopre nella creazione di un prodotto di qualità.
Con interfaccia utente si intende ciò che si interpone tra la macchina (calcolatore nel nostro caso)
e l’utente (persona fisica) e che quindi permette di far comunicare l’uomo con la macchina.
Fondamentalmente è un linguaggio operazionale che permette di tradurre le volontà dell’utente
in operazioni eseguibili dal calcolatore. Si tratta, in altre parole, di un canale di comunicazione che
ha la caratteristica di essere bidirezionale: permette infatti tanto all’utente quanto al computer di
dialogare tra loro. Questo dialogo è costituito, da un lato, da richieste che l’utente invia al
computer per lo svolgimento di determinate funzioni (input) e dall’altro, dalle risposte - di
conferma o insuccesso - che computer invia all’utente (output) relativamente alle richieste
ricevute. Il modo, e la soddisfazione, dell’utente finale nel fornire gli input e nel ricevere gli output
dipendono dalla interfaccia utente a disposizione.
Al giorno d’oggi l’interfaccia utente si è spostata sempre di più verso la GUI (Graphical User
Interface) comunemente abbreviata in “interfaccia grafica”. Non è altro che un paradigma di
sviluppo che mira a consentire all'utente di interagire con il computer manipolando graficamente
degli oggetti, svincolandolo dall'obbligo di imparare una serie di comandi da impartire da tastiera
sulla cosiddetta linea di comando, della shell di sistema, come invece avviene invece nelle più
tradizionali interfacce testuali CLI (Command Line Interface). È quindi lo strato di un'applicazione
software che si occupa del dialogo con l'utente del sistema utilizzando un ambiente grafico.
42
Per rendere al meglio cosa significhi dal punto di vista ‘psicologico’ un’interfaccia utente (grafica
nel nostro caso specifico), calza a pennello un’affermazione di Leonardo da Vinci, che ebbe modo
di sentenziare:
Da questa affermazione possiamo decifrare in parte quale sia la “strategia” dell’interfaccia grafica
e il motivo per cui ha riscosso e continua a riscuotere, in misura sempre più ingente, tanto
successo. Essa sfrutta un bagaglio di conoscenze e percezioni che ognuno di noi ha già acquisito in
modo naturale durante l’esistenza, un po’ come se riuscisse a tirar fuori dagli utenti una
conoscenza potenziale che li accomuna. I vantaggi sono indiscussi: basti pensare che, se la filosofia
dell’interfaccia grafica è quella di rendere naturale l’uso delle applicazioni, senza lunghi percorsi di
apprendimento, sfruttando invece conoscenze innate degli utenti, gli utilizzatori finali
acquisteranno padronanza del prodotto in maniera più rapida e naturale. Ciò permette quindi di
ridurre i tempi e i costi di istruzione degli utenti, apportando notevoli benefici alla produttività e al
bilancio aziendale. Il tempo di apprendimento viene posto ai primi posti nella valutazione di un
applicativo software. Introdurre una nuova tecnologia in azienda significa andare incontro, in un
primo tempo, ad un decremento della produttività aziendale, dovuta proprio al fatto che le
operazioni, che prima si svolgevano in modo quasi meccanico da parte degli utenti, devono essere
eseguite con modalità diverse nella nuova applicazione. L’andamento delle produttività
influenzata dall’introduzione del nuovo prodotto è sintetizzato in Fig. 4.1.
Ad una prima occhiata si possono fare varie considerazioni; innanzitutto l’andamento totale del
grafico ci dice che l’inserimento della nuova tecnologia permette di raggiungere livelli di
43
produttività più elevati, che in sostanza vuol dire “più operazioni svolte, in minor tempo”. Tale
obiettivo non è però esente da difficoltà. La reazione iniziale, (naturale si può dire) è quella di un
calo del livello produttivo, flessione dovuta al rallentamento nello svolgere le mansioni usuali e
all’apprendimento dell’uso del nuovo applicativo. Tanto più la flessione iniziale sarà limitata e
l’incremento finale sostanzioso, tanto si potrà parlare di interfaccia di qualità.
La realizzazione di un’interfaccia di qualità deve tenere conto di molteplici aspetti, primo su tutti si
devono avere ben chiare le categorie di utenti che andranno ad utilizzare l’applicativo. Il loro
livello si discosta anche sensibilmente e può essere così riassunto:
Principianti: sono coloro che non conoscono l’applicazione, cercano ed esplorano prima di
tutto il ‘cosa’ può fare l’applicazione invece che del ‘come’ e utilizzano principalmente il
mouse per muoversi tra i vari settori dell’interfaccia. Sono molto prudenti in quanto è forte
in loro la paura di provocare guai irreparabili. Sarà buona norma, quindi, prevedere
un’interfaccia con messaggi di conferma che avranno lo scopo di far prendere maggior
sicurezza all’utente. Questi utenti evolvono in tipologie successive.
È doveroso sottolineare come le precedenti categorie di utenti non si presentano in modo singolo,
ma coesistono nello stesso momento, rendendo necessario trovare un compromesso, nello
sviluppo dell’interfaccia, che metta d’accordo tutti, non intralciando gli utenti più esperti e non
lasciando senza aiuti quelli meno avvezzi all’utilizzo dell’applicazione.
44
Detto questo, alcuni degli aspetti fondamentali di un’interfaccia grafica possono essere riassunti
come segue:
Usabilità: prima di tutto l’interfaccia deve essere di facile utilizzo. Bisogna cercare di
rendere per così dire, “accogliente” l’ambiente di lavoro dei nostri utenti, indirizzando in
modo naturale le loro scelte, senza l’obbligo di seguire percorsi troppo complicati per
svolgere le operazioni disponibili. La dose giusta di aiuti e consigli, sottoforma ad esempio
di tool-tip o etichette informative può aiutare l’utilizzatore ad acquisire padronanza nelle
prime fasi di approccio all’applicazione. Non a caso si parla di “giusta dose”: una
sovrabbondanza di questi elementi può portare a risultati opposti a quelli desiderati,
rendendo pesante il software e facendo percepire a chi sta usando il programma una
sensazione da ‘fiato sul collo’. Tutte queste considerazioni sono alla base di studi che
cercano di individuare i modi migliori di far entrare in sintonia l’utente con i prodotti. Ciò si
traduce in particolari indicazioni sulla scelta dei colori, dei controlli, della comparsa dei
messaggi d’aiuto e di avviso ecc.
Colore: è un aspetto importantissimo nel applicazione visuale. La scelta dei colori deve
orientarsi su gradazioni che permettano di non stancare l’occhio, anche dopo molte ore di
utilizzo del programma. Assolutamente da evitare maschere e Form stile “arlecchino” con
colori spaiati che diventano elementi di disturbo e fastidio. L’uso dei colori è utile anche
come messaggio di avviso o come mezzo focalizzatore dell’attenzione dell’utente.
Coerenza: bisogna perseguire una coerenza nello stile dell’applicativo. Scelto uno stile, si
deve cercare di non discostarsi da esso, creando una sensazione di armonia tra le varie
finestre, con elementi comuni che diano una personalità propria al software.
Sobrietà: non si devono creare ammassi di controlli in spazi esigui, ossia non dobbiamo
esagerare con l’abbondanza di oggetti nella stessa finestra. In caso di necessità sarà buona
norma pensare a soluzioni alternative per ‘alleggerire’ i vari Form, contribuendo ad
eliminare la classica sensazione di ‘claustrofobia’ e di disorientamento che si ha di fronte
ad una maschera zeppa di oggetti.
45
4.3 Presentazione dell’interfaccia
Passiamo ora all’esposizione delle parti grafiche dell’applicazione. Si da in questo paragrafo una
panoramica dei Form e si fornirà per ognuno una spiegazione delle funzionalità implementate.
Il Form di avvio è quello del [Menù Principale], impostato per essere visualizzato al centro dello
schermo dell’utente. In Fig. 4.2 possiamo vedere una sua immagine.
46
configurazione generale dell’applicazione, come già brevemente anticipato paragrafo relativo della
codifica.
Una nota relativa allo stile grafico: quello utilizzato prende spunto dalla versione precedente del
software. Tale scelta si pone come obiettivo quello di mantenere un filo logico tra la versione
originale e questa in .NET, ed è stata ponderata seguendo le direttive prima descritte secondo cui
il l’interfaccia grafica deve essere coerente e soprattutto deve mettere a proprio agio l’utente. In
sostanza si è pensato che un primo modo per realizzare questo obiettivo fosse quello di
mantenere alcune caratteristiche precedenti, dando la sensazione di un qualcosa di già visto e
conosciuto e contribuendo, quindi, ad un approccio più naturale e rilassato all’uso del software di
nuova introduzione. In Fig. 4.3 possiamo vedere la maschera di avvio del software, sviluppato in
Microsoft Access, di cui si è voluto mantenere lo stile base.
Non c’è comunque dubbio sul fatto che l’utilizzo di Visual Studio e di C# permetta di avere a
disposizione un bagaglio di potenzialità, per quanto riguarda la personalizzazione dell’interfaccia,
notevolmente superiore rispetto all’uso di Access, seppur dignitoso se affiancato dalla gestione
degli eventi con codice VBA (Visual Basic for Application). In un primo utilizzo di queste tecnologie
utilizzate, il tutto può sembrare più complicato e difficoltoso, ma si tratta di una sensazione
momentanea, dovuta proprio al fatto che in C# non vi sono spesso il numero di funzioni e metodi
built-in relativi ai vari controlli, ma è necessario svilupparle personalmente, con indubbiamente un
lavoro mentale e ‘manuale’ maggiore, ma che permette di scrivere, eseguire e creare esattamente
quello di cui si necessita per quello specifico controllo.
47
Cliccando sul pulsante in alto a sinistra [Nuovo Ordine], viene aperto il Form per la gestione dei
nuovi ordini (Fig. 4.4).
È un Form caratterizzato da tre parti fondamentali: due pagine di un TabControl, che permette di
creare dei Form tabulati, e un’area inferiore che risulta essere presente qualsiasi pagina si stia
visualizzando nella maschera. Di default l’apertura del Form avviene sul prima pagina ossia su
quella relativa all’inserimento dei cosiddetti “Estremi dell’ordine”, cioè i dati principali di
identificazione di un ordine.
Al caricamento del Form relativo al nuovo ordine viene innanzitutto caricato nella TextBox
[Numero Ordine] il valore più appropriato da assegnare all’ordinativo. Tale valore, come già
mostrato in Fig. 3.29, è calcolato secondo le richieste del committente, con numerazione ad
incremento di un’unità per ogni ordine e azzeramento del contatore all’inizio del nuovo anno.
Compaiono poi, appena al di sotto del numero dell’ordine, due checkbox relative alla fattura e ad
attività commerciali. Quella per la fattura non trova di solito particolare interesse all’inserimento
dell’ordine, infatti sarà impostata solo all’evasione dell’ordine stesso. È importante invece
segnalare, soprattutto a livello di SAP, attraverso la spunta della checkbox relativa, se l’ordine si
riferisce ad un’attività commerciale. Come richiesto, infatti, qualora sia così, nel documento
riassuntivo dell’ordine sarà aggiunta, accanto al numero dell’ordine anche la sigla “LE”. Campi
compilati in automatico sono anche quelli relativi all’anno di esercizio e alla data dell’ordine,
caricati rispettivamente con l’anno e la data correnti. Di particolare effetto sono i controlli per la
48
scelta della data; è possibile infatti utilizzare un calendario, che compare una volta cliccato il
campo del controllo, andando quindi a selezionare direttamente la data richiesta che viene quindi
impostata come selezione.
La coppia di campi [Numero Offerta] e [Data Offerta] rappresentano informazioni relative
all’eventuale preventivo che la ditta fornitrice ha rilasciato al dipartimento. Sono campi facoltativi,
infatti saranno compilati solo se prima di effettuare l’ordine è stata effettuata un’indagine di
mercato con la raccolta dei vari preventivi. Basti ricordare che per ordini fino ad una certa cifra, il
preventivo può essere e viene richiesto per via telefonica.
Raggruppati dalla GroupBox con titolo “Utente” ci sono i controlli di selezione dell’utente, ossia di
colui che compila ed effettua l’ordine. Tramite un controllo ComboBox, si può scegliere il cognome
dell’operatore e, in caso di omonimie, è possibile aiutarsi con l’indicazione del nome visualizzata
dalla TextBox sottostante.
Con la stessa tecnica si seleziona la ditta fornitrice della merce o dei servizi. Scegliendo una delle
voci disponibili, vengono visualizzati anche le principali informazioni della ditta, tra cui l’indirizzo (e
la città), il CAP, il codice e il numero di Fax associati.
Nella parte destra di questa schermata è stata implementata la funzione di immissione del codice
della commessa o della selezione del centro di costo. Si ricorda infatti che la commessa, utilizzata
per gli acquisti personali è usata in alternativa al centro di costo (impiegato invece per acquisti che
interessano l’intero dipartimento) e viceversa. La scelta avviene prima selezionando uno dei due
RadioButton distinti dalle etichetta [Commessa] e [C.d.C.]. Come già spiegato, dal lato codice
questo scatena l’evento “CheckedChange” a cui abbiamo associato il codice mostrato in Fig. 3.26.
Automaticamente quindi i controlli di uno o dell’altra “modalità” vengono nascosti a seconda della
scelta dell’utente, permettendo quindi di implementare in maniera intuitiva la necessità di
utilizzare o il codice della commessa oppure le informazioni relative al centro di costo.
Si passerà poi alla scelta del fondo mediante la ComboBox relativa.
Infine nella parte inferiore si è inserito un’area per un campo note. In questo spazio l’utente potrà
inserire qualsiasi annotazione riguardi l’ordine.
Come si può notare, per dare una sensazione di organizzazione e ordine, si è fatto largo uso del
controllo “GroupBox” che, come indica il nome, permette di raggruppare vari tipi di controlli per
creare aggregati di oggetti contribuendo a creare più coerenza nell’interfaccia grafica,
suddividendola in varie ‘zone di funzionalità’.
Inoltre per facilitare la navigazione tra i controlli mediante l’utilizzo della tastiera, è possibile
sfruttare il tasto TAB per focalizzare la selezione sul controllo successivo. Impostando la relativa
proprietà del Form, è possibile inoltre decidere in che sequenza verranno selezionati i controlli e
quale sarà il primo elemento della ‘sequenza’ ossia l’oggetto che avrà la selezione attiva al
caricamento del Form, fornendo soluzioni per gli utenti esperti di cui si è parlato poco sopra.
Finita la compilazione dei campi relativi agli estremi dell’ordine si passerà poi alla seconda ‘pagina’
del Form, quella relativa al dettaglio dell’ordine. Tralasciamo, momentaneamente, la descrizione
della parte inferiore della maschera che, come vedremo, è comune anche all’altra pagina che
compone questo Form.
49
Cliccando dunque sul secondo tab, facciamo comparire la pagina mostrata in Fig. 4.5.
Tramite questa finestra l’utente potrà inserire i restanti dati relativi all’ordinativo. Spicca nella
parte centrale, la tabella per l’elenco dei prodotti da richiedere nell’ordine. Infatti in ogni ordine è
possibile specificare più di una tipologia di prodotto e, ad ogni prodotto, corrisponderà una riga in
tale tabella. La sotto-maschera è formata da cinque colonne, di cui l’ultima *Parziali+ è una colonna
calcolata, ossia si serve dei valori inseriti nelle altre per impostare il proprio stato. Per ogni
prodotto si deve specificare la quantità desiderata, la descrizione, il prezzo e l’IVA da applicare. In
caso si volesse eliminare uno dei record del dettaglio, basterà selezionare la riga relativa e fare clic
sul pulsante [Rimuovi Prodotto] per eseguire tale operazione. Il totale parziale è calcolato per ogni
prodotto mediante l’operazione :
Ciò permette di calcolare direttamente nella colonna [Totale Parziale] il totale per il singolo
prodotto, tenendo conto dell’IVA desiderata. Inoltre automaticamente, tenendo conto di ogni
cella dei totali parziali, viene compilato il campo relativo al Totale dell’ordine. Delle cinque colonne
della maschera sono modificabili dall’utente solo quelle relative alla quantità, alla descrizione e al
50
prezzo unitario. Come già detto l’ultima, quella dei totali parziali è calcolata automaticamente,
mentre la colonna dell’IVA viene impostata a seconda delle scelte dell’utente nei radiobutton
appositi. Raggruppati sotto la voce IVA troviamo infatti i tre controlli mediante cui è possibile
scegliere l’IVA da applicare all’ordine. Per la maggior parte degli ordini l’IVA da applicare è del
20%, infatti si è scelto di impostare tale valore come default. In questo caso l’applicativo
provvederà, ad ogni nuova riga inserita nel dettaglio a compilare la cella relativa all’IVA con il
valore 0,2. Il calcolo del totale parziale sarà dunque in questo caso:
In cui: 1,2 = 1+20%. Ci sono altri casi in cui i prezzi dei prodotti presenti nei preventivi richiesti alle
ditte di fornitori, sono ritenersi IVA inclusa. Si utilizzerà quindi la seconda opzione [Iva Inclusa].
Questo farà si che il valore nella colonna IVA della tabella sia impostata in automatico a 0 e il
totale parziale sarà ottenuto semplicemente moltiplicando ogni quantità per il relativo prezzo
unitario. Infine l’ultimo caso che può presentarsi è quello in cui i prodotti da ordinare siano esenti
da IVA, in quanto costituiscono commercio elettronico o forniture di servizi. Anche in questa
situazione la colonna dell’IVA conterrà il valore 0 e il totale parziale di ogni dettaglio sarà calcolato
come al caso precedente.
Infine vi è la possibilità di specificare l’IVA da parte dell’utente con l’ultimo radiobutton e la
relativa casella di testo. La scelta di una delle quattro opzioni risulta inoltre fondamentale anche
per la compilazione dei report degli ordini. Ad ogni ambito dell’IVA, infatti viene scelto il modello
di report da compilare, in quanto ogni condizione dell’IVA presenta delle necessità da
implementare nel resoconto, come il caso dell’esenzione, in cui si richiede di nascondere nel
documento finale, sia la partita IVA che il codice fiscale del dipartimento, permettendo così ai
fornitori di capire con più chiarezza che spetta a loro il compito di pagare l’IVA relativa all’ordine.
La parte più interessante del Form, risulta però essere quella inferiore, in cui compaiono gli
strumenti per varie operazioni (Fig. 4.6).
È possibile infatti, mediante tali controlli, gestire le operazioni di invio mail automatico al fornitore
e di stampa immediata del documento dell’ordine. Il campo di testo sulla sinistra è collegato al
campo [Email] della tabella dei fornitori, quindi a seconda del fornitore selezionato per l’ordine
(vedi Fig. 4.4), l’applicativo compila in automatico questo campo, prelevando l’indirizzo di posta
elettronica dalla tabella fornitori appunto. In caso non ci fosse nessun indirizzo impostato, o
51
comunque, qualora si volesse spedire l’ordine ad un altro indirizzo rispetto a quello di default,
risulta possibile agire su tale campo per indicare un indirizzo email a piacere, che sarà utilizzato
solo per l’ordine che si sta compilando. La scelta dell’invio o meno avviene spuntando la casella a
fianco del campo per l’indirizzo. Ultima funzionalità da descrivere è quella di stampa del report.
Anche qui è possibile decidere di stampare o meno il documento che si sta creando,
semplicemente agendo sulla checkbox [Si/No]. Inoltre è stata prevista la possibilità di specificare
quante copie dell’ordine si debbano stampare.
Se si sono inseriti tutti i valori e si sono effettuate le scelte relative alla stampa e all’invio
dell’ordine, per completare l’inserimento in archivio basterà cliccare sul pulsante “Esegui Ordine”.
La pressione del pulsante genererà l’evento ‘button_click’ che permetterà di eseguire il codice
scritto e presentato nel capitolo precedente. Nell’ordine si eseguono i seguenti passaggi: prima di
tutto si fanno dei controlli sulla coerenza dei valori inseriti nei campi (ad esempio se i campi
numerici sono compilati con stringhe che rappresentano valori numerici corretti). Se vengono
riscontrati degli errori, l’intera procedura si ferma e viene annullata, ponendo a video un
messaggio di allerta per l’utente. Al contrario, se i controlli non rilevano nessun errore, si
eseguono, nell’ordine i seguenti passi:
Creazione del nuovo record nella tabella “Ordini” (codice: Fig. 3.15);
Creazione dei nuovi record relativi al dettaglio degli ordini (codice: Fig. 3.30);
Apertura e modifica del modello Excel: a seconda dell’impostazione dell’IVA scelta, si
aprirà uno dei tre modelli predefiniti da compilare (codice: Fig. 3.20);
Compilazione del modello Excel (codice: Fig. 3.21);
Stampa del modello, se richiesta (codice: Fig. 3.22);
Salvataggio modello (formato XLSX) ed esportazione in formato PDF e chiusura dei file
(codice: Fig. 3.23);
Invio della mail al fornitore, se richiesto (codice: Fig. 3.25).
52
Nella Fig. 4.7 riportiamo il Form che viene aperto quando si effettua un click sul pulsante
“Archivio Ordini” del *Menù Principale+ (Fig. 4.2).
Si presenta quindi la struttura mostrata in figura, costituita da una griglia nella parte superiore, in
cui trovano posto tutti i record relativi agli ordini presenti in archivio. I campi visualizzati nella
tabella rappresentano solo alcune delle informazioni dell’ordine, le restanti vengono esposte nella
parte inferiore, dove i dettagli dell’ordine ci informano sul fornitore, sull’utente che ha effettuato
l’operazione, l’eventuale centro di costo, il fondo e la lista dei prodotti ordinati. L’utente può agire
manualmente per correggere le celle dei valori dell’ordine e successivamente apportare e rendere
effettive le modifiche, mediante il pulsante “Salva Modifiche”. L’uso che più spesso potrà essere
fatto di questa maschera, sarà la modifica delle checkobx relative allo stato di evasione
dell’ordine, ossia i campi “Fattura”. Inoltre, mediante i pulsanti sulla parte destra sarà possibile
tenere traccia dei soli ordini da evadere o di quelli di cui si è già ricevuta la fattura.
La semplice lista che compare (Fig. 4.8) permette di visionare le descrizioni e i codici dei centri di costo
disponibili. Di default le celle della tabella non sono modificabili dall’utilizzatore, ma è possibili apportare
modifiche a tali voci premendo il pulsante “Modifica”. Alla pressione di tale controllo, l’applicativo agirà
sulla proprietà della DataGridView *ReadOnly+, impostandola da ‘True’ a ‘False’ e rendendo quindi
modificabili le celle della tabella. Una volta terminate le operazioni di modifica, basterà cliccare su “salva
Modifiche” per aggiornare i record nel database. Per l’aggiunta di un nuovo centro di costo è disponibile il
collegamento offerto dal pulsante “Nuovo Centro di Costo” che aprirà la maschera di input del nuovo
centro di costo, come mostrato in Fig. 4.9.
Si presenta come una semplice coppia di textbox, una adibita all’inserimento del codice e una per fornire
una descrizione dell’elemento. Alla pressione del pulsante “Salva” l’applicativo verifica che sia il campo
relativo al codice che quello per la descrizione, siano stati compilati in modo corretto, con valori validi.
54
Analoga struttura hanno i form dedicati agli utenti e alle ditte dei fornitori. Cliccando sui rispettivi pulsanti
si potrà accedere alle maschere riportate nelle figure seguenti. Da li poi sarà inoltre possibile inserire nuove
voci relative sia ai fornitori sia agli utenti (Fig. 4.10 – 4.11 – 4.12 – 4.13)-
55
Figura 4.11: Lista dei fornitori
Mediante il pulsante “Salva Modifiche”, è possibile salvare eventuali correzioni o aggiunte nei dati relativi
alla ditta fornitrice. Con la pressione del bottone “Nuovo Fornitore” apriremo il form da compilare per
creare un nuovo fornitore (Fig. 4.13).
56
Figura 4.13: Inserimento nuovo fornitore
Infine, l’ultimo pulsante del menù principale, è quello che permette di aprire la configurazione del
programma. In Fig. 4.14 è mostrata la schermata che appare alla pressione del pulsante “Manutenzione”.
57
Nel primo dei due tab trovano posto alcune informazioni generali sull’applicativo e sul dipartimento che sta
utilizzando il software, mentre la parte più importante è la seconda pagina (Fig. 4.15) contenente
importanti dati come le directory dove risiedono i modelli, il percorso di salvataggio dei documenti e le
informazioni per permettere al programma di stabilire una connessione SMTP e inviare gli ordini via posta
elettronica in automatico.
Per apportare delle modifiche basterà cambiare il contenuto delle textbox e dei vari controlli e
successivamente fare un clic sul pulsante “Salva Modifiche” per memorizzare nella tabella Master del
database le nuove informazioni.
Nelle pagine seguenti è possibile osservare dei modelli di documento prodotti con il software sviluppato.
58
Ordine con IVA personalizzata (qui al 4%).
59
Ordine esente IVA.
60
Ordine con IVA al 20%.
61
Ordine IVA inclusa.
62
Conclusioni
Sviluppi futuri potranno tenere conto di parametri non considerati in questo elaborato, per
migliorare le prestazioni e altri ambiti desiderati. Per la sicurezza, un’implementazione si può
ricercare nella creazione di un sistema di login personalizzato, in cui ogni utente si munirà di
password personale e potrà accedere al sistema, fornendo quindi un livello di sicurezza maggiore,
contro accessi indesiderati al software. Papabili funzionalità aggiuntive sono inoltre l’inserimento
della firma digitale ai documenti d’ordine inviati ai fornitori e sicuramente lo sviluppo di
un’interfaccia web per permettere a tutti i calcolatori collegati alla rete del dipartimento, di poter
utilizzare il programma di gestione degli ordini.
63
Bibliografia
[1] P. Atzeni , S. Ceri, S. Paraboschi, R. Torlone Basi di dati (Modelli e linguaggi di interrogazione). McGraw-
Hill, 2006.
64
Ringraziamenti
Voglio ringraziare in primis, il Prof. Maurizio Fermeglia, per la disponibilità dimostrata in questo
periodo di lavoro e tutti i docenti che mi hanno permesso di acquisire il bagaglio culturale che
possiedo.
Un caloroso grazie va ai miei amici vecchi e nuovi, che mi sono stati vicini e hanno reso tutto più
semplice, anche se inconsciamente e grazie ai quali ho capito che chiedere aiuto non è una forma
di debolezza, anzi.
Intendo ringraziare, inoltre, i miei compagni di università, con cui ho condiviso quest’esperienza
importante e significativa che mi porterò dentro per sempre.
Grazie Monica, per esserci stata quando ne avevo bisogno e, in generale, per avermi
accompagnato in quest’ultimo anno.
Infine il mio pensiero va alla mia famiglia: ai miei genitori, a mio fratello e ai miei zii. Grazie per
avermi dato tutto quello di cui avevo bisogno con l’umiltà incredibile di cui siete capaci.
65