SlideShare ist ein Scribd-Unternehmen logo
1 von 63
Downloaden Sie, um offline zu lesen
UNIVERSITÀ DEGLI STUDI DI TRIESTE




              FACOLTÀ DI INGEGNERIA

              Corso di laurea triennale in
                 Ingegneria Informatica




Migrazione dei meccanismi di workflow
di un sistema informativo assicurativo
 verso l’ambiente SQL Server e .NET



Laureando:                Relatore:
Donato Clun               Chiar.mo Prof. Leonardo Felician




               Anno accademico 2009 / 2010
Sommario



Capitolo 1: Introduzione ................................................................ 5
  Il contenuto di questo documento ................................................................ 5
  Luogo di svolgimento del lavoro documentato .............................................. 7
  Dettagli della migrazione.............................................................................. 7
           L‟ambiente sorgente ............................................................................................... 7
           L‟ambiente obiettivo ............................................................................................... 8

  Le ragioni della migrazione .......................................................................... 9
  Precisazioni su questo documento ............................................................... 9
Capitolo 2: Il sistema informativo di OnLife ................................. 10
  L‟ambiente di esecuzione prima della migrazione ....................................... 10
  La base di dati attuale: concetti chiave dello schema dei dati ..................... 11
           Prospect .............................................................................................................. 11
           Partner ................................................................................................................ 11
           Quotazione .......................................................................................................... 11
           Carico contabile ................................................................................................... 12

Capitolo 3: Descrizione dei requisiti ............................................ 13
  Vincoli non funzionali ................................................................................ 13
           Affidabilità dell‟applicativo ................................................................................... 13
           Prestazioni ........................................................................................................... 14

  Descrizione delle funzioni .......................................................................... 15
           Generazione di PDF ............................................................................................. 15
           Caricamento delle nuove quotazioni e dei nuovi contratti ...................................... 16
           Elaborazione delle mail in ingresso ....................................................................... 16
           Sincronizzazione degli status ............................................................................... 17
           Eliminazione dei dati sensibili .............................................................................. 17
           Elaborazione rendiconti intermediari .................................................................... 17
           Invio di E-mail ..................................................................................................... 18
           Automazione di campagne di comunicazione ........................................................ 18




                                                                   3
Capitolo 4: Analisi dei problemi e definizione delle metodologie
            risolutive ................................................................... 20
  Disponibilità del servizio e robustezza del software..................................... 20
            Il problema .......................................................................................................... 20
            La cause di possibili problemi .............................................................................. 22
            Definizione di una metodologia risolutiva ............................................................. 22

  Creazione di documenti PDF ...................................................................... 31
            La soluzione ........................................................................................................ 32

  Miglioramento delle prestazioni.................................................................. 32
            Analisi della causa ............................................................................................... 33
            Metodologia risolutiva .......................................................................................... 33

Capitolo 5: Implementazione nell‟ambiente target ....................... 35
  Strategia di sviluppo software adottata ...................................................... 35
  “Logger”.......... ........................................................................................... 36
            Creazione della classe Logger ............................................................................... 37

  Funzioni di accesso al database ................................................................. 41
  Separazione tra thread principale e thread supervisore .............................. 42
  Caricamento delle quotazioni ..................................................................... 43
  Invio della posta ........................................................................................ 45
  Lettura della posta..................................................................................... 50
  Automazione di campagne di comunicazione ............................................. 51
  Esecuzione della procedura dei rinnovi ...................................................... 52
  Controllo RID respinti ................................................................................ 54
  Eliminazione dei dati sensibili.................................................................... 55
  Sincronizzazione degli status ..................................................................... 56
  Elaborazione automatica degli incassi........................................................ 58
  Elaborazione degli estratti conto ................................................................ 59
Capitolo 6: Conclusioni ............................................................... 62
Bibliografia........ ........................................................................... 63




                                                                   4
Capitolo 1: Introduzione

                                               In    questa   tesi   vengono   descritti   gli
                                         obiettivi, analizzati i problemi affrontati e
                                         descritte le metodologie risolutive adottate,
                                         nell‟ambito del lavoro di migrazione della logica
                                         funzionale di OnLife, la prima polizza vita ad
                                         essere venduta direttamente ai clienti tramite
                                         internet.




Il contenuto di questo documento

    Per definire chiaramente la parte del sistema informativo oggetto della
migrazione descritta in questa tesi è necessaria una premessa. Per qualunque
organizzazione disporre di un buon sistema informativo informatizzato non
significa soltanto poter disporre delle informazioni necessarie in tempi rapidi,
ma significa anche poter automatizzare parte dei processi operativi aziendali. In
quest‟ottica un criterio lecito (che non considera come è realizzato il sistema,
ma solo l‟aspetto operativo) secondo il quale è possibile distinguere diversi
insiemi di funzionalità in un sistema informativo è il grado di intervento umano
necessario alla raccolta ed    elaborazione dei       dati e, successivamente, alla
produzione e distribuzione delle informazioni a chi (o a cosa) ne ha bisogno.
    Con il progredire della tecnologia di elaborazione automatica delle
informazioni e la crescente disponibilità di questi strumenti, la possibilità di
automatizzare parte dei processi ha infatti assunto un ruolo sempre più
importante. In alcuni casi l‟interazione con gli utenti può essere ridotta a zero,
come nel caso di un sistema che al verificarsi di una predeterminata condizione
dia autonomamente luogo ad una sequenza di operazioni di elaborazione che




                                           5
producono delle informazioni successivamente inviate ad un altro sistema
informatizzato, ad esempio tramite un web service.
     In un sistema informativo complesso è quindi possibile individuare un
insieme di automatismi che hanno luogo con un elevato livello di autonomia
rispetto alla necessità di input da parte dell‟utente (quindi che elaborano
solamente dati provenienti dalla base di dati), e che non hanno inizio a causa
di una interrogazione esterna, ma a causa del verificarsi di una predeterminata
condizione.    Tali   automatismi     possono     essere   definiti   batch,   termine
comunemente utilizzato in informatica per descrivere l‟esecuzione di una serie
di programmi senza intervento manuale. Nell‟ambito di un sistema informativo
gli automatismi batch sono dunque il risultato dell‟automazione di una parte
dei meccanismi di workflow operativo.
     In questo documento viene trattata proprio la migrazione, da un ambiente
software già esistente e funzionante a un nuovo ambiente in grado di
soddisfare meglio le necessità dell‟azienda, degli automatismi batch di OnLife,
la prima polizza vita ad essere venduta direttamente ai clienti tramite internet
in Italia.
     Nell‟ambito di questa tesi la definizione di automatismo batch non va
intesa in maniera rigorosa, dato che sono stati sviluppati anche alcuni
automatismi che vengono eseguiti su richiesta dell‟utente, tuttavia rimane
evidente la contrapposizione con la parte del sistema informativo, molto più
ricca di interfacce, che dipende dall‟utilizzo interattivo da parte di un utente.
     La migrazione effettuata non è stata di tipo 1:1, ma ha puntato a
migliorare diversi aspetti del sistema e a soddisfare nuove necessità incontrate
dall‟azienda. E‟ stato dunque necessario separare il lavoro in più parti:
            Individuazione degli obiettivi
            Analisi dei problemi
            Elaborazione di metodologie risolutive
            Fase di sviluppo software




                                              6
Luogo di svolgimento del lavoro documentato

     Messa sul mercato il 22 maggio 2007, OnLife è stata in Italia la prima
polizza vita ad essere venduta ai clienti utilizzando internet come unico canale
di vendita diretta, segnando un ulteriore passo nella direzione della vendita
senza intermediari già intrapresa nel 1994 da Genertel. OnLife è un prodotto di
L.A. Vita S.p.A. (controllata al 100% dal gruppo Allianz), società per cui è stato
fatto il lavoro oggetto di questa tesi. Essendo stato utilizzato all‟interno
dell‟azienda, il risultato di questa tesi ha dunque avuto utilità pratica.



Dettagli della migrazione

     Di seguito viene data una visione d‟insieme delle caratteristiche del
sistema informativo “sorgente” e del sistema informativo “obiettivo”. Ulteriori
dettagli riguardanti il sistema informativo iniziale verranno specificate nel
capitolo 2, mentre informazioni ancora più dettagliate si possono trovare in
(Gorjan, 2006), anche se relative ad una versione con meno funzionalità
rispetto a quella più recente, oggetto della migrazione.



     L’ambiente sorgente
     La disponibilità sul mercato di Onlife è arrivata solamente dopo la
conclusione dello sviluppo di un sottosistema informativo specifico dedicato
esclusivamente ad Onlife chiamato “DM2” che, affiancando il sistema
informativo di L.A. Vita, ha fornito tutti gli strumenti necessari alla sua
gestione. Da quanto nel 2007 DM2 è entrato in produzione ha subìto
importanti modifiche che hanno aggiunto ulteriori funzionalità per gli utenti e
ulteriori automatismi, di pari passo con l‟incremento del numero di polizze
vendute.




                                            7
La migrazione della parte batch del sistema informativo DM2 di Onlife è
l‟oggetto di questo documento.
     Le caratteristiche tecniche principali dell‟ultima versione di DM2 sono le
seguenti:
            L‟interfaccia è sviluppata in Access 2003, che grazie ai suoi
             strumenti integrati ha permesso ottenere rapidamente un sistema
             completo e funzionante.
            Utilizza il DBMS Microsoft SQL Server 2005 (migrato dal Microsoft
             Jet di Access, che è stato il primo DBMS utilizzato)
            Le “business rules” e i meccanismi di workflow sono programmati in
             VBA all‟interno di Access.
            La produzione di documenti PDF avviene tramite una stampante
             virtuale che riceve l‟input da una istanza di Microsoft Word gestita
             dal codice VBA in Access.



     L’ambiente obiettivo
     Il nuovo ambiente software e gli strumenti di sviluppo utilizzati sono stati
imposti dall‟azienda, che ha scelto Microsoft SQL Server 2005 come DBMS e
Microsoft Visual Studio 2008, .NET Framework 3.5 e il linguaggio C# come
strumenti di sviluppo software. L‟azienda ha anche fornito delle librerie da
utilizzare obbligatoriamente per l‟apertura della connessione con il database e,
se necessario, anche per sfruttare l‟infrastruttura di logging di Allianz. Non
sono stati imposti ulteriori vincoli, ed è quindi stato quindi possibile valutare
l‟utilizzo di librerie open source per realizzare alcune delle funzionalità
richieste.




                                            8
Le ragioni della migrazione

    La migrazione dei meccanismi di workflow rientra in un più ampio
progetto di migrazione dell‟intero sistema informativo DM2 deciso dall‟azienda.
Le ragioni di questa scelta si possono riassumere nei seguenti punti chiave:


           Il vecchio applicativo batch non rispettava gli standard aziendali,
            che prevedono l‟utilizzo di strumenti software completamente
            diversi.
           A causa dell‟inadeguatezza del primo DBMS utilizzato (Microsoft
            Jet), ed a causa della necessità di migliorare le prestazioni
            dell‟interfaccia utente (passando da Access ad una nuova interfaccia
            web) era già stata effettuata la migrazione della base di dati verso
            SQL Server 2005. Si è dunque prefigurata la possibilità di sfruttare
            le funzionalità di questo DBMS per migliorare ulteriormente le
            prestazioni complessive del sistema, sia lato batch, sia lato
            interattivo.



Precisazioni su questo documento

    Tutti i moduli software descritti in questo documento sono stati sviluppati
dall‟autore, ad eccezione della libreria iTextSharp per la creazione di PDF, e la
libreria fornita da Allianz per interfacciarsi con l‟architettura aziendale
(nell‟ambito di questo progetto è stata utilizzata solo la funzione che recupera
la connessione al database).
    Contenendo questo documento alcune parti del codice sorgente creato
nell‟ambito di questo lavoro, in alcuni casi è stato necessario oscurare delle
parti di codice per garantire la riservatezza delle informazioni riguardanti le
misure di sicurezza adottate in Allianz. Tali modifiche saranno comunque
evidenziate.




                                          9
Capitolo 2: Il sistema informativo di OnLife

                                                  Questo     breve   capitolo      fornisce     le
                                            principali     informazioni   necessarie          alla
                                            comprensione della struttura della parte del
                                            sistema informativo che è stata oggetto della
                                            migrazione descritta in questa tesi.




L’ambiente di esecuzione prima della migrazione

     Il sistema informativo che permette la vendita e la gestione della polizza
Onlife è suddiviso in due parti: il sistema informativo DM2, che è specifico di
Onlife e che fornisce principalmente funzioni di CRM1 con i clienti (ex, attuali e
potenziali), e il sistema informativo di L.A. Vita, che si occupa esclusivamente
del workflow interno all‟azienda.
     A questi due elementi si aggiunge un altro server indipendente che è
l‟unico ad essere visibile da internet.
     Il risultato è una struttura divisa nei seguenti elementi distinti:
             Server raggiungibile da internet, con funzionalità di web server e
              mail server. Il web server esegue la web application che rende
              disponibile il questionario tramite il quale i potenziali clienti e i
              broker di assicurazione possono ricevere una quotazione. Il mail
              server si occupa della ricezione e dell‟invio dei messaggi di posta
              elettronica, utilizzando a questo scopo due tabelle (MailIn e MailOut)
              sul database interno che contengono i messaggi in ingresso ed in
              uscita.
             Database server inaccessibile da internet, su cui è in esecuzione il
              DBMS Microsoft SQL Server 2005, e che contiene il database del
              sottosistema informativo DM2 specifico di Onlife.

     1   CRM: Customer Relationship Management


                                             10
   Sistemi host di L.A. Vita: la parte di sistema informativo che non è
            specifica di Onlife. I dati presenti su questi sistemi vengono esposti
            al sistema informativo DM2 con delle query pass through sul
            database server, mentre alcuni servizi più complessi, (come il
            calcolo del premio) vengono resi disponibili tramite un web service.
           Server di automazione di Onlife su cui è in esecuzione il software
            (completamente sviluppato in Access in VBA) che esegue gli
            automatismi batch necessari.

La base di dati attuale: concetti chiave dello schema dei dati

     Maggiori dettagli relativi alle singole entità facenti parte dello schema dei
dati del sistema informativo DM2 (che è composto da 70 tabelle), verranno
illustrati contestualmente alla definizione dei requisiti.
     È comunque opportuno introdurre alcuni concetti base relativi alle entità
più ricorrenti nell‟ambito di questo lavoro ma poco “intuitive”.

     Prospect
     Dal punto di vista commerciale la caratteristica più importante di Onlife,
dopo il prezzo di vendita, è la possibilità di fare un preventivo anonimo in un
tempo    brevissimo,    chiedendo       al   potenziale   cliente   solamente   i   dati
indispensabili al calcolo del premio. L‟individuo che interagisce con Onlife
senza fornire le proprie generalità deve essere comunque identificato, e per
questo scopo si utilizza l‟entità prospect che lo identifica tramite l‟indirizzo
email, la data di nascita e il sesso.

     Partner
     Il partner è l‟individuo di cui si conoscono anche i dati anagrafici. È
identificato dal codice fiscale. In questa categoria rientrato clienti, ex-clienti,
dipendenti, fornitori e broker.

     Quotazione


                                              11
È il risultato della compilazione del questionario anonimo, che serve a
dare al cliente una misura orientativa del premio da pagare qualora decida di
stipulare una polizza.

     Carico contabile
     È un movimento contabile che può rappresentare una stipula, un rinnovo,
o la variazione di una polizza.




                                       12
Capitolo 3: Descrizione dei requisiti

                                               In questo capitolo viene data una visione
                                         d‟insieme    sulle   funzionalità     che   è    stato
                                         necessario    realizzare,   e   sui    vincoli    non
                                         funzionali che hanno inciso sullo sviluppo del
                                         sistema.




Vincoli non funzionali

     Ancor prima di entrare nel dettaglio dei requisiti funzionali richiesti è
necessario evidenziare i requisiti non funzionali che hanno caratterizzato
maggiormente tutto il lavoro di migrazione.



     Affidabilità dell’applicativo
     Come già evidenziato l‟obiettivo del lavoro svolto era quello di migrare un
sistema batch, che per essere considerato tale doveva soddisfare il requisito di
indipendenza dall‟interattività con l‟utente. Questo requisito fondamentale
doveva essere rispettato sia nelle condizioni di utilizzo normale, sia, per quanto
possibile, in condizioni eccezionali: va infatti considerato che l‟accesso “fisico”
al calcolatore su cui l‟applicativo batch viene eseguito deve essere ridotto a
rarissimi casi veramente eccezionali, anche perché all‟interno di realtà di
dimensioni molto grandi come Allianz, è impensabile che non vengano poste
restrizioni a questo proposito.
     A ciò si aggiunge il fatto che l‟allungarsi del tempo necessario ad ottenere
l‟accesso al calcolatore in seguito al verificarsi di una condizione eccezionale
(sia per raccogliere informazioni sul problema da risolvere, sia per attuare la



                                          13
soluzione) inevitabilmente allunga anche l‟MTTR2, ovvero il tempo medio
necessario per ripristinare le funzionalità del sistema.
     In ambito assicurativo l‟indisponibilità di un certo servizio per un certo
periodo di tempo può facilmente tradursi, più o meno direttamente, in una
perdita di denaro, di conseguenza l‟MTTR è un indicatore chiave che è stato
importante ridurre, adottando le opportune straregie di sviluppo.
     Da queste considerazioni si sono ricavati i seguenti requisiti:
             Robustezza: il software deve comportarsi in maniera ragionevole
              anche rispetto a situazioni non previste, onde evitare che errori di
              lieve entità blocchino il servizio.
             MTTR ridotto: in caso di errore deve essere possibile individuarne
              rapidamente la causa.
             Affidabilità: è necessario minimizzare la percentuale di tempo in cui
              il servizio non è accessibile (è una conseguenza dei due punti
              precedenti).



     Prestazioni
     Uno dei motivi che hanno reso necessario questo lavoro di migrazione era
la sicurezza di avere un buon margine per sostenere la futura crescita di
Onlife. Pur non essendosi ancora verificata la situazione limite in cui il tempo
di esecuzione di un ciclo di automatismi avesse superato l‟intervallo di tempo
con cui tale ciclo di automatismi doveva essere avviato, bisogna considerare
che la durata complessiva dell‟esecuzione di un ciclo ha comunque influenza
sulla bontà del sistema.
     Infatti se è vero che alcuni degli automatismi devono essere eseguiti su
base temporale precisa (ad esempio la generazione degli estratti conto per gli
intermediari deve essere svolta una volta al mese), altri invece possono essere
avviati con una frequenza arbitraria, ed una loro esecuzione più frequente può


     2   MTTR: Mean Time To Restore


                                               14
portare degli effettivi vantaggi. Ad esempio nel sistema informativo DM2
l‟automatismo che elabora i messaggi di posta elettronica in ingresso potrebbe
essere eseguito più frequentemente, riducendo così il tempo medio di risposta
ed aumentando quindi il grado di soddisfazione del cliente.




Descrizione delle funzioni

     I successivi requisiti presentati nel resto di questo capitolo sono tutti di
tipo funzionale, e nella maggior parte dei casi sono stati dedotti dall‟analisi del
codice sorgente del software che precedentemente eseguiva gli automatismi
necessari.
     Una trattazione dettagliata di tutte le specifiche funzionali sarebbe
eccessivamente lunga. Dato che lo scopo di questo documento è evidenziare le
parti più originali del lavoro svolto, la maggior parte di essi sarà descritta in
maniera sommaria.




     Generazione di PDF
     La generazione di documenti PDF con contenuti personalizzati (da inviare
ad esempio ai clienti o agli intermediari) è una funzionalità chiave di DM2. Il
vecchio sistema di generazione di PDF, basato su Microsoft Word e su una
stampante virtuale in grado di salvare i documenti nel formato desiderato, era
in grado di soddisfare le necessità di Onlife, ma la migrazione verso il nuovo
ambiente software ha reso necessario un lavoro di riprogettazione.
     L‟azienda infatti ha deciso che nel nuovo ambiente di produzione non
sarebbe stato installato né Microsoft Office né la stampante virtuale, che invece
erano elementi indispensabili nella vecchia soluzione. Si è dunque presentata
la necessità di trovare una soluzione alternativa a questo problema.




                                          15
A proposito della soluzione adottata prima della migrazione va detto che,
pur essendo funzionale allo scopo, non offriva grandi prestazioni in termini di
velocità di produzione dei documenti, ed è quindi presumibile che in futuro,
con l‟aumentare del numero di clienti, si sarebbe rivelata inadeguata.
    Il lavoro di riprogettazione resosi necessario in seguito al cambiamento
dell‟ambiente software ha dunque offerto la possibilità di sviluppare una
soluzione che possa sostenere la crescita futura di Onlife.




    Caricamento delle nuove quotazioni e dei nuovi contratti
    Il compito del server web accessibile da internet è esclusivamente quello di
raccogliere le nuove proposte e quotazioni richieste dai clienti o dai broker e
salvarle sul proprio database, ma prima di poter essere inserite nel sistema
DM2, queste informazioni devono essere normalizzate per rispettare la
struttura dati del sistema informativo. La lettura, la normalizzazione e il
salvataggio dei dati in DM2 sono a carico di questa funzionalità.




    Elaborazione delle mail in ingresso
    Il mail server è configurato per memorizzare tutti i messaggi di posta
elettronica ricevuti all‟interno della tabella “MailIn” presente nel database del
sistema DM2. Essendo Onlife un‟iniziativa basata su internet come unico
canale di vendita e contatto, tutti i nuovi messaggi in ingresso vengono
sottoposti ad un automatismo che li elabora, inviando delle risposte
automatiche quando possibile e minimizzando lo sforzo necessario alla risposta
manuale quando l‟elaborazione automatica non ha avuto esito positivo.




                                          16
Sincronizzazione degli status
      Come detto, il sistema informativo di Onlife è diviso in due parti: il sistema
informativo DM2 che si occupa prevalentemente del CRM di Onlife, e il sistema
informativo di L.A. Vita, che si occupa del workflow interno all‟azienda. Dato
che   questi   due   sistemi   si   basano   su   due   database   indipendenti,   è
indispensabile mantenere sincronizzati gli status dei contratti, dato che la
mancata sincronizzazione potrebbe comportare gravi errori, come il mancato
rendiconto di un contratto in vigore o il rendiconto di un contratto stornato.
      Di conseguenza una funzionalità richiesta è la sincronizzazione periodica
degli status dei contratti, attuata accedendo al database di L.A. Vita tramite
una query pass through e confrontando gli status dei contratti con i dati
contenuti nel database di DM2, evidenziando i casi in cui è stata rilevata una
differenza di status e procedendo con il necessario aggiornamento.




      Eliminazione dei dati sensibili
      L‟algoritmo di calcolo del premio assicurativo necessita di alcuni dati che
