TesiGestioneOrdini

65
UNIVERSITÀ DEGLI STUDI DI TRIESTE FACOLTÀ DI INGEGNERIA Corso di Laurea in Ingegneria Informatica SVILUPPO DI UN APPLICATIVO IN .NET PER LA GESTIONE DEGLI ORDINI AI FORNITORI DI UN DIPARTIMENTO UNIVERSITARIO Laureando: Relatore: Daniele De Gan Chiar.mo Prof. Ing. Fermeglia Anno accademico 2010-2011

Transcript of TesiGestioneOrdini

UNIVERSITÀ DEGLI STUDI DI TRIESTE

FACOLTÀ DI INGEGNERIA

Corso di Laurea in Ingegneria Informatica

SVILUPPO DI UN APPLICATIVO IN .NET PER LA GESTIONE DEGLI ORDINI AI FORNITORI DI UN

DIPARTIMENTO UNIVERSITARIO

Laureando: Relatore:

Daniele De Gan Chiar.mo Prof. Ing. Fermeglia

Anno accademico 2010-2011

Ai Miei Genitori

3

Indice

Indice ................................................................................................................................................................. 3

Introduzione ...................................................................................................................................................... 4

Analisi ................................................................................................................................................................ 5

1.1 Introduzione ...................................................................................................................................... 5

1.2 I requisiti ............................................................................................................................................ 7

La Base di Dati ................................................................................................................................................. 11

2.1 Introduzione .......................................................................................................................................... 11

2.2 Tabelle del Data Base ............................................................................................................................ 11

2.3 Struttura e schema del Data Base ......................................................................................................... 14

L’applicativo .................................................................................................................................................... 15

3.1 Introduzione .......................................................................................................................................... 15

3.2 Obiettivi del programma ....................................................................................................................... 15

3.2.1 Parametri di qualità del Software ................................................................................................... 15

3.3 Scelte progettuali .................................................................................................................................. 17

3.3.1 Microsoft® .NET ............................................................................................................................... 17

3.3.2 Il linguaggio: C# ............................................................................................................................... 18

3.3.3 L’accesso ai dati .............................................................................................................................. 18

3.4 Codifica .................................................................................................................................................. 26

3.5 Test ........................................................................................................................................................ 39

L’interfaccia grafica ......................................................................................................................................... 42

4.1 Introduzione .......................................................................................................................................... 42

4.2 L’interfaccia utente ................................................................................................................................ 42

4.2.1 Linee guida ...................................................................................................................................... 44

4.3 Presentazione dell’interfaccia ............................................................................................................... 46

Conclusioni ...................................................................................................................................................... 63

Bibliografia ...................................................................................................................................................... 64

Ringraziamenti ................................................................................................................................................ 65

4

Introduzione

Il lavoro scelto, ossia la realizzazione di un applicativo per la gestione degli ordini di un

