Sistema di gestione contenuti per portale e

annuncio pubblicitario
UNIVERSITÀ DEGLI STUDI DI PARMA
FACOLTÀ DI SCIENZE MATEMATICHE FISICHE E NATURALI
Corso di Laurea in Informatica
Tesi di Laurea Triennale
Sistema di gestione contenuti
per portale e-commerce nordamericano
Candidato:
Andrea Gandol
Relatore:
Prof. Giulio Destri
Anno Accademico 2011/2012
ii
iii
A Elisa
iv
v
Ringraziamenti
Desidero innanzitutto ringraziare i miei genitori Sergio e Renata, mia sorella Cristina ed
Elisa per il loro sostegno durante questi anni di studio.
Un ringraziamento particolare a Franco Folini e Cristiano Sacchi di Novedge LLC per
avermi dato la possibilità di lavorare con loro sviluppando il progetto descritto in questa
tesi.
Ringrazio l'Ing.
Cesare Chiodelli e il Prof.
Giulio Destri che, n dalla scuola supe-
riore, è stato per me una guida e un punto di riferimento per quanto riguarda il settore
informatico.
Inne un grazie a tutti gli amici del dipartimento con cui ho condiviso quest'avvenura:
Leonardo Bacchi, Federico Fontana, Federico Bacchi, Andrea Disarò, Federico Ferretti,
Matteo Masi, Davide Ponzo, Simone Bertocchi, Alice Pavarani, Beatrice Demaldè, Jessica
Groppi, Ilaria Fulcini, Martina Bonanzi e tanti altri.
vi
INDICE
1
Introduzione
1
2
Il contesto
3
2.1
E-Commerce . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
2.1.1
Tipologie di e-commerce
. . . . . . . . . . . . . . . . . . . . . . .
4
2.1.2
Il problema della sicurezza . . . . . . . . . . . . . . . . . . . . . .
6
3
2.2
Content Management System
. . . . . . . . . . . . . . . . . . . . . . . .
7
2.3
Novedge e il suo business model . . . . . . . . . . . . . . . . . . . . . . .
8
2.4
L'architettura del sistema
9
. . . . . . . . . . . . . . . . . . . . . . . . . .
Obiettivi del progetto di tesi ed analisi
13
3.1
Analisi dei requisiti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
13
3.2
Le entità da gestire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
3.2.1
Prodotti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
3.2.2
Brand
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
15
3.2.3
Special . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
16
3.2.4
Book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
16
3.2.5
Categorie
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17
3.2.6
Documenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17
3.2.7
Aree
17
3.2.8
Clusters
3.2.9
Ordini
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
viii
INDICE
3.2.10 Free Download
4
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
3.2.11 Webinar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
19
3.3
Elenco degli attori e use case . . . . . . . . . . . . . . . . . . . . . . . . .
20
3.4
Coordinamento del progetto
22
Progettazione
23
4.1
La situazione prima del progetto . . . . . . . . . . . . . . . . . . . . . . .
24
4.2
Speciche software
24
4.3
Struttura del progetto
4.4
Struttura delle singole applicazioni
. . . . . . . . . . . . . . . . . . . . .
26
4.5
Le interfacce utente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
27
4.6
La base di dati
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
28
4.7
I web service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
30
4.8
Le tecnologie utilizzate . . . . . . . . . . . . . . . . . . . . . . . . . . . .
31
4.8.1
HTML, CSS e JavaScript
. . . . . . . . . . . . . . . . . . . . . .
31
4.8.2
ASP.NET
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
32
4.8.3
jQuery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
32
4.8.4
AJAX
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
33
4.8.5
JSON
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
33
4.8.6
Amazon Web Services
4.9
5
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
25
. . . . . . . . . . . . . . . . . . . . . . . .
33
Gli strumenti utilizzati . . . . . . . . . . . . . . . . . . . . . . . . . . . .
34
Implementazione
37
5.1
La libreria Novedge Base . . . . . . . . . . . . . . . . . . . . . . . . . . .
37
5.2
La barra di navigazione . . . . . . . . . . . . . . . . . . . . . . . . . . . .
48
5.3
L'applicazione Products
. . . . . . . . . . . . . . . . . . . . . . . . . . .
49
5.3.1
L'autocompletamento dei prodotti . . . . . . . . . . . . . . . . . .
51
5.3.2
Sistema dei messaggi . . . . . . . . . . . . . . . . . . . . . . . . .
54
5.3.3
Il plugin Wikipedia . . . . . . . . . . . . . . . . . . . . . . . . . .
55
5.4
L'applicazione Books . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
57
5.5
L'applicazione Specials . . . . . . . . . . . . . . . . . . . . . . . . . . . .
63
5.6
L'applicazione Documents
. . . . . . . . . . . . . . . . . . . . . . . . . .
66
5.7
L'applicazione Orders . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
69
5.8
L'applicazione Reports . . . . . . . . . . . . . . . . . . . . . . . . . . . .
71
INDICE
ix
5.9
Altre applicazioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
74
5.10 Web services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
74
5.11 Validazione
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
76
5.12 Liste per la consultazione delle entità . . . . . . . . . . . . . . . . . . . .
77
5.13 Funzioni di Wall e Log
79
Conclusioni
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
81
CAPITOLO 1
INTRODUZIONE
Il lavoro della presente tesi nasce entro la collaborazione tra il Professor Giulio Destri e
la sua azienda AREA Professional e l'azienda statunitense Novedge, fondata nel 2003 a
San Francisco da due italiani, Franco Folini e Cristiano Sacchi, che è diventata oggi il più
grande rivenditore online al mondo di software per il CAD.
Novedge opera on-line attraverso un grande portale di vendita dei prodotti, aancato da
numerosi servizi che provvedono contenuti utili per gli utenti e da alcune vere e proprie
community di utenti, integrate con i principali social network. Attraverso una ottimizzazione spinta dei propri processi aziendali, Novedge riesce a garantire ai suoi clienti (principalmente progettisti meccanici, architetti, artisti 3D e game developer) prezzi scontati
rispetto a quelli di listino eettuati da altri rivenditori, fornendo spedizioni veloci e un
supporto di base no all'installazione del software.
L'ottimizzazione dei processi è basata anche su una ampia automazione dei processi stessi, attraverso software scritto ad hoc ed integrato con servizi presenti in rete come quelli
di Amazon.
Dopo 10 anni di operatività coronata da successo, a causa della sua stessa espansione
negli anni, Novedge si è trovata nella necessità di una revisione ed ammodernamento del
proprio software interno. Tale operazione è stata compiuta sia da un punto di vista funzionale, sia adottando una nuova piattaforma tecnologica: ASP.NET 4 ed il linguaggio
C#.
La denizione delle nuove necessità funzionali è stata compiuta dai fondatori stessi di
2
Introduzione
Novedge e l'architettura tecnica delle nuove applicazioni è stata denita dal Dr. Franco
Folini col contributo del Professor Destri.
Il lavoro della tesi si è inserito in questo contesto ed è consistito nella realizzazione dei
moduli del nuovo sistema di gestione dei contenuti (CMS) del portale, attraverso cui gli
addetti di Novedge caricano i prodotti, seguendo le speciche di analisi formalizzate dal
Dr. Folini. La libreria Novedge.Base, estesa ed integrata nel sistema in seguito da me, è
stata scritta dal Dr. Folini stesso.
Durante le fasi di analisi, progettazione e realizzazione dell'applicazione CMS si è utilizzata una metodologia agile di sviluppo in modo di coinvolgere il più possibile il committente
ed avere quindi un feedback continuo riguardo allo stato del progetto e alle sue richieste.
Per far ciò è stato fondamentale l'utilizzo di strumenti di comunicazione e coordinamento
in quanto, data la distanza dagli uci Novedge, è stato impossibile un contatto diretto
per tutta la durata del progetto.
Solo alla ne, con un viaggio negli USA, ho potuto
lavorare di persona alcune settimane entro la sede di Novedge.
Durante la progettazione e la realizzazione del CMS si sono rivelate fondamentali le nozioni apprese durante il mio percorso di studi in informatica presso l'università degli studi
di Parma.
Partendo dai corsi di fondamenti di programmazione, algoritmi e strutture dati e fondamenti dell'informatica che coprono gli aspetti basilari dell'informatica e della programmazione, arrivando ai corsi più specici come metodologie di programmazione, basi di
dati, ingegneria del software e linguaggi di programmazione che arontano tematiche e
argomenti fondamentali per un informatico in quanto insegnano nozioni, metodologie e
procedure che, ad oggi, sono ampiamente utilizzate in ogni ambiente complesso in cui si
fa uso di calcolatori.
Man mano che prendevo conoscenza del sistema e della sua struttura, ho potuto contribuire non solo con la stesura del codice ma anche con evoluzioni rispetto all'architettura
di dettaglio inizialmente denita.
La tesi è organizzata in capitoli: il capitolo 2 presenta una visione del commercio elettronico e dell'azienda Novedge, provvedendo il contesto in cui il lavoro della tesi è nato;
i capitoli successivi mostrano il lavoro secondo le modalità canoniche apprese nel corso di ingegneria del software: obiettivi ed analisi, progettazione, implementazione.
conclusioni completano il progetto con le future prospettive ed estensioni.
Le
CAPITOLO 2
IL CONTESTO
2.1 E-Commerce
Con il termine e-commerce o commercio elettronico ci si riferisce a quell'insieme di attività
d'impresa, per lo scambio di beni o servizi, in cui la transazione tra le parti avviene
attraverso reti di telecomunicazione.
Il signicato del termine è mutato nel tempo. In principio indicava semplicemente l'uso del
calcolatore come strumento di supporto per lo scambio di documenti al ne di velocizzare
una transazione commerciale, mentre oggi, grazie al continuo sviluppo di Internet e delle
tecnologie basate sul Web, si dispone di tecnologie più avanzate che permettono di gestire
in modo completo l'acquisto di beni e servizi attraverso il Wold Wide Web ricorrendo ad
esempio a connessioni sicure e metodi di pagamento elettronici come le carte di credito.
Il fattore che più di tutti ha spinto la crescita di questo modo di fare business è sicuramente l'abbattimento dei costi ssi dato che, non essendo necessario un negozio sico,
diventa possibile anche per piccole aziende o persino per privati aprire il proprio negozio
online e potenzialmente attirare clienti da ogni parte del mondo.
4
Il contesto
2.1.1 Tipologie di e-commerce
Il commercio elettronico si divide in diverse tipologie in base all'attività commerciale in
cui si svolge l'attività e ai soggetti coinvolti che possono avere esigenze diverse.
Tale
suddivisione inuenza anche la scelta degli strumenti tecnologici che un'azienda adotta.
Possiamo identicare quindi tre principali tipologie:
•
Commercio elettronico tra aziende (B2B):
Con questo termine si indica un'attività a supporto delle transazioni commerciali tra
aziende e non coinvolge direttamente gli utilizzatori nali dei beni e servizi prodotti.
I soggetti coinvolti sono aziende che si servono dei prodotti di altre aziende per
realizzare i propri. Un esempio classico è la gestione della catena di distribuzione.
•
Commercio elettronico tra aziende e consumatori (B2C):
Questa è la forma più nota di e-commerce e rigurda la fornitura di beni e servizi
tra un'azienda e il consumatore nale. In questo caso il consumatore si reca sulla
pagina web dell'azienda e può visualizzare ed eventualmente acquistare i prodotti
mostrati eettuando pagamenti online. La maggior parte dei siti di e-commerce che
fanno parte di questa categoria comprendono almeno i seguenti elementi:
1. Un catalogo elettronico dei prodotti e servizi oerti.
2. Un'area di navigazione e ricerca che permette di trovare facilmente i prodotti.
3. Un sistema di carrello virtuale dove l'utente può aggiungere gli oggetti da
acquistare e procedere eventualmente al pagamento e all'evasione dell'ordine.
4. Un sistema di pagamento online sicuro.
5. Un sistema di controllo degli ordini che permette di seguire il processo di
elaborazione dell'ordine e facilitarne il tracciamento.
•
Commercio elettronico tra consumatori (C2C):
Questa forma di commercio è più recente rispetto alle altre ed è diventata popolare
grazie ai siti di aste online (primo fra tutti eBay), che orono al consumatore la
possibilità di vendere ad altri consumatori i propri prodotti e servizi. In questo caso
è il sito che ore il servizio di asta a imporre le regole e ad amministrare l'ambiente
e gli utenti si registrano utilizzando i propri dati al ne di fornire le informazioni
necessarie per garantire l'identità dei soggetti coinvolti nella trattativa.
2.1 E-Commerce
5
Per realizzare e gestire un'attività di commercio elettronico di tipo B2C occorre tenere
in considerazione alcuni fattori cruciali necessari per il successo:
•
Creazione del valore per il cliente orendo prodotti o servizi di qualità a prezzi
competitivi.
•
Ispirare ducia e sicurezza.
•
Puntare sul web-marketing, ovvero pubblicità e azioni sui social network per farsi
conoscere e creare un'immagine seria e adabile dell'azienda.
•
Creare un sito web accattivante e di facile utilizzo.
•
Incentivare il cliente all'acquisto e delizzarlo proponendo sconti e oerte speciali.
•
Cercare di conoscere il cliente senza però essere troppo invadenti.
•
Assistere il cliente nel suo ruolo di consumatore.
Anche se un venditore seguisse le linee guida sopra citate possono comunque sorgere
alcune problematiche, tra le quali:
•
Dicoltà nella comprensione del comportamento dei clienti ovvero capire le aspettative e le motivazioni che spingono la clientela ad acquistare un certo prodotto.
•
Mancanza di analisi dello scenario concorrenziale.
•
Incapacità di prevedere le reazioni nell'ambiente in cui opera l'impresa. Altri siti
potrebbero copiare l'idea e vendere gli stessi prodotti o fornire lo stesso servizio.
•
Sovrastima delle competenze aziendali o dei sistemi hardware/software adottati.
•
Mancanza di coordinazione.
•
Incapacità nell'assicurarsi l'impegno dei vertici aziendali.
Spesso non è possibile
raggiungere un determinato obiettivo a causa delle scarse risorse allocate.
•
Incapacità nell'assicurarsi l'impegno dei dipendenti. Quando i progettisti non traducono in modo chiaro la loro strategia ai dipendenti.
•
Scarso addestramento all'utilizzo della piattaforma e-commerce realizzata da parte
del committente.
6
Il contesto
•
Sottovalutazione dei tempi richiesti per il raggiungimento degli obiettivi aziendali.
•
Incapacità di rispettare la pianicazione dei tempi.
•
Incapacità di rispettare livelli di servizio, soprattutto i tempi, per le consegne ai
clienti.
2.1.2 Il problema della sicurezza
Oltre alle dicoltà elencate dovute alla gestione dell'impresa un altro problema da affrontare è quello della sicurezza sui dati. Durante l'acquisto on-line viaggiano su Internet
dati sensibili come le generalità del cliente e soprattutto durante la fase di pagamento
della merce è necessario utilizzare metodi e tecnologie per evitare che persone esterne
all'operazione intercettino queste informazioni e le utilizzino a scopo fraudolento.
Si
sono adottati quindi elevati standard di sicurezza per garantire questo tipo di riservatezza. In particolare la maggior parte dei siti di e-commerce ad oggi utilizzano le seguenti
tecnologie:
•
L'HTTPS (HyperText Transfer Protocol Secure) è il risultato dell'applicazione di
un protocollo di crittograa asimmetrica, come il TLS (Transport Layer Security)
e il suo predecessore SSL (Secure Sockets Layer), al protocollo HTTP. In questo
modo i dati viene creato un canale di comunicazione sicuro tra il client e il server
attraverso uno scambio di chiavi pubbliche tra le parti. Una volta stabilito questo
canale i dati che vi transitano sono decifrabili solamente dai due partecipanti alla
comunicazione e non sono quindi intercettabili da altri.
•
Con la procedura di autenticazione il server chiede all'utente di identicarsi, generalmente inserendo uno username e una password associata, limitando il numero
di tentativi in modo da evitare attacchi con tentativi ripetuti di trovare la password sugli account (i cosiddetti attacchi a forza bruta). Per questo motivo, oggi,
viene sempre più consigliato all'utente il cambio periodico della propria password
scegliendola di una certa complessità evitando, ad esempio, date di nascita e nomi
propri di persona.
•
Il venditore può avvalersi della rma digitale per evitare il ripudio da parte del
cliente della merce acquistata.
Questa tecnologia fa sì che un contratto rmato
digitalmente non possa essere disconosciuto da coloro che l'hanno sottoscritto.
2.2 Content Management System
•
7
Un altro punto fondamentale è la sicurezza interna all'azienda, ovvero gestire la
sicurezza e la manutenzione dei server su cui risiede la struttura di e-commerce sia
nel caso in cui esso risieda presso l'azienda stessa sia nel caso in cui sia ospitato nei
server di una società di hosting.
2.2 Content Management System
Un CMS (Content Management System) è un'applicazione che facilita e rende più sicuro il compito dell'amministratore di inserire o modicare i contenuti di un sito internet
dinamico.
Questi software creano un livello (astrazione) tra il database dove vengono
memorizzati i contenuti e le persone addette all'aggiornamento del sito web, svincolando
costoro da conoscenze tecniche e orendo un ulteriore controllo sui dati che vengono inseriti.
Esistono CMS di ogni genere, alcuni specializzati e progettati in base al tipo di contenuti
da gestire (ad esempio blog, forum, siti di e-commerce) ed altri generici che si adattano
a qualsiasi tipo di sito web. Possiamo inoltre dividere questi software in base alla piattaforma su cui possono operare che dipende dal linguaggio di programmazione utilizzato e
dal framework su cui si appoggiano; tra i più comuni troviamo PHP, ASP.NET e Java.
Oggi, sul mercato, si possono trovare centinaia di CMS preconfezionati, molti di questi
gratuiti, che necessitano solamente di installazione e consentono in pochi minuti di creare
un sito web.
Tuttavia questi pacchetti, cercando di andare incontro alle esigenze più
comuni del pubblico, hanno uno scarso livello di personalizzazione e, a meno di interventi
sul codice sorgente, non consentono all'utente di ottenere sempre la essibilità e la specializzazione desiderata in relazione al proprio specico obiettivo. Questi problemi sono in
parte risolubili utilizzando software open source. Avendo accesso ai codici sorgenti si può
personalizzare il CMS in base alle proprie esigenze, ma vanno tenuti in considerazione il
tempo e i costi necessari per imparare a creare moduli personalizzati per la piattaforma
specica e la sua struttura. Spesso, in caso di personalizzazioni estreme, i costi per realizzare tali moduli diventano superiori a quelli della costruzione di un CMS partendo da
zero.
8
Il contesto
2.3 Novedge e il suo business model
Novedge LLC. è un'azienda di e-commerce statunitense con sede a San Francisco (California) che si occupa della vendita online di software di progettazione e graca, perlopiù
nel territorio nordamericano. Fondata nel 2003 da Franco Folini e Cristiano Sacchi è, ad
oggi, il più grande rivenditore online al mondo di questo tipo di software. Novedge ha
un catalogo di circa ottomila prodotti da centocinquanta produttori dierenti ed utilizza
strumenti e modalità con un forte supporto tecnologico in modo da automatizzare e rendere il più eciente possibile il processo di approvvigionamento e vendita.
Per questo possiamo catalogare l'azienda sia come B2B che come B2C.
La parte B2B è quella che si occupa delle comunicazioni tra l'azienda, le case produttrici
di software e le compagnie di trasporti. Ogni fornitore ha regole di business diverse, con
metodi di interazione e gestione degli ordini d'acquisto dierenti. Per gestire al meglio
questa parte sono stati deniti processi estremamente ecienti e automatizzati che eliminano o riducono al minimo indispensabile l'intervento umano nelle transazioni.
Per quanto riguarda la vendita al pubblico (B2C) l'azienda si ada al proprio sito web in
cui è possibile consultare il catalogo prodotti ltrandoli per marca o categoria e mostrandoli suddivisi per sottocategorie in modo da consentire all'utente una navigazione tra
le pagine intuitiva e capace di indirizzarlo velocemente sul tipo di software cercato, che
può essere acquistato direttamente dal sito con pagamento elettronico oppure attraverso
ordine telefonico.
Novedge riesce a garantire ai suoi clienti (principalmente progettisti
meccanici, architetti, artisti 3D e game developer) prezzi scontati rispetto a quelli di listino eettuati da altri rivenditori, fornendo spedizioni veloci e un supporto di base no
all'installazione del software.
Oltre alla vendita di software Novedge fornisce altri importanti servizi di contorno come:
2.4 L'architettura del sistema
•
9
Ask Novedge: un servizio di supporto email che consente all'utente di contattare
l'azienda per chiarire i propri dubbi o fare domande riguardo ai prodotti.
•
Mailing list a cui è possibile registrarsi per ricevere le ultime notizie sui nuovi
prodotti o quelli di prossima presentazione.
•
Materiale di supporto ai prodotti, come: suggerimenti di libri acquistabili da Amazon; video, documenti e gallerie immagini di recensioni, tutorial e case study;
download di sofware trial, utility e plugin; suggerimenti di prodotti simili o di
complemento.
•
Webinars gratuiti: dirette video in cui esperti mostrano come utilizzare al meglio i
prodotti e le loro caratteristiche più avanzate.
•
Blog contenente interviste e news del settore.
•
Forte interazione con i Social Media (Twitter, Facebook, Google+, Pinterest e
LinkedIn) in cui l'utente può ricevere gli aggiornamenti sulle oerte e le attività
dell'azienda.
•
Pulse: un sistema di aggregatore di notizie che mostra notizie e aggiornamenti da
oltre trecento blog e cinquecento dierenti autori del settore.
•
Rhino Jungle,WikiCAD e Vectorworking, che sono comunità online gestite da Novedge in cui si può discutere di un determinato argomento e dei prodotti relativi.
Il Dr. Franco Folini si occupa del sistema informatico di Novedge ed è la persona con
cui sono stato in contatto per tutta la durata del progetto discutendo insieme le diverse
problematiche riguardanti la progettazione e l'implementazione del sistema. Laureato in
scienze dell'informazione ha lavorato come ricercatore dal 1991 al 2001 presso la facoltà
di ingegneria dell'università degli studi di Parma dove ha insegnato disegno CAD per il
corso di ingegneria meccanica.
2.4 L'architettura del sistema
Il nucleo del sistema informatico su cui si basa l'intera architettura dell'azienda è il Novedge Main Website, un'applicazione web ad hoc scritta in Visual Basic su piattaforma
10
Il contesto
Figura 2.1: Architettura del sistema informatico di Novedge
ASP classica gestita dal web server Microsoft IIS che si appoggia a una serie di sottosistemi per usufruire di servizi esterni all'azienda con cui ha necessità di comunicare. Sulla
stessa macchina su cui opera il web server è installato anche il database Microsoft SQL
Server, contenente tutte le informazioni necessarie all'applicazione per svolgere il proprio
lavoro. Le tabelle del database non vengono interrogate direttamente dall'applicazione
web mediante query SQL ma, come scelta architetturale, i record vengono richiesti attraverso l'invocazione di stored procedures salvate sul database stesso. Questo approccio è
dettato dalla necessità di accedere ai dati contenuti nel database da applicazioni diverse
(principalmente Main Website e CMS) scritte in linguaggi diversi che si appoggiano a
frameworks dierenti.
I le di grosse dimensioni, come download di versioni trial dei prodotti, video e documenti, vengono salvati su Amazon S3, un servizio di cloud computing per lo storage di le.
In questo modo i download sono sempre disponibili a una velocità di trasferimento alta
e non si rallenta il server su cui gira il sito.
2.4 L'architettura del sistema
11
Tra i servizi che Novedge utilizza per gestire il processo di vendita troviamo un sistema
di validazione degli ordini che consente, dato l'indirizzo sico dell'utente, il suo indirizzo
IP e il metodo di pagamento selezionato, di capire la zona di provenienza e l'adabilità,
in modo da attribuire all'ordine un fattore di rischio e decidere successivamente come
procedere. Una volta che l'ordine viene accettato (automaticamente dal sistema se l'indice di rischio basso o manualmente nel caso contrario) si passa alla fase di evasione
dell'ordine, che può avvenire digitalmente o attraverso i servizi di spedizione tradizionali.
Nel secondo caso il sistema contatta la compagnia logistica segnalando la spedizione e facendosi restituire un tracking number con cui sarà possibile tracciare il percorso del pacco.
12
Il contesto
CAPITOLO 3
OBIETTIVI DEL PROGETTO DI TESI ED
ANALISI
3.1 Analisi dei requisiti
L'obiettivo del lavoro di tesi è la progettazione e realizzazione di un nuovo CMS per
Novedge che soddis i seguenti requisiti:
•
sia in grado di gestire le operazioni di consultazione, inserimento, modica e cancellazione dei prodotti a catalogo e di una serie di altre entità ad essi collegate.
•
avere un'interfaccia graca semplice in modo da renderlo utilizzabile anche a persone
con una scarsa conoscenza delle tecnologie informatiche cercando di nascondere la
logica, talvolta complessa, delle operazioni.
•
essere accessibile attraverso Internet in modo da permettere il telelavoro dei dipendenti.
Il sistema deve essere aancato al sito web attuale e accessibile al solo personale dell'azienda, adottando quindi protocolli e standard di sicurezza necessari per garantire la
riservatezza delle informazioni.
14
Obiettivi del progetto di tesi ed analisi
Figura 3.1: Rappresentazione della collocazione del sistema
3.2 Le entità da gestire
3.2.1 Prodotti
I prodotti sono le entità principali dell'applicazione a cui tutte le altre fanno riferimento.
Il sistema deve consentire l'inserimento e la modica di nuovi prodotti con la possibilità di
creare collegamenti tra di loro in modo da poter raggruppare prodotti simili che verranno
poi mostrati sul sito web. Le informazioni base che devono essere editabili sono: SKU
(Stock-Keeping Unit, ossia un identicativo univoco della categoria di prodotto), nome,
versione, breve descrizione, disponibilità, produttore, tipo di prodotto, tipo di licenza,
formato (digitale o sico), immagine della scatola.
I prezzi sono divisi in tre campi: prezzo del fornitore (costo), prezzo di listino e prezzo
Novedge.
Ricoprendo un ruolo fondamentale è necessario adottare riscontri visivi per
capire immediatamente durante l'inserimento lo sconto eettuato rispetto al prezzo di
listino (discount) e quanto è il margine sulla vendita.
Oltre a queste informazioni deve essere possibile:
•
Inserire una descrizione completa in formato HTML che può contenere collegamenti
ad altri prodotti, brand, documenti e a pagine Wikipedia.
3.2 Le entità da gestire
15
•
Inserire informazioni di supporto sul prodotto.
•
Inserire collegamenti a versioni di prova (trial) del prodotto con una breve descrizione che ne specica i limiti.
•
Inserire in una sezione denominata facts le capacità e compatibilità del prodotto.
•
Associare tag e parole chiave che semplichino la ricerca.
•
Specicare i formati di input e di output supportati dal software.
Come detto in precedenza l'applicazione deve essere in grado di creare collegamenti logici
tra i prodotti in modo da creare una sorta di gerarchia che semplichi la ricerca e la
navigazione nel sito web da parte del visitatore. Le connessioni che devono essere possibili
tra i prodotti sono:
•
Per i software di tipo plugin specicare i prodotti su cui possono venire installati.
•
Creare collegamenti a pacchetti dello stesso software ma per sistemi operativi differenti.
•
Creare prodotti di tipo bundle, ovvero prodotti che in realtà sono raggruppamenti
di altri prodotti.
•
Raggruppare prodotti in categorie.
•
Raggruppare prodotti in aree. Le aree sono entità composte da prodotti, categorie
e download.
•
Collegamento tra un prodotto e i suoi master, ovvero prodotti da cui esso è strettamente legato.
3.2.2 Brand
I brand rappresentano i marchi, ovvero le case produttrici dei software, che vengono
associate ai prodotti, documenti e ai download gratuiti.
I campi contenuti in questa
entità sono:
•
I campi elementari come nome, descrizione e logo dell'azienda
16
Obiettivi del progetto di tesi ed analisi
•
Alcuni ag per indicare la visibilità dei prezzi per i prodotti associati; se il brand
è visibile dal sito; se Novedge è un rivenditore autorizzato e se la casa produttrice
accetta i resi.
•
Una serie di indirizzi (sia sici che elettronici) per contattare i vari reparti dell'azienda in base alla necessità, ad esempio supporto tecnico e accounting.
•
Altre informazioni necessarie per lo scambio di informazioni tra Novedge e l'azienda.
3.2.3 Special
Gli special vengono utilizzati per creare promozioni ed oerte a cui è possibile associare
uno o più prodotti. Ogni promozione è caratterizzata da:
•
Una data di inizio e ne.
•
I campi necessari per la composizione del messaggio da mostrare nel prodotto in
promozione. Questi sono titolo, label (testo mostrato con caratteri grandi), testo e
footer (testo piccolo mostrato ai piedi del messaggio).
•
Possibilità di attivare e disattivare lo special.
•
Un'area in cui associare i prodotti allo special. Per ognuno di questi deve essere
possibile cambiare i prezzi, cambiare gli SKU (identicativi) che fanno riferimento
al pacchetto del produttore e associare un prodotto target ovvero un prodotto a cui
il prodotto in promozione fa riferimento.
Un vincolo importante da tenere in considerazione è che ogni prodotto può appartenere
ad un solo special attivo. Occorrerà quindi implementare sistemi di controllo adeguati
che avvisino l'utente quando questo cerca di associare un prodotto già in promozione ad
un altro special. Altre funzionalità richieste per gli special sono la possibilità di vedere
un'anteprima di come apparirà il messaggio che verrà mostrato nella pagina del prodotto
in promozione e una pagina contenente un calendario con il riassunto delle scadenze delle
promozioni attualmente attive.
3.2.4 Book
I book sono entità che permettono di associare un libro a una o più categorie di prodotti.
Ogni libro è composto da un identicativo, l'anno di pubblicazione, il titolo e l'autore.
3.2 Le entità da gestire
17
Il sistema deve implementare un modulo per raccogliere le informazioni sui libri dal
catalogo on-line di Amazon, in modo dal sollevare l'utente dal compito di inserire i dati
manualmente.
3.2.5 Categorie
Le categorie consentono di raggruppare i prodotti e sono composte da due campi testuali:
nome e descrizione. Oltre a questi sono necessari alcuni ag per poter attivare o disattivare la categoria e specicare se questa è una categoria ad alta priorità e se deve essere
mostrata nei menù del sito web.
3.2.6 Documenti
I documenti sono entità che consentono di associare pdf, video o altri le a un prodotto
o a un brand. Ognuno di questi oggetti contiene:
•
I campi per settare il titolo, l'URL, la descrizione ed eventualmente la data e l'autore
del documento.
•
Una regione per specicare il tipo di documento e con che icona deve essere visualizzato sul sito web.
•
La possibilità di disattivare il documento
•
Le associazioni a un brand e a uno o più prodotti.
Nel campo URL si può specicare l'indirizzo di un le o di una pagina già presente sul web,
tuttavia deve essere possibile, attraverso un sistema integrato, scegliere un le locale dal
computer per farne l'upload su Amazon S3. In questo caso il sistema dovrà preoccuparsi
di inserire negli appositi campi l'URL e la dimensione del le appena caricato.
3.2.7 Aree
Le aree sono raggruppamenti di uno o più prodotti, categorie e download gratuiti. Oltre
alle sezioni per poter associare queste entità le aree dovranno specicare un nome, una
breve descrizione, l'URL relativo sul sito Novedge, un logo e opzionalmente il prodotto
principale. Anche questo tipo di entità dev'essere disattivabile.
18
Obiettivi del progetto di tesi ed analisi
3.2.8 Clusters
I cluster sono un altro tipo di raggruppamento di prodotti. Questi hanno il solo campo
nome e vengono utilizzati dal sito web per mostrare i prodotti associati all'interno di
menù a tendina in contesti specici. Il sistema deve prevedere per i prodotti contenuti in
un cluster la possibilità di cambiare ad essi il nome (di solito per sintetizzarlo), di inserire
un separatore tra un prodotto e l'altro e un metodo per cambiarne velocemente l'ordine.
3.2.9 Ordini
Le entità degli ordini contenute nel database vengono generate automaticamente quando
il visitatore del sito web aggiunge dei prodotti al proprio carrello virtuale e conferma
l'acquisto della merce pagando con uno dei metodi disponibili. Il CMS opera solamente
su ordini già esistenti e deve permettere agli operatori di:
•
Modicare le informazioni degli indirizzi di spedizione e fatturazione.
•
Modicare i dati dei prodotti che compongono l'ordine (come prezzo e quantità).
•
Inserire o cancellare prodotti.
•
Esplodere i bundle, ovvero sostituire il prodotto nell'ordine con i prodotti contenuti
nel bundle.
Questa operazione dev'essere eettuata non modicando l'importo
totale.
•
Modicare i dati dell'intero ordine come totale, tasse e costi di spedizione.
3.2.10 Free Download
I free download rappresentano software scaricabile direttamente dal sito. Queste entità
hanno le stesse funzionalità dei documenti ma vengono associate solamente ai brand e
alle aree, quindi non direttamente ai prodotti. Le dierenze con i documenti riguardano:
•
I free download non devono specicare un'icona o un tipo di documento in quanto
la maggior parte delle volte sono le eseguibili.
•
I free download contengono tre campi booleani che deniscono se il software funziona
su Windows, su Linux e su Mac.
3.2 Le entità da gestire
19
3.2.11 Webinar
Le entità webinar consentono di gestire i collegamenti ai webinar realizzati da Novedge.
Le informazioni da specicare sono:
•
L'identicativo del video su Vimeo (la piattaforma, simile alla più nota YouTube,
dove sono salvati i video).
•
La data del webinar.
•
Il prodotto trattato nel webinar.
•
Titolo, descrizione e a chi si rivolge il webinar.
•
Informazioni sulla persona che tiene il webinar ovvero nome, sito web, immagine e
biograa.
•
Informazioni su eventuali oerte collegate e possibilità di specicare un prodotto.
•
Durata del video.
Per tutte le entità sopra descritte occorre implementare un sistema per la navigazione e
la ricerca veloce degli oggetti già presenti nel database.
Alcune di queste entità (quelle che modicano dati importanti come i prezzi) dovranno
contenere le funzionalità di wall e log. Il wall è una sorta di bacheca che consente all'operatore di inserire dei commenti o dei memo per motivare l'operazione eseguita o ricordare
qualcosa che andrà fatto in futuro. Il log invece è un diario che tiene traccia di tutte le
modiche eettuate a un'entità.
Il CMS oltre ad orire le funzionalità sopra descritte dovrà contenere una sezione Reports,
accessibile all'amministratore, che permetta di interrogare il database su determinate
regole (ad esempio il prezzo di un prodotto deve avere un valore compreso tra il costo e
il prezzo di listino del fornitore) in modo da avere un riscontro sulla conformità dei dati
e poter procedere alla correzione di eventuali incongruenze.
20
Obiettivi del progetto di tesi ed analisi
3.3 Elenco degli attori e use case
Gli attori, secondo la terminologia di UML (Unied Modeling Language), sono le categorie di entità esterne, tipicamente persone, che dovranno interagire con il sistema. Per
il progetto attuale abbiamo tre attori in quanto, essendo un'area riservata del sito, i visitatori non hanno accesso a questa parte. Verranno illustrati anche gli Use Case Diagram
di UML, che consentono di associare a un attore le operazioni che esso può eseguire.
•
Products Operator: sono gli impiegati che hanno accesso all'applicazione e possono
modicare i dati relativi ai prodotti e alle altre entità ad essi associate. E' il tipo di
attore con meno permessi per il sistema, mentre gli altri due hanno autorizzazioni
maggiori.
Figura 3.2: Products Operator use case diagram
•
Orders Operator: questa categoria di operatori, oltre ad avere gli stessi permessi
dei products operator, ha accesso alla modica degli ordini dei clienti.
3.3 Elenco degli attori e use case
21
Figura 3.3: Orders Operator use case diagram
•
Amministratore: è colui che gestisce il sistema e deve avere accesso ad ogni parte
dell'applicazione compresa la possibilità di monitoring, ovvero vedere quali utenti
sono loggati e cosa stanno facendo. E' inoltre l'unico a poter accedere all'area di
report che permette di eseguire operazioni delicate sul database.
Figura 3.4: Administrator use case diagram
Tutti gli attori che utilizzano il portale non necessitano di competenze particolari nel
settore web o informatico in generale in quanto uno degli obbiettivi è la semplicità del
sistema. Tuttavia il ruolo di amministratore è limitato a un numero ristretto di persone.
22
Obiettivi del progetto di tesi ed analisi
3.4 Coordinamento del progetto
Durante le fasi di analisi, progettazione e realizzazione dell'applicazione CMS si è utilizzata una metodologia agile di sviluppo in modo di coinvolgere il più possibile il committente
ed avere quindi un feedback continuo riguardo allo stato del progetto e alle sue richieste.
Per far ciò è stato fondamentale l'utilizzo di strumenti di comunicazione e coordinamento
in quanto, data la distanza dagli uci Novedge, è stato impossibile un contatto diretto
per tutta la durata del progetto.
Oltre all'email, strumento indispensabile per la co-
municazione testuale, si è fatto ampio uso del software Skype che consente di eettuare
videochiamate a livello globale completamente gratuite orendo funzionalità, come la
condivisione dello schermo, che si sono dimostrate irrinunciabili per illustrare le caratteristiche e le problematiche che emergevano dal progetto. Un altro strumento utilizzato
ampiamente per il coordinamento del progetto è stato BitBucket, un'applicazione web che
fornisce strumenti di supporto agli sviluppatori per il lavoro congiunto su progetti software. In particolare BitBucket consente di salvare online il codice sorgente del progetto
permettendo agli sviluppatori di accedervi mediante strumenti di controllo di revisione come Mercurial e Git e, grazie a un sistema di issues tracking, segnalare eventuali
malfunzionamenti del codice o richiedere l'implementazione di nuove caratteristiche.
CAPITOLO 4
PROGETTAZIONE
La fase di progettazione si occupa di denire come il sistema dovrà rendere possibili le
operazioni discusse nel processo di analisi. Per questo durante la progettazione bisogna
tenere in considerazione i fattori, le potenzialità e i limiti relativi alle tecnologie che verranno adoperate per la realizzazione. L'obbiettivo di questo processo è quindi ottenere
una descrizione accurata di tutte le parti del sistema, dall'architettura software e del
database no all'interfaccia graca con cui l'utente dovrà interagire.
Ciò che contraddistingue il progetto rispetto ad altri CMS che si possono trovare sul mercato è la possibilità di dare ai prodotti e alle entità collegate a loro una gerarchia in modo
da poter creare collegamenti tra di essi nalizzati a rendere l'esperienza di navigazione
del visitatore più immediata proponendo suggerimenti coerenti con ciò che l'utente sta
cercando. Altri siti web creano collegamenti tra i loro prodotti in base a logiche che non
sempre hanno il risultato desiderato. Ad esempio, selezionato un prodotto, viene suggerito un prodotto con un nome simile o, in base ad acquisti di utenti precedenti, viene
fornita una lista di ciò che hanno acquistato gli utenti interessati al prodotto.
Questa
scelta di progettazione è fondamentale per la tipologia di prodotti trattati e richiede a chi
si occupa dei contenuti un lavoro maggiore rispetto all'utilizzo di algoritmi automatizzati
ma il risultato che ne deriva è uno dei fattori che rendono Novedge leader nel settore.
24
Progettazione
4.1 La situazione prima del progetto
Prima della realizzazione del progetto i dati relativi ai contenuti del sito web venivano
inseriti o modicati attraverso l'utilizzo di form create in Microsoft Access oppure, nel
caso delle entità più semplici, editando direttamente le tabelle del database.
Questi
strumenti consentono di eettuare le stesse operazioni ed ottenere gli stessi risultati che
si avrebbero utilizzando un CMS ma in un modo molto più laborioso e senza controlli di
validazione che potrebbero portare l'operatore a commettere errori nell'inserimento dei
dati. L'unico punto a favore di questo approccio è l'abbattimento dei costi derivanti dal
dover sviluppare un'applicazione CMS ad hoc. Con la crescita della mole di informazioni
presenti nella base di dati e della loro complessità si è arrivati ad un punto in cui si è reso
necessario l'utilizzo di strumenti più avanzati. Per avere un'idea del volume di dati che il
sito web e il CMS devono gestire basti pensare che attualmente il database contiene oltre
ottomila SKU, trecentomila utenti registrati, tremila recensioni di prodotti, quattromila
documenti, cinquecento download gratuiti, cento special, settanta webinar ed altre entità
tutte interconnesse tra di loro.
4.2 Speciche software
Data la natura, orientata al web, del progetto, si è deciso di implementarlo come applicazione web.
La scelta del linguaggio di programmazione lato server e delle tecnologie con le quali è
stato implementato il CMS sono state dettate in parte dall'ambiente in cui è stato installato l'applicativo, ovvero lo stesso del sito internet di Novedge.
Sul server in questione, acquistato da un hosting provider esterno all'azienda, è installato
il sistema operativo Microsoft Windows, con un web server IIS e un database SQL Server.
Si è quindi fatta un'analisi delle funzionalità supportate dal server di hosting e si è scelta
la tecnologia più recente e completa supportata dal sistema, ovvero ASP.NET 4.0 Web
Forms.
4.3 Struttura del progetto
25
4.3 Struttura del progetto
Data la complessità del progetto è stato necessario suddividerlo in più parti in modo
da separare i concetti che stanno alla base delle classi che lo compongono e renderlo
quindi manutenibile. Le due componenti principali in cui è stato ripartito l'applicativo
sono Novedge.Base e Novedge.CMS. Il namespace Base contiene quelle classi adibite
all'interfacciamento col database e modellano le entità rendendole accessibili agli strati
di software superiori, sviluppate internamente a Novedge.
Nel CMS invece sono stati
collocati tutti i le relativi alle singole applicazioni che compongono il progetto, ognuna
delle quali risiede in una sottocartella separata dalle altre.
Figura 4.1: Struttura del progetto Novedge.CMS
Oltre a queste la cartella radice del progetto CMS contiene i seguenti elementi:
•
Il le index.htm che rappresenta la pagina iniziale dell'applicazione.
•
I le di congurazione Web.cong e Global.asax presenti in tutte le applicazioni
ASP.NET.
•
I le relativi alla barra di navigazione denominati Toolbar.
•
I web service, con presso Ajax, che vengono chiamati da javascript lato client
attraverso la tecnologia AJAX.
26
Progettazione
•
La cartella CommonCode contenente Validator.cs che è la classe base di tutte le
classi di validazioni.
•
La cartella CustomControls dove sono stati implementati controlli personalizzati
utilizzati in tutto il progetto.
•
La cartella js contenente gli script javascript utilizzati lato client dalle applicazioni.
•
La cartella css con gli stili delle pagine.
Tipicamente le cartelle delle applicazioni sono composte da almeno tre le principali:
•
Un le aspx con il nome dell'applicazione contenente il codice della form che consente di editare l'entità e di salvarle nella base di dati.
•
Un le aspx denominato List che permette all'utente di consultare la lista degli
elementi presenti nel database.
•
Una classe Validator che denisce i metodi necessari per controllare che i dati inseriti
dall'utente siano validi.
Se tutti hanno esito positivo allora l'entità può essere
inserita o aggiornata nel database.
4.4 Struttura delle singole applicazioni
Nella tecnologia ASP.NET ogni le aspx rappresenta una pagina web dinamica e viene
separata in due parti: una contenente il codice HTML che denisce la struttura e i contenuti visibili della pagina e una classe denominata code behind dove risiede la logica
dell'applicazione.
In questo modo vengono separati i due concetti e il risultato nale
risulta molto più comprensibile e manutenibile.
Il CMS è composto da diverse pagine aspx, ognuna delle quali rappresenta un'applicazione web relativa alla gestione di una singola entità o una funzionalità associata ad essa.
Oltre a contenere il codice HTML necessario per mostrare all'utente i contenuti e i controlli della form le pagine sono classi derivate da System.Web.UI.Page che mantengono
tutte la stessa struttura di base e contengono:
4.5 Le interfacce utente
•
27
Attributi relativi all'oggetto che rappresentano lo stato della pagina o contengono
riferimenti ad istanze di oggetti utilizzati (come ad esempio i validator).
•
Gli eventi legati alla pagina sono metodi speciali che vengono richiamati dal framework durante i vari stadi del ciclo di vita della pagina.
Tra i più utilizzati
troviamo Page_PreInit in cui vengono istanziati gli oggetti e i controlli necessari
all'applicazione, Page_Load richiamato durante il caricamento della pagina e Page_PreRender utilizzato per impostare gli attributi e gli stili dei controlli prima
che la pagina venga renderizzata.
•
Le proprietà sono una caratteristica di C# (in altri linguaggi, come Java, si utilizzerebbero i metodi get e set) e vengono utilizzate per impostare dall'esterno di una
classe valori che possono corrispondere ad attributi privati oppure nascondere una
logica più complessa al loro interno.
•
Gli eventi dei controlli sono metodi che rispondono a eventi scatenati dai controlli
della pagina web (come bottoni o check box) con cui l'utente interagisce.
•
I metodi di validazione sono associati ai controlli della form e vengono invocati
automaticamente dal sistema per controllare che i dati inseriti siano conformi al
tipo di informazione richiesta.
•
Altri metodi, ovvero funzioni che non ricadono nelle precedenti categorie e vengono
utilizzate dal programma per spezzare il usso di esecuzione rendendo i frammenti
di codice riutilizzabili e più comprensibili.
4.5 Le interfacce utente
L'interfaccia utente è quello strato del software che gli utenti utilizzano per interagire col
sistema. Per questo il CMS, nonostante sia stato suddiviso in diverse sottoapplicazioni
web, mantiene un'interfaccia graca simile e coerente per ognuna di queste. Queste applicazioni permettono, per ogni entità, di svolgere le classiche operazioni CRUD (Create,
Read, Update and Delete) che si eettuano solitamente su una base di dati, oltre ad orire
il controllo e validazione delle informazioni inserite nella form, automatizzando e semplicando il più possibile il lavoro dell'utente nale. Nella tecnologia ASP.NET l'interfaccia
graca viene creata mediante l'utilizzo delle pagine aspx contenenti il codice HTML che
28
Progettazione
verrà mostrato nel browser oltre a supportare funzioni JavaScript per le operazioni lato
client e i fogli di stile CSS.
Figura 4.2: Disposizione degli elementi nell'interfaccia utente
Nella parte superiore della pagina è sempre presente la barra di navigazione che consente
all'utente di passare da un'applicazione all'altra ed eettuare il login/logout nel CMS.
A sua volta la struttura delle pagine delle applicazioni può essere suddivisa in tre parti.
Quella superiore mostra il titolo o il nome dell'entità che si sta editando, l'identicativo e,
quando necessario, le tab in cui questa è stata suddivisa. In basso sono presenti i bottoni
che consentono di salvare, cancellare o creare un nuovo oggetto. In alcuni casi possiamo
trovare anche il tasto per accedere alla lista di tutti gli elementi o un menù a tendina
per la scelta veloce. Nel centro della pagina sono invece situati i controlli necessari per
la modica dell'entità caricata.
4.6 La base di dati
La base di dati con cui il progetto interagisce è la stessa su cui si appoggia il sito web,
quindi non è stato necessario progettarla da zero ma sono state apportate solo modiche
superciali alle tabelle e aggiunte le stored procedure necessarie. Il database contiene le
tabelle con i record relativi alle entità gestite dal CMS e i relativi collegamenti. Questi
dati vengono gestiti dallo strato software addetto all'accesso ai dati mediante chiamate
a stored procedure, in questo modo la libreria Novedge.Base non contiene direttamente
4.6 La base di dati
29
codice SQL e le query sono centralizzate nel database. Per ogni entità presente abbiamo
quattro stored procedure:
•
La sp_GetEntity ritorna tutti i campi di un'entità in base all'identicativo.
•
sp_GetEntities serve per avere la lista di tutte i record presenti nella tabella di
un'entità.
•
La stored procedure sp_CreateOrUpdateEntity ha come parametri i campi dell'entità. Quando viene invocata controlla se nel database è già presente un oggetto con
l'ID specicato, se questo esiste aggiorna il record, in caso contrario ne aggiunge
uno nuovo.
•
sp_DeleteEntity cancella (se esiste) il record con l'identicativo passato come parametro.
Figura 4.3: Diagramma ER della base di dati
30
Progettazione
Il diagramma ER mostra le relazioni e le cardinalità tra le tabelle gestite dal CMS, da
questa rappresentazione si può notare come i prodotti abbiano un ruolo centrale nella base
di dati e come tutte le altre entità siano collegate ad essi direttamente o indirettamente.
Per chiarezza sono state omesse le tabelle che vengono utilizzate solamente dal Novedge
Web Site e quelle dei log e commenti in quanto possono contenere dati relativi a tutte le
altre entità.
4.7 I web service
Per rendere le pagine web ancora più dinamiche si è scelto di implementare anche alcuni
web service interni all'applicazione in modo da consentire al codice lato client eseguito dal
browser di accedere a informazioni presenti nel database. Questo scambio di dati avviene
attraverso la tecnologia AJAX utilizzando il formato JSON, molto più leggero rispetto
a XML e ugualmente supportato.
Una volta ricevuta la risposta il codice JavaScript
si occupa di modicare il DOM della pagina senza dover eettuare una nuova richiesta
HTTP che richiederebbe il refresh della pagina.
Figura 4.4: Schema di funzionamento di un web service
4.8 Le tecnologie utilizzate
31
4.8 Le tecnologie utilizzate
4.8.1 HTML, CSS e JavaScript
Queste tre sono le tecnologie fondamentali che stanno alla base di tutte le web application
moderne. HTML (Hyper Text Markup Language) è un linugaggio di formattazione utilizzato per creare la struttura di una pagina web e inserirne i contenuti. La formattazione
consiste nell'inserire nel testo una serie di marcatori (tag) che deniscono come questo
deve essere visualizzato e disposto.
Ogni documento di questo tipo inizia con un tag,
detto document type, che segnala al browser che versione di HTML è stata usata nella
pagina. Dopo di questo, il documento HTML presenta una struttura ad albero annidato
composta da sezioni delimitate da tag opportuni che al loro interno contengono a loro
volta sottosezioni sempre delimitate da tag. La struttura più esterna delimita l'interno
documento ed è compresa tra i tag <html> e </html>. All'intergno dei tag <html> lo
standard prevede la denizione di due sezioni ben distinte e disposte in sequenza ordinata:
•
l'intestazione (header), delimitata dai tag <head> e </head>, contiene informazioni di controllo come titolo, metatag e collegamenti a script e fogli di stile. Queste
informazioni solitamente non appaiono nella pagina.
•
Il corpo (body), compreso tra i tag <body> e </body>, contiene i contenuti veri e propri, ossia il testo, le immagini e i collegamenti che costituiscono la parte
visualizzata dal browser.
L'ultima versione disponibile è HTML5 che ore funzionalità più avanzate rispetto alle
versioni precedenti ma è ancora in una fase di sviluppo e non ancora supportata da tutti
i browser, quindi si è optato per l'utilizzo di HTML4.
CSS (Cascading Style Sheets) è un linguaggio usato per denire la formattazione e lo
stile di una pagina HTML. Questa tecnologia è stata introdotta per separare i contenuti
di una pagina (descritti nell'HTML) dalla formattazione; in questo modo strutturando
correttamente un documento HTML è possibile cambiarne lo stile modicando semplicemente alcune proprietà nel le CSS associato.
Inne JavaScript è un linguaggio di programmazione orientato agli oggetti. A dierenza
di altri linguaggi di programmazione, che permettono la scrittura di programmi stand-
32
Progettazione
alone, JavaScript viene utilizzato soprattutto come linguaggio di scripting, ovvero viene
integrato con altri software per programmarne alcuni aspetti. Nel caso delle web application un'interprete JavaScript viene implementato come programma ospite dai browser
che si occupano di riconoscere il codice contenuto in una pagina HTML e lo eseguono.
L'interfaccia che JavaScript utilizza per interagire con la struttura del documento visualizzato nel browser (lato client) è chiamata DOM (Document Object Model).
Questo
permette di creare applicazioni web dinamiche, modicando la struttura del documento
senza richiedere al server di riprocessare la pagina per inviarne al browser una versione
modicata.
4.8.2 ASP.NET
ASP.NET 4.0 è un insieme di tecnologie lato server basate sul framework .NET di Microsoft per lo sviluppo di applicazioni web e web services.
ASP.NET Web Forms è la
tecnologia maggiormente usata nel progetto e consente allo sviluppatore di creare pagine web dinamiche utilizzando il paradigma dell'interfaccia graca (GUI) abbinato alla
cosiddetta programmazione ad eventi, ovvero utilizza un approccio molto simile allo sviluppo di applicazioni per il desktop.
Ogni pagina web creata consiste di due le: uno
con estensione .aspx contenente il markup della pagina e uno con estensione che dipende
dal linguaggio di programmazione utilizzato (.aspx.cs nel caso del progetto corrente in
quanto sviluppato in C#), chiamato code behind, che contiene la logica della pagina e il
codice legato agli eventi. Questa divisione consente allo sviluppatore di separare la view,
ovvero la parte che si occupa di mostrare e formattare i dati, dal model e controller che
deniscono rispettivamente la strutturazione dei dati e la logica che consente di modicarne lo stato. Il framework .NET denisce il ciclo di vita della pagina, ovvero una serie
di operazioni che il web server esegue per generare la pagina richiesta, partendo dalla
creazione dei controlli e arrivando no alla renderizzazione completa della pagina. Questo modello denisce degli eventi intermedi in cui l'utente può inserire il proprio codice
da eseguire.
4.8.3 jQuery
jQuery è una libreria javascript cross-browser, che fornisce metodi e funzioni per gestire gli
aspetti graci e strutturali di una pagina web. Il punto di forza di jQuery, rispetto ad altre
4.8 Le tecnologie utilizzate
33
librerie concorrenti, è l'estrema compattezza dei comandi che consente, con poche righe di
codice, di eettuare svariate operazioni sul DOM e aggiungere alla pagina eetti graci.
Inoltre, essendo un libreria facilmente estendibile, si possono trovare online numerosi
plugin che ne estendono le funzionalità.
Una delle estensioni più famose (e utilizzata
all'interno del progetto) è jQuery UI che comprende un'insieme di componenti graci
personalizzabili con supporto ad interazioni, animazioni ed eetti avanzati. Nel progetto
sono stati utilizzati ampiamente il controllo autocompleter per mostrare le scelte possibili
in base al testo inserito e il calendar ossia un controllo che visualizza un piccolo calendario
associato a quelle textbox che richiedono l'immisione di una data.
4.8.4 AJAX
AJAX, acronimo di Asynchronous JavaScript and XML, è una tecnologia che consente
al codice client side di una pagina web di richiamare servizi web server side. In questo
modo le due parti possono scambiarsi informazioni senza la necessità di fare il postback
dell'intera pagina.
Questa tecnologia permette la creazione di applicazioni web forte-
mente interattive (Rich Internet Applications) che forniscono all'utente la possibilità di
interagire con l'applicazione come se si stesse usando un'interfaccia desktop.
4.8.5 JSON
JSON (JavaScript Object Notation) è un formato adatto allo scambio di dati in applicazioni client-server. La sua semplicità e leggerezza rispetto a XML ne hanno decretato
una rapida ascesa, specialmente nella programmazione AJAX. Il suo utilizzo tramite JavaScript è particolarmente semplice, infatti l'interprete è in grado di eseguirne il parsing
attraverso la funzione eval().
4.8.6 Amazon Web Services
Gli Amazon Web Services (AWS) sono un insieme di servizi oerti da Amazon accessibili dal web attraverso un'interfaccia REST (Representational State Transfer), ovvero
richiamando le risorse web mediante un URL e ricevendo come risposta un documento in
formato HTML, XML o JSON contenente le informazioni richieste. Per l'accesso ai servizi sono anche disponibili librerie SDK speciche per ogni linguaggio di programmazione
che facilitano lo scambio di dati svincolando l'utente dal dover comporre manualmente
34
Progettazione
l'URL necessario per la richiesta e semplicando l'accesso ai dati ricevuti, che vengono
organizzati in oggetti del linguaggio ospite.
Nel progetto si è fatto uso di due dei nu-
meosi servizi oerti: il primo è Product Advertising API che consente di interrogare il
catalogo prodotti (per lo più libri) di Amazon e fare ricerche in base a determinati parametri. Il secondo servizio utilizzato è Amazon S3 (Simple Storage Service) che permette
il salvataggio online di le per poi renderli accessibili al pubblico.
4.9 Gli strumenti utilizzati
Per la realizzazione del progetto è stato fondamentale l'utilizzo di strumenti software
adeguati. Microsoft Visual Studio 2010 è un ambiente di sviluppo integrato (IDE) che
ore un supporto completo allo sviluppo di applicazioni che hanno alla base il framework
.NET. Questo strumento comprende alcune funzionalità che facilitano lo sviluppatore
rendendo tutto a portata di mano. Tra le caratteristiche degne di nota ci sono:
•
Integrazione con il compilatore
•
Editor di testo avanzato con IntelliSense che ore il competamento automatico dei
nomi degli oggetti in base al contesto.
•
Modalità debug integrata con possibilità di fermarsi ai breakpoint in base a condizioni denite dall'utente e di controllare il valore corrente delle variabili.
•
Il proler consente di ottenere statistiche sull'utilizzo di CPU e di memori, conoscere
le funzioni più chiamate e quelle in cui il usso di esecuzione passa la maggior parte
del tempo.
Microsoft SQL Server Management Studio consente di congurare e gestire tutti i componenti relativi a una base di dati SQL Server utilizzando editor graci e testuali. La
principale caratteristica di questo strumento è l'object explorer che consente all'utente di
accedere ai record relativi alle tabelle ed esequire query su di essi.
Per il controllo di versione e l'accesso al codice sorgente è stato utilizzato TortoiseHg.
Questa applicazione fornisce un'interfaccia graca a Mercurial che, a dierenza di software più datati come CVS e SVN, consente di lavorare creandosi un repository locale su
cui apportare le modiche che verranno poi inviate al server principale per essere unite a
4.9 Gli strumenti utilizzati
35
quelle degli altri sviluppatori.
Inne, trattandosi dello sviluppo di un'applicazione web, sono stati utilizzati per controllare che tutto funzionasse i principali browser disponibili sul mercato tra i quali Google
Chrome, Mozilla Firefox, Internet Explorer e Opera.
36
Progettazione
CAPITOLO 5
IMPLEMENTAZIONE
5.1 La libreria Novedge Base
Alla base di tutte le web application che formano il CMS c'è la libreria Novedge.Base che
funge da DAL (Data Access Layer) ovvero lo strato software che si interpone tra le applicazioni e il database. Le classi che compongono questa libreria deniscono il modello dei
dati fornendo alle applicazioni che la utilizzano un'interfaccia per accedervi e, in alcuni
casi, dei meccanismi di cache in modo da mantenere in memoria gli oggetti più utilizzati
per i quali sarebbe costoso un accesso frequente al database.
Novedge.Base non utilizza frameworks di terze parti per l'accesso ai dati, come ad esempio
potrebbero essere Nhibernate o l'Entity Framework di Microsoft, ma vengono richiamate
stored procedures memorizzate all'interno del database attraverso l'uso della libreria System.Data del framework .NET. Il pattern tipico per la maggior parte delle entità presenti
nella libreria Base si suddivide in tre classi: Entity.cs, EntityList.cs e EntityDictionary.cs.
Vediamo il class diagram delle classi in Base per la gestione dell'entità categoria:
38
Implementazione
Figura 5.1: Class Diagram delle classi in Novedge.Base utilizzate per le categorie
Entity.cs è la classe base per ogni tipo di entità e denisce al suo interno:
•
Le proprietà in sola lettura per ogni campo della tabella.
•
Un costruttore statico che inserisce in un dizionario FieldLoaders le funzioni necessarie a mappare i campi del database nelle proprietà della classe.
•
Un costruttore privato che setta i valori di default dei campi.
•
Un costruttore publico che consente di creare un nuovo oggetto passandogli i valori
dei campi.
•
Un costruttore publico che prende come input un record del database (DbDataReader) e, attraverso le funzioni contenute in FieldLoaders inserisce i valori nell'istanza
corrente della classe.
•
Un metodo CopyFrom per ottenere la copia di un oggetto.
5.1 La libreria Novedge Base
•
39
I metodi Save e Delete necessari per l'inserimento, aggiornamento e cancellazione
di un elemento.
•
Il metodo ToLog, implementato dall'interfaccia ILoggable, ritorna l'oggetto corrente
sottoforma di stringa e viene utilizzato nei log.
namespace Novedge.Base {
public class Category : ILoggable {
private delegate void FieldLoader(Category p_EuCategory, SqlDataReader
p_Reader, int p_Position);
public static class FieldsMap {
public const string ID = "uid";
public const string Name = "cname";
public const string Description = "cdescription";
public const string IsVertical = "cvertical";
public const string IsOnline = "cavailable";
public const string ShowInMenus = "cshowinmenu";
}
public int ID { get; private set; }
public string Name { get; protected set; }
public string Description { get; protected set; }
public bool IsOnline { get; protected set; }
public bool ShowInMenus { get; protected set; }
public bool IsVertical { get; protected set; }
// Dictionary (field-name,field-loader)
private static Dictionary<string, FieldLoader> FieldLoaders { get; set; }
public static Category Empty { get; private set; }
private string ModificationsCollector { get; set; }
static Category() {
Empty = new Category();
// Populate the FieldLoaders Dictionary
FieldLoaders = new Dictionary<string, FieldLoader>();
40
Implementazione
FieldLoaders[FieldsMap.ID] = (p_EuCategory, p_Reader, i) =>
p_EuCategory.ID = p_Reader.GetInt32(i);
// Other fields...
}
private Category() {
ID = IdUndefined;
Name = string.Empty;
Description = string.Empty;
IsOnline = false;
ShowInMenus = false;
IsVertical = false;
ModificationsCollector = string.Empty;
}
public Category(string p_Name, string p_Description, bool p_IsOnline,
bool p_ShowInMenus, bool p_IsVertical) {
ID = IdUndefined;
Name = p_Name;
Description = p_Description;
IsOnline = p_IsOnline;
ShowInMenus = p_ShowInMenus;
IsVertical = p_IsVertical;
ModificationsCollector = string.Empty;
}
// Build an End User category object out of a sql reader
public Category(SqlDataReader p_Reader)
:this() {
for (int i = 0; i < p_Reader.FieldCount; i++) {
if (p_Reader.IsDBNull(i))
continue;
FieldLoader loader;
if (FieldLoaders.TryGetValue(p_Reader.GetName(i).ToLower(), out
loader))
loader.Invoke(this, p_Reader, i);
else
Debug.WriteLine("Error: key not found in loading a field into a
5.1 La libreria Novedge Base
41
data-member from a query.");
}
ModificationsCollector = string.Empty;
}
public bool Save(){
bool success;
var isNew = (ID == IdUndefined || CategoriesDictionary.Dictionary[ID] ==
null);
using (var cmd = new DbCommand()) {
try {
cmd.Connection.Open();
cmd.AddParameter("Name", SqlDbType.Char).Value = Name;
cmd.AddParameter("Description", SqlDbType.Char).Value = Description;
cmd.AddParameter("IsVertical", SqlDbType.Bit).Value = IsVertical;
cmd.AddParameter("ShowInMenus", SqlDbType.Bit).Value = ShowInMenus;
cmd.AddParameter("IsOnline", SqlDbType.Bit).Value = IsOnline;
if (isNew)
using (var reader = cmd.ExecuteSp("sp_CreateCategory")) {
reader.Read();
ID = DbCommand.GetInt(reader, FieldsMap.ID, IdUndefined);
reader.Close();
}
else {
cmd.AddParameter("UID", SqlDbType.Int).Value = ID;
cmd.ExecuteNoQuery("sp_UpdateCategory");
}
success = true;
}
catch {
success = false;
}
finally {
cmd.Connection.Close();
}
}
42
Implementazione
if (!success)
return false;
CategoriesDictionary.Dictionary.AddOrUpdate(this);
if (isNew)
Log.Creation(LogObject.Category, ID, ToLog());
else
Log.Modification(LogObject.Category, ID, ModificationsCollector);
ModificationsCollector = string.Empty;
return true;
}
public int CopyFrom( Category p_Category) {
var collector = string.Empty;
Log.Changes(ref collector, "Name", Name, p_Category.Name);
Name = p_Category.Name;
// Other fields...
ModificationsCollector += collector;
return ID;
}
// Delete the category in the database.
public bool Delete() {
bool success;
using (var cmd = new DbCommand()) {
try {
cmd.Connection.Open();
cmd.AddParameter("UID", SqlDbType.Decimal).Value = ID;
cmd.ExecuteNoQuery("sp_DeleteCategory");
success = true;
}
catch {
5.1 La libreria Novedge Base
43
success = false;
}
finally {
cmd.Connection.Close();
}
}
if (!success)
return false;
Log.Deletion(LogObject.Category, ID, ToLog());
CategoriesDictionary.Dictionary.Remove(ID);
return true;
}
public string ToLog() {
return "(" + ID + ": '" + Name + "')";
}
}
}
EntityList.cs rappresenta una lista di entità di un certo tipo, implementa l'interfaccia
IEnumerable<Entity> e aggiunge ai classici metodi per l'accesso alla struttura dati
funzionalità speciche l'entità in questione.
namespace Novedge.Base {
public class CategoriesList : IEnumerable<Category>, ILoggable {
private readonly List<Category> Categories;
// Build an empty list of categories
public CategoriesList() {
Categories = new List<Category>();
}
// Build a list of categories from a SQL reader
public CategoriesList(SqlDataReader p_Reader)
:this() {
if (p_Reader == null || !p_Reader.HasRows)
44
Implementazione
return;
while (p_Reader.Read()) {
var id = DbCommand.GetInt(p_Reader, Category.FieldsMap.ID,
Catego-ry.IdUndefined);
if (id == Category.IdUndefined)
continue;
var category = CategoriesDictionary.Dictionary[id];
if (category != null && !Categories.Contains(category))
Categories.Add(category);
}
}
public CategoriesList( IEnumerable<string> p_IDs ) {
Categories = CategoriesDictionary.Dictionary.Values
.SelectMany( category => p_IDs, (category, idstr) => new {category,
idstr} )
.Where( pair => { int i; return int.TryParse(pair.idstr, out i) &&
pair.category.ID == i;} )
.Select( pair => pair.category )
.ToList();
}
IEnumerator<Category> IEnumerable<Category>.GetEnumerator() {
return Categories.GetEnumerator();
}
public IEnumerator GetEnumerator() {
return Categories.GetEnumerator();
}
public bool Contains( Category p_Category ) {
return Categories.Contains(p_Category);
}
public bool Contains( int p_CategoryID ) {
return this[p_CategoryID] != null;
}
5.1 La libreria Novedge Base
45
public CategoriesList GetCopy() {
return new CategoriesList(Categories.Select(cat => cat.ID.ToString()));
}
public CategoriesList Remove(int p_ID) {
if (Contains(p_ID))
Categories.Remove(this[p_ID]);
return this;
}
public CategoriesList RemoveAll() {
foreach(var category in Categories)
Categories.Remove(category);
return this;
}
public CategoriesList Add(Category p_Category) {
if (!Categories.Contains(p_Category))
Categories.Add(p_Category);
return this;
}
private Category this [int p_ID] {
get { return Categories.SingleOrDefault( category => category.ID == p_ID);
}
}
public string CSV {
get {
var ids = Categories.OrderBy(category => category.ID).Select(category
=> cate-gory.ID.ToString()).Distinct().ToArray();
return string.Join(",", ids);
}
}
public string ToLog() {
return "(" + CSV + ")";
}
46
Implementazione
public int Length {
get { return Categories.Count; }
}
}
}
Per quelle entità che necessitano del meccanismo di cache viene implementata anche la
classe EntityDictionary.cs. Questa struttura utilizza il pattern singleton in modo tale che
ne venga creata soltanto un'istanza e si occupa di memorizzare tutti gli elementi della
tabella di un'entità in un dizionario che ha come chiave l'identicativo dell'oggetto e come
valore l'oggetto stesso. Questo approccio evita l'accesso frequente al database ma viene
utilizzato solo per quegli oggetti di utilizzo frequente.
namespace Novedge.Base {
// This is a Singleton! It includes all Categories
public sealed class CategoriesDictionary : IEnumerable {
public static CategoriesDictionary Dictionary { get; private set; }
private readonly ConcurrentDictionary<int, Category> Categories;
static CategoriesDictionary() {
Dictionary = new CategoriesDictionary();
}
// The private constructor can be called only by a static member
// It returns always the complete list of all categories
private CategoriesDictionary() {
Categories = new ConcurrentDictionary<int, Category>();
using (var cmd = new DbCommand()) {
using (var reader = cmd.ExecuteQuery("sp_Get_EndUserCategories")) {
if (reader == null || !reader.HasRows) {
Debug.WriteLine("Warning: Stored Procedure returned an empty
dataset.");
return;
}
while (reader.Read()) {
var id = DbCommand.GetInt(reader, Category.FieldsMap.ID,
5.1 La libreria Novedge Base
Catego-ry.IdUndefined);
if (id != Category.IdUndefined)
Categories.TryAdd(id, new Category(reader));
}
reader.Close();
}
cmd.Connection.Close();
}
}
public IEnumerator GetEnumerator() {
return Categories.Values.GetEnumerator();
}
public IEnumerable<Category> Values {
get { return Categories.Values; }
}
public bool Contains(Category p_Category) {
return Categories.ContainsKey(p_Category.ID);
}
public bool Contains(int p_CategoryID) {
return Categories.ContainsKey(p_CategoryID);
}
public void Add(Category p_Category) {
if (p_Category.ID == Category.IdUndefined)
return;
Categories.TryAdd(p_Category.ID, p_Category);
}
public void AddOrUpdate(Category p_Category) {
if (p_Category.ID == Category.IdUndefined)
return;
Categories.AddOrUpdate(p_Category.ID, p_Category, (id, category) =>
{catego-ry.CopyFrom(p_Category);return category;});
}
47
48
Implementazione
public void Remove(int p_ID) {
if (p_ID == Category.IdUndefined)
return;
Category category;
Categories.TryRemove(p_ID, out category);
}
public Category this[int p_ID] {
get { return Categories.SingleOrDefault(pair => pair.Value.ID ==
p_ID).Value; }
}
}
}
5.2 La barra di navigazione
La barra di navigazione è la parte del CMS sempre visibile posizionata in alto e svolge due
funzioni. La prima è quella che consente all'utente di identicarsi tramite uno username
e una password per accedere alle applicazioni.
Figura 5.2: Barra di navigazione prima del login
Quando l'operatore inserisce le proprie credenziali il sistema ne controlla l'esistenza e i
permessi all'interno del database mostrando solo i collegamenti alle applicazioni accessibili
in base al ruolo dell'utente.
Le applicazioni implementate e disponibili vengono salvate in una lista nel codice della
toolbar che ne specica l'URL in cui si trova il le aspx principale e il ruolo minimo
necessario per poterla utilizzare. Nel caso in cui il login non vada a buon ne o un utente
non autorizzato provi ad accedere a un'applicazione che richiede un ruolo più alto viene
mostrata una pagina d'errore.
Figura 5.3: Barra di navigazione dopo il login
5.3 L'applicazione Products
49
Una volta loggati viene salvato un cookie nel browser dell'utente in modo da identicarlo
nei successivi accessi al CMS evitando ogni volta il processo di autenticazione. La navigation bar consente anche di vedere quanti utenti sono attualmente loggati nel sistema
(nel quadrato rosso vicino al tasto logout) e, se si è amministratori, si può avere una lista
dettagliata di questi utenti e che applicazioni stanno utilizzando.
Figura 5.4: Finestra che mostra gli utenti connessi al sistema
Per motivi di sicurezza non viene mostrato il codice relativo all'autenticazione e ai
permessi degli utenti.
5.3 L'applicazione Products
Products è l'applicazione più utilizzata all'interno del CMS in quanto capita spesso di dover modicare qualche caratteristica legata a un prodotto o di doverne inserire uno nuovo.
La cancellazione di un prodotto, invece, non è supportata in quanto è un'operazione che
avviene raramente e per essere eseguita occorre che nessun altro oggetto all'interno del
database faccia riferimento in qualche modo al prodotto.
Figura 5.5: Schermata dell'applicazione Products
50
Implementazione
La pagina web che si presenta all'avvio è divisa in due parti. La parte superiore consente
la ricerca dei prodotti in base al brand e al nome del prodotto con alcune possibilità
di ltrare i risultati (in base al genere o allo stato) e di ordinarli.
Un altro modo per
selezionare un prodotto è mediante la textbox posizionata in basso a sinistra; qui è
possibile inserire direttamente lo SKU, ovvero l'identicativo di un prodotto e premere il
tasto GoTo.
Una volta eettuata la selezione i dati del prodotto vengono caricati nella form presente
nella parte inferiore della pagina web. A questo punto è anche possibile nascondere la
barra di ricerca (attraverso il tasto a forma di triangolo vicino alla tab Main) in modo
da non avere spazio occupato da questa funzione quando non è necessaria.
La form contenente i controlli HTML necessari per modicare il prodotto è stata suddivisa
in più tab in modo da poter disattivare quelle non necessarie in base a determinate regole
(ad esempio se un prodotto non è un bundle non è necessario compilare il contenuto della
tab Bundles, che di conseguenza viene disattivata); inoltre, utilizzando questo approccio,
la form ha una dimensione che le consente di restare sempre completamente visibile
all'interno della nestra del browser. Segue una descrizione delle tab:
•
La tab Main è la tab principale della applicazione Products in cui si possono settare
le caratteristiche basilari. Tra le più importanti troviamo: lo stato (online o oine),
il brand, il tipo di prodotto, il nome, la versione, ecc.
•
Prices permette di settare i prezzi del prodotto.
Inserendo il prezzo di listino, il
costo e il prezzo fatto da Novedge si ottiene immediatamente un risultato visivo che
mostra lo sconto eettuato, il margine sulla vendita, le percentuali e un messaggio
riassuntivo.
•
La tab Bundles viene attivata solamente se un prodotto è di tipo bundle, ossia non
è un vero e proprio prodotto ma un insieme di più prodotti venduti a un prezzo
inferiore rispetto all'acquisto dei singoli prodotti separatamente; quindi in questa
sezione vengono selezionati i prodotti che compongono un bundle.
•
HTML contiene la descrizione del prodotto.
Oltre a supportare i tag HTML la
descrizione può contenere altri tag che consentono di inserire collegamenti ad altri
prodotti, brand, documenti o a pagine di wikipedia.
Durante il salvataggio del
prodotto questi tag vengono riconosciuti tramite regular expression e compilati in
quello che sarà il risultato nale da mostrare sulla pagina.
5.3 L'applicazione Products
•
51
Support e Facts sono due tab che consentono di modicare i rispettivi campi. Il
primo contiene informazioni sul supporto tecnico mentre il secondo informazioni
speciche sulle proprietà e capacità del prodotto.
•
La tab Trials consente di inserire i link alle versioni di prova del prodotto per i vari
sistemi operativi aggiungendo una descrizione dei limiti del trial.
•
Le tab Tags, Categories, Masters, Input e Output sono simili dal punto di vista del
metodo di inserimento dei valori, esse infatti consentono di associare al prodotto
più valori presi da un elenco pressato. I tags deniscono attributi sulle capacità
e compatibilità del prodotto.
Le categorie permettono di dividere i prodotti in
determinati gruppi in base alle funzionalità oerte.
La tab masters è attiva solo
quando un prodotto deve fare riferimento a un altro prodotto, come nel caso di
aggiornamenti di versione. Input e output, invece, permettono di settare i formati
di le supportati dal programma.
Il punto di forza di questa applicazione sta nel poter creare collegamenti tra i prodotti.
Ad esempio se un prodotto è l'aggiornamento di un altro o una versione dierente questa
relazione viene inserita nella form.
Questo approccio consente agli utenti del sito web
che sono alla ricerca di un prodotto di ottenere suggerimenti pertinenti alla ricerca ed
arrivare con pochi click alla pagina cercata.
Lo sviluppo dell'applicazione products contiene alcune funzionalità, sviluppate in javascript, che sono state utilizzate anche negli altri progetti.
5.3.1 L'autocompletamento dei prodotti
Quando, in qualche parte del CMS, si ha la necessità di selezionare o far riferimento a un
prodotto viene utilizzato un autocompleter.
Questo plugin fa parte dei controlli contenuti nella libreria jQueryUI e viene applicato
a una textbox dove, inserendo parte del nome o del codice SKU di un prodotto, viene
visualizzata una lista di prodotti che contengono il testo inserito indicando con sfondo
di diverso colore se il prodotto è attualmente in vendita o è disattivo. Per far questo il
plugin richiama, utilizzando la tecnologia AJAX, il web service AjaxGetCompletionList
presente nel progetto che prende in input la stringa di ricerca e ritorna la lista di risultati
in formato JSON. A questo punto viene elaborata lato client la lista dei risultati e viene
52
Implementazione
Figura 5.6: Autocompleter in funzione applicato a una textbox
visualizzata sotto la textbox.
Questo approccio consente alla pagina web di essere più leggera non dovendo contenere
la lista intera di oltre seimila prodotti.
La funzione javaScript che si occupa di collegare l'autocompleter ad un campo di testo è
chiamata attachLocalAutocompleter e ha come parametri:
•
textboxId: identicativo del textbox target.
•
serviceUrl: URL in cui si trova il web service di autocompletamento.
•
doPostBackOnSelection: booleano che indica se è necessario fare il post della pagina
per farla elaborare al server.
•
callerObject: specica il riferimento all'oggetto javaScript che ha invocato la funzione (opzionale).
•
onSelectFunction: riferimento a una funzione del callerObject da invocare quando
viene selezionato un elemento dall'autocompleter (opzionale).
•
onCloseClearTextbox: booleano che indica se è necessario cancellare il contenuto
della textbox alla chiusura dell'autocompleter (opzionale).
5.3 L'applicazione Products
function attachLocalAutocompleter(textboxId, serviceUrl, doPostBackOnSelection,
callerObject, onSelectFunction, onCloseClearTextbox) {
jQuery("#" + textboxId).autocomplete({
minLength: 3,
source: function (request, response) {
jQuery.ajax({
type: "POST",
url: serviceUrl + "?str=" + request.term,
success: function (data) {
var j = data;
response(jQuery.map(j.results, function (item) {
return {
value: item.value,
online: item.online
};
}));
}
});
},
select: function (event, ui) {
jQuery("#" + textboxId).val(ui.item.value);
jQuery("#" + textboxId).attr('online', ui.item.online.toString());
if (typeof (callerObject) != 'undefined' &&
typeof (onSelectFunction) != 'undefined')
onSelectFunction.apply(callerObject);
if (doPostBackOnSelection)
__doPostBack("'" + textboxId + "'", '');
},
close: function (event, ui) {
if (onCloseClearTextbox == true)
jQuery('#' + textboxId).val('');
}
})
.data('autocomplete')
._renderItem = function (ul, item) {
var listItem = jQuery('<li></li>')
.data('item.autocomplete', item)
53
54
Implementazione
.append('<a>' + item.label + "</a>")
.appendTo(ul);
if (item.online)
listItem.addClass('activeOption');
else
listItem.addClass('notActiveOption');
return listItem;
};
}
5.3.2 Sistema dei messaggi
Questo plugin ha la funzione di mostrare messaggi all'utente svolgendo in pratica lo stesso
compito delle funzioni alert e conrm di javaScript ma in modo più gradevole e meno
invasivo, non bloccando la pagina in attesa di risposta.
Figura 5.7: Esempio di messaggio di worning mostrato all'utente
I messaggi vengono visualizzati nell'angolo in basso a destra della pagina e sono stati
divisi in tre categorie:
•
I messaggi di avviso e di warning vengono mostrati rispettivamente su sfondo verde
e arancione per avvertire l'operatore se un'operazione richiesta è andata a buon ne
o se si sono vericati dei problemi. Il messaggio comprende un bottone denominato
`OK' che consente di chiudere il messaggio manualmente, in alternativa l'utente
vedrà scomparire il messaggio dopo cinque secondi
5.3 L'applicazione Products
•
55
I messaggi di errore hanno uno sfondo rosso e vengono utilizzati per informare
l'utente gli errori più gravi. Questo tipo di messaggio resta visibile no alla pressione
del tasto `OK'.
•
I messaggi di conferma sono su sfondo verde e presentano due possibili scelte `Yes'
o `No' con cui l'operatore può confermare l'operazione richiesta.
I messaggi vengono posizionati nella pagina attraverso i fogli di stile CSS settando i valori
position:xed, right:10px e bottom:0 agli elementi con ID dialogBox. In questo modo il
plugin è indipendente dal contenuto e dalla formattazione della pagina prendendo come
riferimento l'area visibile del browser.
Le animazioni del messaggio sono state realizzate utilizzando lo slide di jQuery. Quando
infatti attraverso questa libreria si specica se un elemento del DOM deve passare dallo
stato visibile a nascosto o viceversa, è possibile specicare se la transizione deve essere
animata (scegliendo tra diversi eetti graci) e quanto deve durare.
jQuery("#dialogBox").show('slide', { direction: 'down' }, 1000);
setTimeout(function () {
jQuery("#dialogBox").hide('slide', { direction: 'down' }, 1000);
}, 5000);
5.3.3 Il plugin Wikipedia
Questa funzione javascript consente all'utente che sta navigando sul sito Novedge di
cliccare su un link a una pagina wikipedia e vedere il risultato in un riquadro senza dover
lasciare il sito.
Alcune parti del CMS consentono di inserire nelle descrizioni delle entità riferimenti a
pagine di Wikipedia.
Questi collegamenti vengono rappresentati nel testo con dei tag
che verranno poi sostituiti con la chiamata alla funzione che attiva il plugin realizzato.
Il contenuto del plugin viene acquisito mediante l'utilizzo dei web service di Wikipedia
che consentono di ottenere, in diversi formati, le parti della pagina scegliendo poi cosa
mostrare al visitatore. Mediante una funzione C# viene generato l'URL necessario per
richiedere i contenuti dell'header e del body della pagina Wikipedia specicata come
argomento.
A questo punto viene generato il contenuto del riquadro da visualizzare
56
Implementazione
Figura 5.8: Plugin wikipedia in azione sul sito Novedge
togliendo le parti non necessarie (come il menù laterale, l'intestazione e i collegamenti
per editare la pagina).
private void GetWikipediaPage(string p_Page)
{
var url = "http://en.wikipedia.org/w/api.php?" +
"action=parse&format=xml&prop=text%7Cheadhtml&redirects&page=";
url += HttpUtility.HtmlEncode(p_Page);
var request = (HttpWebRequest)WebRequest.Create(url);
request.UserAgent = "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.4 (KHTML,
like Gecko) Chrome/22.0.1229.79 Safari/537.4";
using (var response = (HttpWebResponse)request.GetResponse())
{
var xmlDoc = new XmlDocument();
xmlDoc.Load(response.GetResponseStream());
XmlNodeList header = xmlDoc.GetElementsByTagName("headhtml");
var headerDecoded = HttpUtility.HtmlDecode(header[0].InnerText);
Header.Controls.AddAt(0, new Literal() { Text = headerDecoded });
5.4 L'applicazione Books
57
XmlNodeList body = xmlDoc.GetElementsByTagName("text");
var bodyDecoded = FixLinksLocation(HttpUtility.HtmlDecode(body[0].InnerText));
h_wikipedia_content.Controls.Add(new Literal() { Text = bodyDecoded });
}
}
5.4 L'applicazione Books
Books è l'applicazione il cui compito è quello di associare un libro a una o più categorie
di prodotti.
Novedge non si occupa direttamente della vendita dei libri ma fornisce
collegamenti a libri presenti su Amazon.
Figura 5.9: Schermata dell'applicazione Books
Quando si inserisce un ASIN (Amazon Standard Identication Number) nella form il
sistema controlla se il libro è già presente nel database.
In questo caso viene mostra-
to il bottone Load elds from Novedge che carica i dati del libro e le associazioni dal
database.
Se invece il libro non è ancora stato inserito appare il bottone Load elds
from Amazon che, attraverso una chiamata al web service Product Advertising API di
58
Implementazione
Amazon, permette di caricare tutti i dati del libro automaticamente evitando all'utente
l'inserimento manuale.
Nella parte inferiore dell'applicazione troviamo tre sezioni denominate Suggested Books,
Suggested Books already inserted e Last Books added. Le prime due mostrano una lista
di libri, ottenuta sempre grazie ai web service AWS, che sono pertinenti all'argomento
del libro attualmente caricato nella form. In questo modo l'utente riesce con pochi click
del mouse ad inserire un'enorme quantità di entità all'interno della base di dati.
L'ultima sezione, invece, mostra gli ultimi cinque libri inseriti in ordine cronologico inverso.
Tra le funzioni che agevolano ulteriormente il lavoro dell'operatore abbiamo l'anteprima
della copertina quando si passa col mouse sui collegamenti presenti nelle liste e i due bottoni in alto a destra che permettono di aprire in una nestra separata le pagine relative
al libro selezionato su Amazon e sul sito Novedge.
Per l'accesso ad Amazon sono state realizzate tre classi: AmazonRequest, AmazonItemLookup e AmazonSimilarityLookup.
AmazonRequest è una classe astratta da cui le altre due derivano e il suo compito è quello
di generare l'URL necessario per la richiesta di informazioni. Per fare ciò questa classe
utilizza una coppia di chiavi (una pubblica e una privata), salvate nel le di congurazione dell'applicazione, necessarie per identicarsi e per creare la rma del messaggio che
altrimenti verrebbe riutato.
public abstract class AmazonRequest
{
// CONSTANTS
protected readonly string AccessKeyId =
ConfigurationManager.AppSettings["AWSAccessKey"];
protected readonly string SecretAccessKey =
ConfigurationManag-er.AppSettings["AWSSecretKey"];
protected const string AssociateTag = "novedge";
protected const string Service = "AWSECommerceService";
protected const string Version = "2011-08-01";
protected const string StringToSignPrefix = "GET\necs.amazonaws.com\n/onca/xml\n";
protected const string WebServiceUrl = "http://ecs.amazonaws.com/onca/xml";
// ATTRIBUTES
protected Dictionary<string, string> RequestParams;
5.4 L'applicazione Books
// PROPERTIES
private XmlDocument _responseXmlDocument;
public XmlDocument ResponseXmlDocument
{
get { return _responseXmlDocument ?? (_responseXmlDocument =
GetResponseXmlDocu-ment()); }
protected set { _responseXmlDocument = value; }
}
// CONSTRUCTOR
protected AmazonRequest()
{
RequestParams = new Dictionary<string, string>();
RequestParams["AWSAccessKeyId"] = AccessKeyId;
RequestParams["AssociateTag"] = AssociateTag;
RequestParams["Service"] = Service;
RequestParams["Version"] = Version;
}
// PRIVATE METHODS
private XmlDocument GetResponseXmlDocument()
{
var responseXmlDoc = new XmlDocument();
try {
var url = GetRequestUrl();
responseXmlDoc.Load(url);
}
catch {
return null;
}
return responseXmlDoc;
}
private string GetRequestUrl()
{
var requestParams = GetRequestParamsAsUrlString();
var signature = GetSignature(requestParams);
return WebServiceUrl + "?" + requestParams + "&Signature=" + signature;
59
60
Implementazione
}
private string GetRequestParamsAsUrlString()
{
var timestamp = string.Format("{0:s}Z", DateTime.Now.ToUniversalTime());
RequestParams["Timestamp"] = timestamp;
var paramRequestUrlString = new StringBuilder();
paramRequestUrlString.Append("AWSAccessKeyId=")
.Append(RequestParams["AWSAccessKeyId"])
.Append("&");
foreach (var key in RequestParams.Select(param => param.Key).Where(key => key
!= "AWSAccessKeyId").OrderBy(key => key))
paramRequestUrlString.Append(key)
.Append("=")
.Append(RequestParams[key])
.Append("&");
return paramRequestUrlString.Remove(paramRequestUrlString.Length - 1,
1).ToString();
}
private string GetSignature(string p_ParamsStringToSign)
{
var stringToSign = StringToSignPrefix +
p_ParamsStringToSign.Replace(",", "%2C").Replace(":", "%3A");
return SignString(SecretAccessKey, stringToSign);
}
private string SignString(string p_SecretKey, string p_StringToSing)
{
var key = Encoding.UTF8.GetBytes(p_SecretKey);
var myHash256 = new HMACSHA256(key);
var urlBytes = Encoding.UTF8.GetBytes(p_StringToSing);
var hashValue = myHash256.ComputeHash(urlBytes);
var signedString = Convert.ToBase64String(hashValue);
return signedString.Replace("/", "%2F").Replace("=", "%3D").Replace("+",
5.4 L'applicazione Books
61
"%2B");
}
}
La classe AmazonItemLookup viene richiamata alla pressione del bottone Load elds
from Amazon per ricevere tutte le informazioni necessarie per riempire i campi della
form relativi a un libro.
public class AmazonItemLookup : AmazonRequest
{
// CONSTANTS
private const string IdType = "ASIN";
private const string Operation = "ItemLookup";
private const string ResponseGroup = "ItemAttributes,Images,Reviews,OfferSummary";
private const string MerchantId = "Featured";
// CONSTRUCTOR
public AmazonItemLookup(string p_ASIN)
{
RequestParams["ItemId"] = p_ASIN;
RequestParams["IdType"] = IdType;
RequestParams["Operation"] = Operation;
RequestParams["ResponseGroup"] = ResponseGroup;
RequestParams["MerchantId"] = "Featured";
}
// PROPERTIES
public string Title {
get {
if (ResponseXmlDocument == null)
return "";
var xmlNode = ResponseXmlDocument.GetElementsByTagName("Title")[0];
return xmlNode != null ? xmlNode.InnerText : "";
}
}
public string Year { get; }
// Codice omesso per compattezza
public double LowestPrice { get; }
62
Implementazione
public string Author { get; }
public string ImageUrl { get; }
}
Inne AmazonSimilarityLookup serve per ottenere una lista di prodotti simili a quello
specicato. In questo caso occorre ltrare i risultati in modo da mostrare all'utente solo
i prodotti di tipo libro e ignorare tutti gli altri. La classe SimilarBook è una struttura
dati di supporto per gli elementi ottenuti.
public class SimilarBook
{
public string ASIN { get; private set; }
public string Title { get; private set; }
public string ImageUrl { get; private set; }
public SimilarBook(string p_Asin, string p_Title, string p_ImageUrl) {
ASIN = p_Asin;
Title = p_Title;
ImageUrl = p_ImageUrl;
}
}
public class AmazonSimilarityLookup : AmazonRequest
{
// CONSTANTS
private const string Operation = "SimilarityLookup";
private const string ResponseGroup = "Images,Small";
// CONSTRUCTOR
public AmazonSimilarityLookup(string p_ASIN) {
RequestParams["ItemId"] = p_ASIN;
RequestParams["Operation"] = Operation;
RequestParams["ResponseGroup"] = ResponseGroup;
}
// PROPERTIES
public IEnumerable<SimilarBook> SimilarBooks {
get {
var similarBooks = new List<SimilarBook>();
5.5 L'applicazione Specials
63
if (ResponseXmlDocument == null)
return similarBooks;
var xmlItemTags = ResponseXmlDocument.GetElementsByTagName("Item");
foreach (XmlNode xmlItemTag in xmlItemTags) {
if (xmlItemTag["ItemAttributes"]["ProductGroup"].InnerText != "Book")
continue;
similarBooks.Add(new SimilarBook(xmlItemTag["ASIN"].InnerText,
xmlI-temTag["ItemAttributes"]["Title"].InnerText,
xmlItemTag["LargeImage"]["URL"].InnerText));
}
return similarBooks;
}
}
}
5.5 L'applicazione Specials
Quando un prodotto del catalogo viene messo in promozione, oltre ad abbassarne il prezzo, occorre mostrare sulla pagina un messaggio con la descrizione o motivazione della
promozione.
L'applicazione Specials si occupa proprio di questo, dando la possibilità
all'utente di creare nuove promozioni e di associare ad esse uno o più prodotti che mostreranno lo stesso messaggio promozionale.
Anche in questo caso si è suddiviso il contenuto della form in diverse tab in modo da
separare concettualmente le operazioni che si stanno eseguendo.
La prima tab è denominata Post It e permette di settare i contenuti del messaggio da
visualizzare (simile appunto a un post it) oltre alle date di inizio e ne della promozione.
Il post it è composto da quattro parti: il titolo e il footer appaiono rispettivamente in
cima e in fondo al messaggio, mentre nella parte centrale sono situati il testo della promozione e la label che, di solito, ha un carattere molto più grande rispetto agli altri per
attirare l'attenzione.
Esistono due tipi di testo per lo special, uno on target e uno o target. Quello on target
è il messaggio mostrato quando il prodotto è in promozione, mentre quello o target
64
Implementazione
quando il prodotto fa riferimento a un altro prodotto in promozione.
Mentre vengono editati i campi della form vengono visualizzate ai piedi della pagina le
anteprime di come verrà visualizzato il messaggio sul sito web, aggiornate lato client ad
ogni modica utilizzando javaScript.
Figura 5.10: Schermata della tab Post It dell'applicazione Specials
La seconda tab, invece, consente di associare i prodotti allo special. Scrivendo lo SKU o
parte del nome di un prodotto nella textbox libera della lista appare l'autocompleter che
consente di selezionare il prodotto interessato, dopodiché è possibile cambiarne i prezzi,
gli SKU esterni e associare un altro prodotto di riferimento.
Prima di poter associare un prodotto ad uno special il sistema deve controllare che questo
non sia già in promozione in un altro special attivo. In questo caso l'utente viene informato
del conitto con un messaggio e l'elemento non può essere salvato a meno che non si risolva
in qualche modo il conitto.
La gestione di questa parte avviente completamente lato client utilizzando un oggetto javaScript denominato SpecialProductRow contenente le funzioni per gestire ogni prodotto
associato.
5.5 L'applicazione Specials
65
Figura 5.11: Schermata della tab Products dell'applicazione Specials
function SpecialProductRow() {
this.loadFields = function () { ... }
this.initializeRow = function () { ... }
this.productSelected = function () { ... }
this.showProductPicture = function () { ... }
this.hideProductRow = function () { ... }
this.checkUniqueness = function() { ... }
}
I metodi contenuti in questo oggetto sono:
•
loadFields carica nella form tutti i dati relativi al prodotto attraverso l'utilizzo
del web service AjaxGetSpecialProductInfos. Tra le informazioni contenute nella
risposta AJAX troviamo anche quella che specica se il prodotto è già attivo in
un altro special; in questo caso l'utente viene avvisato da un messaggio su sfondo
rosso.
•
initializeRow setta le proprietà e gli stili dei controlli durante l'inserimento di una
nuova riga.
•
productSelected è la funzione che viene richiamata dall'autocompleter quando si
sceglie un nuovo prodotto da associare allo special. Questa ha il compito di creare
una nuova riga richiamando gli altri metodi per inizializzarla e riempirla con i dati
del prodotto.
•
showProductPicture richiama il web service AjaxGetProductPicture per farsi ritornare l'immagine della scatola del prodotto che verrà poi visualizzata all'inizio della
66
Implementazione
riga.
•
hideProductRow viene invocata quando l'utente cancella una riga. La funzione si
occupa di marcarla come cancellata nascondendola all'utente.
•
checkUniqueness ha il compito di controllare che il prodotto di una nuova associazione non sia già presente nella lista dei prodotti dello special.
Le ultime due tab sono quelle dei commenti e dei log, già illustrate in precedenza.
Specials consente anche, premendo il bottone Calendar, di avere una rappresentazione
tabellare stampabile del calendario delle oerte attive in un determinato mese, fornendo
in questo modo una visualizzazione che consente di tenere sotto controllo le scadenze.
5.6 L'applicazione Documents
L'applicazione documents consente di associare un documento a una lista di prodotti o
ad un intero brand.
I le che si vogliono inserire nel database possono essere collegamenti a risorse disponibili
su internet oppure le presenti sul computer dell'operatore. Nel secondo caso i documenti
devono essere caricati su S3, una piattaforma cloud di storage fornita da Amazon.
L'upload avviene in due fasi. Come prima cosa l'utente sceglie dal proprio computer il
documento da caricare premendo il bottone Upload New File. Questo viene trasferito
sul server Novedge dopodichè la web application contatta i server di Amazon utilizzando
le API speciche per il framework .NET, identicandosi attraverso una coppia di chiavi
(una pubblica e una privata segreta), ed eetua l'upload denitivo del le. Il documento
sarà quindi raggiungibile da internet attraverso un indirizzo specico.
La pressione del bottone Upload richiama l'esecuzione dell'evento contenente il seguente
codice:
protected void UploadSelectedDocumentButtonClick(object sender, EventArgs e)
{
var fileName = h_document_fileupload.FileName;
if ((!string.IsNullOrEmpty(fileName.Trim())) &&
h_document_fileupload.FileContent.Length == 0) {
Html.ShowWarning(this, "The selected file is empty");
return;
5.6 L'applicazione Documents
67
}
if (!h_document_fileupload.HasFile || string.IsNullOrEmpty(fileName.Trim())) {
Html.ShowWarning(this, "Select a file before pushing the Upload button");
return;
}
if (JustUploadedS3Document != "")
DeleteObjectFromAmazonS3(JustUploadedS3Document);
var fileSizeInMb = h_document_fileupload.FileContent.Length/1048576f;
var inputStream = new MemoryStream();
h_document_fileupload.FileContent.CopyTo(inputStream);
var accessKeyId = ConfigurationManager.AppSettings["AWSAccessKey"];
var secretAccessKey = ConfigurationManager.AppSettings["AWSSecretKey"];
var bucketName = ConfigurationManager.AppSettings["DocumentsBucketName"];
try {
var transferUtilityConfig = new TransferUtilityConfig {DefaultTimeout =
1200000};
var fileTransferUtility = new TransferUtility(accessKeyId, secretAccessKey,
transferU-tilityConfig);
fileTransferUtility.Upload(inputStream, bucketName, fileName);
using (var client = Amazon.AWSClientFactory.CreateAmazonS3Client(accessKeyId,
secre-tAccessKey)) {
var setAclRequest = new SetACLRequest {
BucketName = bucketName,
Key = fileName,
CannedACL = S3CannedACL.PublicRead
};
var setAclResponse = client.SetACL(setAclRequest);
setAclResponse.Dispose();
}
h_hidden_just_uploaded_s3_document.Value = fileName;
}
catch {
68
Implementazione
Html.ShowError(this, "An Error occurred during file upload");
return;
}
h_document_url.Text = "http://" + bucketName + ".s3.amazonaws.com/" +
HttpUtility.UrlEncode(fileName);
Html.ShowAcknowledgment(this, "File uploaded correctly");
h_upload_panel.Visible = false;
h_document_size.Text = "-1";
if ((int) (fileSizeInMb*100) != 0)
h_document_size.Text = string.Format("{0:0.00}", fileSizeInMb);
}
Dopo una serie di controlli nalizzati a capire se l'operatore abbia eettivamente selezionato un le e che questo non sia vuoto il sistema prova (nel blocco try catch) a inviare il
le.
Se il documento viene caricato correttamente su S3 l'applicazione si preoccupa di correggere il campo size della form con la dimensione eettiva del documento, inoltre si
tiene traccia del documento in modo tale che se l'utente non salva eettivamente l'enità
document all'interno del database questo viene scartato ed eliminato da S3. Nel caso in
cui l'operazione non vada a buon ne viene mostrato un messaggio d'errore.
Figura 5.12: Sequence diagram del caricamento dei le nell'applicazione Documents
5.7 L'applicazione Orders
69
Di default una web application ASP.NET supporta, per ovvie ragioni di sicurezza, il
trasferimento in upload per le di massimo 4 megabyte di dimensione. Questo limite è
stato tolto nell'applicazione corrente in quanto può capitare di dover processare le di
dimensioni maggiori ed essendo utilizzata dal personale interno all'azienda non è soggetta
ad attacchi dall'esterno.
Figura 5.13: Schermata dell'applicazione Documents
5.7 L'applicazione Orders
L'applicazione Orders è stata creata per consentire la modica degli ordini eettuati
dai clienti. Da notare che per la consultazione di tali ordini l'azienda fa uso di un'altra
applicazione web integrata nel sito sviluppata precedentemente alla realizzazione di questo
CMS.
All'avvio la pagina mostra il template di un ordine vuoto utilizzabile per eseguire test e
operazioni su un ordine non esistente, in quanto non è possibile creare un nuovo ordine
ma solo modicare quelli già presenti nella base di dati.
Per caricare i dati di un ordine presente nel database nella form si inserisce l'identicativo
nella casella in basso a sinistra premendo poi invio o il bottone GoTo.
Una volta che i campi sono stati riempiti con i dati dell'ordine l'applicazione funziona per
la quasi totalità lato client, utilizzando funzioni e oggetti javaScript, in modo da eseguire
70
Implementazione
le operazioni richieste in modo uido e veloce evitando quindi il postback e il refresh della
pagina.
Le operazioni consentite su un ordine sono:
•
Modica degli indirizzi di spedizione e fatturazione.
•
Modica del prezzo unitario e quantità dei prodotti che compongono l'ordine.
•
Inserire e cancellare prodotti.
•
Modica del metodo di pagamento.
•
Aggiungere o modicare coupon di sconto.
•
Modicare i dati relativi all'ordine stesso come sconto, costo spedizione, tasse e
totale.
•
Esplosione di un bundle, ovvero sostituire la voce del bundle nell'ordine con i
prodotti in esso contenuti.
Figura 5.14: Schermata dell'applicazione Orders
La funzione di autocalcolo dei valori entra in azione appena dopo il caricamento dei valori
nella form. Partendo dai dati base come il prezzo unitario e la quantità dei prodotti questa
5.8 L'applicazione Reports
71
funzione prova a calcolare i valori dell'ordine in modo automatico. Se questi combaciano
con quelli caricati (presenti nel database) allora la funzione rimane attiva ricalcolando
tutti i valori ad ogni modica dei campi, in caso contrario l'autocalcolamento viene disattivato e l'utente dovrà occuparsi del calcolo dei campi non conformi. Le motivazioni
per cui i valori del database e quelli calcolati potrebbero non coincidere sono dovute alla
modica della percentuale delle tasse (che in genere cambia annualmente), alla modica
dei costi di spedizione o a regole non ancora introdotte nella logica dell'applicazione.
5.8 L'applicazione Reports
Inizialmente reports era un'applicazione concepita solo con l'intento di controllare i dati
contenuti nel database in base a regole predenite generando appunto un report della
situazione, poi con l'evolversi del CMS sono state aggiunte le seguenti funzionalità:
•
Recompile website si occupa di convertire tutti quei campi di testo presenti nel
database che contengono dei tag (ad esempio i testi degli specials) sostituendoli
con il testo opportuno. In questo modo si alleggerisce il lavoro del web server che
altrimenti dovrebbe svolgere l'operazione ad ogni richiesta di pagina.
•
Clean database elimina del database quei record che non sono più referenziati da
altri oggetti o che sono datati e considerati inutili. Questi elementi sono generati da
prove varie eseguite sulla base di dati o dovuti a cambiamenti avvenuti nel tempo.
•
Latest log entries permette di consultare tutti i log di ogni applicazione ltrandoli
anche per un periodo di tempo specico.
Per quanto riguarda le regole da controllare nella funzionalità di consistency check è
stata sviluppata una classe astratta contenente i campi fondamentali da cui ogni regola
implementata deriva.
La classe CheckerBase contiene un Nome e una descrizione che
spiegano che tipo di controllo svolge la regola, un campo enumerabile Module per il tipo
di modulo su cui opera la funzione e una metodo Check() che conterrà il codice di controllo
e restituisce una lista di oggetti CheckerResult per ogni singolo test eettuato.
namespace Novedge.CMS.Reports.Checkers {
public abstract class CheckerBase {
public abstract string Name { get; }
public abstract string Description { get; }
72
Implementazione
public abstract Security.Module Module { get; }
public abstract List<CheckerResult> Check();
}
}
La classe CheckerResult rappresenta il risultato del controllo di una regola applicato a
un singolo elemento.
Oltre ai campi ItemId e Title che rappresentano rispettivamente
l'identicativo e il titolo (o nome) dell'oggetto testato vengono forniti:
un messaggio
testuale che viene visualizzato dall'applicazione, un campo Status con l'esito del test e
un campo ActionTaken che specica l'azione del checker in base al risultato (None =
nessuna azione, Alerted = utente avvisato, Fixed = errore risolto dal sistema).
namespace Novedge.CMS.Reports.Checkers {
public class CheckerResult {
public int ItemId { get; set; }
public Status Status { get; set; }
public ActionTaken ActionTaken { get; set; }
public string Message { get; set; }
public string Title { get; set; }
public CheckerResult(int p_ItemId, string p_Message, Status p_Status =
Status.Ok, ActionTaken p_ActionTaken = ActionTaken.None, string p_Title =
"") {
ItemId = p_ItemId;
Message = p_Message;
Status = p_Status;
ActionTaken = p_ActionTaken;
Title = p_Title;
}
}
public enum Status {
Ok,
Warning,
Error
}
public enum ActionTaken {
5.8 L'applicazione Reports
73
None,
Alerted,
Fixed
}
}
L'applicazione Consistency Check contiene una lista di tutti i checker utilizzabili consentendo all'amministratore di vedere i report. Attualmente sono state implementate le
seguenti regole:
•
Verica che tutti i prezzi (per i prodotti attivi) siano maggiori di zero.
•
Verica che i prezzi Novedge siano compresi tra il costo e il prezzo di listino.
•
Verica che i prodotti contenuti in un bundle non siano a loro volta bundle.
•
Verica che tutti i prodotti che contengono altri prodotti siano categorizzati come
bundle.
•
Verica che i bundle non contengano se stessi. (molto raro)
•
Verica che i prezzi dei bundle siano inferiori alla somma dei singoli prodotti in esso
contenuti.
•
Verica che tutti i prodotti abbiano associato almeno un tag di platform (ovvero
su che sistema operativo possono essere utilizzati).
•
Verica che tutti i prodotti abbiano l'immagine della scatola.
•
Vericare che tutti i prodotti abbiano almeno una categoria associata e una sola
categoria principale.
•
Vericare che tutti i libri abbiano almeno una categoria associata e una sola categoria principale.
•
Vericare che tutti i link ai documenti siano online e raggiungibili.
74
Implementazione
Figura 5.15: Schermata dell'applicazione Reports
5.9 Altre applicazioni
Il CMS è composto da altre applicazioni, descritte brevemente nell'analisi, che non vengono illustrate in quanto sono simili a quelle già discusse in precedenza per quanto riguarda
funzionalità e utilizzo.
5.10 Web services
I web service implementati in questo progetto sono simili a pagine web dinamiche ma
funzionano in modo leggermente diverso.
Il processo chiamante invoca il web service
attraverso un URL specico passandogli i parametri necessari all'elaborazione come query
string, ovvero una lista di argomenti in formato chiave=valore separati dal carattere ?.
Se le chiavi o i valori contengono caratteri speciali questi devono essere codicati in modo
da essere conformi all'HTML.
Una volta ricevuta la richiesta il code behind del web service controlla che l'utente del
processo che lo ha invocato sia loggato nel sistema e che nell'URL ci siano tutti i parametri
necessari per elaborare la risposta. Se una di queste due condizioni non viene soddisfatta
verrà ritornato un messaggio di errore indicandone il motivo.
Nel caso in cui il web service riesca a soddisfare la richiesta, il risultato dell'elaborazione
viene ritornato in formato JSON e utilizzato dal codice JavaScript che lo ha invocato.
Si è scelto questo formato in quanto i web sevices vengono utilizzati esclusivamente lato
5.10 Web services
75
client attraverso la tecnologia AJAX.
Sono stati implementati i seguenti web services:
•
AjaxInsertComment e AjaxDeleteComment servono alle applicazioni che implementano il wall dei commenti. Utilizzando questi web service è possibile inserire o eliminare i commenti senza dover ricorrere al refresh della pagina rendendo questo
processo molto simile agli odierni social network.
•
AjaxGetBundledProducts ritorna i prodotti contenuti in un budle il cui SKU è
passato come parametro.
•
AjaxGetCompletionList serve all'autocompleter per avere una lista dei prodotti che
contengono nel nome una sottostringa passata.
•
AjaxGetProductPicture ritorna gli URL delle immagini della scatola del prodotto
in diverse risoluzioni.
•
AjaxGetSimpleProduct ha il compito di recuperare le informazioni basilari di un
prodotto.
•
AjaxGetSpecialProductInfos ritorna i dati di un prodotto in promozione come i
prezzi prima e dopo lo sconto.
public partial class AjaxGetBundledProducts : Page {
protected void Page_Load(object sender, EventArgs e) {
Response.ContentType = "application/json";
int productSku;
if (!int.TryParse(Request.QueryString["sku"], out productSku)) {
Response.Write(JSON.Error("AjaxGetBundledProducts", "Null Product"));
return;
}
var product = new Product(productSku);
if (product.SKU == Product.SkuUndefined) {
Response.Write(JSON.Error("AjaxGetBundledProducts", "Null Product"));
return;
}
76
Implementazione
Response.Write(product.ToJSON());
}
}
5.11 Validazione
Il processo di validazione viene eseguito in tutte le applicazioni del CMS ed è necessario
per controllare che i dati nella form siano conformi prima che questi vengano inseriti nel
database.
La tecnologia ASP.NET include già alcuni meccanismi di validazione per i controlli più
comuni, come ad esempio vericare che un campo non sia senza valore o che sia in un
range di valori, tuttavia si è scelto di implementare un proprio meccanismo di validazione
dei contenuti in modo da poter gestire gli errori integrandoli con il sistema di messaggi
già presente in tutte le applicazioni.
Ogni applicazione contiene nella propria cartella una classe Validator specica, ognuna
della quali deriva dalla classe base Validator.cs localizzata nella cartella CommonCode.
Questa classe contiene una lista di messaggi per ogni regola infranta e la proprietà ValidatorsMessagesAsHtmlList che ritorna questi messaggi in un formato HTML già pronto
per essere visualizzato nel sistema di messaggi integrato nelle applicazioni.
Il metodo
CheckFieldNotEmpty, necessario per controllare che un campo non sia vuoto, è stato
inserito in questa classe in quanto è uno dei controlli più frequenti e utilizzato da tutti i
validatori.
namespace Novedge.CMS.CommonCode {
public abstract class Validator {
// CONSTANTS
protected readonly Color ERROR_COLOR = Color.Khaki;
// ATTRIBUTES
protected List<string> ValidatorsMessages;
// PROPERTIES
public string ValidatorsMessagesAsHtmlList {
get {
var messagesHtmlList = new StringBuilder();
5.12 Liste per la consultazione delle entità
77
messagesHtmlList.Append("<ul>");
foreach (var message in ValidatorsMessages)
messagesHtmlList.Append("<li>").Append(message).Append("</li>");
messagesHtmlList.Append("</ul>");
return messagesHtmlList.ToString();
}
}
public bool HasMessages {
get { return ValidatorsMessages.Count > 0; }
}
// CONSTRUCTOR
protected Validator() {
ValidatorsMessages = new List<string>();
}
// GENERAL FUNCTIONS
protected bool CheckFieldNotEmpty(string p_Field, string p_ErrorMessage) {
if (p_Field.Trim().Length == 0) {
ValidatorsMessages.Add(p_ErrorMessage);
return false;
}
return true;
}
}
}
5.12 Liste per la consultazione delle entità
La maggior parte delle applicazioni realizzate rende disponibile un bottone, situato in basso a sinistra, denominato List che consente di consultare la lista delle entità attualmente
presenti nel database.
Questo elenco viene visualizzato come tabella HTML contenente i campi più signicativi
per ogni entità in modo da fornire all'operatore le informazioni necessarie per scegliere
l'oggetto da editare nella form.
78
Implementazione
Figura 5.16: Schermata della lista di Brands
Per la generazione di queste tabelle è stato utilizzato il controllo GridView incluso nella
piattaforma ASP.NET che consente di specicare, attraverso la proprietà DataSource,
l'origine dei dati (sia questa una lista di oggetti o una DataView ottenuta mediante
una query sul database) occupandosi poi di generare la vista in modo completamente
automatico o secondo parametri specicati.
<asp:GridView ID="h_brands_gridview" runat="server" AutoGenerateColumns="False"
AllowSort-ing="True" OnRowDataBound="GridViewRowDataBound"
OnSorting="SelectionGridViewSorting" DataKeyNames="ID"
OnRowCom-mand="SelectionGridViewRowCommand" style="width:100%" >
<HeaderStyle BackColor="#FFEECC" />
<AlternatingRowStyle BackColor="#FFFF8F" />
<Columns>
<asp:ButtonField DataTextField="ID" HeaderText="Brand ID" SortExpression="ID"
Button-Type="Link" CommandName="Select" />
<asp:ImageField HeaderText="Logo" DataImageUrlField="Logo" ReadOnly="True"
NullDisplay-Text="">
<ControlStyle Width="60"></ControlStyle>
</asp:ImageField>
<asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />
<asp:BoundField DataField="TagLine" HeaderText="Tag Line"
SortExpression="TagLine" />
<asp:BoundField DataField="PriceMode" HeaderText="Price Mode"
SortExpres-sion="PriceMode" />
<asp:TemplateField HeaderText="Is Online" ItemStyle-HorizontalAlign="Center"
5.13 Funzioni di Wall e Log
79
SortEx-pression="IsOnline">
<ItemTemplate>
<asp:CheckBox runat="server" Enabled="False" Checked='<%# (bool)
DataBin-der.Eval(Container.DataItem, "IsOnline") %>'/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Settando il parametro AllowSorting a true viene attivata la funzione di ordinamento che
consente, selezionando un campo nell'intestazione, di ottenere la tabella ordinata in base
alla scelta eettuata.
Un'altra caratteristica del controllo GridView che è tornata utile è il fatto di poter cambiare lo sfondo delle singole righe; impostando un colore grigio per quelle entità che non
sono attive l'operatore ha un feedback graco immediato.
5.13 Funzioni di Wall e Log
Le funzionalità di wall e log sono accessibili, per quelle entità che le implementano,
attraverso delle tab dedicate.
La tab Wall consente di associare dei commenti (lasciati dagli operatori) a un'entita.
Questi vengono caricati assieme all'entità selezionata e visualizzati in ordine cronologico
inverso in modo da spingere l'utente a cancellare i più datati una volta che questi non sono
più ritenuti necessari. Un piccolo numero vicino nell'etichetta della tab mostra quanti
commenti sono stati attualmente inseriti.
Figura 5.17: Schermata della funzione wall nei Brands
80
Implementazione
L'inserimento e la cancellazione dei messaggi avviene attraverso chiamate AJAX ai web
service AjaxInsertComment e AjaxDeleteComment rendendo la gestione dei commenti
uida e simile a quella dei moderni social network.
La tab Log presenta all'operatore una vista tabellare con la storia dell'entità, dalla sua
creazione no all'ultima modica eettuata, specicando data, ora, autore, modulo e
descrizione dei cambiamenti avvenuti.
Figura 5.18: Schermata della funzione log negli Specials
81
Conclusioni
Il lavoro svolto è stato molto duro ma entusiasmante.
Ho potuto per la prima volta
vedere come nasce un software aziendale e partecipare al processo, comprendendone appieno dettagli e contesto di operazione. Applicando ed integrando sul campo le nozioni
apprese separatamente nei vari esami di Informatica, ho potuto acquisire l'esperienza di
un programmatore professionista.
L'esperienza di lavoro con Novedge è stata fantastica e il periodo trascorso negli USA mi
ha mostrato le potenzialità di un ambiente dinamico ed internazionale, consentendomi
un salto di qualità notevole.
Una ulteriore esperienza di lavoro con AREA Professional mi ha consentito di migliorare
ulteriormente la conoscenza dei più avanzati strumenti del mondo .NET, raggiungendo
una notevole conoscenza dello strumento.
Il CMS realizzato per Novedge è attualmente in produzione e si è rivelato uno strumento
potente in grado di gestire ecientemente i compiti di gestione dei prodotti e di tutte le
entità a contorno.
Il progetto passa quindi in una fase di manutenzione in cui è necessario modicare il
codice sorgente solo in caso di malfunzionamenti dovuti a bug non ancora corretti o all'introduzione di nuove regole e funzionalità.
La soddisfazione di Novedge è dimostrata dalla proposta di continuare la collaborazione
sino al 2014. Nel nuovo progetto lavorerò su nuove parti del sistema.
ELENCO DELLE FIGURE
2.1
Architettura del sistema informatico di Novedge . . . . . . . . . . . . . .
10
3.1
Rappresentazione della collocazione del sistema
. . . . . . . . . . . . . .
14
3.2
Products Operator use case diagram
. . . . . . . . . . . . . . . . . . . .
20
3.3
Orders Operator use case diagram . . . . . . . . . . . . . . . . . . . . . .
21
3.4
Administrator use case diagram
21
4.1
Struttura del progetto Novedge.CMS
4.2
Disposizione degli elementi nell'interfaccia utente
4.3
Diagramma ER della base di dati
4.4
Schema di funzionamento di un web service
5.1
Class Diagram delle classi in Novedge.Base utilizzate per le categorie
5.2
Barra di navigazione prima del login
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
25
. . . . . . . . . . . . .
28
. . . . . . . . . . . . . . . . . . . . . .
29
. . . . . . . . . . . . . . . .
30
. .
38
. . . . . . . . . . . . . . . . . . . .
48
5.3
Barra di navigazione dopo il login . . . . . . . . . . . . . . . . . . . . . .
48
5.4
Finestra che mostra gli utenti connessi al sistema
. . . . . . . . . . . . .
49
5.5
Schermata dell'applicazione Products . . . . . . . . . . . . . . . . . . . .
49
5.6
Autocompleter in funzione applicato a una textbox
. . . . . . . . . . . .
52
5.7
Esempio di messaggio di worning mostrato all'utente
. . . . . . . . . . .
54
5.8
Plugin wikipedia in azione sul sito Novedge . . . . . . . . . . . . . . . . .
56
5.9
Schermata dell'applicazione Books . . . . . . . . . . . . . . . . . . . . . .
57
5.10 Schermata della tab Post It dell'applicazione Specials . . . . . . . . . . .
64
5.11 Schermata della tab Products dell'applicazione Specials . . . . . . . . . .
65
84
ELENCO DELLE FIGURE
5.12 Sequence diagram del caricamento dei le nell'applicazione Documents
.
68
5.13 Schermata dell'applicazione Documents . . . . . . . . . . . . . . . . . . .
69
5.14 Schermata dell'applicazione Orders
. . . . . . . . . . . . . . . . . . . . .
70
5.15 Schermata dell'applicazione Reports . . . . . . . . . . . . . . . . . . . . .
74
5.16 Schermata della lista di Brands
. . . . . . . . . . . . . . . . . . . . . . .
78
5.17 Schermata della funzione wall nei Brands . . . . . . . . . . . . . . . . . .
79
5.18 Schermata della funzione log negli Specials . . . . . . . . . . . . . . . . .
80
BIBLIOGRAFIA
[1] Giulio Destri.
Introduzione ai sistemi informativi aziendali. Monte Università Parma
Editore, 2007.
[2] Abijit
Chaudhury
and
Jean-Pierre
Infrastructure. McGraw-Hill, 2002.
[3] Ulrich Kampmeyer.
Kuilboer.
e-Business and e-Commerce
ECM Enterprise Content Management. McGraw-Hill, 2006.
[4] Matthew MacDonald and Adam Freeman.
Pro ASP.NET 4 in C# 2010.
APress,
2010.
[5] Mike White Paul Nielsen, Uttam Paru.
Microsoft SQL Server 2008 Bible.
Wiley,
2009.
[6] World Wide Web Consortium (W3C). Speciche uciali HTML.
http://www.w3.
org/community/webed/wiki/HTML/Specifications.
[7] World Wide Web Consortium (W3C).
Speciche uciali CSS.
http://www.w3.
org/Style/CSS/current-work.
[8] Wikipedia - The free encyclopedia. JavaScript.
http://it.wikipedia.org/wiki/
Javascript.
[9] The Ocial Microsoft ASP.NET Site. ASP.NET Web Pages.
web-pages.
http://www.asp.net/
86
BIBLIOGRAFIA
[10] Wikipedia - The free encyclopedia.
jQuery.
http://it.wikipedia.org/wiki/
jQuery.
[11] Jesse James Garrett. Ajax: A New Approach to Web Applications.
http://www.
adaptivepath.com/ideas/ajax-new-approach-web-applications.
[12] ECMA (European Computer Manufacturers Association). Introducing JSON.
http:
//json.org.
[13] Wikipedia - The free encyclopedia. Amazon Web Services.
http://en.wikipedia.
org/wiki/Amazon_Web_Services.
[14] Data
gn
Manager
Software
Online.
Videointervista.
Novedge,
The
Desi-
http://www.datamanager.it/news/
SuperStore.
videointervista-novedge-design-software-superstore-43260.html.
[15] Gazzetta
di
Parma.
Da
Parma
alla
leadership
negli
States.
//www.gazzettadiparma.it/primapagina/dettaglio/3/41106/Da_Parma_
alla_leadership_negli_States__.html.
http:
Scarica