secondo il Codice sulla protezione dei dati personali (D. Lgs. 196/2003) sono
considerati “dati sensibili”. È necessario che tali dati vengano eliminati da tutte
le proposte che non sono diventate polizze, dopo che sia trascorso un periodo
di tempo prestabilito.




      Elaborazione rendiconti intermediari
      L‟obiettivo di questa funzione è la generazione degli estratti conto da
inviare agli intermediari di vendita, e l‟invio delle disposizioni di pagamento a
beneficio degli intermediari che hanno diritto a una provvigione.




                                             17
In entrambi i casi è necessario sfruttare la funzionalità di generazione di
documenti PDF per inserire all‟interno dei rispettivi modelli di documento i dati
estratti dal database.




     Invio di E-mail
     L‟invio di un messaggio di posta elettronica non consiste solamente nel
suo inoltro al mail server opportuno (operazione a carico del mail server
presente sul server internet di Onlife), ma richiede anche una serie di
operazioni da svolgere all‟interno del sistema DM2. Il sistema informativo
prevede che venga associato ad ogni Prospect o Partner ogni messaggio inviato
o ricevuto che lo riguarda. In questo modo viene minimizzato lo sforzo
necessario a gestire la comunicazione, essendo possibile avere per ogni
soggetto lo storico completo dei messaggi scambiati.




     Automazione di campagne di comunicazione
     L‟obiettivo di questa funzione è automatizzare l‟invio di grandi moli di
email consentendo la loro più libera ed assoluta personalizzazione secondo le
diverse esigenze. Si tratta di una funzionalità importantissima di DM2, che
viene utilizzata sia per l‟invio di campagne di marketing sia per l‟invio di
comunicazioni di massa ai clienti. Si basa su dei modelli di messaggio
standard, delle query che determinano gli insiemi dei destinatari, e delle
“campagne” (delle coppie modello di messaggio / query dei destinatari).




     Lo schema dei dati alla base di queste funzionalità è il seguente:




                                          18
MessaggiTesti         Workflow                Query
      ID            ID Messaggio                 ID
  standard
   Oggetto            ID Query              Descrizione
    Testo             Standard              StringaSQL
                  ID Automatismo
  Allegato1          Destinatari
  Allegato2
                                   SELECT Nome, Cognome,
                                   Email FROM Partner
WkflAutomatismi                    WHERE .....
       ID
     Codice        ALTRE
     Nome
      Note
                  TABELLE




                         19
Capitolo 4: Analisi dei problemi e definizione
                     delle metodologie risolutive

                                              In questo capitolo vengono analizzate in
                                        dettaglio le singole problematiche affrontate e
                                        vengono illustrate le metodologie risolutive
                                        adottate.




Disponibilità del servizio e robustezza del software

     Nel capitolo 3 è stata messa in luce l‟importanza di produrre dei moduli
software robusti (ovvero che gestiscano ragionevolmente situazioni impreviste)
e facilmente riparabili. Vista la complessità del progetto è stato necessario
studiare una strategia per affrontare il problema in maniera coerente durante
tutto l‟arco del lavoro di sviluppo.



     Il problema
     Il problema affrontato può essere così riassunto:


     “Creare un applicativo batch che riesca a gestire opportunamente situazioni
impreviste successe durante il funzionamento, minimizzando i casi in cui queste
possano dar luogo alla sospensione del servizio, e agevolando il più possibile il
lavoro di debug e ripristino.”


     Il vecchio sistema di automazione sviluppato in Microsoft Access era
costituito da oltre 300 funzioni per un totale di circa 15 mila righe di codice.
Oltre alla probabilità di bug dovuti a errata codifica del software (che



                                         20
comunque può essere ridotta testando approfonditamente i singoli moduli
parallelamente al lavoro di codifica), bisogna considerare che il buon
funzionamento di molti moduli dipende da fattori esterni non controllabili dal
software, come il rispetto delle specifiche da parte dei dati in ingresso, oppure
l„accessibilità di alcune risorse necessarie all‟esecuzione (database, file, ecc).
      In questo capitolo con il termine “disponibilità” si intende la percentuale di
tempo in cui il servizio è correttamente funzionante. Tale quantità dipende da
due valori fondamentali: MTBF e MTTR.
      L‟MTBF (Mean Time Between Failures) è il tempo che, in media, passa tra
l‟istante in cui il sistema viene messo in funzione e l‟istante in cui il
funzionamento viene interrotto a causa di un problema non previsto.
      L‟MTTR (Mean Time To Repair) è il tempo che, in media, è necessario per
ripristinare le funzionalità del sistema in seguito ad un malfunzionamento.


    Stato del                      Istante in cui il servizio        Istante in cui il servizio
    servizio                           viene ripristinato              cessa di funzionare



Funzionamento

                                                                                                         Tempo di
                                                        Tempo tra due                                   riparazione
                                                       malfunzionamenti
   Riparazione



                                                                                                                      Tempo



      La disponibilità media del servizio dipende dalle due quantità sopra
descritte, secondo la relazione
                                                                       ������������������������
                             Disponibilità media =
                                                                 ������������������������ + ������������������������
dalla quale, ricordando che il risultato ideale è una disponibilità media del
100%, si ha immediata conferma di due fatti intuitivi:
                Riducendo l‟MTTR si migliora la disponibilità media.
                Aumentando     l‟MTBF            diminuisce                   l‟incidenza        dell‟MTTR      sulla
                 disponibilità media.



                                                                21
La cause di possibili problemi
     Come già accennato, una probabile fonte di anomalie di funzionamento è il
mancato rispetto delle specifiche di programma da parte dei dati da elaborare.
Di conseguenza, la possibilità che il sistema debba affrontare una situazione
non prevista non risulta essere eliminabile neanche in seguito ad una accurata
fase di test.
     Il sistema di automazione dell‟invio di messaggi di posta elettronica
personalizzati, ad esempio, deve elaborare i tag contenuti in un testo standard
caricato dal database, e deve eseguire una stringa SQL anch‟essa definita nel
database. Se i tag contenuti nel messaggio non rispettano le specifiche oppure
se la query SQL dà luogo ad un errore, il sistema si trova di fronte ad una
situazione non prevista, che non può essere risolta in maniera interattiva con
un utente, dato che l‟applicativo è batch.
     E‟ possibile individuare una stretta relazione tra la robustezza (termine
con cui si indica la misura in cui il sistema si comporta in modo ragionevole in
situazioni impreviste), MTTR e MTBF. Un sistema che risponde in maniera
“ragionevole” ad una situazione inattesa infatti non si fermerà se la situazione
di errore non è critica e anche in questa eventualità non si bloccherà senza
averne dato opportuna segnalazione: nel primo caso avrà evitato di mettere
fuori servizio l‟intero sistema per un errore di poco conto (aumentando quindi
l‟MTBF), mentre nel secondo caso la segnalazione dell‟errore permetterà di
reagire tempestivamente (riducendo l‟MTTR).



     Definizione di una metodologia risolutiva
     Il problema è stato diviso in tre punti, corrispondenti a tre parti della frase
che lo sintetizza. Nei prossimi paragrafi ad ogni parte del problema verranno
associati dei principi da rispettare.




                                             22
A) “Creare un applicativo batch che riesca a gestire opportunamente
  situazioni impreviste successe durante il normale funzionamento,
  minimizzando i casi in cui queste possano dar luogo a sospensione del
  servizio, e agevolando il più possibile il lavoro di debug/riparazione.”


     Il software deve prendersi l‟onere di verificare i dati in input, in
      modo da riconoscere le situazioni anomale.
     Ad ogni situazione di errore deve corrispondere una strategia di
      gestione opportuna. Ogni componente deve contenere il codice
      necessario per gestire autonomamente il problema. Se questo non è
      possibile,   la       gestione        dell‟errore   diventa   di   competenza     del
      componente chiamante.
     La gestione delle situazioni di errore deve essere progettata tenendo
      in mente l‟integrità dei dati e delle operazioni svolte.


B) “Creare un applicativo batch che riesca a gestire opportunamente
  situazioni impreviste successe durante il normale funzionamento,
  minimizzando          i    casi      in     cui    queste   possano     dar   luogo    a
  sospensione del servizio, e agevolando il più possibile il lavoro di
  debug/riparazione.”


     E‟ necessario adottare una strategia di codifica che permetta di
      distinguere gli errori gravi che impediscono il proseguimento degli
      automatismi dagli errori non gravi che non ne pregiudicano il
      funzionamento.
     L‟applicativo deve sospendere l‟esecuzione di un automatismo
      solamente nell‟eventualità di un errore definito “grave” secondo la
      distinzione del punto precedente.




                                                23
C) “Creare un applicativo batch che riesca a gestire opportunamente
         situazioni impreviste successe durante il normale funzionamento,
         minimizzando i casi in cui queste possano dar luogo a sospensione del
         servizio,    e     agevolando       il    più    possibile      il   lavoro   di
         debug/riparazione.”


            Mai, in nessun caso, il software deve terminare in maniera anomala
             senza averne dato segnalazione.
            Quando       possibile   le   segnalazioni    di   errore    devono   essere
             memorizzate nel database del sistema DM2, in modo da essere
             immediatamente evidenziate e facilmente consultabili.
            Per evitare di perdere informazioni potenzialmente molto utili, se
             non dovesse essere possibile collegarsi al database, le segnalazioni
             devono essere memorizzate su un altro supporto.
            Deve essere possibile individuare immediatamente la gravità
             dell‟errore, in modo da dare subito la giusta priorità alla sua analisi.
            Ogni segnalazione di errore deve dare il maggior numero possibile di
             informazioni significative necessarie all‟individuazione del problema
             e conseguente soluzione.


    Il meccanismo di lancio/gestione delle eccezioni contenuto nei più comuni
linguaggi di programmazione correntemente utilizzati, è stato uno strumento
che ha fornito delle funzionalità di base molto utili al raggiungimento dello
scopo.


    Premessa: nel linguaggio C# le istanze della classe Exception contengono
diverse proprietà, ma le seguenti sono ampiamente utilizzate nella soluzione
del problema:
            Message: è una stringa di testo che contiene la descrizione
             dell‟errore.



                                                  24
   InnerException: è un riferimento ad un‟altra eccezione.
           StackTrace: contiene una rappresentazione testuale dello stack delle
            chiamate.


    La soluzione adottata si basa su una serie di norme da seguire durante la
codifica dei moduli:
        1. Il dettaglio di ogni errore deve essere salvato sul log (la definizione di
            “dettaglio dell‟errore” verrà data in seguito)
        2. Il compito di salvare il dettaglio dell‟errore spetta sempre alla
            funzione che lo gestisce, e mai alla funzione che lo genera, a meno
            che generazione e gestione avvengano nella stessa funzione.
        3. Il passaggio del controllo del flusso di esecuzione deve essere
            passato da una funzione ad un‟altra tramite eccezioni solo ed
            esclusivamente in caso di errore.
        4. Quando una funzione riceve un‟eccezione che non è in grado di
            gestire, deve creare una nuova eccezione con tutti i dettagli del caso
            (punto 6). Se invece è in grado di gestire l‟eccezione, scrive il
            dettaglio sul log (per rispettare il punto 2).
        5. Quando una funzione incontra una situazione anomala, se non è in
            grado di gestirla lancia un‟eccezione contenente tutti i dettagli del
            caso (punto 6). Se è in grado di gestirla, scrive il dettaglio sul log
            (per rispettare il punto 1).
        6. Come già accennato nei punti 4 e 5, ogni funzione che incontra una
            situazione anomala o che riceve un‟eccezione da una funzione
            chiamata, e non è in grado di gestire la situazione, deve lanciare
            una eccezione così strutturata: la proprietà Message deve contenere
            una stringa che definisca l‟errore e la proprietà InnerException deve
            contenere un riferimento all‟eccezione eventualmente ricevuta
            (altrimenti deve essere null). Il risultato è che ogni errore genera una
            lista concatenata di eccezioni, rappresentata nella seguente figura.



                                            25
7. Il “dettaglio dell‟errore” che deve essere salvato sul log è composto
   dai seguenti elementi:
      o Un messaggio definito dalla funzione che ha gestito l‟errore,
         che indica di che errore si tratta, in che contesto è avvenuto, e
         che implicazioni ha avuto.
      o La sequenza dei messaggi di errore specifici presi da ogni
         elemento della lista concatenata di eccezioni.
      o Lo stack delle chiamate preso dall‟eccezione alla fine della
         catena.
      o Un indicatore della gravità dell‟errore, determinato dalla
         funzione che gestisce l‟errore.
8. Per evitare che un loop infinito possa bloccare il servizio per un
   tempo indeterminato, l‟esecuzione degli automatismi deve avvenire
   in un thread separato, detto “principale”. Un altro thread, detto
   “supervisore”     si    occupa   di    segnalare    l‟eccessivo   prolungarsi
   dell‟esecuzione    di    un   automatismo,     ed    ha   la   possibilità   di
   interrompere la sua esecuzione (solo in casi estremi, dopo un‟attesa
   molto lunga).




                                     26
9. Normalmente i dettagli di ogni errore devono essere salvati sul
   database. Se questo non è disponibile, devono essere salvati su un
   file di log.




Adottando le norme descritte, il codice avrà le seguenti caratteristiche:
      Durante la codifica dei moduli software per qualunque situazione
       anomala si è liberi di programmare il lancio di un‟eccezione. La
       gravità non sarà intrinseca dell‟errore in sé, ma dipenderà dal
       livello a cui viene bloccata. Questo fatto è coerente con l‟idea
       intuitiva che un errore provocato, ad esempio, durante l‟invio di
       una singola email può essere considerato non critico nell‟ambito
       di una campagna pubblicitaria, mentre è senz‟altro critico
       nell‟ambito dell‟invio di un ordine di pagamento.              Questa
       caratteristica affronta i punti A e B del problema.
      L‟unica condizione in cui termina l‟esecuzione di un automatismo
       si ottiene quando l‟eccezione risale fino al thread principale; tale
       condizione indica che il software ha incontrato una situazione
       critica che non può essere risolta. Questa caratteristica affronta
       il punto B del problema.
      Il   log   conterrà   molte   informazioni   utili   all‟individuazione
       dell‟errore e delle cause che lo hanno scatenato, e conterrà un
       indicatore della gravità dell‟errore rilevato. In questo modo il
       tempo necessario a ripristinare il sistema sarà inferiore, e sarà
       possibile agire tempestivamente in caso di un errore grave.
       Questa caratteristica affronta il punto C del problema.
      L‟adozione di una metodologia di gestione degli errori coerente in
       tutto il codice ne facilita la lettura e la manutenzione. Una volta
       compresa questa strategia di base, risulta molto facile aggiungere




                                     27
la gestione di nuove situazioni di errore. Questa caratteristica
              affronta il punto C del problema.




    Nelle prossime pagine vi sono alcuni esempi che illustrano l‟utilizzo pratico
della metodologia applicata.




                                         28
29
Esempio pratico di log:
Rilevanza dell’errore:
         25

Messaggio di errore:
         Errore durante l’esecuzione del workflow di apertura. Impossibile
         Lanciare la campagna con ID = 23
         Impossibile continuare.

DebugInfo:
         Dettagli eccezione:
         - lanciaCampagna(23, 74, 0, ""): errore durante l’invio del
                                                                   messaggio!
         - inviaMessaggioStandard(23,”dest@email.it”,...): errore durante il
                                                                  mail merge.
         - EseguiMailMerge(“oggetto”,...): tag NUMERO_CONTRATTO non trovato.

         Stack delle chiamate:
           at OnLifeBatch.Onlife.lanciaCampagna([parametri]) in
                                                         Campagne.cs:line 246
           at OnLifeBatch.Onlife.inviaMessaggioStandard([parametri]) in
                                      EMAIL – Funzioni principali.cs:line 453
           at OnLifeBatch.Onlife.EseguiMailMerge([parametri]) in
                                                   EMAIL – Merge.cs: line 187




                                        30
Dall‟esempio di log riportato si deducono immediatamente le seguenti
informazioni:
                   Si sta avendo a che fare con un errore grave che richiede
                    immediata attenzione (nell‟implementazione di Onlife, una
                    rilevanza maggiore di 19 indica un problema critico)
                   L‟errore è avvenuto durante il lancio di una campagna,
                    nell‟ambito del workflow di inizio giornata.
                   L‟errore riguarda il mail merge del messaggio standard con ID
                    uguale a 23.
                   L‟errore riguarda il mail merge dell‟oggetto del messaggio. È
                    stato trovato un tag non presente nella query dei destinatari.
                   Se dovesse essere un bug, sono immediatamente disponibili le
                    righe del codice sorgente in cui ha avuto luogo l‟errore.




Creazione di documenti PDF

    La generazione di PDF personalizzati è un problema che è stato necessario
affrontare rispettando i nuovi standard aziendali imposti da Allianz per il nuovo
ambiente di produzione.


    Il sistema di generazione dei PDF deve soddisfare i seguenti requisiti:
           I documenti devono essere prodotti a partire da dei modelli che ne
            impostano il contenuto e ne contengono la parte statica.
           All‟interno dei modelli di documento devono essere presenti delle
            aree personalizzabili, in cui verranno inserite le parti dinamiche.
           Non può essere utilizzato Microsoft Office o una stampante virtuale,
            perché non rispetterebbe gli standard aziendali.
           La velocità di produzione deve essere maggiore o uguale a quella
            della soluzione precedentemente adottata.



                                             31
La soluzione
     Inizialmente si è ipotizzato l‟utilizzo di OpenOffice, una soluzione open
source che offre anche delle API utilizzabili per l‟automazione. I primi test
hanno però messo in luce seri problemi quando venivano creati molti
documenti nell‟arco di una sessione di automatismi: a causa di un evidente
memory leak3, il consumo di memoria dell‟applicativo batch cresceva
notevolmente ad ogni singolo documento creato, e dopo un certo numero di
documenti prodotti, il software cominciava a produrre documenti corrotti.
Questo problema unito anche alla scarsa documentazione di queste API ha
portato all‟abbandono di questa soluzione.
     La seconda alternativa analizzata è stata l‟utilizzo delle librerie open
source iTextSharp, delle librerie che permettono di creare dei documenti PDF ex
novo, e permettono anche di modificare dei form PDF (analoghi ai classici PDF
ma contenenti dei campi di testo in cui è possibile scrivere) creati ad esempio
con OpenOffice, e salvarli come PDF classici.
     I test di generazione di PDF fatti su questa soluzione hanno dato risultati
al di sopra delle aspettative: nell‟ambito di un test di generazione di documenti
personalizzati di una pagina, è stata raggiunga la velocità di circa 50
documenti al secondo, e i documenti prodotti non hanno mostrato difetti come
poteva accadere con la prima soluzione.



Miglioramento delle prestazioni

     Come è già stato sottolineato, la velocità di esecuzione del vecchio sistema
batch era considerata soddisfacente, di conseguenza il problema delle
prestazioni deve essere considerato di importanza decisamente inferiore
rispetto agli altri due già affrontati.
     Tuttavia per garantire un buon margine di crescita futura, al solo costo
del rispetto di qualche accorgimento durante la fase di sviluppo sviluppo, è

      3 Un particolare tipo di consumo non voluto di memoria dovuto alla mancata

deallocazione di variabili/dati non più utilizzati da parte dei processi.


                                          32
stato ritenuto opportuno porsi il problema di come raggiungere una migliore
efficienza.
     In questa sezione viene dunque studiata una metodologia da utilizzare per
velocizzare l‟esecuzione delle operazioni batch.

     Analisi della causa
     Dato che la potenza di calcolo degli attuali calcolatori si misura in decine
di miliardi di istruzioni al secondo, l‟anello debole su cui si è concentrata
l‟attenzione è l‟accesso ai dati.
     Il fatto che l‟applicativo batch e il DBMS vengano eseguiti su due
calcolatori diversi inevitabilmente introduce un tempo di latenza ogni volta che
viene effettuata un‟interrogazione al database di DM2. L‟ordine di grandezza
della somma del tempo necessario affinché l‟interrogazione arrivi al DB server e
del tempo necessario affinché la risposta partita dal DB server sia resa
disponibile     all‟applicativo   batch,   generalmente   è   nell‟ordine   di   diversi
millisecondi; di conseguenza nell‟ambiente di Onlife tale tempo è sicuramente
superiore a 8 ms, dato che questo è il tempo misurato con il comando ping, che
misura il Round Trip Time con pacchetti di dimensioni molto ridotte.
     Se si considera che l‟automatismo di caricamento delle quotazioni esegue
svariate decine di interrogazioni per ogni singola quotazione che deve essere
elaborata, risulta evidente che il numero di interrogazioni è un fattore da tenere
sotto controllo.



     Metodologia risolutiva
             Non ripetere interrogazioni inutili. Nel vecchio applicativo capitava
              che una stessa interrogazione venisse eseguita più volte all‟interno
              di un ciclo. Le interrogazioni ridondanti vanno assolutamente
              evitate, facendo solo una interrogazione e salvando il dato in una
              variabile.




                                              33
   Accorpare più interrogazioni in una sola. Sapendo che un algoritmo
    richiede sicuramente un certo insieme di dati, tali dati vanno
    ricavati subito tutti in un‟unica interrogazione.
   Utilizzare JOIN e (NOT) IN per unire più query. Nel vecchio
    applicativo capitava di fare in più query successive esattamente
    quello che avrebbe fatto una query che utilizza dei JOIN.
   Utilizzare stored procedure e stored functions per spostare parte
    della logica all‟interno del database. Questi elementi vengono
    eseguiti direttamente dal DBMS, e quindi permettono di ridurre
    ulteriormente il numero di interrogazioni necessarie.




                                   34
Capitolo 5: Implementazione nell‟ambiente
                                         target

                                               In questo capitolo viene affrontato il
                                         problema        dell‟implementazione        delle
                                         funzionalità    richieste.    In     particolare:
                                         l‟applicazione delle metodologie elaborate nel
                                         capitolo   precedente,   la   definizione   della
                                         strategia di sviluppo software, e la descrizione
                                         del lavoro svolto, mostrando anche qualche
                                         parte del codice prodotto.




Strategia di sviluppo software adottata


    Lo sviluppo dell‟applicativo è stato diviso nelle seguenti fasi:
          Sviluppo delle funzioni di base di accesso al database e logging.
          Suddivisione del progetto in diversi settori funzionali, evidenziando i
           moduli che sarebbe stato necessario programmare per primi a causa
           della presenza di altri moduli che da essi dipendono.
          Programmazione     del   singolo    settore   funzionale,     seguendo      la
           strategia di sviluppo che sarà indicata in seguito.


    Con il termine “settore funzionale” si intende l‟insieme di funzioni
necessarie allo sviluppo di una particolare funzionalità. Questo termine ha
particolarmente senso in questo contesto perché l‟insieme delle funzioni
automatizzate di Onlife è suddivisibile in diversi insiemi che tra loro hanno un
accoppiamento (ovvero dati e funzioni comuni) estremamente basso. Ad
esempio l‟elaborazione degli estratti conto ed il caricamento delle quotazioni


                                          35