dipartimento universitario, mira alla creazione di un software sviluppato in ambiente .net (C#) per

facilitare e migliorare il sistema di gestione attualmente in uso dalla segreteria amministrativa del

dipartimento. Questa è la seconda fase di un miglioramento già iniziato qualche anno fa, quando si

passò dalla compilazione degli ordini tramite foglio Excel, all’uso di un applicativo ADP (Access

Data Project) sviluppato da un altro studente. Microsoft .NET non è altro che la visione di

Microsoft per lo sviluppo di applicazioni e soluzioni basate sui servizi, un progetto di unificazione. Il

prodotto realizzato, che verrà qui descritto, risulta essere il risultato della normale successione di

fasi di sviluppo software come: la raccolta dei requisiti, l’analisi degli stessi, la progettazione e

realizzazione del Data Base e delle applicazioni e la fase finale di test. Lo sviluppo ha sfruttato una

macchina con sistema operativo Windows 7 (64 bit). L’ambiente di sviluppo utilizzato è Microsoft

Visual Studio 2010 e in particolare il linguaggio scelto è C#, mentre per la parte dati si è optato per

Microsoft SQL Server 2008 R2. Va inoltre sottolineata la necessità, ai fini del completo

funzionamento dell’applicativo, di Microsoft Excel (usato nella versione 2007), indispensabile per

la creazione dei report degli ordini inseriti.

5

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.

Figura 1.1: Modello sviluppo software.

6

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.

Figura 1.2: Modello di sviluppo a cascata.

7

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.

INTERVISTA ALL’IMPIEGATO DELLA SEGRETERIA AMMINISTRATIVA DEL DIPARTIMENTO

Nell’ordine che devo compilare devo inserire innanzitutto il codice del fornitore.

-Avete una tabella dei fornitori?

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’.

-Cosa significa “POS.FIN.”?

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.

-Cosa significa quel codice nel campo della commessa?

È 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.”

8

-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.

-Avete una tabella dei prodotti?

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.

-Fate sempre un preventivo?

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.

-Perché si crea un ordine?

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

9

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.

Riorganizzando le informazioni colloquiali ottenute mediante intervista si ottiene l’insieme delle

caratteristiche che il sistema deve avere, ossia il documento dei requisiti.

DOCUMENTO DEI REQUISITI

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

10

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.

11

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.

2.2 Tabelle del Data Base

Il database utilizzato si compone di 7 tabelle utilizzate per organizzare i dati al meglio.

TABELLA ‘CENTRI DI COSTO’:

Figura 2.1: Tabella Centri di Costo

In questa tabella sono (e possono essere) memorizzati i Centri di Costo con i relativi codici univoci

di identificazione.

TABELLA ‘DETTAGLIO ORDINE’:

Figura 2.2: Tabella Dettaglio Ordini

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

12

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’

Contiene i numeri dei fondi e la loro descrizione.

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’:

Figura 2.3: Tabella Fondi

Figura 2.4: Tabella Ordini

Figura 2.5: Tabella Master-1

Figura 2.6: Tabella Master-2

13

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.

Figura 2.7: Tabelle Impiegati

Figura 2.8: Tabella Fornitori

14

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.

Figura 2.9: Schema Fisico

15

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.

3.2 Obiettivi del programma

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.

3.2.1 Parametri di qualità del Software

La qualità del software è un insieme di caratteristiche che ne influenzano l’uso e la manutenzione.

Si dividono in:

Esterne: apprezzabili dall’utente di un software;

Interne: rilevabili da un esperto software. Influenzano le caratteristiche esterne.

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:

16

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.

Solitamente non è possibile massimizzare contemporaneamente tutti questi parametri,

bisogna scendere a qualche compromesso, in quanto alcuni sono direttamente influenzati da

altri.

17

Sicurezza Usabilità

Efficienza Portabilità

3.3 Scelte progettuali

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.

3.3.1 Microsoft® .NET

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

Esempi di parametri in conflitto.

18

(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#

C# (C sharp) è un linguaggio di programmazione ad alto livello, object-oriented,sviluppato dalla

stessa Microsoft all'interno dell'iniziativa .NET, e successivamente approvato come standard

ECMA. La sintassi del C# prende spunto da quella del Delphi (hanno il medesimo autore, ovvero

Anders Hejlsberg), del C++, da quella di Java e da Visual Basic per gli strumenti di programmazione

visuale e per la sua semplicità (meno simbolismo rispetto a C++, meno elementi decorativi rispetto

a Java).

C# è, in un certo senso, il linguaggio che meglio degli altri descrive le linee guida sulle quali ogni

programma .NET viene eseguito; questo linguaggio infatti è stato creato da Microsoft

specificatamente per la programmazione nel Framework .NET. I suoi tipi di dati "primitivi" hanno

una corrispondenza univoca con i tipi .NET e molte delle sue astrazioni, come classi, interfacce,

delegati ed eccezioni, sono particolarmente adatte a gestire il .NET Framework.

3.3.3 L’accesso ai dati

Di particolare interesse sono le funzionalità di accesso ai dati, notevolmente semplificate come il

binding automatico dei controlli alle sorgenti dati mediante semplici operazioni di ‘trascinamento’

o di wizard all’interno dell’IDE. Sono state utilizzate due vie per relazionarsi con il database prima

19

descritto: la prima seguendo appunto le procedure di binding automatico, la seconda istanziando

via codice gli oggetti necessari all’accesso.

ACCESSO ‘VIA INTERFACCIA’ IDE:

Prima di tutto è stato necessario definire una sorgente dati da associare al nostro progetto.

Mediante la procedura guidata “Configurazione

guidata origine dati” si è creato un Data Set ossia un

modello ‘sosia’ del database a livello del nostro

applicativo. Da notare che mediante questa procedura

non è necessario conoscere in dettaglio il

funzionamento che sta dietro all’accesso ai dati.

Infatti, una volta creato il Data Set, nella finestra

“Origini dati” si troveranno gli elementi del database

che abbiamo, per così dire, importato (vedi Fig. 3.1).

Vediamo come la procedura guidata ci abbia messo a

disposizione tutte le tabelle del database (c’è la

possibilità anche di poterne importare solo alcune). Il

Data Set rappresenta quindi un’immagine del Data

Base sottostante che mediante opportune istruzioni

può essere popolato con i veri dati del DB.

Ma tutto è reso ancor più semplice dal fatto che, se

non si necessita di manipolazioni particolari, è

possibile creare una tabella sia leggibile che

modificabile, direttamente collegata ad una

qualsiasi tabella del Data Set. Niente di più

intuitivo: basta semplicemente trascinare una

delle tabelle elencate in “Origini Dati”

all’interno di una Windows Form per ottenere il

risultato mostrato in Fig. 3.2. Visual Studio

2010 crea in modo totalmente automatico una

tabella (precisamente un controllo

DataGridView) che ha come sorgente dati la

tabella scelta in precedenza. Inoltre, ad una

prima occhiata d’insieme, noteremo che sono stati inseriti nella parte bassa della finestra di

progettazione del Form anche altri controlli che noi non abbiamo esplicitamente creato. In Fig. 3.3

possiamo vederli; essi sono: il Dataset, un oggetto Binding Source, un oggetto Table Adapter, oltre

che agli oggetti TableAdapterManager e BindingNavigator.

Figura 3.1: Finestra Origini Dati

Figura 3.2: Creazione del controllo DataGridView

20

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.

21

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.

CONTROLLI DI DETTAGLIO DEL DATASET

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

Figura 3.4: Proprietà DataSource del DataGridView

22

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.

Figura 3.5: Dettagli Tabella

Figura 3.6: Utilizzo Misto Controlli

Figura 3.7: Binding Navigator

23

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).