condividono un insieme di funzioni sostanzialmente limitato alle sole funzioni
di accesso al database e di logging.


     Nell‟ambito di un singolo settore funzionale, la strategia di sviluppo
adottata non è ben inquadrabile nei classici schemi top-down o botton-up, ma
è stata una strategia di tipo misto. Inizialmente tutti i problemi più complessi
che sono stati affrontati, sono stati prima suddivisi in elementi di più facile
gestione, applicando quindi una strategia top-down, mentre successivamente è
stata adottata una strategia finalizzata al permettere un precoce debug delle
funzioni create.




“Logger”

     Un elemento fondamentale per rispettare la metodologia indicata nel
precedente capitolo, è il sistema che permette di salvare il log degli errori o di
altre informazioni che si ritiene opportuno salvare.
     Per questa funzionalità è stato necessario modificare la struttura della
tabella Log già presente nel vecchio sistema informativo, ed utilizzata per scopi
analoghi. La vecchia tabella prevedeva un campo ID determinato da un
contatore, un timestamp per indicare l‟istante in cui è stato aggiunto
l‟elemento, e un campo di testo contenente la descrizione dell‟errore o il
messaggio informativo. Per poter memorizzare separatamente anche le
informazioni di debug (sequenza dei messaggi delle eccezioni e stack delle
chiamate in forma testuale) e la rilevanza dell‟errore, si è deciso di aggiungervi
due campi: un campo di testo per le informazioni di debug, e un valore intero
per la rilevanza.
     Il significato del valore di rilevanza è così stabilito:
           Valori da 0 a 9 – Non indicano una situazione di errore ma hanno
            contenuto puramente informativo. Ad esempio possono indicare il



                                             36
numero di email inviate in seguito all‟esecuzione del workflow di
            inizio giornata.
           Valori da 10 a 19 – Indicano una situazione di errore che è stata
            gestita con successo, ma essendo una situazione anomala richiede
            l‟attenzione da parte di un responsabile. Ad esempio se durante
            l‟invio di una campagna di email, il campo Email di un record
            restituito dalla query dei destinatari è NULL, quel record sarà
            semplicemente saltato. Non avrebbe senso interrompere il lancio
            della campagna a causa di un solo errore, ma siccome potrebbe
            essere il sintomo di una query dei destinatari da rivedere, è
            opportuno che venga salvato un messaggio di errore.
           Valori da 20 a 29 – Indicano una situazione di errore grave, che ha
            provocato il blocco di un automatismo e che richiede un intervento
            tempestivo. Ad esempio se all‟inizio dell‟automatismo di rinnovo, la
            query che individua i carichi contabili da rinnovare produce un
            errore, la procedura di rinnovo non può continuare.



     Creazione della classe Logger
     Per avere garanzia del fatto che esista solamente un‟unica istanza della
classe Logger, è stato utilizzato il design pattern Singleton (Vlissides, et al.,
1994). Questo design pattern prevede che la classe Logger abbia un solo
costruttore che ha la caratteristica di essere privato; in questo modo non è
possibile creare direttamente una nuova istanza della classe. Per far si che
possa comunque esistere un‟istanza, la classe fornisce una proprietà statica di
sola lettura, a cui è associato un metodo get che restituisce il riferimento
all‟istanza della classe. Questo design pattern rende tra l‟altro possibile la lazy
initialization (inizializzazione “pigra”), ovvero la creazione dell‟istanza della
classe solamente al momento della prima chiamata.


     Di seguito viene riportata l‟implementazione della classe Logger:


                                          37
public sealed class Logger
{
      static Logger istanza = null; // la variabile statica privata che
                                    // contiene l'unica istanza di Logger

      // è necessario evitare l'esecuzione concorrente di alcune parti
      // critiche quindi dichiaro un oggetto per il lock
      static readonly object loglock = new object();

      DbConnection LogConnection;
      StreamWriter logTxt;

      Logger() //costruttore privato
      {
            LogConnection = [codice necessario all'utilizzo dei
                             sistemi di sicurezza di Allianz]

            logTxt = new
           StreamWriter(Config.getSetting(settingsNames.PercorsoLog), false);

            logTxt.WriteLine("----- Log dei messaggi che non è stato
                                 possibile memorizzare sul database. -----");

      }

      public static Logger Istanza // La proprietà statica di sola lettura
                                   // che fornisce accesso all'unica istanza
      {
            get
            {
                  lock (loglock)
                  {
                        if (istanza == null) // la classe viene istanziata
                        {                    // al primo utilizzo
                              istanza = new Logger();
                        }
                        return istanza;
                  }
            }
      }

      ...
      funzioni della classe Logger
      ...

}


     Dal codice sorgente si nota anche che sono state prese le precauzioni
necessarie per gestire l‟esecuzione concorrente di più richieste dell‟istanza della
classe, dato che entrambi i thread (principale e supervisore) ne fanno uso.




                                          38
Riprendendo quanto definito nel capitolo 4, l‟insieme dei dettagli di ogni
errore è costituito da:
           Un messaggio definito dalla funzione che ha gestito l‟errore, che
            indica di che errore si tratta, in che contesto è avvenuto, e che
            implicazioni ha avuto.
           La sequenza dei messaggi di errore specifici presi da ogni elemento
            della lista concatenata di eccezioni.
           Lo stack delle chiamate preso dall‟eccezione alla fine della catena.
           Un indicatore della gravità dell‟errore, determinato dalla funzione
            che gestisce l‟errore.


     Il compito della classe Logger è quello di scrivere queste informazioni sul
log. Di seguito viene illustrata l‟implementazione delle funzioni necessarie.


     Avendo a che fare con una lista concatenata di eccezioni, è necessario
individuare la prima eccezione che è stata lanciata, ovvero l‟ultima nella catena
delle eccezioni. Per far questo è stata sviluppata la semplice funzione ricorsiva
getInnermostException:


static Exception getInnermostException(Exception ex)
{
      if (ex.InnerException == null) return ex;
      else return getInnermostException(ex.InnerException);
}


     Dalla lista concatenata di eccezioni è necessario ricavare anche la
sequenza dei messaggi presi da ogni eccezione della lista. Questo compito viene
svolto dalla funzione ricorsiva dettagliEccezione:


        public static string dettagliEccezione(Exception ex)
        {
            if (ex.InnerException != null) return ex.TargetSite.Name + ": " +
                  ex.Message + "rn" + dettagliEccezione(ex.InnerException);
            else return ex.TargetSite.Name + ": " + ex.Message;
        }



                                           39
La memorizzazione nel database avviene tramite la chiamata di una stored
procedure. Il codice utilizzato per richiamarla è il seguente:


void StoredProcedureAddToLog(dbInputParam[] parametri)
{
      DbCommand comando = LogConnection.CreateCommand();
      if (parametri.GetLength(0) > 0) aggiungiParametriAComando(parametri,
                                                                    comando);
      comando.CommandType = CommandType.StoredProcedure;
      comando.CommandText = "[dbo].[addToLog]";
      comando.ExecuteNonQuery();
}

void aggiungiParametriAComando(dbInputParam[] parametri, DbCommand comando)
{
      foreach (dbInputParam parametro in parametri)
      {
            DbParameter paramDaAggiungere = comando.CreateParameter();
            paramDaAggiungere.ParameterName = parametro.nome;
            paramDaAggiungere.Direction = ParameterDirection.Input;
            paramDaAggiungere.DbType = parametro.tipo;
            paramDaAggiungere.Value = parametro.valore;
            comando.Parameters.Add(paramDaAggiungere);
      }
}


     L‟insieme di funzioni fin‟ora indicate è stato infine utilizzato per creare la
funzione addToLog, che riceve le informazioni necessarie dalle funzioni che
hanno la necessità di loggare qualcosa, e scrive il tutto sulla tabella Log del
database (se il database è accessibile) oppure sul file di log (se il database non
è accessibile).


public void addToLog(string messaggio, Exception ex, Int16 rilevanza)
{
      lock (loglock)
      {
            string debugInfo;
            //se viene passata un'eccezione, ne scrivo i dettagli. Altrimenti
                                          scrivo solo lo stack delle chiamate.
            if (ex != null)
            {
                  debugInfo = "Dettagli eccezione:rn" +
                                                 Onlife.dettagliEccezione(ex);
                  debugInfo += "rnrnStack delle chiamate:rn" +
                              getInnermostException(ex).StackTrace.ToString();
            }


                                          40
else
            {
                   debugInfo = "Stack delle chiamate:rn" +
                                            Environment.StackTrace.ToString();
            }

            if (LogConnection.State == ConnectionState.Open)
            {
                  try
                  {
                        dbInputParam[] parametri = new dbInputParam[3];
                        parametri[0] = new dbInputParam("@messaggio",
                                                   DbType.String, messaggio);
                        parametri[1] = new dbInputParam("@debugInfo",
                                                   DbType.String, debugInfo);
                        parametri[2] = new dbInputParam("@rilevanza",
                                                     DbType.Int16, rilevanza);
                        StoredProcedureAddToLog(parametri);
                  }
                  catch
                  {
                        logTxt.WriteLine(messaggio + " -- Call stack:");
                        logTxt.WriteLine(debugInfo);

      logTxt.WriteLine("================================================
                                                                      rn");
                  }
            }
            else
            {
                  logTxt.WriteLine(messaggio + " -- Call stack:");
                  logTxt.WriteLine(debugInfo);

      logTxt.WriteLine("================================================
                                                                      rn");
            }
      }
}



Funzioni di accesso al database

     Un altro elemento fondamentale che è stato preparato durante la prima
fase dello sviluppo dell‟applicativo batch, è l‟insieme delle funzioni di accesso al
database, essendo questo un elemento indispensabile per tutti gli automatismi.
     Dato che il batch resta in esecuzione solamente fin quando ci sono
automatismi da eseguire, e dato che tutti gli automatismi necessitano di
accesso al database, ne consegue che la necessità di una connessione al
database accompagna tutta l‟esecuzione del batch. Per questa ragione si è



                                           41
scelto di inserire nella classe Onlife una variabile statica contenente il
riferimento alla connessione al database. La connessione verrà aperta
immediatamente dopo l‟inizio dell‟esecuzione, e verrà chiusa immediatamente
prima della fine.
     Oltre alle funzioni di apertura, chiusura e verifica della connessione, è
stato creato un ampio insieme di funzioni e di strutture dati, volte a facilitare la
scrittura del resto del codice.



Separazione tra thread principale e thread supervisore

     Nel capitolo precedente si è deciso che per evitare che un loop infinito
possa bloccare il servizio per un tempo indeterminato, l‟esecuzione degli
automatismi deve avvenire in un thread separato, detto principale, mentre un
altro thread, detto supervisore si occupa di segnalare l‟eccessivo prolungarsi
dell‟esecuzione di un automatismo.
     Questa separazione avviene nella procedura principale, dopo che è stata
caricata la lista di automatismi da eseguire:


static void Main(string[] args)
{
      if (Onlife.openDB() == false) {
            Logger.Istanza.addToLog("Impossibile collegarsi al database.",
                                                                         25);
            Logger.Istanza.Chiudi();
            return;
      }
      Config.load();

      Onlife.loadIntMasterData();

      // Dichiaro il thread che eseguirà gli automatismi necessari.
      // Onlife.eseguiFunzione(nomeAutomatismo) è la funzione principale
                                                      da cui parte il thread.
      Thread threadAutomatismo;
      DateTime istanteInizioEsecuzione;

      string[] funzioniDaEseguire;
      bool dacmd;

      if (args.Length > 0)
      {



                                           42
funzioniDaEseguire = new string[1];
                funzioniDaEseguire[0] = args[0];
                dacmd = true;
        }
        else
        {
                funzioniDaEseguire = Onlife.getListaAutomatismiDaEseguire();
                dacmd = false;
        }

        foreach (string nomeFunzione in funzioniDaEseguire)
        {
              threadAutomatismo = new Thread(new
                              ParameterizedThreadStart(Onlife.eseguiFunzione));
              istanteInizioEsecuzione = DateTime.Now;
              Console.WriteLine("Eseguo " + nomeFunzione);
              threadAutomatismo.Start(nomeFunzione);
              TimeSpan tempoEsecuzione;
              while (true)
              {
                    Thread.Sleep(1000);
                    if (threadAutomatismo.ThreadState == ThreadState.Stopped)
                                                                         break;
                    Console.Write('.');
                    tempoEsecuzione =
                                DateTime.Now.Subtract(istanteInizioEsecuzione);

                     if (tempoEsecuzione.Seconds == 0 & tempoEsecuzione.Minutes
    > 0) Logger.Istanza.addToLog("Sto eseguendo l'automatismo " + nomeFunzione +
                               " da " + tempoEsecuzione.Minutes + " minuti", 4);

                       //L'attuale implementazione non prevede la terminazione
                                                      forzata dopo un tempo limite
                }

                 . . . . .
               [codice che verifica l’esito della funzione chiamata]
                 . . . . .

        }
        Console.WriteLine();
        Onlife.closeDB();
        Console.WriteLine("Esecuzione terminata.");
        Logger.Istanza.Chiudi();

}




Caricamento delle quotazioni




                                             43
In questa particolare funzione l‟accesso ai dati del server su cui sono
presenti le quotazioni avviene tramite una query pass through definita in SQL
Server.
     Il processo di caricamento delle nuove quotazioni può essere semplificato e
sintetizzato in questa sequenza di azioni:


                1. Recupera una quotazione da elaborare dalla query pass
                   through. Se non ci sono più quotazioni da elaborare, termina
                   l‟esecuzione.
                2. Salva i dati della nuova quotazione/preventivo nel sistema
                   DM2.
                3. Elabora il canale di vendita.
                4. Se non è una proposta o un contratto: salva il Prospect, salva
                   l‟indirizzo email, associa l‟indirizzo al Prospect, torna al punto
                   1.
                5. Salva i dati della proposta o del contratto
                6. Se il codice fiscale esiste già in DM2, aggiorna i dati del
                   partner, altrimenti aggiungi un nuovo Partner.
                7. Salva l‟email e associala al Partner.
                8. Se l‟email era già associata ad un Prospect, promuovi il
                   Prospect a Partner.
                9. Torna al punto 1.


     Questa     funzionalità    opera   esclusivamente     su   dati    provenienti   dal
database, di conseguenza per seguire la metodologia di miglioramento delle
prestazioni indicata nel capitolo precedente, è stato deciso di realizzarla
completamente tramite stored procedure.
     La complessità dell‟algoritmo ha reso indispensabile l‟utilizzo di un
cursore   per    leggere   in   sequenza    i   dati   dalla    query    pass   through
Query_Onlife_Quotazioni ed eseguire la sequenza di operazioni per ogni record
letto.


                                             44
Un esempio di ottimizzazione che è stato possibile fare su questa funzione
è il seguente: precedentemente la funzione di ricaricamento delle quotazioni
che non è stato possibile caricare in un primo momento, doveva eseguire i
seguenti passaggi:
           Veniva letto da LogQuotazioni l‟ID di una quotazione da ricaricare
           Tale id veniva passato alla funzione di caricamento tramite un
            parametro
           La funzione eseguiva una query pass through verso il database del
            server internet, per recuperare la quotazione.
           Se c‟erano altre quotazioni da ricaricare, si ricominciava.


    Tale problema è stato velocizzato notevolmente con una semplice modifica
della query di ricaricamento delle quotazioni:


SELECT CAST(NUMERO_QUOTAZIONE AS INT) AS NUMQUOT,
DATA_QUOTAZIONE, TIPO_RECORD,
ID_SESSIONE, E_MAIL,
SESSO, DATA_NASCITA,
CAPITALE, COD_FUMO,
CAP, PREMIO,
DA_DOVE_CONOSCIUTI, TIPO_RISCHIO,
FLAG_PROCAM, CANALE_VENDITA,
SUB_CANALE_VENDITA, ID_CONTRATTO,
FLAG_PRIV_COMM
FROM Query_Onlife_Quotazioni
WHERE CAST(NUMERO_QUOTAZIONE AS INT) IN (SELECT DISTINCT IDQuotazione FROM
                                                               logQuotazioni)


    La parte evidenziata individua tutte le quotazioni che è necessario
ricaricare, che quindi verranno elaborate tramite una sola query. Ora è
sufficiente chiamare la funzione di caricamento delle quotazioni passando un
apposito parametro ricaricaLogQuotazioni settato a True, per ottenere con una
sola esecuzione della stored procedure, ciò che prima ne richiedeva una per
ogni quotazione.

Invio della posta



                                           45
La funzionalità di invio di messaggi di posta elettronica, richiede che venga
eseguito un certo numero di operazioni sul database di DM2, al fine di
memorizzare ogni messaggio inviato nello storico del Prospect o al Partner
destinatario.
    Tutte le funzioni relative alla posta elettronica in generale devono eseguire
operazioni anche i file allegati: questi elementi non sono memorizzati nel
database ma nel filesystem del sistema, quindi è stato necessario cercare una
soluzione   che     minimizzi    il   numero      di   richieste   al    database     ma
contemporaneamente permetta di gestire i file.
    La prima opzione presa in considerazione è stata l‟utilizzo del supporto
agli assembly CLR offerto da SQL Server. In questo modo le operazioni sui files
sarebbero   state   realizzate   in   dei   moduli     programmati      in   C#   inseriti
direttamente nel DBMS, e richiamabili da stored procedure. Le restrizioni di
sicurezza imposte da Allianz hanno però obbligato l‟abbandono di questa
strada.
    È stato necessario percorrere l‟unica alternativa rimanente: tutte le
funzioni che avevano a che fare con gli allegati sono state programmante
all‟interno del file batch, mentre le restanti funzioni che operavano solo sul
database sono stare realizzate tramite stored procedure.
    Un esempio di funzione realizzata tramite stored procedure è la seguente:


CREATE PROCEDURE [dbo].[logComunication]
      @idEmail int,
      @direzionePosta int,
      @tipoPosta int,
      @Mittente varchar(200),
      @IDEmailMittente int,
      @Destinatario varchar(200),
      @idEmailDestinatario int,
      @Oggetto varchar(200),
      @Testo varchar(max),
      @idCampagna int = NULL,
      @numAllegati int = 0,
      @DataInvio datetime = NULL,
      @DataRicezione datetime = NULL,
      @RisultatoInvio int = 0,
      @WebCons int = NULL,
      @IdCasella int = NULL,
      @flg_errore bit = 0


                                             46
AS
BEGIN
         SET NOCOUNT ON;
         DECLARE @PA_direzione AS nvarchar(3)
         DECLARE @PA_letta AS bit
         DECLARE @PA_idposta AS int
         DECLARE @PA_idPartnerTeam AS int


         IF @direzionePosta = 1 SET @PA_direzione = 'IN'
         ELSE IF @direzionePosta = 2 SET @PA_direzione = 'OUT'
         ELSE IF @direzionePosta = 0 SET @PA_direzione = NULL

         IF @direzionePosta = 2 OR @direzionePosta = 0 SET @PA_letta = 1
         ELSE SET @PA_letta = 0


      EXEC @PA_idposta = [dbo].LogPosta @direzionePosta, @tipoPosta,
  @Mittente, @IDEmailMittente, @Destinatario, @idEmailDestinatario, @Oggetto,
    @Testo, @numAllegati, @DataInvio, @DataRicezione, @IdCasella, @flg_errore

         SET @PA_idPartnerTeam = 0

         INSERT INTO PostaArchivio (IDMail, Direzione, IdPosta, IDCampagna,
                             "Letta?", RisultatoInvio, IDWebCons, IDPartnerTeam)
               VALUES (@idEmail, @PA_direzione, @PA_idposta, @idCampagna,
                        @PA_letta, @RisultatoInvio, @WebCons, @PA_idPartnerTeam)

         RETURN SCOPE_IDENTITY()
END


       Mentre un esempio di funzione realizzata all‟interno dell‟applicativo batch,
che esegue operazioni sui files, è la funzione AttachAttachmentsToMailOut, che
riceve l‟ID del messaggio e i percorsi dei file da allegare, e copia gli allegati da
inviare nella apposita cartella degli allegati in uscita.


static void AttachAttachmentsToMailOut(int idEmail, string[] allegati)
{
      string errInfo ="AttachAttachmentsToMailOut(" + idEmail + ", [array
                                                                  allegati])";
      FileInfo allegato;
      FileInfo destfile;
      FileInfo backup;
   string destFileStr;
   string backupStr;
   int n = 0;
   int i = 0;

      foreach (string allegatoStr in allegati)
      {
         n++;



                                            47
allegato = new FileInfo(allegatoStr);
       if (!allegato.Exists)
       {
          string msg = "AttachAttachmentsToMailOut: ERRORE! L'allegato " +
                                                  allegatoStr + " non esiste!";
          Logger.Istanza.addToLog(msg, 15);
          throw new System.Exception("AttachAttachmentsToMailOut: ERRORE!
                                  L'allegato " + allegatoStr + " non esiste!");
       }

       destFileStr = IM_DirectoryAllegatiOUT + getNomeAllegatoForIT(idEmail,
                                                       n) + allegato.Extension;
       destfile = new FileInfo(destFileStr);

       if (destfile.Exists)
       {   //è già presente un file con lo stesso nome. lo rinomino.

          backupStr = IM_DirectoryAllegatiOUT + getNomeAllegatoForIT(idEmail,
                                           n) + "_backup" + allegato.Extension;
          backup = new FileInfo(backupStr);

         while (backup.Exists)
         {
            backupStr = IM_DirectoryAllegatiOUT +
        getNomeAllegatoForIT(idEmail, n) + "_backup" + i + allegato.Extension;
            backup = new FileInfo(backupStr);
            i++;
         }
         i = 0;

          destfile.MoveTo(backupStr);
          Logger.Istanza.addToLog("Attenzione: stranamente, il file di
       destinazione " + destFileStr + " esisteva già. È stato rinominato in " +
                           backupStr + " prima di salvare il nuovo file.", 15);
       }
       allegato.CopyTo(destFileStr);
    } // foreach...
}


     Per migliorare la manutenibilità del codice scritto è stata creata una classe
EmailOut; le istanze della quale rappresentano messaggi da inviare tramite
l‟apposita funzione InviaEmail.
     public class EmailOut
     {
         public SqlString destinatario;
         public SqlString oggetto;
         public SqlString testo;
         public bool daSpedire;
         public string[] allegati = { };

         /// <summary> Default = NULL </summary>
         public SqlInt32 webcons;




                                           48
/// <summary> Default = NULL </summary>
    public int? idMessaggioStandard;

    /// <summary> Default = EMAIL </summary>
    public enumTipoPosta tipoPosta;

    /// <summary> Default = TRUE </summary>
    public bool archiviaEmailSN;

    /// <summary> Default = TRUE </summary>
    public bool salvaAllegatiInArchivioSN;

    /// <summary> Default = 1 (non cambiare! nel vecchio sistema in
                                             Access era fisso) </summary>
    public SqlInt32 _tipoMessaggio;

    /// <summary> Default = 1 (non cambiare! nel vecchio sistema in
                                             Access era fisso) </summary>
    public SqlInt32 _idAutorizzato;

    public EmailOut()
    {
        idMessaggioStandard = null;
        _idAutorizzato = 1;
        _tipoMessaggio = 1;
        tipoPosta = enumTipoPosta.email;
        archiviaEmailSN = true;
        salvaAllegatiInArchivioSN = true;
        webcons = SqlInt32.Null;
    }

    public int numAllegati
    {
        get { return allegati.GetLength(0); }
    }

    public void aggiungiAllegato(string allegato)
    {
        int dimAttuale = allegati.GetLength(0);
        Array.Resize(ref allegati, dimAttuale + 1);
        allegati[dimAttuale] = allegato;
    }

    public override string ToString()
    {
        return "Destinatario: "" + destinatario.ToString() + ""
                     Oggetto: "" + oggetto.ToString() + "" Testo: "" +
            testo.ToString().Substring(0, 30) + "[..] " DaSpedire: "" +
             daSpedire.ToString() + "" Numero allegati: " + numAllegati;
    }

    public void resetAllegati()
    {
        allegati = new string[0];
    }
}



                                    49
Lettura della posta

     La gestione automatizzata della posta in ingresso è una caratteristica
molto importante, dato che in Onlife questo è il mezzo di comunicazione
principale con i clienti.
     I nuovi messaggi in ingresso devono essere sottoposti ad un automatismo
che li elabora ed invia delle risposte automatiche quando possibile, mentre
quando non è possibile li associa al giusto partner o prospect.


     Ogni nuova email deve dunque essere sottoposta ai seguenti passaggi:
           Si prova ad eseguire il trattamento automatico.
           Se il trattamento automatico non ha dato esito positivo, analizzando
            l‟indirizzo del mittente la mail viene archiviata associandola al
            Prospect o al Partner da cui proviene, il quale viene messo “in
            evidenza”.
           Se non proviene da un Prospect o da un Partner noto, viene
            aggiunta alla “posta da classificare”.


     Il trattamento automatico avviene cercando nell‟oggetto del messaggio
delle parole chiave, ed eseguendo la funzione opportuna in base alle eventuali
corrispondenze trovate. Il meccanismo si basa su delle tabelle che indicano le
parole chiave e i nomi delle funzioni da chiamare.


     Questa funzione è stata realizzata nel seguente modo:
           Una funzione principale LeggiPosta interroga il database alla ricerca
            di nuove email da elaborare (restituite da una vista definita sul
            database, che per ottimizzare gli accessi al database esegue già
            alcune stored function di base e restituisce i risultati nei campi della
            vista)

                                           50
   Il risultato dell‟interrogazione è un DataReader, il cui riferimento
               viene passato a diverse funzioni, secondo le necessità. Le funzioni
               che lo ricevono però devono elaborare solo il record corrente, quindi
               non possono nè chiudere il datareader nè eseguire il suo metodo
               Read().
              LeggiPosta contiene un ciclo di lettura che tenta di esegue il
               trattamento automatico di tutti i messaggi in ingresso



Automazione di campagne di comunicazione

     La funzione LanciaCampagna deve creare ed inviare grandi quantità di
messaggi personalizzati. In fase di invio infatti il testo di ogni messaggio deve
essere personalizzato per il singolo destinatario inserendo dati estratti dalla
query dei destinatari dal database al posto di specifici tag presenti nel
messaggio.
     Dato che questa funzione deve poter gestire anche gli allegati delle email, è
stata programmata interamente all‟interno dell‟applicativo batch.
     Se gli allegati sono dei form PDF è possibile personalizzarne il contenuto
analogamente a come viene fatto per il testo del messaggio. Per determinare se
il   PDF       deve   essere   personalizzato     oppure       no,   si   usa   la   funzione
nomiCampiInPDF,          che   utilizzando   le    librerire    iTextSharp      permette   di
individuare gli eventuali campi del Form PDF:


public static string[] nomiCampiInPDF(string percorsoPDF)
{
      string[] nomi = { };
      PdfReader documento = new PdfReader(percorsoPDF);
      foreach (KeyValuePair<string, AcroFields.Item> campo in
documento.AcroFields.Fields)
      {
            Array.Resize(ref nomi, nomi.Length + 1);
            nomi[nomi.Length - 1] = campo.Key;
      }
      documento.Close();
      return nomi;
}




                                                51
Diverse campagne possono essere raggruppate, per poter essere lanciate
secondo un ordine prestabilito, in automatismi. Quando si avvia un
automatismo le campagne che ne fanno parte vengono lanciate in sequenza.
     Questa funzione viene svolta da EseguiWorkflow:


public static int eseguiWorkflow(enumAutomatismo automatismo, int? valoreID,
                                                                bool? flg_log)
{
      string errInfo = "eseguiWorkflow(" + automatismo.ToString() + ", " +
                        valoreID.ToString() + ", " + flg_log.ToString() + ")";
      dbInputParam[] parametro = new dbInputParam[1];
      parametro[0] = new dbInputParam("@idAutomatismo", DbType.Int32,
                                                            (int)automatismo);
      IDataReader operazioni = dataReaderDaSQL("SELECT IDMessaggio, IDQuery,
         StringaUpdate FROM Workflow WHERE [InVigore?] = 1 AND IDAutomatismo =
                          @idAutomatismo ORDER BY OrdineChiamata", parametro);
      string strUpdate;
      int mailInviate = 0;
      while (operazioni.Read())
      {
            if (operazioni.IsDBNull(2)) strUpdate = "";
            else strUpdate = operazioni.GetString(2);
            try
            {
                  mailInviate += lanciaCampagna(operazioni.GetInt32(0),
                                        operazioni.GetInt32(1), 0, strUpdate);
            }
            catch (Exception ex)
            {
                  operazioni.Close();
                  operazioni.Dispose();
                  throw new Exception(errInfo + ": Si è verificato un errore
         durante l'esecuzione dell'automatismo " + automatismo.ToString() + ".
                                       L'esecuzione è stata interrotta.", ex);
            }
      }
      operazioni.Close();
      return mailInviate;
}


     In questa funzione si può tra l‟altro notare un esempio di applicazione
della metodologia di gestione degli errori precedentemente definita: se
LanciaCampagna invia un‟eccezione, questa viene concatenata all‟eccezione
definita nel blocco catch.



Esecuzione della procedura dei rinnovi

                                         52
La parte di sistema informativo che si occupa del calcolo del premio non è
inclusa in DM2, ma fa parte del sistema informativo di L.A. Vita. Per
interfacciarsi con questo sistema, nel caso del calcolo del premio è stato
necessario utilizzare un web service.
    La funzione calcoloPremioOL si occupa della connessione al web service e
della corretta interpretazione dei dati restituiti, lanciando un‟eccezione se il
risultato ricevuto ha un formato inatteso:


public static string calcoloPremioOL(int numProposta, double
capitaleAssicurato, DateTime dataDecorrenza)
{
      string errInfo = "calcoloPremioOL(" + numProposta + ", " +
                 capitaleAssicurato.ToString() + ", " + dataDecorrenza + ")";

      GrlWsOnlifeSoapClient ClientWs = new GrlWsOnlifeSoapClient();

      ClientWs.ClientCredentials.UserName.UserName = [credenziali di accesso]
      ClientWs.ClientCredentials.UserName.Password = [credenziali di accesso]

      string risultatoXml = ClientWs.CalcoloPremioOL(numProposta,
                                         capitaleAssicurato, dataDecorrenza);

      XmlTextReader xmlReader = new XmlTextReader(new
                                                 StringReader(risultatoXml));

      string risultato = "";
      string errore = "";
      string premio = "";

      while (xmlReader.Read())
      {
            if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name
                                                                 == "Result")
            {
                  xmlReader.Read();
                  risultato = xmlReader.Value;
            }
            if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name
                                                       == "ErrorDescription")
            {
                  xmlReader.Read();
                  errore = xmlReader.Value;
            }
            if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name
                                                                == "anyType")
            {
                  xmlReader.Read();
                  premio = xmlReader.Value;
            }
      }


                                         53
xmlReader.Close();
      ClientWs.Close();

      string[] premio_splitted = premio.Split(';');

      if (risultato.ToUpper().Trim() == "TRUE" && premio_splitted.Length ==
                                                                               4)
      {
             return premio_splitted[3];
      }
      else
      {
             addToBacheca(enumBacheca.segnalazioniDM2, "Premio non calcolato
                                                     [e altre informazioni]");
             throw new Exception([messaggio di errore dettagliato]);
      }
}


     Per aumentare la velocità di elaborazione il resto della logica di rinnovo dei
contratti è stata programmata in una stored procedure.




Controllo RID respinti

     Questa funzione si limita a verificare la presenza di RID respinti, contando
il numero dei contratti che hanno uno specifico status. Anche questo è un
esempio di funzione che è stato possibile realizzare molto semplicemente in
un‟unica stored procedure. In particolare questa funzione è talmente semplice
che poteva essere realizzata definendo una vista, tuttavia per garantire piena
libertà di modifica si è deciso di utilizzare comunque una stored procedure.
     Attualmente il compito di scrivere sul log l‟informazione spetta alla
funzione chiamante, ma essendo una stored procedure in futuro si potrebbe
aggiungere una chiamata alla stored procedure che si occupa della scrittura
sulla tabella Log.
CREATE PROCEDURE ControllaRIDrespinti
AS
BEGIN
      SET NOCOUNT ON;
      DECLARE @ris INT
      SELECT @ris = count(*) FROM Contratti WHERE STATUS = 226
      RETURN @ris
END


                                          54
Eliminazione dei dati sensibili

     Analogamente al controllo dei RID respinti, l‟eliminazione dei dati sensibili
è stata realizzata tramite la stored procedure qui riportata:


DECLARE @dataElim datetime
SET @dataElim = GETDATE()
DECLARE @eliminati int

UPDATE Contratti
SET
    QuestAltezza = NULL,
    QuestPeso = NULL,
    QuestPressioneMax = NULL,
    QuestTrigliceridi = NULL,
    QuestColesteroloTot = NULL,
    QuestColesteroloHdl = NULL,
    [QuestFlagDiabete?] = NULL,
    [QuestFlagInfarti?] = NULL,
    DataCancellazioneDatiSensibili = NULL,
    Note=Note+'Scaduta validità proposta in data '+CAST(GETDATE() AS nvarchar)
WHERE NOT DataCancellazioneDatiSensibili IS NULL AND
    DataCancellazioneDatiSensibili < DateAdd(d, 1, @dataElim) AND
    Status <> 100 AND
    Status <> 200 AND
    NOT ID IN (SELECT NumeroProposta
                                FROM CarichiContabili
                                WHERE TipoCarico = 1) AND
    Contratti.ID NOT IN (SELECT Contratti.ID
                                                FROM Contratti
                                                WHERE (((Contratti.IDPartner) IN
                                          (SELECT DISTINCT Contratti.IDPartner
                                            FROM Contratti INNER JOIN
            CarichiContabili ON Contratti.ID = CarichiContabili.NumeroProposta
                                   WHERE (((CarichiContabili.TipoCarico)=1)))))
                                          )

SET @eliminati = @@ROWCOUNT

UPDATE IntMaster SET DataUltimaEliminazioneDatiSensibili = GETDATE()

DECLARE @risultato as nvarchar(50)
SET @risultato = 'Eliminati i dati sensibili di ' + CAST(@eliminati as
nvarchar) + ' proposte'
EXEC [dbo].[addToLog] @risultato, 'Stored procedure: eliminaDatiSensibili', 5




                                          55
Sincronizzazione degli status

     La sincronizzazione periodica degli status dei contratti viene realizzata
accedendo al database di L.A. Vita tramite una query pass through e
confrontando gli status dei contratti con i dati contenuti nel database di DM2.
     L‟obiettivo è evidenziare i casi in cui è stata rilevata una differenza di
status e procedere all‟aggiornamento dei dati presenti in DM2.
     Dato che questa funzione elabora solamente dati provenienti dal database
di DM2 e dal database di Onlife (a cui si accede tramite una query pass
through), si è deciso di realizzarla tramite una stored procedure che restituirà il
numero di differenze individuate.


CREATE PROCEDURE [dbo].[ControllaStatusContratti]

AS
BEGIN
        SET NOCOUNT ON;

        DECLARE @strModificatoStatus as nvarchar(1000)
        SET @strModificatoStatus = ''
        DECLARE @idPartner as int
        DECLARE @numDifferenze as int
        SET @numDifferenze = 0

        DECLARE   @ID as int
        DECLARE   @DataDecorrenza as datetime
        DECLARE   @DataDecorrenza_onlife as datetime
        DECLARE   @DataScadenza as datetime
        DECLARE   @DataScadenza_onlife as datetime
        DECLARE   @DataSottoscrizione as datetime
        DECLARE   @DataSottoscrizione_onlife as datetime
        DECLARE   @RataLorda as decimal(14,2)
        DECLARE   @RataLorda_onlife as numeric
        DECLARE   @Status as smallint
        DECLARE   @Status_onlife as smallint
        DECLARE   @PrestazioneIniziale_onlife as numeric
        DECLARE   @PrestazioneIniziale as decimal(13,2)

        DECLARE sorgDifferenze CURSOR FAST_FORWARD FOR
              SELECT ID
                      ,DataDecorrenza, DataDecorrenza_onlife, DataScadenza
                      ,DataScadenza_onlife ,DataSottoscrizione
                      ,DataSottoscrizione_onlife ,RataLorda ,RataLorda_onlife
                      ,Status ,Status_onlife ,PrestazioneIniziale_onlife
                      ,PrestazioneIniziale
              FROM [dbo].[qry_differenze_STATUS]




                                            56
OPEN sorgDifferenze

     FETCH NEXT FROM sorgDifferenze
           INTO @ID, @DataDecorrenza, @DataDecorrenza_onlife, @DataScadenza,
      @DataScadenza_onlife, @DataSottoscrizione, @DataSottoscrizione_onlife,
                     @RataLorda, @RataLorda_onlife, @Status, @Status_onlife,
                           @PrestazioneIniziale_onlife, @PrestazioneIniziale

     WHILE @@FETCH_STATUS = 0 BEGIN
           IF @Status_onlife <> 0 BEGIN

                  UPDATE Contratti
                        SET Status = @Status_onlife,
                              DataDecorrenza = @DataDecorrenza_onlife,
                              DataScadenza = @DataScadenza_onlife,
                              DataSottoscrizione = @DataSottoscrizione_onlife
                        WHERE ID = @ID

                 IF @RataLorda <> @RataLorda_onlife BEGIN
                             SET @strModificatoStatus = convert(nvarchar,
 GETDATE(), 103) + ': Modificato il premio del contratto numero ' + cast(@ID
          as nvarchar) + ' da € ' + cast(@RataLorda as nvarchar) + ' a € ' +
                   cast(@RataLorda_onlife as nvarchar) + char(13) + char(10)

                              UPDATE Contratti SET RataLorda =
                                             @RataLorda_onlife WHERE ID = @ID
                  END

                  IF @PrestazioneIniziale <> @PrestazioneIniziale_onlife
                  BEGIN
                              SET @strModificatoStatus = @strModificatoStatus
+ convert(nvarchar, GETDATE(), 103) + ': Modificato il capitale del contratto
   numero ' + cast(@ID as nvarchar) + ' da € ' + cast(@PrestazioneIniziale as
        nvarchar) + ' a € ' + cast(@PrestazioneIniziale_onlife as nvarchar) +
                                                          char(13) + char(10)

                              UPDATE Contratti SET PrestazioneIniziale =
                                   @PrestazioneIniziale_onlife WHERE ID = @ID
                  END

                  IF @Status_onlife = 200 UPDATE Contratti SET
                         DataCancellazioneDatiSensibili = NULL WHERE ID = @ID

                 IF NOT(@Status_onlife = 100 OR @Status_onlife = 200) BEGIN
                       SELECT @idPartner = IDPartner FROM Contratti WHERE ID
                                                                       = @ID
                       SET @strModificatoStatus = convert(nvarchar,
     GETDATE(), 103) + ': Modificato status contratto numero ' + cast(@ID as
 nvarchar) + ' in ' + cast(@status_onlife as nvarchar) + char(13) + char(10)

                        EXEC dbo.evidenziaPartner @idPartner,
                                                         @strModificatoStatus

                       INSERT INTO Log (Testo, DebugInfo, Rilevanza) VALUES
     (@strModificatoStatus, 'Stored procedure: ControllaStatusContratti', 5)
                 END



                                          57
Migrazione dei meccanismi di workflow di un sistema informativo assicurativo verso l'ambiente SQL Server e .NET
Migrazione dei meccanismi di workflow di un sistema informativo assicurativo verso l'ambiente SQL Server e .NET
Migrazione dei meccanismi di workflow di un sistema informativo assicurativo verso l'ambiente SQL Server e .NET
Migrazione dei meccanismi di workflow di un sistema informativo assicurativo verso l'ambiente SQL Server e .NET
Migrazione dei meccanismi di workflow di un sistema informativo assicurativo verso l'ambiente SQL Server e .NET
Migrazione dei meccanismi di workflow di un sistema informativo assicurativo verso l'ambiente SQL Server e .NET

Weitere ähnliche Inhalte

Ähnlich wie Migrazione dei meccanismi di workflow di un sistema informativo assicurativo verso l'ambiente SQL Server e .NET

Analisi e sviluppo di un sistema collaborativo simultaneo per la modifica di ...
Analisi e sviluppo di un sistema collaborativo simultaneo per la modifica di ...Analisi e sviluppo di un sistema collaborativo simultaneo per la modifica di ...
Analisi e sviluppo di un sistema collaborativo simultaneo per la modifica di ...Filippo Muscolino
 
Documentazione progetto software - IoSegnalo
Documentazione progetto software - IoSegnaloDocumentazione progetto software - IoSegnalo
Documentazione progetto software - IoSegnaloMarco Vaiano
 
Openfisca Managing Tool: a tool to manage fiscal sistems
Openfisca Managing Tool: a tool to manage fiscal sistemsOpenfisca Managing Tool: a tool to manage fiscal sistems
Openfisca Managing Tool: a tool to manage fiscal sistemsLorenzo Stacchio
 
Rilevamento di attacchi di rete tramite protocolli di monitoraggio per router...
Rilevamento di attacchi di rete tramite protocolli di monitoraggio per router...Rilevamento di attacchi di rete tramite protocolli di monitoraggio per router...
Rilevamento di attacchi di rete tramite protocolli di monitoraggio per router...Ce.Se.N.A. Security
 
Progetto e sviluppo di un'applicazionemobile multipiattaforma per il supporto...
Progetto e sviluppo di un'applicazionemobile multipiattaforma per il supporto...Progetto e sviluppo di un'applicazionemobile multipiattaforma per il supporto...
Progetto e sviluppo di un'applicazionemobile multipiattaforma per il supporto...maik_o
 
Sistemi SCADA - Supervisory control and data acquisition
Sistemi SCADA - Supervisory control and data acquisitionSistemi SCADA - Supervisory control and data acquisition
Sistemi SCADA - Supervisory control and data acquisitionAmmLibera AL
 
Rilevamento di facce in flussi video per l'ausilio ai non vedenti - Tesi
Rilevamento di facce in flussi video per l'ausilio ai non vedenti - TesiRilevamento di facce in flussi video per l'ausilio ai non vedenti - Tesi
Rilevamento di facce in flussi video per l'ausilio ai non vedenti - Tesitemp temp
 
Autenticazione Continua Durante la Navigazione Web Basata sulla Dinamica del ...
Autenticazione Continua Durante la Navigazione Web Basata sulla Dinamica del ...Autenticazione Continua Durante la Navigazione Web Basata sulla Dinamica del ...
Autenticazione Continua Durante la Navigazione Web Basata sulla Dinamica del ...danieledegan
 
Porting evolutivo dell'applicazione per la gestione dei dispositivi del Comun...
Porting evolutivo dell'applicazione per la gestione dei dispositivi del Comun...Porting evolutivo dell'applicazione per la gestione dei dispositivi del Comun...
Porting evolutivo dell'applicazione per la gestione dei dispositivi del Comun...ozacchig
 
Tesi: Progetto e realizzazione di un sistema robusto di gestione dei dati per...
Tesi: Progetto e realizzazione di un sistema robusto di gestione dei dati per...Tesi: Progetto e realizzazione di un sistema robusto di gestione dei dati per...
Tesi: Progetto e realizzazione di un sistema robusto di gestione dei dati per...Paolo Morandini
 
Tesi Specialistica - L'ottimizzazione delle risorse della Grid di EGEE median...
Tesi Specialistica - L'ottimizzazione delle risorse della Grid di EGEE median...Tesi Specialistica - L'ottimizzazione delle risorse della Grid di EGEE median...
Tesi Specialistica - L'ottimizzazione delle risorse della Grid di EGEE median...Davide Ciambelli
 
Realizzazione di un workflow integrato per la rilevazione di domini phishing
Realizzazione di un workflow integrato per la rilevazione di domini phishingRealizzazione di un workflow integrato per la rilevazione di domini phishing
Realizzazione di un workflow integrato per la rilevazione di domini phishingGiuliaMilan4
 
Publish/Subscribe EDI with Content-Based Routing
Publish/Subscribe EDI with Content-Based RoutingPublish/Subscribe EDI with Content-Based Routing
Publish/Subscribe EDI with Content-Based RoutingNicola Mezzetti
 
Analisi e realizzazione di uno strumento per la verifica di conformità su sis...
Analisi e realizzazione di uno strumento per la verifica di conformità su sis...Analisi e realizzazione di uno strumento per la verifica di conformità su sis...
Analisi e realizzazione di uno strumento per la verifica di conformità su sis...Davide Bravin
 
Strategie ingestigative in ambito di criminalità informatica
Strategie ingestigative in ambito di criminalità informaticaStrategie ingestigative in ambito di criminalità informatica
Strategie ingestigative in ambito di criminalità informaticapeppespe
 
Implementazione hardware/software di un sistemamultitouch per l'interazione u...
Implementazione hardware/software di un sistemamultitouch per l'interazione u...Implementazione hardware/software di un sistemamultitouch per l'interazione u...
Implementazione hardware/software di un sistemamultitouch per l'interazione u...Pier Giuliano Nioi
 
Linee guida AGID su acquisizione e riuso di software per le pubbliche amminis...
Linee guida AGID su acquisizione e riuso di software per le pubbliche amminis...Linee guida AGID su acquisizione e riuso di software per le pubbliche amminis...
Linee guida AGID su acquisizione e riuso di software per le pubbliche amminis...Simone Aliprandi
 