Figura 3.8: Definizione degli oggetti necessari

Figura 3.9: Ricavare la Connection String

24

Infine chiamiamo il metodo Open() per l’apertura della connessione.

Per quanto riguarda il secondo oggetto definito (il Data Set) abbiamo già detto che si tratta di un

contenitore di tabelle che dovremo riempire con i dati che ci interessano. Dopo averlo definitivo,

creiamo un’istanza con l’istruzione new ( Fig. 3.11).

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

che consenta

di mettere in

comunicazione queste due entità. Si tratta dell’ultimo oggetto che abbiamo definito, ossia

l’SQLDataAdapter. Per istanziare l’adattatore è necessario fornire al costruttore una stringa in

linguaggio SQL e una connessione aperta e valida (Fig. 3.12). Successivamente, una volta creata

l’istanza, basterà richiamare il metodo FILL per riempire il Data Set con i dati specificati nella

stringa SQL, con il comando mostrato in Fig. 3.13. Va specificato inoltre il nome con cui ci si vorrà

riferire alla tabella ne Data Set.

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

Figura 3.10: Apertura della Connessione

Figura 3.11 Istanziare il DataSet

Figura 3.12: Creazione dell’istanza di un SQLAdapter

Figura 3.13: Caricamento dei record nel DataSet

25

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).

Figura 3.14: Inserimento Record nella tabella “Impiegati”

Figura 3.15: Come liberare le risorse allocate

26

3.4 Codifica

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).

//Inserisco nella nuova riga del dataset i valori immessi dall'utente. DataRow nuovaRiga = dataSet1.Tables["Ordini"].NewRow(); 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 { } //Aggiungo la nuova linea al DataSet dataSet1.Tables["Ordini"].Rows.Add(nuovaRiga); //Aggiorno il dataAdapter. dataAdapter1.Update(dataSet1, "Ordini");

Figura 3.15: Salvataggio nuovo record

27

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.

//Controllo che il campo txtNumeroOrdine contenga un valore numerico.