Progettazione e Sviluppo di un Sistema per Migliorare il Codice Generato da u...
Progettazione e Sviluppo di un Sistema per Migliorare il Codice Generato da u...Progettazione e Sviluppo di un Sistema per Migliorare il Codice Generato da u...
Progettazione e Sviluppo di un Sistema per Migliorare il Codice Generato da u...DamianoRavalico
 

Ähnlich wie Migrazione dei meccanismi di workflow di un sistema informativo assicurativo verso l'ambiente SQL Server e .NET (20)

Analisi e sviluppo di un sistema collaborativo simultaneo per la modifica di ...
Analisi e sviluppo di un sistema collaborativo simultaneo per la modifica di ...Analisi e sviluppo di un sistema collaborativo simultaneo per la modifica di ...
Analisi e sviluppo di un sistema collaborativo simultaneo per la modifica di ...
 
Documentazione progetto software - IoSegnalo
Documentazione progetto software - IoSegnaloDocumentazione progetto software - IoSegnalo
Documentazione progetto software - IoSegnalo
 
Openfisca Managing Tool: a tool to manage fiscal sistems
Openfisca Managing Tool: a tool to manage fiscal sistemsOpenfisca Managing Tool: a tool to manage fiscal sistems
Openfisca Managing Tool: a tool to manage fiscal sistems
 
Rilevamento di attacchi di rete tramite protocolli di monitoraggio per router...
Rilevamento di attacchi di rete tramite protocolli di monitoraggio per router...Rilevamento di attacchi di rete tramite protocolli di monitoraggio per router...
Rilevamento di attacchi di rete tramite protocolli di monitoraggio per router...
 
Progetto e sviluppo di un'applicazionemobile multipiattaforma per il supporto...
Progetto e sviluppo di un'applicazionemobile multipiattaforma per il supporto...Progetto e sviluppo di un'applicazionemobile multipiattaforma per il supporto...
Progetto e sviluppo di un'applicazionemobile multipiattaforma per il supporto...
 
Compas Project
Compas ProjectCompas Project
Compas Project
 
Sistemi SCADA - Supervisory control and data acquisition
Sistemi SCADA - Supervisory control and data acquisitionSistemi SCADA - Supervisory control and data acquisition
Sistemi SCADA - Supervisory control and data acquisition
 
Rilevamento di facce in flussi video per l'ausilio ai non vedenti - Tesi
Rilevamento di facce in flussi video per l'ausilio ai non vedenti - TesiRilevamento di facce in flussi video per l'ausilio ai non vedenti - Tesi
Rilevamento di facce in flussi video per l'ausilio ai non vedenti - Tesi
 
Autenticazione Continua Durante la Navigazione Web Basata sulla Dinamica del ...
Autenticazione Continua Durante la Navigazione Web Basata sulla Dinamica del ...Autenticazione Continua Durante la Navigazione Web Basata sulla Dinamica del ...
Autenticazione Continua Durante la Navigazione Web Basata sulla Dinamica del ...
 
Porting evolutivo dell'applicazione per la gestione dei dispositivi del Comun...
Porting evolutivo dell'applicazione per la gestione dei dispositivi del Comun...Porting evolutivo dell'applicazione per la gestione dei dispositivi del Comun...
Porting evolutivo dell'applicazione per la gestione dei dispositivi del Comun...
 
Tesi: Progetto e realizzazione di un sistema robusto di gestione dei dati per...
Tesi: Progetto e realizzazione di un sistema robusto di gestione dei dati per...Tesi: Progetto e realizzazione di un sistema robusto di gestione dei dati per...
Tesi: Progetto e realizzazione di un sistema robusto di gestione dei dati per...
 
Tesi Specialistica - L'ottimizzazione delle risorse della Grid di EGEE median...
Tesi Specialistica - L'ottimizzazione delle risorse della Grid di EGEE median...Tesi Specialistica - L'ottimizzazione delle risorse della Grid di EGEE median...
Tesi Specialistica - L'ottimizzazione delle risorse della Grid di EGEE median...
 
Realizzazione di un workflow integrato per la rilevazione di domini phishing
Realizzazione di un workflow integrato per la rilevazione di domini phishingRealizzazione di un workflow integrato per la rilevazione di domini phishing
Realizzazione di un workflow integrato per la rilevazione di domini phishing
 
TesiEtta
TesiEttaTesiEtta
TesiEtta
 
Publish/Subscribe EDI with Content-Based Routing
Publish/Subscribe EDI with Content-Based RoutingPublish/Subscribe EDI with Content-Based Routing
Publish/Subscribe EDI with Content-Based Routing
 
Analisi e realizzazione di uno strumento per la verifica di conformità su sis...
Analisi e realizzazione di uno strumento per la verifica di conformità su sis...Analisi e realizzazione di uno strumento per la verifica di conformità su sis...
Analisi e realizzazione di uno strumento per la verifica di conformità su sis...
 
Strategie ingestigative in ambito di criminalità informatica
Strategie ingestigative in ambito di criminalità informaticaStrategie ingestigative in ambito di criminalità informatica
Strategie ingestigative in ambito di criminalità informatica
 
Implementazione hardware/software di un sistemamultitouch per l'interazione u...
Implementazione hardware/software di un sistemamultitouch per l'interazione u...Implementazione hardware/software di un sistemamultitouch per l'interazione u...
Implementazione hardware/software di un sistemamultitouch per l'interazione u...
 
Linee guida AGID su acquisizione e riuso di software per le pubbliche amminis...
Linee guida AGID su acquisizione e riuso di software per le pubbliche amminis...Linee guida AGID su acquisizione e riuso di software per le pubbliche amminis...
Linee guida AGID su acquisizione e riuso di software per le pubbliche amminis...
 
Progettazione e Sviluppo di un Sistema per Migliorare il Codice Generato da u...
Progettazione e Sviluppo di un Sistema per Migliorare il Codice Generato da u...Progettazione e Sviluppo di un Sistema per Migliorare il Codice Generato da u...
Progettazione e Sviluppo di un Sistema per Migliorare il Codice Generato da u...
 

Kürzlich hochgeladen

Alessandro Nasi, COO @Djungle Studio – “Cosa delegheresti alla copia di te st...
Alessandro Nasi, COO @Djungle Studio – “Cosa delegheresti alla copia di te st...Alessandro Nasi, COO @Djungle Studio – “Cosa delegheresti alla copia di te st...
Alessandro Nasi, COO @Djungle Studio – “Cosa delegheresti alla copia di te st...Associazione Digital Days
 
Luigi Di Carlo, CEO & Founder @Evometrika srl – “Ruolo della computer vision ...
Luigi Di Carlo, CEO & Founder @Evometrika srl – “Ruolo della computer vision ...Luigi Di Carlo, CEO & Founder @Evometrika srl – “Ruolo della computer vision ...
Luigi Di Carlo, CEO & Founder @Evometrika srl – “Ruolo della computer vision ...Associazione Digital Days
 
Federico Bottino, Lead Venture Builder – “Riflessioni sull’Innovazione: La Cu...
Federico Bottino, Lead Venture Builder – “Riflessioni sull’Innovazione: La Cu...Federico Bottino, Lead Venture Builder – “Riflessioni sull’Innovazione: La Cu...
Federico Bottino, Lead Venture Builder – “Riflessioni sull’Innovazione: La Cu...Associazione Digital Days
 
Programma Biennale Tecnologia 2024 Torino
Programma Biennale Tecnologia 2024 TorinoProgramma Biennale Tecnologia 2024 Torino
Programma Biennale Tecnologia 2024 TorinoQuotidiano Piemontese
 
Daniele Lunassi, CEO & Head of Design @Eye Studios – “Creare prodotti e servi...
Daniele Lunassi, CEO & Head of Design @Eye Studios – “Creare prodotti e servi...Daniele Lunassi, CEO & Head of Design @Eye Studios – “Creare prodotti e servi...
Daniele Lunassi, CEO & Head of Design @Eye Studios – “Creare prodotti e servi...Associazione Digital Days
 
Edoardo Di Pietro – “Virtual Influencer vs Umano: Rubiamo il lavoro all’AI”
Edoardo Di Pietro – “Virtual Influencer vs Umano: Rubiamo il lavoro all’AI”Edoardo Di Pietro – “Virtual Influencer vs Umano: Rubiamo il lavoro all’AI”
Edoardo Di Pietro – “Virtual Influencer vs Umano: Rubiamo il lavoro all’AI”Associazione Digital Days
 
Gabriele Mittica, CEO @Corley Cloud – “Come creare un’azienda “nativa in clou...
Gabriele Mittica, CEO @Corley Cloud – “Come creare un’azienda “nativa in clou...Gabriele Mittica, CEO @Corley Cloud – “Come creare un’azienda “nativa in clou...
Gabriele Mittica, CEO @Corley Cloud – “Come creare un’azienda “nativa in clou...Associazione Digital Days
 
Alessio Mazzotti, Aaron Brancotti; Writer, Screenwriter, Director, UX, Autore...
Alessio Mazzotti, Aaron Brancotti; Writer, Screenwriter, Director, UX, Autore...Alessio Mazzotti, Aaron Brancotti; Writer, Screenwriter, Director, UX, Autore...
Alessio Mazzotti, Aaron Brancotti; Writer, Screenwriter, Director, UX, Autore...Associazione Digital Days
 
Mael Chiabrera, Software Developer; Viola Bongini, Digital Experience Designe...
Mael Chiabrera, Software Developer; Viola Bongini, Digital Experience Designe...Mael Chiabrera, Software Developer; Viola Bongini, Digital Experience Designe...
Mael Chiabrera, Software Developer; Viola Bongini, Digital Experience Designe...Associazione Digital Days
 

Kürzlich hochgeladen (9)

Alessandro Nasi, COO @Djungle Studio – “Cosa delegheresti alla copia di te st...
Alessandro Nasi, COO @Djungle Studio – “Cosa delegheresti alla copia di te st...Alessandro Nasi, COO @Djungle Studio – “Cosa delegheresti alla copia di te st...
Alessandro Nasi, COO @Djungle Studio – “Cosa delegheresti alla copia di te st...
 
Luigi Di Carlo, CEO & Founder @Evometrika srl – “Ruolo della computer vision ...
Luigi Di Carlo, CEO & Founder @Evometrika srl – “Ruolo della computer vision ...Luigi Di Carlo, CEO & Founder @Evometrika srl – “Ruolo della computer vision ...
Luigi Di Carlo, CEO & Founder @Evometrika srl – “Ruolo della computer vision ...
 
Federico Bottino, Lead Venture Builder – “Riflessioni sull’Innovazione: La Cu...
Federico Bottino, Lead Venture Builder – “Riflessioni sull’Innovazione: La Cu...Federico Bottino, Lead Venture Builder – “Riflessioni sull’Innovazione: La Cu...
Federico Bottino, Lead Venture Builder – “Riflessioni sull’Innovazione: La Cu...
 
Programma Biennale Tecnologia 2024 Torino
Programma Biennale Tecnologia 2024 TorinoProgramma Biennale Tecnologia 2024 Torino
Programma Biennale Tecnologia 2024 Torino
 
Daniele Lunassi, CEO & Head of Design @Eye Studios – “Creare prodotti e servi...
Daniele Lunassi, CEO & Head of Design @Eye Studios – “Creare prodotti e servi...Daniele Lunassi, CEO & Head of Design @Eye Studios – “Creare prodotti e servi...
Daniele Lunassi, CEO & Head of Design @Eye Studios – “Creare prodotti e servi...
 
Edoardo Di Pietro – “Virtual Influencer vs Umano: Rubiamo il lavoro all’AI”
Edoardo Di Pietro – “Virtual Influencer vs Umano: Rubiamo il lavoro all’AI”Edoardo Di Pietro – “Virtual Influencer vs Umano: Rubiamo il lavoro all’AI”
Edoardo Di Pietro – “Virtual Influencer vs Umano: Rubiamo il lavoro all’AI”
 
Gabriele Mittica, CEO @Corley Cloud – “Come creare un’azienda “nativa in clou...
Gabriele Mittica, CEO @Corley Cloud – “Come creare un’azienda “nativa in clou...Gabriele Mittica, CEO @Corley Cloud – “Come creare un’azienda “nativa in clou...
Gabriele Mittica, CEO @Corley Cloud – “Come creare un’azienda “nativa in clou...
 
Alessio Mazzotti, Aaron Brancotti; Writer, Screenwriter, Director, UX, Autore...
Alessio Mazzotti, Aaron Brancotti; Writer, Screenwriter, Director, UX, Autore...Alessio Mazzotti, Aaron Brancotti; Writer, Screenwriter, Director, UX, Autore...
Alessio Mazzotti, Aaron Brancotti; Writer, Screenwriter, Director, UX, Autore...
 
Mael Chiabrera, Software Developer; Viola Bongini, Digital Experience Designe...
Mael Chiabrera, Software Developer; Viola Bongini, Digital Experience Designe...Mael Chiabrera, Software Developer; Viola Bongini, Digital Experience Designe...
Mael Chiabrera, Software Developer; Viola Bongini, Digital Experience Designe...
 