Boolean okCheck = true;//Variabile posta a FALSE se riscontrato qualche errore. try { int.Parse(txtNumeroOrdine.Text); } catch { txtNumeroOrdine.BackColor = Color.Red; okCheck = false; } //Controllo che il campo txtEsercizio contenga un valore numerico. try { int.Parse(txtEsercizio.Text); } catch { txtEsercizio.BackColor = Color.Red; okCheck = false; } if (okCheck == false) { return; }

Figura 3.16: Alcuni controlli sui campi

28

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).

Creazione

Oggetti EXCEL.

Apertura File

EXCEL da

percorso

predefinito.

Modifica celle del

modello secondo

input dell’utente.

Salvataggio del

nuovo documento.

Chiusura file e

liberazione delle

risorse allocate.

Stampa? Eseguo stampa.

Mail?

SI

NO

Invio Mail.

TERMINE

OPERAZIONI.

SI

NO

Figura 3.17: Schema a blocchi operazioni

29

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.

Figura 3.18: Aggiunta riferimento alle librerie Excel

Figura 3.19: Direttiva using per lo spazio dei nomi di Excel

30

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; //Prelevo il percorso dove sono salvati i modelli; String Path = dataSet1.Tables["Master"].Rows[0]["DirectoryModelli"].ToString(); MyApp = new Excel.Application(); if (rdbIva20.Checked == true) { Path = Path + "\\ModuloIva20.xlsx"; } if (rdbIvaInclusa.Checked == true) { Path = Path + "\\ModuloIvaInclusa.xlsx"; } if (rdbEsenteIva.Checked == true) { Path = Path + "\\ModuloEsenteIVA.xlsx"; }

MyWb = MyApp.Workbooks.Open(Path, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);

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).

Figura 3.20: Apertura modello Excel

31

try

{ //Riempio le celle con i valori dell'ordine (Quantità, Descrizioe e Prezzo Unitario). for (int righe = 0; righe < righeDettaglio - 1; righe++) { MyWs.Cells.get_Range("B" + (19 + righe).ToString(), o).Value2 = dgwDettaglio.Rows[righe].Cells["Quantità"].Value.ToString(); MyWs.Cells.get_Range("C" + (19 + righe).ToString(), o).Value2 = dgwDettaglio.Rows[righe].Cells["Descrizione"].Value.ToString(); MyWs.Cells.get_Range("H" + (19 + righe).ToString(), o).Value2 = dgwDettaglio.Rows[righe].Cells["Prezzo"].Value.ToString(); } //Riempio le altre parti relative all'ordine: try{ MyWs.Cells.get_Range("C10", o).Value2 = dtpDataOrdine.Text; } catch { }

try{ if (ckbCommerciale.Checked == true) { MyWs.Cells.get_Range("C12", o).Value2 = txtNumeroOrdine.Text + "LE"; } else{MyWs.Cells.get_Range("C12", o).Value2 = txtNumeroOrdine.Text; }

} catch { } try{ MyWs.Cells.get_Range("H10", o).Value2 = cmbFornitore.Text; } catch { } try{ MyWs.Cells.get_Range("G11", o).Value2 = indirizzoTextBox.Text; } catch { } try{ MyWs.Cells.get_Range("G12", o).Value2 = cAPTextBox.Text; } catch { } try{ MyWs.Cells.get_Range("H12", o).Value2 = cittàTextBox.Text; } catch { } try{ MyWs.Cells.get_Range("H13", o).Value2 = faxTextBox.Text; } catch { } try{ MyWs.Cells.get_Range("E14", o).Value2 = txtNumeroOfferta.Text; } catch { } try{ MyWs.Cells.get_Range("G14", o).Value2 = dtpDataOfferta.Text; } catch { } try{ MyWs.Cells.get_Range("C44", o).Value2 = txtEsercizio.Text; } catch { } try{ if (txtCommessa.Enabled == true) { MyWs.Cells.get_Range("F44", o).Value2 = txtCommessa.Text; }} catch { } try{ MyWs.Cells.get_Range("C45", o).Value2 = numeroFondoTextBox.Text; } catch { } try{ if (groupBox10.Enabled == true) { MyWs.Cells.get_Range("F45", o).Value2 = codiceCdCTextBox.Text; }} catch { } try{ MyWs.Cells.get_Range("F46", o).Value2 = codiceFornitoreTextBox.Text; } catch { } } catch { MyWb.Close(false, o, o); MyApp.Quit();

MessageBox.Show("Impossibile effettuare la creazione del report"); }