Migrazione dei meccanismi di workflow di un sistema informativo assicurativo verso l'ambiente SQL Server e .NET

  • 1. UNIVERSITÀ DEGLI STUDI DI TRIESTE FACOLTÀ DI INGEGNERIA Corso di laurea triennale in Ingegneria Informatica Migrazione dei meccanismi di workflow di un sistema informativo assicurativo verso l’ambiente SQL Server e .NET Laureando: Relatore: Donato Clun Chiar.mo Prof. Leonardo Felician Anno accademico 2009 / 2010
  • 2.
  • 3. Sommario Capitolo 1: Introduzione ................................................................ 5 Il contenuto di questo documento ................................................................ 5 Luogo di svolgimento del lavoro documentato .............................................. 7 Dettagli della migrazione.............................................................................. 7 L‟ambiente sorgente ............................................................................................... 7 L‟ambiente obiettivo ............................................................................................... 8 Le ragioni della migrazione .......................................................................... 9 Precisazioni su questo documento ............................................................... 9 Capitolo 2: Il sistema informativo di OnLife ................................. 10 L‟ambiente di esecuzione prima della migrazione ....................................... 10 La base di dati attuale: concetti chiave dello schema dei dati ..................... 11 Prospect .............................................................................................................. 11 Partner ................................................................................................................ 11 Quotazione .......................................................................................................... 11 Carico contabile ................................................................................................... 12 Capitolo 3: Descrizione dei requisiti ............................................ 13 Vincoli non funzionali ................................................................................ 13 Affidabilità dell‟applicativo ................................................................................... 13 Prestazioni ........................................................................................................... 14 Descrizione delle funzioni .......................................................................... 15 Generazione di PDF ............................................................................................. 15 Caricamento delle nuove quotazioni e dei nuovi contratti ...................................... 16 Elaborazione delle mail in ingresso ....................................................................... 16 Sincronizzazione degli status ............................................................................... 17 Eliminazione dei dati sensibili .............................................................................. 17 Elaborazione rendiconti intermediari .................................................................... 17 Invio di E-mail ..................................................................................................... 18 Automazione di campagne di comunicazione ........................................................ 18 3
  • 4. Capitolo 4: Analisi dei problemi e definizione delle metodologie risolutive ................................................................... 20 Disponibilità del servizio e robustezza del software..................................... 20 Il problema .......................................................................................................... 20 La cause di possibili problemi .............................................................................. 22 Definizione di una metodologia risolutiva ............................................................. 22 Creazione di documenti PDF ...................................................................... 31 La soluzione ........................................................................................................ 32 Miglioramento delle prestazioni.................................................................. 32 Analisi della causa ............................................................................................... 33 Metodologia risolutiva .......................................................................................... 33 Capitolo 5: Implementazione nell‟ambiente target ....................... 35 Strategia di sviluppo software adottata ...................................................... 35 “Logger”.......... ........................................................................................... 36 Creazione della classe Logger ............................................................................... 37 Funzioni di accesso al database ................................................................. 41 Separazione tra thread principale e thread supervisore .............................. 42 Caricamento delle quotazioni ..................................................................... 43 Invio della posta ........................................................................................ 45 Lettura della posta..................................................................................... 50 Automazione di campagne di comunicazione ............................................. 51 Esecuzione della procedura dei rinnovi ...................................................... 52 Controllo RID respinti ................................................................................ 54 Eliminazione dei dati sensibili.................................................................... 55 Sincronizzazione degli status ..................................................................... 56 Elaborazione automatica degli incassi........................................................ 58 Elaborazione degli estratti conto ................................................................ 59 Capitolo 6: Conclusioni ............................................................... 62 Bibliografia........ ........................................................................... 63 4
  • 5. Capitolo 1: Introduzione In questa tesi vengono descritti gli obiettivi, analizzati i problemi affrontati e descritte le metodologie risolutive adottate, nell‟ambito del lavoro di migrazione della logica funzionale di OnLife, la prima polizza vita ad essere venduta direttamente ai clienti tramite internet. Il contenuto di questo documento Per definire chiaramente la parte del sistema informativo oggetto della migrazione descritta in questa tesi è necessaria una premessa. Per qualunque organizzazione disporre di un buon sistema informativo informatizzato non significa soltanto poter disporre delle informazioni necessarie in tempi rapidi, ma significa anche poter automatizzare parte dei processi operativi aziendali. In quest‟ottica un criterio lecito (che non considera come è realizzato il sistema, ma solo l‟aspetto operativo) secondo il quale è possibile distinguere diversi insiemi di funzionalità in un sistema informativo è il grado di intervento umano necessario alla raccolta ed elaborazione dei dati e, successivamente, alla produzione e distribuzione delle informazioni a chi (o a cosa) ne ha bisogno. Con il progredire della tecnologia di elaborazione automatica delle informazioni e la crescente disponibilità di questi strumenti, la possibilità di automatizzare parte dei processi ha infatti assunto un ruolo sempre più importante. In alcuni casi l‟interazione con gli utenti può essere ridotta a zero, come nel caso di un sistema che al verificarsi di una predeterminata condizione dia autonomamente luogo ad una sequenza di operazioni di elaborazione che 5
  • 6. producono delle informazioni successivamente inviate ad un altro sistema informatizzato, ad esempio tramite un web service. In un sistema informativo complesso è quindi possibile individuare un insieme di automatismi che hanno luogo con un elevato livello di autonomia rispetto alla necessità di input da parte dell‟utente (quindi che elaborano solamente dati provenienti dalla base di dati), e che non hanno inizio a causa di una interrogazione esterna, ma a causa del verificarsi di una predeterminata condizione. Tali automatismi possono essere definiti batch, termine comunemente utilizzato in informatica per descrivere l‟esecuzione di una serie di programmi senza intervento manuale. Nell‟ambito di un sistema informativo gli automatismi batch sono dunque il risultato dell‟automazione di una parte dei meccanismi di workflow operativo. In questo documento viene trattata proprio la migrazione, da un ambiente software già esistente e funzionante a un nuovo ambiente in grado di soddisfare meglio le necessità dell‟azienda, degli automatismi batch di OnLife, la prima polizza vita ad essere venduta direttamente ai clienti tramite internet in Italia. Nell‟ambito di questa tesi la definizione di automatismo batch non va intesa in maniera rigorosa, dato che sono stati sviluppati anche alcuni automatismi che vengono eseguiti su richiesta dell‟utente, tuttavia rimane evidente la contrapposizione con la parte del sistema informativo, molto più ricca di interfacce, che dipende dall‟utilizzo interattivo da parte di un utente. La migrazione effettuata non è stata di tipo 1:1, ma ha puntato a migliorare diversi aspetti del sistema e a soddisfare nuove necessità incontrate dall‟azienda. E‟ stato dunque necessario separare il lavoro in più parti:  Individuazione degli obiettivi  Analisi dei problemi  Elaborazione di metodologie risolutive  Fase di sviluppo software 6
  • 7. Luogo di svolgimento del lavoro documentato Messa sul mercato il 22 maggio 2007, OnLife è stata in Italia la prima polizza vita ad essere venduta ai clienti utilizzando internet come unico canale di vendita diretta, segnando un ulteriore passo nella direzione della vendita senza intermediari già intrapresa nel 1994 da Genertel. OnLife è un prodotto di L.A. Vita S.p.A. (controllata al 100% dal gruppo Allianz), società per cui è stato fatto il lavoro oggetto di questa tesi. Essendo stato utilizzato all‟interno dell‟azienda, il risultato di questa tesi ha dunque avuto utilità pratica. Dettagli della migrazione Di seguito viene data una visione d‟insieme delle caratteristiche del sistema informativo “sorgente” e del sistema informativo “obiettivo”. Ulteriori dettagli riguardanti il sistema informativo iniziale verranno specificate nel capitolo 2, mentre informazioni ancora più dettagliate si possono trovare in (Gorjan, 2006), anche se relative ad una versione con meno funzionalità rispetto a quella più recente, oggetto della migrazione. L’ambiente sorgente La disponibilità sul mercato di Onlife è arrivata solamente dopo la conclusione dello sviluppo di un sottosistema informativo specifico dedicato esclusivamente ad Onlife chiamato “DM2” che, affiancando il sistema informativo di L.A. Vita, ha fornito tutti gli strumenti necessari alla sua gestione. Da quanto nel 2007 DM2 è entrato in produzione ha subìto importanti modifiche che hanno aggiunto ulteriori funzionalità per gli utenti e ulteriori automatismi, di pari passo con l‟incremento del numero di polizze vendute. 7
  • 8. La migrazione della parte batch del sistema informativo DM2 di Onlife è l‟oggetto di questo documento. Le caratteristiche tecniche principali dell‟ultima versione di DM2 sono le seguenti:  L‟interfaccia è sviluppata in Access 2003, che grazie ai suoi strumenti integrati ha permesso ottenere rapidamente un sistema completo e funzionante.  Utilizza il DBMS Microsoft SQL Server 2005 (migrato dal Microsoft Jet di Access, che è stato il primo DBMS utilizzato)  Le “business rules” e i meccanismi di workflow sono programmati in VBA all‟interno di Access.  La produzione di documenti PDF avviene tramite una stampante virtuale che riceve l‟input da una istanza di Microsoft Word gestita dal codice VBA in Access. L’ambiente obiettivo Il nuovo ambiente software e gli strumenti di sviluppo utilizzati sono stati imposti dall‟azienda, che ha scelto Microsoft SQL Server 2005 come DBMS e Microsoft Visual Studio 2008, .NET Framework 3.5 e il linguaggio C# come strumenti di sviluppo software. L‟azienda ha anche fornito delle librerie da utilizzare obbligatoriamente per l‟apertura della connessione con il database e, se necessario, anche per sfruttare l‟infrastruttura di logging di Allianz. Non sono stati imposti ulteriori vincoli, ed è quindi stato quindi possibile valutare l‟utilizzo di librerie open source per realizzare alcune delle funzionalità richieste. 8
  • 9. Le ragioni della migrazione La migrazione dei meccanismi di workflow rientra in un più ampio progetto di migrazione dell‟intero sistema informativo DM2 deciso dall‟azienda. Le ragioni di questa scelta si possono riassumere nei seguenti punti chiave:  Il vecchio applicativo batch non rispettava gli standard aziendali, che prevedono l‟utilizzo di strumenti software completamente diversi.  A causa dell‟inadeguatezza del primo DBMS utilizzato (Microsoft Jet), ed a causa della necessità di migliorare le prestazioni dell‟interfaccia utente (passando da Access ad una nuova interfaccia web) era già stata effettuata la migrazione della base di dati verso SQL Server 2005. Si è dunque prefigurata la possibilità di sfruttare le funzionalità di questo DBMS per migliorare ulteriormente le prestazioni complessive del sistema, sia lato batch, sia lato interattivo. Precisazioni su questo documento Tutti i moduli software descritti in questo documento sono stati sviluppati dall‟autore, ad eccezione della libreria iTextSharp per la creazione di PDF, e la libreria fornita da Allianz per interfacciarsi con l‟architettura aziendale (nell‟ambito di questo progetto è stata utilizzata solo la funzione che recupera la connessione al database). Contenendo questo documento alcune parti del codice sorgente creato nell‟ambito di questo lavoro, in alcuni casi è stato necessario oscurare delle parti di codice per garantire la riservatezza delle informazioni riguardanti le misure di sicurezza adottate in Allianz. Tali modifiche saranno comunque evidenziate. 9
  • 10. Capitolo 2: Il sistema informativo di OnLife Questo breve capitolo fornisce le principali informazioni necessarie alla comprensione della struttura della parte del sistema informativo che è stata oggetto della migrazione descritta in questa tesi. L’ambiente di esecuzione prima della migrazione Il sistema informativo che permette la vendita e la gestione della polizza Onlife è suddiviso in due parti: il sistema informativo DM2, che è specifico di Onlife e che fornisce principalmente funzioni di CRM1 con i clienti (ex, attuali e potenziali), e il sistema informativo di L.A. Vita, che si occupa esclusivamente del workflow interno all‟azienda. A questi due elementi si aggiunge un altro server indipendente che è l‟unico ad essere visibile da internet. Il risultato è una struttura divisa nei seguenti elementi distinti:  Server raggiungibile da internet, con funzionalità di web server e mail server. Il web server esegue la web application che rende disponibile il questionario tramite il quale i potenziali clienti e i broker di assicurazione possono ricevere una quotazione. Il mail server si occupa della ricezione e dell‟invio dei messaggi di posta elettronica, utilizzando a questo scopo due tabelle (MailIn e MailOut) sul database interno che contengono i messaggi in ingresso ed in uscita.  Database server inaccessibile da internet, su cui è in esecuzione il DBMS Microsoft SQL Server 2005, e che contiene il database del sottosistema informativo DM2 specifico di Onlife. 1 CRM: Customer Relationship Management 10
  • 11. Sistemi host di L.A. Vita: la parte di sistema informativo che non è specifica di Onlife. I dati presenti su questi sistemi vengono esposti al sistema informativo DM2 con delle query pass through sul database server, mentre alcuni servizi più complessi, (come il calcolo del premio) vengono resi disponibili tramite un web service.  Server di automazione di Onlife su cui è in esecuzione il software (completamente sviluppato in Access in VBA) che esegue gli automatismi batch necessari. La base di dati attuale: concetti chiave dello schema dei dati Maggiori dettagli relativi alle singole entità facenti parte dello schema dei dati del sistema informativo DM2 (che è composto da 70 tabelle), verranno illustrati contestualmente alla definizione dei requisiti. È comunque opportuno introdurre alcuni concetti base relativi alle entità più ricorrenti nell‟ambito di questo lavoro ma poco “intuitive”. Prospect Dal punto di vista commerciale la caratteristica più importante di Onlife, dopo il prezzo di vendita, è la possibilità di fare un preventivo anonimo in un tempo brevissimo, chiedendo al potenziale cliente solamente i dati indispensabili al calcolo del premio. L‟individuo che interagisce con Onlife senza fornire le proprie generalità deve essere comunque identificato, e per questo scopo si utilizza l‟entità prospect che lo identifica tramite l‟indirizzo email, la data di nascita e il sesso. Partner Il partner è l‟individuo di cui si conoscono anche i dati anagrafici. È identificato dal codice fiscale. In questa categoria rientrato clienti, ex-clienti, dipendenti, fornitori e broker. Quotazione 11
  • 12. È il risultato della compilazione del questionario anonimo, che serve a dare al cliente una misura orientativa del premio da pagare qualora decida di stipulare una polizza. Carico contabile È un movimento contabile che può rappresentare una stipula, un rinnovo, o la variazione di una polizza. 12
  • 13. Capitolo 3: Descrizione dei requisiti In questo capitolo viene data una visione d‟insieme sulle funzionalità che è stato necessario realizzare, e sui vincoli non funzionali che hanno inciso sullo sviluppo del sistema. Vincoli non funzionali Ancor prima di entrare nel dettaglio dei requisiti funzionali richiesti è necessario evidenziare i requisiti non funzionali che hanno caratterizzato maggiormente tutto il lavoro di migrazione. Affidabilità dell’applicativo Come già evidenziato l‟obiettivo del lavoro svolto era quello di migrare un sistema batch, che per essere considerato tale doveva soddisfare il requisito di indipendenza dall‟interattività con l‟utente. Questo requisito fondamentale doveva essere rispettato sia nelle condizioni di utilizzo normale, sia, per quanto possibile, in condizioni eccezionali: va infatti considerato che l‟accesso “fisico” al calcolatore su cui l‟applicativo batch viene eseguito deve essere ridotto a rarissimi casi veramente eccezionali, anche perché all‟interno di realtà di dimensioni molto grandi come Allianz, è impensabile che non vengano poste restrizioni a questo proposito. A ciò si aggiunge il fatto che l‟allungarsi del tempo necessario ad ottenere l‟accesso al calcolatore in seguito al verificarsi di una condizione eccezionale (sia per raccogliere informazioni sul problema da risolvere, sia per attuare la 13
  • 14. soluzione) inevitabilmente allunga anche l‟MTTR2, ovvero il tempo medio necessario per ripristinare le funzionalità del sistema. In ambito assicurativo l‟indisponibilità di un certo servizio per un certo periodo di tempo può facilmente tradursi, più o meno direttamente, in una perdita di denaro, di conseguenza l‟MTTR è un indicatore chiave che è stato importante ridurre, adottando le opportune straregie di sviluppo. Da queste considerazioni si sono ricavati i seguenti requisiti:  Robustezza: il software deve comportarsi in maniera ragionevole anche rispetto a situazioni non previste, onde evitare che errori di lieve entità blocchino il servizio.  MTTR ridotto: in caso di errore deve essere possibile individuarne rapidamente la causa.  Affidabilità: è necessario minimizzare la percentuale di tempo in cui il servizio non è accessibile (è una conseguenza dei due punti precedenti). Prestazioni Uno dei motivi che hanno reso necessario questo lavoro di migrazione era la sicurezza di avere un buon margine per sostenere la futura crescita di Onlife. Pur non essendosi ancora verificata la situazione limite in cui il tempo di esecuzione di un ciclo di automatismi avesse superato l‟intervallo di tempo con cui tale ciclo di automatismi doveva essere avviato, bisogna considerare che la durata complessiva dell‟esecuzione di un ciclo ha comunque influenza sulla bontà del sistema. Infatti se è vero che alcuni degli automatismi devono essere eseguiti su base temporale precisa (ad esempio la generazione degli estratti conto per gli intermediari deve essere svolta una volta al mese), altri invece possono essere avviati con una frequenza arbitraria, ed una loro esecuzione più frequente può 2 MTTR: Mean Time To Restore 14
  • 15. portare degli effettivi vantaggi. Ad esempio nel sistema informativo DM2 l‟automatismo che elabora i messaggi di posta elettronica in ingresso potrebbe essere eseguito più frequentemente, riducendo così il tempo medio di risposta ed aumentando quindi il grado di soddisfazione del cliente. Descrizione delle funzioni I successivi requisiti presentati nel resto di questo capitolo sono tutti di tipo funzionale, e nella maggior parte dei casi sono stati dedotti dall‟analisi del codice sorgente del software che precedentemente eseguiva gli automatismi necessari. Una trattazione dettagliata di tutte le specifiche funzionali sarebbe eccessivamente lunga. Dato che lo scopo di questo documento è evidenziare le parti più originali del lavoro svolto, la maggior parte di essi sarà descritta in maniera sommaria. Generazione di PDF La generazione di documenti PDF con contenuti personalizzati (da inviare ad esempio ai clienti o agli intermediari) è una funzionalità chiave di DM2. Il vecchio sistema di generazione di PDF, basato su Microsoft Word e su una stampante virtuale in grado di salvare i documenti nel formato desiderato, era in grado di soddisfare le necessità di Onlife, ma la migrazione verso il nuovo ambiente software ha reso necessario un lavoro di riprogettazione. L‟azienda infatti ha deciso che nel nuovo ambiente di produzione non sarebbe stato installato né Microsoft Office né la stampante virtuale, che invece erano elementi indispensabili nella vecchia soluzione. Si è dunque presentata la necessità di trovare una soluzione alternativa a questo problema. 15
  • 16. A proposito della soluzione adottata prima della migrazione va detto che, pur essendo funzionale allo scopo, non offriva grandi prestazioni in termini di velocità di produzione dei documenti, ed è quindi presumibile che in futuro, con l‟aumentare del numero di clienti, si sarebbe rivelata inadeguata. Il lavoro di riprogettazione resosi necessario in seguito al cambiamento dell‟ambiente software ha dunque offerto la possibilità di sviluppare una soluzione che possa sostenere la crescita futura di Onlife. Caricamento delle nuove quotazioni e dei nuovi contratti Il compito del server web accessibile da internet è esclusivamente quello di raccogliere le nuove proposte e quotazioni richieste dai clienti o dai broker e salvarle sul proprio database, ma prima di poter essere inserite nel sistema DM2, queste informazioni devono essere normalizzate per rispettare la struttura dati del sistema informativo. La lettura, la normalizzazione e il salvataggio dei dati in DM2 sono a carico di questa funzionalità. Elaborazione delle mail in ingresso Il mail server è configurato per memorizzare tutti i messaggi di posta elettronica ricevuti all‟interno della tabella “MailIn” presente nel database del sistema DM2. Essendo Onlife un‟iniziativa basata su internet come unico canale di vendita e contatto, tutti i nuovi messaggi in ingresso vengono sottoposti ad un automatismo che li elabora, inviando delle risposte automatiche quando possibile e minimizzando lo sforzo necessario alla risposta manuale quando l‟elaborazione automatica non ha avuto esito positivo. 16
  • 17. Sincronizzazione degli status Come detto, il sistema informativo di Onlife è diviso in due parti: il sistema informativo DM2 che si occupa prevalentemente del CRM di Onlife, e il sistema informativo di L.A. Vita, che si occupa del workflow interno all‟azienda. Dato che questi due sistemi si basano su due database indipendenti, è indispensabile mantenere sincronizzati gli status dei contratti, dato che la mancata sincronizzazione potrebbe comportare gravi errori, come il mancato rendiconto di un contratto in vigore o il rendiconto di un contratto stornato. Di conseguenza una funzionalità richiesta è la sincronizzazione periodica degli status dei contratti, attuata accedendo al database di L.A. Vita tramite una query pass through e confrontando gli status dei contratti con i dati contenuti nel database di DM2, evidenziando i casi in cui è stata rilevata una differenza di status e procedendo con il necessario aggiornamento. Eliminazione dei dati sensibili L‟algoritmo di calcolo del premio assicurativo necessita di alcuni dati che secondo il Codice sulla protezione dei dati personali (D. Lgs. 196/2003) sono considerati “dati sensibili”. È necessario che tali dati vengano eliminati da tutte le proposte che non sono diventate polizze, dopo che sia trascorso un periodo di tempo prestabilito. Elaborazione rendiconti intermediari L‟obiettivo di questa funzione è la generazione degli estratti conto da inviare agli intermediari di vendita, e l‟invio delle disposizioni di pagamento a beneficio degli intermediari che hanno diritto a una provvigione. 17
  • 18. In entrambi i casi è necessario sfruttare la funzionalità di generazione di documenti PDF per inserire all‟interno dei rispettivi modelli di documento i dati estratti dal database. Invio di E-mail L‟invio di un messaggio di posta elettronica non consiste solamente nel suo inoltro al mail server opportuno (operazione a carico del mail server presente sul server internet di Onlife), ma richiede anche una serie di operazioni da svolgere all‟interno del sistema DM2. Il sistema informativo prevede che venga associato ad ogni Prospect o Partner ogni messaggio inviato o ricevuto che lo riguarda. In questo modo viene minimizzato lo sforzo necessario a gestire la comunicazione, essendo possibile avere per ogni soggetto lo storico completo dei messaggi scambiati. Automazione di campagne di comunicazione L‟obiettivo di questa funzione è automatizzare l‟invio di grandi moli di email consentendo la loro più libera ed assoluta personalizzazione secondo le diverse esigenze. Si tratta di una funzionalità importantissima di DM2, che viene utilizzata sia per l‟invio di campagne di marketing sia per l‟invio di comunicazioni di massa ai clienti. Si basa su dei modelli di messaggio standard, delle query che determinano gli insiemi dei destinatari, e delle “campagne” (delle coppie modello di messaggio / query dei destinatari). Lo schema dei dati alla base di queste funzionalità è il seguente: 18
  • 19. MessaggiTesti Workflow Query ID ID Messaggio ID standard Oggetto ID Query Descrizione Testo Standard StringaSQL ID Automatismo Allegato1 Destinatari Allegato2 SELECT Nome, Cognome, Email FROM Partner WkflAutomatismi WHERE ..... ID Codice ALTRE Nome Note TABELLE 19
  • 20. Capitolo 4: Analisi dei problemi e definizione delle metodologie risolutive In questo capitolo vengono analizzate in dettaglio le singole problematiche affrontate e vengono illustrate le metodologie risolutive adottate. Disponibilità del servizio e robustezza del software Nel capitolo 3 è stata messa in luce l‟importanza di produrre dei moduli software robusti (ovvero che gestiscano ragionevolmente situazioni impreviste) e facilmente riparabili. Vista la complessità del progetto è stato necessario studiare una strategia per affrontare il problema in maniera coerente durante tutto l‟arco del lavoro di sviluppo. Il problema Il problema affrontato può essere così riassunto: “Creare un applicativo batch che riesca a gestire opportunamente situazioni impreviste successe durante il funzionamento, minimizzando i casi in cui queste possano dar luogo alla sospensione del servizio, e agevolando il più possibile il lavoro di debug e ripristino.” Il vecchio sistema di automazione sviluppato in Microsoft Access era costituito da oltre 300 funzioni per un totale di circa 15 mila righe di codice. Oltre alla probabilità di bug dovuti a errata codifica del software (che 20
  • 21. comunque può essere ridotta testando approfonditamente i singoli moduli parallelamente al lavoro di codifica), bisogna considerare che il buon funzionamento di molti moduli dipende da fattori esterni non controllabili dal software, come il rispetto delle specifiche da parte dei dati in ingresso, oppure l„accessibilità di alcune risorse necessarie all‟esecuzione (database, file, ecc). In questo capitolo con il termine “disponibilità” si intende la percentuale di tempo in cui il servizio è correttamente funzionante. Tale quantità dipende da due valori fondamentali: MTBF e MTTR. L‟MTBF (Mean Time Between Failures) è il tempo che, in media, passa tra l‟istante in cui il sistema viene messo in funzione e l‟istante in cui il funzionamento viene interrotto a causa di un problema non previsto. L‟MTTR (Mean Time To Repair) è il tempo che, in media, è necessario per ripristinare le funzionalità del sistema in seguito ad un malfunzionamento. Stato del Istante in cui il servizio Istante in cui il servizio servizio viene ripristinato cessa di funzionare Funzionamento Tempo di Tempo tra due riparazione malfunzionamenti Riparazione Tempo La disponibilità media del servizio dipende dalle due quantità sopra descritte, secondo la relazione ������������������������ Disponibilità media = ������������������������ + ������������������������ dalla quale, ricordando che il risultato ideale è una disponibilità media del 100%, si ha immediata conferma di due fatti intuitivi:  Riducendo l‟MTTR si migliora la disponibilità media.  Aumentando l‟MTBF diminuisce l‟incidenza dell‟MTTR sulla disponibilità media. 21
  • 22. La cause di possibili problemi Come già accennato, una probabile fonte di anomalie di funzionamento è il mancato rispetto delle specifiche di programma da parte dei dati da elaborare. Di conseguenza, la possibilità che il sistema debba affrontare una situazione non prevista non risulta essere eliminabile neanche in seguito ad una accurata fase di test. Il sistema di automazione dell‟invio di messaggi di posta elettronica personalizzati, ad esempio, deve elaborare i tag contenuti in un testo standard caricato dal database, e deve eseguire una stringa SQL anch‟essa definita nel database. Se i tag contenuti nel messaggio non rispettano le specifiche oppure se la query SQL dà luogo ad un errore, il sistema si trova di fronte ad una situazione non prevista, che non può essere risolta in maniera interattiva con un utente, dato che l‟applicativo è batch. E‟ possibile individuare una stretta relazione tra la robustezza (termine con cui si indica la misura in cui il sistema si comporta in modo ragionevole in situazioni impreviste), MTTR e MTBF. Un sistema che risponde in maniera “ragionevole” ad una situazione inattesa infatti non si fermerà se la situazione di errore non è critica e anche in questa eventualità non si bloccherà senza averne dato opportuna segnalazione: nel primo caso avrà evitato di mettere fuori servizio l‟intero sistema per un errore di poco conto (aumentando quindi l‟MTBF), mentre nel secondo caso la segnalazione dell‟errore permetterà di reagire tempestivamente (riducendo l‟MTTR). Definizione di una metodologia risolutiva Il problema è stato diviso in tre punti, corrispondenti a tre parti della frase che lo sintetizza. Nei prossimi paragrafi ad ogni parte del problema verranno associati dei principi da rispettare. 22
  • 23. A) “Creare un applicativo batch che riesca a gestire opportunamente situazioni impreviste successe durante il normale funzionamento, minimizzando i casi in cui queste possano dar luogo a sospensione del servizio, e agevolando il più possibile il lavoro di debug/riparazione.”  Il software deve prendersi l‟onere di verificare i dati in input, in modo da riconoscere le situazioni anomale.  Ad ogni situazione di errore deve corrispondere una strategia di gestione opportuna. Ogni componente deve contenere il codice necessario per gestire autonomamente il problema. Se questo non è possibile, la gestione dell‟errore diventa di competenza del componente chiamante.  La gestione delle situazioni di errore deve essere progettata tenendo in mente l‟integrità dei dati e delle operazioni svolte. B) “Creare un applicativo batch che riesca a gestire opportunamente situazioni impreviste successe durante il normale funzionamento, minimizzando i casi in cui queste possano dar luogo a sospensione del servizio, e agevolando il più possibile il lavoro di debug/riparazione.”  E‟ necessario adottare una strategia di codifica che permetta di distinguere gli errori gravi che impediscono il proseguimento degli automatismi dagli errori non gravi che non ne pregiudicano il funzionamento.  L‟applicativo deve sospendere l‟esecuzione di un automatismo solamente nell‟eventualità di un errore definito “grave” secondo la distinzione del punto precedente. 23
  • 24. C) “Creare un applicativo batch che riesca a gestire opportunamente situazioni impreviste successe durante il normale funzionamento, minimizzando i casi in cui queste possano dar luogo a sospensione del servizio, e agevolando il più possibile il lavoro di debug/riparazione.”  Mai, in nessun caso, il software deve terminare in maniera anomala senza averne dato segnalazione.  Quando possibile le segnalazioni di errore devono essere memorizzate nel database del sistema DM2, in modo da essere immediatamente evidenziate e facilmente consultabili.  Per evitare di perdere informazioni potenzialmente molto utili, se non dovesse essere possibile collegarsi al database, le segnalazioni devono essere memorizzate su un altro supporto.  Deve essere possibile individuare immediatamente la gravità dell‟errore, in modo da dare subito la giusta priorità alla sua analisi.  Ogni segnalazione di errore deve dare il maggior numero possibile di informazioni significative necessarie all‟individuazione del problema e conseguente soluzione. Il meccanismo di lancio/gestione delle eccezioni contenuto nei più comuni linguaggi di programmazione correntemente utilizzati, è stato uno strumento che ha fornito delle funzionalità di base molto utili al raggiungimento dello scopo. Premessa: nel linguaggio C# le istanze della classe Exception contengono diverse proprietà, ma le seguenti sono ampiamente utilizzate nella soluzione del problema:  Message: è una stringa di testo che contiene la descrizione dell‟errore. 24
  • 25. InnerException: è un riferimento ad un‟altra eccezione.  StackTrace: contiene una rappresentazione testuale dello stack delle chiamate. La soluzione adottata si basa su una serie di norme da seguire durante la codifica dei moduli: 1. Il dettaglio di ogni errore deve essere salvato sul log (la definizione di “dettaglio dell‟errore” verrà data in seguito) 2. Il compito di salvare il dettaglio dell‟errore spetta sempre alla funzione che lo gestisce, e mai alla funzione che lo genera, a meno che generazione e gestione avvengano nella stessa funzione. 3. Il passaggio del controllo del flusso di esecuzione deve essere passato da una funzione ad un‟altra tramite eccezioni solo ed esclusivamente in caso di errore. 4. Quando una funzione riceve un‟eccezione che non è in grado di gestire, deve creare una nuova eccezione con tutti i dettagli del caso (punto 6). Se invece è in grado di gestire l‟eccezione, scrive il dettaglio sul log (per rispettare il punto 2). 5. Quando una funzione incontra una situazione anomala, se non è in grado di gestirla lancia un‟eccezione contenente tutti i dettagli del caso (punto 6). Se è in grado di gestirla, scrive il dettaglio sul log (per rispettare il punto 1). 6. Come già accennato nei punti 4 e 5, ogni funzione che incontra una situazione anomala o che riceve un‟eccezione da una funzione chiamata, e non è in grado di gestire la situazione, deve lanciare una eccezione così strutturata: la proprietà Message deve contenere una stringa che definisca l‟errore e la proprietà InnerException deve contenere un riferimento all‟eccezione eventualmente ricevuta (altrimenti deve essere null). Il risultato è che ogni errore genera una lista concatenata di eccezioni, rappresentata nella seguente figura. 25
  • 26. 7. Il “dettaglio dell‟errore” che deve essere salvato sul log è composto dai seguenti elementi: o Un messaggio definito dalla funzione che ha gestito l‟errore, che indica di che errore si tratta, in che contesto è avvenuto, e che implicazioni ha avuto. o La sequenza dei messaggi di errore specifici presi da ogni elemento della lista concatenata di eccezioni. o Lo stack delle chiamate preso dall‟eccezione alla fine della catena. o Un indicatore della gravità dell‟errore, determinato dalla funzione che gestisce l‟errore. 8. Per evitare che un loop infinito possa bloccare il servizio per un tempo indeterminato, l‟esecuzione degli automatismi deve avvenire in un thread separato, detto “principale”. Un altro thread, detto “supervisore” si occupa di segnalare l‟eccessivo prolungarsi dell‟esecuzione di un automatismo, ed ha la possibilità di interrompere la sua esecuzione (solo in casi estremi, dopo un‟attesa molto lunga). 26
  • 27. 9. Normalmente i dettagli di ogni errore devono essere salvati sul database. Se questo non è disponibile, devono essere salvati su un file di log. Adottando le norme descritte, il codice avrà le seguenti caratteristiche:  Durante la codifica dei moduli software per qualunque situazione anomala si è liberi di programmare il lancio di un‟eccezione. La gravità non sarà intrinseca dell‟errore in sé, ma dipenderà dal livello a cui viene bloccata. Questo fatto è coerente con l‟idea intuitiva che un errore provocato, ad esempio, durante l‟invio di una singola email può essere considerato non critico nell‟ambito di una campagna pubblicitaria, mentre è senz‟altro critico nell‟ambito dell‟invio di un ordine di pagamento. Questa caratteristica affronta i punti A e B del problema.  L‟unica condizione in cui termina l‟esecuzione di un automatismo si ottiene quando l‟eccezione risale fino al thread principale; tale condizione indica che il software ha incontrato una situazione critica che non può essere risolta. Questa caratteristica affronta il punto B del problema.  Il log conterrà molte informazioni utili all‟individuazione dell‟errore e delle cause che lo hanno scatenato, e conterrà un indicatore della gravità dell‟errore rilevato. In questo modo il tempo necessario a ripristinare il sistema sarà inferiore, e sarà possibile agire tempestivamente in caso di un errore grave. Questa caratteristica affronta il punto C del problema.  L‟adozione di una metodologia di gestione degli errori coerente in tutto il codice ne facilita la lettura e la manutenzione. Una volta compresa questa strategia di base, risulta molto facile aggiungere 27
  • 28. la gestione di nuove situazioni di errore. Questa caratteristica affronta il punto C del problema. Nelle prossime pagine vi sono alcuni esempi che illustrano l‟utilizzo pratico della metodologia applicata. 28
  • 29. 29
  • 30. Esempio pratico di log: Rilevanza dell’errore: 25 Messaggio di errore: Errore durante l’esecuzione del workflow di apertura. Impossibile Lanciare la campagna con ID = 23 Impossibile continuare. DebugInfo: Dettagli eccezione: - lanciaCampagna(23, 74, 0, ""): errore durante l’invio del messaggio! - inviaMessaggioStandard(23,”dest@email.it”,...): errore durante il mail merge. - EseguiMailMerge(“oggetto”,...): tag NUMERO_CONTRATTO non trovato. Stack delle chiamate: at OnLifeBatch.Onlife.lanciaCampagna([parametri]) in Campagne.cs:line 246 at OnLifeBatch.Onlife.inviaMessaggioStandard([parametri]) in EMAIL – Funzioni principali.cs:line 453 at OnLifeBatch.Onlife.EseguiMailMerge([parametri]) in EMAIL – Merge.cs: line 187 30
  • 31. Dall‟esempio di log riportato si deducono immediatamente le seguenti informazioni:  Si sta avendo a che fare con un errore grave che richiede immediata attenzione (nell‟implementazione di Onlife, una rilevanza maggiore di 19 indica un problema critico)  L‟errore è avvenuto durante il lancio di una campagna, nell‟ambito del workflow di inizio giornata.  L‟errore riguarda il mail merge del messaggio standard con ID uguale a 23.  L‟errore riguarda il mail merge dell‟oggetto del messaggio. È stato trovato un tag non presente nella query dei destinatari.  Se dovesse essere un bug, sono immediatamente disponibili le righe del codice sorgente in cui ha avuto luogo l‟errore. Creazione di documenti PDF La generazione di PDF personalizzati è un problema che è stato necessario affrontare rispettando i nuovi standard aziendali imposti da Allianz per il nuovo ambiente di produzione. Il sistema di generazione dei PDF deve soddisfare i seguenti requisiti:  I documenti devono essere prodotti a partire da dei modelli che ne impostano il contenuto e ne contengono la parte statica.  All‟interno dei modelli di documento devono essere presenti delle aree personalizzabili, in cui verranno inserite le parti dinamiche.  Non può essere utilizzato Microsoft Office o una stampante virtuale, perché non rispetterebbe gli standard aziendali.  La velocità di produzione deve essere maggiore o uguale a quella della soluzione precedentemente adottata. 31
  • 32. La soluzione Inizialmente si è ipotizzato l‟utilizzo di OpenOffice, una soluzione open source che offre anche delle API utilizzabili per l‟automazione. I primi test hanno però messo in luce seri problemi quando venivano creati molti documenti nell‟arco di una sessione di automatismi: a causa di un evidente memory leak3, il consumo di memoria dell‟applicativo batch cresceva notevolmente ad ogni singolo documento creato, e dopo un certo numero di documenti prodotti, il software cominciava a produrre documenti corrotti. Questo problema unito anche alla scarsa documentazione di queste API ha portato all‟abbandono di questa soluzione. La seconda alternativa analizzata è stata l‟utilizzo delle librerie open source iTextSharp, delle librerie che permettono di creare dei documenti PDF ex novo, e permettono anche di modificare dei form PDF (analoghi ai classici PDF ma contenenti dei campi di testo in cui è possibile scrivere) creati ad esempio con OpenOffice, e salvarli come PDF classici. I test di generazione di PDF fatti su questa soluzione hanno dato risultati al di sopra delle aspettative: nell‟ambito di un test di generazione di documenti personalizzati di una pagina, è stata raggiunga la velocità di circa 50 documenti al secondo, e i documenti prodotti non hanno mostrato difetti come poteva accadere con la prima soluzione. Miglioramento delle prestazioni Come è già stato sottolineato, la velocità di esecuzione del vecchio sistema batch era considerata soddisfacente, di conseguenza il problema delle prestazioni deve essere considerato di importanza decisamente inferiore rispetto agli altri due già affrontati. Tuttavia per garantire un buon margine di crescita futura, al solo costo del rispetto di qualche accorgimento durante la fase di sviluppo sviluppo, è 3 Un particolare tipo di consumo non voluto di memoria dovuto alla mancata deallocazione di variabili/dati non più utilizzati da parte dei processi. 32
  • 33. stato ritenuto opportuno porsi il problema di come raggiungere una migliore efficienza. In questa sezione viene dunque studiata una metodologia da utilizzare per velocizzare l‟esecuzione delle operazioni batch. Analisi della causa Dato che la potenza di calcolo degli attuali calcolatori si misura in decine di miliardi di istruzioni al secondo, l‟anello debole su cui si è concentrata l‟attenzione è l‟accesso ai dati. Il fatto che l‟applicativo batch e il DBMS vengano eseguiti su due calcolatori diversi inevitabilmente introduce un tempo di latenza ogni volta che viene effettuata un‟interrogazione al database di DM2. L‟ordine di grandezza della somma del tempo necessario affinché l‟interrogazione arrivi al DB server e del tempo necessario affinché la risposta partita dal DB server sia resa disponibile all‟applicativo batch, generalmente è nell‟ordine di diversi millisecondi; di conseguenza nell‟ambiente di Onlife tale tempo è sicuramente superiore a 8 ms, dato che questo è il tempo misurato con il comando ping, che misura il Round Trip Time con pacchetti di dimensioni molto ridotte. Se si considera che l‟automatismo di caricamento delle quotazioni esegue svariate decine di interrogazioni per ogni singola quotazione che deve essere elaborata, risulta evidente che il numero di interrogazioni è un fattore da tenere sotto controllo. Metodologia risolutiva  Non ripetere interrogazioni inutili. Nel vecchio applicativo capitava che una stessa interrogazione venisse eseguita più volte all‟interno di un ciclo. Le interrogazioni ridondanti vanno assolutamente evitate, facendo solo una interrogazione e salvando il dato in una variabile. 33
  • 34. Accorpare più interrogazioni in una sola. Sapendo che un algoritmo richiede sicuramente un certo insieme di dati, tali dati vanno ricavati subito tutti in un‟unica interrogazione.  Utilizzare JOIN e (NOT) IN per unire più query. Nel vecchio applicativo capitava di fare in più query successive esattamente quello che avrebbe fatto una query che utilizza dei JOIN.  Utilizzare stored procedure e stored functions per spostare parte della logica all‟interno del database. Questi elementi vengono eseguiti direttamente dal DBMS, e quindi permettono di ridurre ulteriormente il numero di interrogazioni necessarie. 34
  • 35. Capitolo 5: Implementazione nell‟ambiente target In questo capitolo viene affrontato il problema dell‟implementazione delle funzionalità richieste. In particolare: l‟applicazione delle metodologie elaborate nel capitolo precedente, la definizione della strategia di sviluppo software, e la descrizione del lavoro svolto, mostrando anche qualche parte del codice prodotto. Strategia di sviluppo software adottata Lo sviluppo dell‟applicativo è stato diviso nelle seguenti fasi:  Sviluppo delle funzioni di base di accesso al database e logging.  Suddivisione del progetto in diversi settori funzionali, evidenziando i moduli che sarebbe stato necessario programmare per primi a causa della presenza di altri moduli che da essi dipendono.  Programmazione del singolo settore funzionale, seguendo la strategia di sviluppo che sarà indicata in seguito. Con il termine “settore funzionale” si intende l‟insieme di funzioni necessarie allo sviluppo di una particolare funzionalità. Questo termine ha particolarmente senso in questo contesto perché l‟insieme delle funzioni automatizzate di Onlife è suddivisibile in diversi insiemi che tra loro hanno un accoppiamento (ovvero dati e funzioni comuni) estremamente basso. Ad esempio l‟elaborazione degli estratti conto ed il caricamento delle quotazioni 35
  • 36. condividono un insieme di funzioni sostanzialmente limitato alle sole funzioni di accesso al database e di logging. Nell‟ambito di un singolo settore funzionale, la strategia di sviluppo adottata non è ben inquadrabile nei classici schemi top-down o botton-up, ma è stata una strategia di tipo misto. Inizialmente tutti i problemi più complessi che sono stati affrontati, sono stati prima suddivisi in elementi di più facile gestione, applicando quindi una strategia top-down, mentre successivamente è stata adottata una strategia finalizzata al permettere un precoce debug delle funzioni create. “Logger” Un elemento fondamentale per rispettare la metodologia indicata nel precedente capitolo, è il sistema che permette di salvare il log degli errori o di altre informazioni che si ritiene opportuno salvare. Per questa funzionalità è stato necessario modificare la struttura della tabella Log già presente nel vecchio sistema informativo, ed utilizzata per scopi analoghi. La vecchia tabella prevedeva un campo ID determinato da un contatore, un timestamp per indicare l‟istante in cui è stato aggiunto l‟elemento, e un campo di testo contenente la descrizione dell‟errore o il messaggio informativo. Per poter memorizzare separatamente anche le informazioni di debug (sequenza dei messaggi delle eccezioni e stack delle chiamate in forma testuale) e la rilevanza dell‟errore, si è deciso di aggiungervi due campi: un campo di testo per le informazioni di debug, e un valore intero per la rilevanza. Il significato del valore di rilevanza è così stabilito:  Valori da 0 a 9 – Non indicano una situazione di errore ma hanno contenuto puramente informativo. Ad esempio possono indicare il 36
  • 37. numero di email inviate in seguito all‟esecuzione del workflow di inizio giornata.  Valori da 10 a 19 – Indicano una situazione di errore che è stata gestita con successo, ma essendo una situazione anomala richiede l‟attenzione da parte di un responsabile. Ad esempio se durante l‟invio di una campagna di email, il campo Email di un record restituito dalla query dei destinatari è NULL, quel record sarà semplicemente saltato. Non avrebbe senso interrompere il lancio della campagna a causa di un solo errore, ma siccome potrebbe essere il sintomo di una query dei destinatari da rivedere, è opportuno che venga salvato un messaggio di errore.  Valori da 20 a 29 – Indicano una situazione di errore grave, che ha provocato il blocco di un automatismo e che richiede un intervento tempestivo. Ad esempio se all‟inizio dell‟automatismo di rinnovo, la query che individua i carichi contabili da rinnovare produce un errore, la procedura di rinnovo non può continuare. Creazione della classe Logger Per avere garanzia del fatto che esista solamente un‟unica istanza della classe Logger, è stato utilizzato il design pattern Singleton (Vlissides, et al., 1994). Questo design pattern prevede che la classe Logger abbia un solo costruttore che ha la caratteristica di essere privato; in questo modo non è possibile creare direttamente una nuova istanza della classe. Per far si che possa comunque esistere un‟istanza, la classe fornisce una proprietà statica di sola lettura, a cui è associato un metodo get che restituisce il riferimento all‟istanza della classe. Questo design pattern rende tra l‟altro possibile la lazy initialization (inizializzazione “pigra”), ovvero la creazione dell‟istanza della classe solamente al momento della prima chiamata. Di seguito viene riportata l‟implementazione della classe Logger: 37
  • 38. public sealed class Logger { static Logger istanza = null; // la variabile statica privata che // contiene l'unica istanza di Logger // è necessario evitare l'esecuzione concorrente di alcune parti // critiche quindi dichiaro un oggetto per il lock static readonly object loglock = new object(); DbConnection LogConnection; StreamWriter logTxt; Logger() //costruttore privato { LogConnection = [codice necessario all'utilizzo dei sistemi di sicurezza di Allianz] logTxt = new StreamWriter(Config.getSetting(settingsNames.PercorsoLog), false); logTxt.WriteLine("----- Log dei messaggi che non è stato possibile memorizzare sul database. -----"); } public static Logger Istanza // La proprietà statica di sola lettura // che fornisce accesso all'unica istanza { get { lock (loglock) { if (istanza == null) // la classe viene istanziata { // al primo utilizzo istanza = new Logger(); } return istanza; } } } ... funzioni della classe Logger ... } Dal codice sorgente si nota anche che sono state prese le precauzioni necessarie per gestire l‟esecuzione concorrente di più richieste dell‟istanza della classe, dato che entrambi i thread (principale e supervisore) ne fanno uso. 38
  • 39. Riprendendo quanto definito nel capitolo 4, l‟insieme dei dettagli di ogni errore è costituito da:  Un messaggio definito dalla funzione che ha gestito l‟errore, che indica di che errore si tratta, in che contesto è avvenuto, e che implicazioni ha avuto.  La sequenza dei messaggi di errore specifici presi da ogni elemento della lista concatenata di eccezioni.  Lo stack delle chiamate preso dall‟eccezione alla fine della catena.  Un indicatore della gravità dell‟errore, determinato dalla funzione che gestisce l‟errore. Il compito della classe Logger è quello di scrivere queste informazioni sul log. Di seguito viene illustrata l‟implementazione delle funzioni necessarie. Avendo a che fare con una lista concatenata di eccezioni, è necessario individuare la prima eccezione che è stata lanciata, ovvero l‟ultima nella catena delle eccezioni. Per far questo è stata sviluppata la semplice funzione ricorsiva getInnermostException: static Exception getInnermostException(Exception ex) { if (ex.InnerException == null) return ex; else return getInnermostException(ex.InnerException); } Dalla lista concatenata di eccezioni è necessario ricavare anche la sequenza dei messaggi presi da ogni eccezione della lista. Questo compito viene svolto dalla funzione ricorsiva dettagliEccezione: public static string dettagliEccezione(Exception ex) { if (ex.InnerException != null) return ex.TargetSite.Name + ": " + ex.Message + "rn" + dettagliEccezione(ex.InnerException); else return ex.TargetSite.Name + ": " + ex.Message; } 39
  • 40. La memorizzazione nel database avviene tramite la chiamata di una stored procedure. Il codice utilizzato per richiamarla è il seguente: void StoredProcedureAddToLog(dbInputParam[] parametri) { DbCommand comando = LogConnection.CreateCommand(); if (parametri.GetLength(0) > 0) aggiungiParametriAComando(parametri, comando); comando.CommandType = CommandType.StoredProcedure; comando.CommandText = "[dbo].[addToLog]"; comando.ExecuteNonQuery(); } void aggiungiParametriAComando(dbInputParam[] parametri, DbCommand comando) { foreach (dbInputParam parametro in parametri) { DbParameter paramDaAggiungere = comando.CreateParameter(); paramDaAggiungere.ParameterName = parametro.nome; paramDaAggiungere.Direction = ParameterDirection.Input; paramDaAggiungere.DbType = parametro.tipo; paramDaAggiungere.Value = parametro.valore; comando.Parameters.Add(paramDaAggiungere); } } L‟insieme di funzioni fin‟ora indicate è stato infine utilizzato per creare la funzione addToLog, che riceve le informazioni necessarie dalle funzioni che hanno la necessità di loggare qualcosa, e scrive il tutto sulla tabella Log del database (se il database è accessibile) oppure sul file di log (se il database non è accessibile). public void addToLog(string messaggio, Exception ex, Int16 rilevanza) { lock (loglock) { string debugInfo; //se viene passata un'eccezione, ne scrivo i dettagli. Altrimenti scrivo solo lo stack delle chiamate. if (ex != null) { debugInfo = "Dettagli eccezione:rn" + Onlife.dettagliEccezione(ex); debugInfo += "rnrnStack delle chiamate:rn" + getInnermostException(ex).StackTrace.ToString(); } 40
  • 41. else { debugInfo = "Stack delle chiamate:rn" + Environment.StackTrace.ToString(); } if (LogConnection.State == ConnectionState.Open) { try { dbInputParam[] parametri = new dbInputParam[3]; parametri[0] = new dbInputParam("@messaggio", DbType.String, messaggio); parametri[1] = new dbInputParam("@debugInfo", DbType.String, debugInfo); parametri[2] = new dbInputParam("@rilevanza", DbType.Int16, rilevanza); StoredProcedureAddToLog(parametri); } catch { logTxt.WriteLine(messaggio + " -- Call stack:"); logTxt.WriteLine(debugInfo); logTxt.WriteLine("================================================ rn"); } } else { logTxt.WriteLine(messaggio + " -- Call stack:"); logTxt.WriteLine(debugInfo); logTxt.WriteLine("================================================ rn"); } } } Funzioni di accesso al database Un altro elemento fondamentale che è stato preparato durante la prima fase dello sviluppo dell‟applicativo batch, è l‟insieme delle funzioni di accesso al database, essendo questo un elemento indispensabile per tutti gli automatismi. Dato che il batch resta in esecuzione solamente fin quando ci sono automatismi da eseguire, e dato che tutti gli automatismi necessitano di accesso al database, ne consegue che la necessità di una connessione al database accompagna tutta l‟esecuzione del batch. Per questa ragione si è 41
  • 42. scelto di inserire nella classe Onlife una variabile statica contenente il riferimento alla connessione al database. La connessione verrà aperta immediatamente dopo l‟inizio dell‟esecuzione, e verrà chiusa immediatamente prima della fine. Oltre alle funzioni di apertura, chiusura e verifica della connessione, è stato creato un ampio insieme di funzioni e di strutture dati, volte a facilitare la scrittura del resto del codice. Separazione tra thread principale e thread supervisore Nel capitolo precedente si è deciso che per evitare che un loop infinito possa bloccare il servizio per un tempo indeterminato, l‟esecuzione degli automatismi deve avvenire in un thread separato, detto principale, mentre un altro thread, detto supervisore si occupa di segnalare l‟eccessivo prolungarsi dell‟esecuzione di un automatismo. Questa separazione avviene nella procedura principale, dopo che è stata caricata la lista di automatismi da eseguire: static void Main(string[] args) { if (Onlife.openDB() == false) { Logger.Istanza.addToLog("Impossibile collegarsi al database.", 25); Logger.Istanza.Chiudi(); return; } Config.load(); Onlife.loadIntMasterData(); // Dichiaro il thread che eseguirà gli automatismi necessari. // Onlife.eseguiFunzione(nomeAutomatismo) è la funzione principale da cui parte il thread. Thread threadAutomatismo; DateTime istanteInizioEsecuzione; string[] funzioniDaEseguire; bool dacmd; if (args.Length > 0) { 42
  • 43. funzioniDaEseguire = new string[1]; funzioniDaEseguire[0] = args[0]; dacmd = true; } else { funzioniDaEseguire = Onlife.getListaAutomatismiDaEseguire(); dacmd = false; } foreach (string nomeFunzione in funzioniDaEseguire) { threadAutomatismo = new Thread(new ParameterizedThreadStart(Onlife.eseguiFunzione)); istanteInizioEsecuzione = DateTime.Now; Console.WriteLine("Eseguo " + nomeFunzione); threadAutomatismo.Start(nomeFunzione); TimeSpan tempoEsecuzione; while (true) { Thread.Sleep(1000); if (threadAutomatismo.ThreadState == ThreadState.Stopped) break; Console.Write('.'); tempoEsecuzione = DateTime.Now.Subtract(istanteInizioEsecuzione); if (tempoEsecuzione.Seconds == 0 & tempoEsecuzione.Minutes > 0) Logger.Istanza.addToLog("Sto eseguendo l'automatismo " + nomeFunzione + " da " + tempoEsecuzione.Minutes + " minuti", 4); //L'attuale implementazione non prevede la terminazione forzata dopo un tempo limite } . . . . . [codice che verifica l’esito della funzione chiamata] . . . . . } Console.WriteLine(); Onlife.closeDB(); Console.WriteLine("Esecuzione terminata."); Logger.Istanza.Chiudi(); } Caricamento delle quotazioni 43
  • 44. In questa particolare funzione l‟accesso ai dati del server su cui sono presenti le quotazioni avviene tramite una query pass through definita in SQL Server. Il processo di caricamento delle nuove quotazioni può essere semplificato e sintetizzato in questa sequenza di azioni: 1. Recupera una quotazione da elaborare dalla query pass through. Se non ci sono più quotazioni da elaborare, termina l‟esecuzione. 2. Salva i dati della nuova quotazione/preventivo nel sistema DM2. 3. Elabora il canale di vendita. 4. Se non è una proposta o un contratto: salva il Prospect, salva l‟indirizzo email, associa l‟indirizzo al Prospect, torna al punto 1. 5. Salva i dati della proposta o del contratto 6. Se il codice fiscale esiste già in DM2, aggiorna i dati del partner, altrimenti aggiungi un nuovo Partner. 7. Salva l‟email e associala al Partner. 8. Se l‟email era già associata ad un Prospect, promuovi il Prospect a Partner. 9. Torna al punto 1. Questa funzionalità opera esclusivamente su dati provenienti dal database, di conseguenza per seguire la metodologia di miglioramento delle prestazioni indicata nel capitolo precedente, è stato deciso di realizzarla completamente tramite stored procedure. La complessità dell‟algoritmo ha reso indispensabile l‟utilizzo di un cursore per leggere in sequenza i dati dalla query pass through Query_Onlife_Quotazioni ed eseguire la sequenza di operazioni per ogni record letto. 44
  • 45. Un esempio di ottimizzazione che è stato possibile fare su questa funzione è il seguente: precedentemente la funzione di ricaricamento delle quotazioni che non è stato possibile caricare in un primo momento, doveva eseguire i seguenti passaggi:  Veniva letto da LogQuotazioni l‟ID di una quotazione da ricaricare  Tale id veniva passato alla funzione di caricamento tramite un parametro  La funzione eseguiva una query pass through verso il database del server internet, per recuperare la quotazione.  Se c‟erano altre quotazioni da ricaricare, si ricominciava. Tale problema è stato velocizzato notevolmente con una semplice modifica della query di ricaricamento delle quotazioni: SELECT CAST(NUMERO_QUOTAZIONE AS INT) AS NUMQUOT, DATA_QUOTAZIONE, TIPO_RECORD, ID_SESSIONE, E_MAIL, SESSO, DATA_NASCITA, CAPITALE, COD_FUMO, CAP, PREMIO, DA_DOVE_CONOSCIUTI, TIPO_RISCHIO, FLAG_PROCAM, CANALE_VENDITA, SUB_CANALE_VENDITA, ID_CONTRATTO, FLAG_PRIV_COMM FROM Query_Onlife_Quotazioni WHERE CAST(NUMERO_QUOTAZIONE AS INT) IN (SELECT DISTINCT IDQuotazione FROM logQuotazioni) La parte evidenziata individua tutte le quotazioni che è necessario ricaricare, che quindi verranno elaborate tramite una sola query. Ora è sufficiente chiamare la funzione di caricamento delle quotazioni passando un apposito parametro ricaricaLogQuotazioni settato a True, per ottenere con una sola esecuzione della stored procedure, ciò che prima ne richiedeva una per ogni quotazione. Invio della posta 45
  • 46. La funzionalità di invio di messaggi di posta elettronica, richiede che venga eseguito un certo numero di operazioni sul database di DM2, al fine di memorizzare ogni messaggio inviato nello storico del Prospect o al Partner destinatario. Tutte le funzioni relative alla posta elettronica in generale devono eseguire operazioni anche i file allegati: questi elementi non sono memorizzati nel database ma nel filesystem del sistema, quindi è stato necessario cercare una soluzione che minimizzi il numero di richieste al database ma contemporaneamente permetta di gestire i file. La prima opzione presa in considerazione è stata l‟utilizzo del supporto agli assembly CLR offerto da SQL Server. In questo modo le operazioni sui files sarebbero state realizzate in dei moduli programmati in C# inseriti direttamente nel DBMS, e richiamabili da stored procedure. Le restrizioni di sicurezza imposte da Allianz hanno però obbligato l‟abbandono di questa strada. È stato necessario percorrere l‟unica alternativa rimanente: tutte le funzioni che avevano a che fare con gli allegati sono state programmante all‟interno del file batch, mentre le restanti funzioni che operavano solo sul database sono stare realizzate tramite stored procedure. Un esempio di funzione realizzata tramite stored procedure è la seguente: CREATE PROCEDURE [dbo].[logComunication] @idEmail int, @direzionePosta int, @tipoPosta int, @Mittente varchar(200), @IDEmailMittente int, @Destinatario varchar(200), @idEmailDestinatario int, @Oggetto varchar(200), @Testo varchar(max), @idCampagna int = NULL, @numAllegati int = 0, @DataInvio datetime = NULL, @DataRicezione datetime = NULL, @RisultatoInvio int = 0, @WebCons int = NULL, @IdCasella int = NULL, @flg_errore bit = 0 46
  • 47. AS BEGIN SET NOCOUNT ON; DECLARE @PA_direzione AS nvarchar(3) DECLARE @PA_letta AS bit DECLARE @PA_idposta AS int DECLARE @PA_idPartnerTeam AS int IF @direzionePosta = 1 SET @PA_direzione = 'IN' ELSE IF @direzionePosta = 2 SET @PA_direzione = 'OUT' ELSE IF @direzionePosta = 0 SET @PA_direzione = NULL IF @direzionePosta = 2 OR @direzionePosta = 0 SET @PA_letta = 1 ELSE SET @PA_letta = 0 EXEC @PA_idposta = [dbo].LogPosta @direzionePosta, @tipoPosta, @Mittente, @IDEmailMittente, @Destinatario, @idEmailDestinatario, @Oggetto, @Testo, @numAllegati, @DataInvio, @DataRicezione, @IdCasella, @flg_errore SET @PA_idPartnerTeam = 0 INSERT INTO PostaArchivio (IDMail, Direzione, IdPosta, IDCampagna, "Letta?", RisultatoInvio, IDWebCons, IDPartnerTeam) VALUES (@idEmail, @PA_direzione, @PA_idposta, @idCampagna, @PA_letta, @RisultatoInvio, @WebCons, @PA_idPartnerTeam) RETURN SCOPE_IDENTITY() END Mentre un esempio di funzione realizzata all‟interno dell‟applicativo batch, che esegue operazioni sui files, è la funzione AttachAttachmentsToMailOut, che riceve l‟ID del messaggio e i percorsi dei file da allegare, e copia gli allegati da inviare nella apposita cartella degli allegati in uscita. static void AttachAttachmentsToMailOut(int idEmail, string[] allegati) { string errInfo ="AttachAttachmentsToMailOut(" + idEmail + ", [array allegati])"; FileInfo allegato; FileInfo destfile; FileInfo backup; string destFileStr; string backupStr; int n = 0; int i = 0; foreach (string allegatoStr in allegati) { n++; 47
  • 48. allegato = new FileInfo(allegatoStr); if (!allegato.Exists) { string msg = "AttachAttachmentsToMailOut: ERRORE! L'allegato " + allegatoStr + " non esiste!"; Logger.Istanza.addToLog(msg, 15); throw new System.Exception("AttachAttachmentsToMailOut: ERRORE! L'allegato " + allegatoStr + " non esiste!"); } destFileStr = IM_DirectoryAllegatiOUT + getNomeAllegatoForIT(idEmail, n) + allegato.Extension; destfile = new FileInfo(destFileStr); if (destfile.Exists) { //è già presente un file con lo stesso nome. lo rinomino. backupStr = IM_DirectoryAllegatiOUT + getNomeAllegatoForIT(idEmail, n) + "_backup" + allegato.Extension; backup = new FileInfo(backupStr); while (backup.Exists) { backupStr = IM_DirectoryAllegatiOUT + getNomeAllegatoForIT(idEmail, n) + "_backup" + i + allegato.Extension; backup = new FileInfo(backupStr); i++; } i = 0; destfile.MoveTo(backupStr); Logger.Istanza.addToLog("Attenzione: stranamente, il file di destinazione " + destFileStr + " esisteva già. È stato rinominato in " + backupStr + " prima di salvare il nuovo file.", 15); } allegato.CopyTo(destFileStr); } // foreach... } Per migliorare la manutenibilità del codice scritto è stata creata una classe EmailOut; le istanze della quale rappresentano messaggi da inviare tramite l‟apposita funzione InviaEmail. public class EmailOut { public SqlString destinatario; public SqlString oggetto; public SqlString testo; public bool daSpedire; public string[] allegati = { }; /// <summary> Default = NULL </summary> public SqlInt32 webcons; 48
  • 49. /// <summary> Default = NULL </summary> public int? idMessaggioStandard; /// <summary> Default = EMAIL </summary> public enumTipoPosta tipoPosta; /// <summary> Default = TRUE </summary> public bool archiviaEmailSN; /// <summary> Default = TRUE </summary> public bool salvaAllegatiInArchivioSN; /// <summary> Default = 1 (non cambiare! nel vecchio sistema in Access era fisso) </summary> public SqlInt32 _tipoMessaggio; /// <summary> Default = 1 (non cambiare! nel vecchio sistema in Access era fisso) </summary> public SqlInt32 _idAutorizzato; public EmailOut() { idMessaggioStandard = null; _idAutorizzato = 1; _tipoMessaggio = 1; tipoPosta = enumTipoPosta.email; archiviaEmailSN = true; salvaAllegatiInArchivioSN = true; webcons = SqlInt32.Null; } public int numAllegati { get { return allegati.GetLength(0); } } public void aggiungiAllegato(string allegato) { int dimAttuale = allegati.GetLength(0); Array.Resize(ref allegati, dimAttuale + 1); allegati[dimAttuale] = allegato; } public override string ToString() { return "Destinatario: "" + destinatario.ToString() + "" Oggetto: "" + oggetto.ToString() + "" Testo: "" + testo.ToString().Substring(0, 30) + "[..] " DaSpedire: "" + daSpedire.ToString() + "" Numero allegati: " + numAllegati; } public void resetAllegati() { allegati = new string[0]; } } 49
  • 50. Lettura della posta La gestione automatizzata della posta in ingresso è una caratteristica molto importante, dato che in Onlife questo è il mezzo di comunicazione principale con i clienti. I nuovi messaggi in ingresso devono essere sottoposti ad un automatismo che li elabora ed invia delle risposte automatiche quando possibile, mentre quando non è possibile li associa al giusto partner o prospect. Ogni nuova email deve dunque essere sottoposta ai seguenti passaggi:  Si prova ad eseguire il trattamento automatico.  Se il trattamento automatico non ha dato esito positivo, analizzando l‟indirizzo del mittente la mail viene archiviata associandola al Prospect o al Partner da cui proviene, il quale viene messo “in evidenza”.  Se non proviene da un Prospect o da un Partner noto, viene aggiunta alla “posta da classificare”. Il trattamento automatico avviene cercando nell‟oggetto del messaggio delle parole chiave, ed eseguendo la funzione opportuna in base alle eventuali corrispondenze trovate. Il meccanismo si basa su delle tabelle che indicano le parole chiave e i nomi delle funzioni da chiamare. Questa funzione è stata realizzata nel seguente modo:  Una funzione principale LeggiPosta interroga il database alla ricerca di nuove email da elaborare (restituite da una vista definita sul database, che per ottimizzare gli accessi al database esegue già alcune stored function di base e restituisce i risultati nei campi della vista) 50
  • 51. Il risultato dell‟interrogazione è un DataReader, il cui riferimento viene passato a diverse funzioni, secondo le necessità. Le funzioni che lo ricevono però devono elaborare solo il record corrente, quindi non possono nè chiudere il datareader nè eseguire il suo metodo Read().  LeggiPosta contiene un ciclo di lettura che tenta di esegue il trattamento automatico di tutti i messaggi in ingresso Automazione di campagne di comunicazione La funzione LanciaCampagna deve creare ed inviare grandi quantità di messaggi personalizzati. In fase di invio infatti il testo di ogni messaggio deve essere personalizzato per il singolo destinatario inserendo dati estratti dalla query dei destinatari dal database al posto di specifici tag presenti nel messaggio. Dato che questa funzione deve poter gestire anche gli allegati delle email, è stata programmata interamente all‟interno dell‟applicativo batch. Se gli allegati sono dei form PDF è possibile personalizzarne il contenuto analogamente a come viene fatto per il testo del messaggio. Per determinare se il PDF deve essere personalizzato oppure no, si usa la funzione nomiCampiInPDF, che utilizzando le librerire iTextSharp permette di individuare gli eventuali campi del Form PDF: public static string[] nomiCampiInPDF(string percorsoPDF) { string[] nomi = { }; PdfReader documento = new PdfReader(percorsoPDF); foreach (KeyValuePair<string, AcroFields.Item> campo in documento.AcroFields.Fields) { Array.Resize(ref nomi, nomi.Length + 1); nomi[nomi.Length - 1] = campo.Key; } documento.Close(); return nomi; } 51
  • 52. Diverse campagne possono essere raggruppate, per poter essere lanciate secondo un ordine prestabilito, in automatismi. Quando si avvia un automatismo le campagne che ne fanno parte vengono lanciate in sequenza. Questa funzione viene svolta da EseguiWorkflow: public static int eseguiWorkflow(enumAutomatismo automatismo, int? valoreID, bool? flg_log) { string errInfo = "eseguiWorkflow(" + automatismo.ToString() + ", " + valoreID.ToString() + ", " + flg_log.ToString() + ")"; dbInputParam[] parametro = new dbInputParam[1]; parametro[0] = new dbInputParam("@idAutomatismo", DbType.Int32, (int)automatismo); IDataReader operazioni = dataReaderDaSQL("SELECT IDMessaggio, IDQuery, StringaUpdate FROM Workflow WHERE [InVigore?] = 1 AND IDAutomatismo = @idAutomatismo ORDER BY OrdineChiamata", parametro); string strUpdate; int mailInviate = 0; while (operazioni.Read()) { if (operazioni.IsDBNull(2)) strUpdate = ""; else strUpdate = operazioni.GetString(2); try { mailInviate += lanciaCampagna(operazioni.GetInt32(0), operazioni.GetInt32(1), 0, strUpdate); } catch (Exception ex) { operazioni.Close(); operazioni.Dispose(); throw new Exception(errInfo + ": Si è verificato un errore durante l'esecuzione dell'automatismo " + automatismo.ToString() + ". L'esecuzione è stata interrotta.", ex); } } operazioni.Close(); return mailInviate; } In questa funzione si può tra l‟altro notare un esempio di applicazione della metodologia di gestione degli errori precedentemente definita: se LanciaCampagna invia un‟eccezione, questa viene concatenata all‟eccezione definita nel blocco catch. Esecuzione della procedura dei rinnovi 52
  • 53. La parte di sistema informativo che si occupa del calcolo del premio non è inclusa in DM2, ma fa parte del sistema informativo di L.A. Vita. Per interfacciarsi con questo sistema, nel caso del calcolo del premio è stato necessario utilizzare un web service. La funzione calcoloPremioOL si occupa della connessione al web service e della corretta interpretazione dei dati restituiti, lanciando un‟eccezione se il risultato ricevuto ha un formato inatteso: public static string calcoloPremioOL(int numProposta, double capitaleAssicurato, DateTime dataDecorrenza) { string errInfo = "calcoloPremioOL(" + numProposta + ", " + capitaleAssicurato.ToString() + ", " + dataDecorrenza + ")"; GrlWsOnlifeSoapClient ClientWs = new GrlWsOnlifeSoapClient(); ClientWs.ClientCredentials.UserName.UserName = [credenziali di accesso] ClientWs.ClientCredentials.UserName.Password = [credenziali di accesso] string risultatoXml = ClientWs.CalcoloPremioOL(numProposta, capitaleAssicurato, dataDecorrenza); XmlTextReader xmlReader = new XmlTextReader(new StringReader(risultatoXml)); string risultato = ""; string errore = ""; string premio = ""; while (xmlReader.Read()) { if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name == "Result") { xmlReader.Read(); risultato = xmlReader.Value; } if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name == "ErrorDescription") { xmlReader.Read(); errore = xmlReader.Value; } if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name == "anyType") { xmlReader.Read(); premio = xmlReader.Value; } } 53
  • 54. xmlReader.Close(); ClientWs.Close(); string[] premio_splitted = premio.Split(';'); if (risultato.ToUpper().Trim() == "TRUE" && premio_splitted.Length == 4) { return premio_splitted[3]; } else { addToBacheca(enumBacheca.segnalazioniDM2, "Premio non calcolato [e altre informazioni]"); throw new Exception([messaggio di errore dettagliato]); } } Per aumentare la velocità di elaborazione il resto della logica di rinnovo dei contratti è stata programmata in una stored procedure. Controllo RID respinti Questa funzione si limita a verificare la presenza di RID respinti, contando il numero dei contratti che hanno uno specifico status. Anche questo è un esempio di funzione che è stato possibile realizzare molto semplicemente in un‟unica stored procedure. In particolare questa funzione è talmente semplice che poteva essere realizzata definendo una vista, tuttavia per garantire piena libertà di modifica si è deciso di utilizzare comunque una stored procedure. Attualmente il compito di scrivere sul log l‟informazione spetta alla funzione chiamante, ma essendo una stored procedure in futuro si potrebbe aggiungere una chiamata alla stored procedure che si occupa della scrittura sulla tabella Log. CREATE PROCEDURE ControllaRIDrespinti AS BEGIN SET NOCOUNT ON; DECLARE @ris INT SELECT @ris = count(*) FROM Contratti WHERE STATUS = 226 RETURN @ris END 54
  • 55. Eliminazione dei dati sensibili Analogamente al controllo dei RID respinti, l‟eliminazione dei dati sensibili è stata realizzata tramite la stored procedure qui riportata: DECLARE @dataElim datetime SET @dataElim = GETDATE() DECLARE @eliminati int UPDATE Contratti SET QuestAltezza = NULL, QuestPeso = NULL, QuestPressioneMax = NULL, QuestTrigliceridi = NULL, QuestColesteroloTot = NULL, QuestColesteroloHdl = NULL, [QuestFlagDiabete?] = NULL, [QuestFlagInfarti?] = NULL, DataCancellazioneDatiSensibili = NULL, Note=Note+'Scaduta validità proposta in data '+CAST(GETDATE() AS nvarchar) WHERE NOT DataCancellazioneDatiSensibili IS NULL AND DataCancellazioneDatiSensibili < DateAdd(d, 1, @dataElim) AND Status <> 100 AND Status <> 200 AND NOT ID IN (SELECT NumeroProposta FROM CarichiContabili WHERE TipoCarico = 1) AND Contratti.ID NOT IN (SELECT Contratti.ID FROM Contratti WHERE (((Contratti.IDPartner) IN (SELECT DISTINCT Contratti.IDPartner FROM Contratti INNER JOIN CarichiContabili ON Contratti.ID = CarichiContabili.NumeroProposta WHERE (((CarichiContabili.TipoCarico)=1))))) ) SET @eliminati = @@ROWCOUNT UPDATE IntMaster SET DataUltimaEliminazioneDatiSensibili = GETDATE() DECLARE @risultato as nvarchar(50) SET @risultato = 'Eliminati i dati sensibili di ' + CAST(@eliminati as nvarchar) + ' proposte' EXEC [dbo].[addToLog] @risultato, 'Stored procedure: eliminaDatiSensibili', 5 55
  • 56. Sincronizzazione degli status La sincronizzazione periodica degli status dei contratti viene realizzata accedendo al database di L.A. Vita tramite una query pass through e confrontando gli status dei contratti con i dati contenuti nel database di DM2. L‟obiettivo è evidenziare i casi in cui è stata rilevata una differenza di status e procedere all‟aggiornamento dei dati presenti in DM2. Dato che questa funzione elabora solamente dati provenienti dal database di DM2 e dal database di Onlife (a cui si accede tramite una query pass through), si è deciso di realizzarla tramite una stored procedure che restituirà il numero di differenze individuate. CREATE PROCEDURE [dbo].[ControllaStatusContratti] AS BEGIN SET NOCOUNT ON; DECLARE @strModificatoStatus as nvarchar(1000) SET @strModificatoStatus = '' DECLARE @idPartner as int DECLARE @numDifferenze as int SET @numDifferenze = 0 DECLARE @ID as int DECLARE @DataDecorrenza as datetime DECLARE @DataDecorrenza_onlife as datetime DECLARE @DataScadenza as datetime DECLARE @DataScadenza_onlife as datetime DECLARE @DataSottoscrizione as datetime DECLARE @DataSottoscrizione_onlife as datetime DECLARE @RataLorda as decimal(14,2) DECLARE @RataLorda_onlife as numeric DECLARE @Status as smallint DECLARE @Status_onlife as smallint DECLARE @PrestazioneIniziale_onlife as numeric DECLARE @PrestazioneIniziale as decimal(13,2) DECLARE sorgDifferenze CURSOR FAST_FORWARD FOR SELECT ID ,DataDecorrenza, DataDecorrenza_onlife, DataScadenza ,DataScadenza_onlife ,DataSottoscrizione ,DataSottoscrizione_onlife ,RataLorda ,RataLorda_onlife ,Status ,Status_onlife ,PrestazioneIniziale_onlife ,PrestazioneIniziale FROM [dbo].[qry_differenze_STATUS] 56
  • 57. OPEN sorgDifferenze FETCH NEXT FROM sorgDifferenze INTO @ID, @DataDecorrenza, @DataDecorrenza_onlife, @DataScadenza, @DataScadenza_onlife, @DataSottoscrizione, @DataSottoscrizione_onlife, @RataLorda, @RataLorda_onlife, @Status, @Status_onlife, @PrestazioneIniziale_onlife, @PrestazioneIniziale WHILE @@FETCH_STATUS = 0 BEGIN IF @Status_onlife <> 0 BEGIN UPDATE Contratti SET Status = @Status_onlife, DataDecorrenza = @DataDecorrenza_onlife, DataScadenza = @DataScadenza_onlife, DataSottoscrizione = @DataSottoscrizione_onlife WHERE ID = @ID IF @RataLorda <> @RataLorda_onlife BEGIN SET @strModificatoStatus = convert(nvarchar, GETDATE(), 103) + ': Modificato il premio del contratto numero ' + cast(@ID as nvarchar) + ' da € ' + cast(@RataLorda as nvarchar) + ' a € ' + cast(@RataLorda_onlife as nvarchar) + char(13) + char(10) UPDATE Contratti SET RataLorda = @RataLorda_onlife WHERE ID = @ID END IF @PrestazioneIniziale <> @PrestazioneIniziale_onlife BEGIN SET @strModificatoStatus = @strModificatoStatus + convert(nvarchar, GETDATE(), 103) + ': Modificato il capitale del contratto numero ' + cast(@ID as nvarchar) + ' da € ' + cast(@PrestazioneIniziale as nvarchar) + ' a € ' + cast(@PrestazioneIniziale_onlife as nvarchar) + char(13) + char(10) UPDATE Contratti SET PrestazioneIniziale = @PrestazioneIniziale_onlife WHERE ID = @ID END IF @Status_onlife = 200 UPDATE Contratti SET DataCancellazioneDatiSensibili = NULL WHERE ID = @ID IF NOT(@Status_onlife = 100 OR @Status_onlife = 200) BEGIN SELECT @idPartner = IDPartner FROM Contratti WHERE ID = @ID SET @strModificatoStatus = convert(nvarchar, GETDATE(), 103) + ': Modificato status contratto numero ' + cast(@ID as nvarchar) + ' in ' + cast(@status_onlife as nvarchar) + char(13) + char(10) EXEC dbo.evidenziaPartner @idPartner, @strModificatoStatus INSERT INTO Log (Testo, DebugInfo, Rilevanza) VALUES (@strModificatoStatus, 'Stored procedure: ControllaStatusContratti', 5) END 57