Figura 3.21: Compilazione del modulo

32

Ecco dunque che si passa alla modifica del modello originale, inserendo i valori dell’ordine. Il ciclo

for iniziale è utilizzato per scorrere tutte le righe della tabella di inserimento (vedi Interfaccia

grafica) e ricavarne, per ogni riga quantità, descrizione e prezzo unitario di ogni prodotto.

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.

//Se è richiesta la stampa procedo.. 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);}

}

Mediante il metodo PrintOutEx() possiamo richiamare la stampa di un nostro Workbook,

specificando vari parametri, tra cui il numero di copie, se volgiamo o meno visualizzare l’anteprima

di stampa, la stampante da utilizzare, la fascicolatura delle pagine oppure intervalli di pagine da

stampare. Nel nostro caso è bastato specificare il numero di copie (prelevato da un controllo

dell’interfaccia) e i restanti parametri sono stati passati come valori MISSING (vedi Fig. 3.20).

Come sempre, per gestire eventuali eccezioni, si è fatto uso dei blocchi try{} e catch{}. In caso di

malfunzionamenti, semplicemente la stampa non verrà effettuata e verrà visualizzato un

Figura 3.22: Procedura di stampa

33

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); MyWb.Close(true, Percorso + "\\" + cmbFornitore.Text.TrimEnd() + "_" + DateTime.Today.Day.ToString() + "_" + DateTime.Today.Month.ToString() + "_" + DateTime.Today.Year.ToString() + + "_" + txtNumeroOrdine.Text + ".xlsx", o); MyApp.Quit(); MessageBox.Show("Salvataggio Riuscito. Campi non indicati nell'ordine:", "Operazione riuscita", MessageBoxButtons.OK);

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.

Figura 3.23: Salvataggio e chiusura documento

34

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.

//Invio della mail al fonrnitore if (ckbMail.Checked == true){ 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

Figura 3.25 Invio automatico mail

35

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

Figura 3.26: Attivazione - disattivazione campi

36

DataGridView, ossia quando viene lasciata una cella della griglia l’evento esegue queste operazioni

(Fig. 3.27) che ora descriveremo. private void dgwDettaglio_CellEndEdit(object sender, DataGridViewCellEventArgs e){

//Codice per aggiornare la colonna calcolata relativa al totale parziale del prodotto. int riga = dgwDettaglio.CurrentCell.RowIndex; int colonna = dgwDettaglio.CurrentCell.ColumnIndex; //Controllo il valore dell'IVA; if (rdbIva20.Checked == true){ dgwDettaglio.Rows[riga].Cells["IVA"].Value = 0.2; } if (rdbIvaInclusa.Checked == true) {dgwDettaglio.Rows[riga].Cells["IVA"].Value = 0.0; } if (rdbEsenteIva.Checked ==true){ dgwDettaglio.Rows[riga].Cells["IVA"].Value = 0.0;} if(colonna == 0 || colonna == 2 || colonna==3){

if (dgwDettaglio.Rows[riga].Cells[0].Value != null && dgwDettaglio.Rows[riga].Cells[2].Value != null && dgwDettaglio.Rows[riga].Cells[3].Value != null){

try{ double quantità = double.Parse(dgwDettaglio.Rows[riga].Cells[0].Value.ToString()); double prezzo = double.Parse(dgwDettaglio.Rows[riga].Cells[2].Value.ToString()); double iva = double.Parse(dgwDettaglio.Rows[riga].Cells[3].Value.ToString()); double parziale = (prezzo * quantità) * (1 + iva); 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%).

Figura 3.27: Aggiornamento dettaglio

37

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()); double parziale = (prezzo * quantità) * (1 + iva); 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.

//Verifico l'ultimo ordine e calcolo il numero d'prdine più appropriato int quantiOrdini = dataSet1.Tables["Ordini"].Rows.Count; int ultimoOrdineCodice = int.Parse(dataSet1.Tables["Ordini"].Rows[quantiOrdini - 1]["Numero"].ToString()); DateTime dataordine = Convert.ToDateTime(dataSet1.Tables["Ordini"] .Rows[quanti Ordini-1]["DataOrdine"].ToString()); if (dataordine.Year == DateTime.Now.Year) { txtNumeroOrdine.Text = (ultimoOrdineCodice + 1).ToString(); } if (dataordine.Year != DateTime.Now.Year) { txtNumeroOrdine.Text = "0"; }

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.

Figura 3.28: Adeguamento IVA al 20%

Figura 3.29: Calcolo numero ordine

38

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”.

//Inserisco nella nuova riga del dataset i valori immessi dall'utente. int righeDettaglio = dgwDettaglio.Rows.Count; for (int i = 0; i < (righeDettaglio-1); i++) { 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()); //Aggiungo la nuova linea al DataSet dataSet1.Tables["DettaglioOrdini"].Rows.Add(n1); } //Aggiorno il dataAdapter. dataAdapter2.Update(dataSet1, "DettaglioOrdini");

Figura 3.30: Creazione record Dettaglio Ordine

39

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:

Verifiche statiche: viene verificata la correttezza del software senza eseguirlo:

Verifiche informali: in base all’esperienza;

Verifiche formali: utilizzando tecniche matematiche;

Ispezione del codice: molto efficace nel rilevamento degli errori (60-90% di errori

rilevati). È la tecnica utilizzata maggiormente per questo lavoro.

Testing: il codice viene suddiviso in ‘test-case’, ognuno comprendente:

Dati di Input: relativi al modulo da testare; sono decisi in base al programma, alle

specifiche e all’esperienza;

Descrizione della funzione interna al modulo;

Output atteso dalla funzione.

Esistono inoltre diversi modi di procedere nel testing:

Black Box Testing: i dati di input derivano solo dalle specifiche di programma, senza

considerare il codice. Viene partizionato l’insieme di input ammissibili in ‘classi di

equivalenza’ (uguale potere di testing); in particolar modo si utilizza almeno un dato per

ogni classe, compresi i dati di ‘ frontiera’.

Testing strutturale: viene condotto in base alla struttura del programma (flow-chart). Si

dati in input che portino a tutte le computazione possibili. È una strategia migliore del

Black Box Testing.

40

Strumenti automatici: forniscono supporti per la ripetibilità dei test (gestione dei test-case

e dei test-data, memorizzazione dei test effettuati e reporting analitico).

Simulatori: utilizzati su software che presentano situazioni di eccezione o pericolosità (che

possono provocare cioè danni o catastrofi) e per provare sistemi in condizioni di carico

particolare (stress-testing).

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).

Va inoltre sottolineata la differenza che intercorre tra il test e il debugging:

Il Testing permette di rilevare la presenza di un errore;

Il Debugging consiste nella localizzazione dell’errore, nella sua analisi e nella correzione.

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.

41

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.

Figura 3.31: Distribuzione errori - A Figura 3.32: Distribuzione errori - B

42

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à.

4.2 L’interfaccia utente

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.

43

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:

“Tutta la conoscenza ha le proprie origini nelle nostre percezioni.”

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.

Figura 4.1: Produttività con nuove tecnologie

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

44

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à.

4.2.1 Linee guida

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.

Intermedi: hanno già un’idea dell’applicazione e desiderano ricevere suggerimenti sul

‘come’ eseguire le operazioni disponibili. In particolare a loro si rivolgono la guida in linea e

la ricerca veloce di aiuto.

Esperti: conoscono a fondo l’applicazione e si muovono con naturalezza e scioltezza tra i

vari menù. La loro velocità di utilizzo è data anche dall’uso quasi esclusivo della tastiera,

utilizzando solo molto raramente il mouse. Questa tipologia di utenti richiede anche

possibilità di personalizzazione dell’interfaccia che si adatti al meglio alle loro esigenze.

È 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.

45

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.

46

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.

La maschera del menù principale contiene i collegamenti a tutte le funzionalità dell’applicativo.

Sono presenti sette Button, ognuno provvisto di testo informativo sull’utilità dello stesso.

Partendo da in alto a sinistra, troviamo il pulsante per aprire il Form di inserimento di un nuovo

ordine. È forse il Form più importante dell’intero applicativo, come vedremo in seguito. Con

[Archivio Ordini], invece, è possibile visualizzare uno storico degli ordini, con la possibilità di

filtrare i contenuti e di ‘spuntare’ e catalogare gli ordini evasi o meno. Con il pulsante [Centri Di

Costo] sarà possibile aprire il menù relativo ai centri di costo e le funzionalità relative.

Analogo discorso per i pulsanti sulla destra, tutti destinati ad aprire i menù dedicati agli altri ambiti

come gli utenti, i fornitori e i fondi.

Ultimo ma non meno importante bottone, presente nella schermata di avvio, è quello denominato

[Manutenzione]. È di fondamentale importanza perché permette di accedere al menù di

Figura 4.2: Menù Principale

47

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.

Figura 4.3: Menù della vecchia versione

48

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

Figura 4.4.: Form Inserimento Nuovo Ordine

49

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.

50

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

Figura 4.5: Finestra del Dettaglio dell’ordine

51

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

Figura 4.6: Dettaglio funzionalità

52

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).

53

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).

Figura 4.7: Form Archivio Ordini

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.

Da questa posizione del programma è possibile anche collegarsi direttamente al form di

inserimento di un nuovo ordine, semplicemente cliccando sul relativo pulsante. Se richiesto poi, si

potrà eliminare uno degli ordini archiviati, selezionando prima la riga nella tabella e poi premendo

il pulsante “Elimina Record”. Infine è stato implementato un filtro che permette di visualizzare gli

ordini appartenenti a certi campi di ricerca; selezionando il parametro, compilando la textbox

“Valore” e cliccando su “Filtra”, la visualizzazione degli ordini terra conto delle indicazioni

del’utente, mostrando solo i record che coincidono, per quanto riguarda il parametro scelto, con il

54

valore inserito. Per annullare la visualizzazione filtrata, basterà un clic sul pulsante “Visualizza

Tutto”. Col pulsante “Centri di costo”, sempre dal menù principale, è possibile visualizzare la lista

dei centri di costo inseriti in archivio, con le loro descrizioni.

Figura 4.8: Form Centri di Costo

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.

Figura 4.9: Form Nuovo C.d.C,

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.

55

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)-

Figura 4.10: Form Utenti

Figura 4.11: Inserimento nuovo Utente

56

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).

Figura 4.11: Lista dei fornitori

Figura 4.12: Dettagli Fornitori

57

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”.

Figura 4.14: Form di configurazione

58

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.

Figura 4.15: Form di configurazione 2

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.

59

Ordine con IVA personalizzata (qui al 4%).

60

Ordine esente IVA.

61

Ordine con IVA al 20%.

62

Ordine IVA inclusa.

63

Conclusioni

Il lavoro qui descritto ha portato alla creazione di un applicativo in grado di gestire la

memorizzazione degli ordini ai fornitori, ma soprattutto si è creato un programma che permette

agli utenti di compilare, in modo più semplice e rapido, il documento necessario alla richiesta delle

merci o dei servizi. Parte del tempo speso per la realizzazione, è stato impiegato per definire i

requisiti del prodotto finale. Un altro lasso di tempo è stato dedicato invece alla conoscenza e

all’approfondimento nell’uso delle tecnologie di sviluppo utilizzate, per passare infine alla

realizzazione vera e propria, con la stesura del codice. In generale si ritiene di aver soddisfatto gli

obiettivi prefissati ad inizio dei lavori. L’interfaccia è stata sviluppata in linea con le richieste

pervenute ed ha mantenuto una certa coerenza con la versione precedente dell’applicativo.

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.

Il prodotto ha inoltre permesso di approfondire l’uso di nuove tecnologie, utili al bagaglio

informatico futuro e ha permesso di relazionarsi con una ideale situazione di lavoro, in cui bisogna

soddisfare le richieste iniziali, apportare eventualmente modifiche in corso d’opera e testare il

prodotto fisicamente dal committente.

64

Bibliografia

[1] P. Atzeni , S. Ceri, S. Paraboschi, R. Torlone Basi di dati (Modelli e linguaggi di interrogazione). McGraw-

Hill, 2006.

[2] M. Fermeglia. Corso di Basi di dati, 2008-2009.

[3] L. Felician. Corso di Sistemi Informativi II. Edizioni Goliardiche, 2007.

[4] F. Sbroiavacca. Corso di Sistemi informativi I, 2008.

[5] S. Robinson, O. Cornes, J. Glynn C#-Guida per lo sviluppatore.

[6] Microsoft. Supporto tecnico Microsoft (MSDN), http://msdn.microsoft.com.

65

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.