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

63
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

description

Tesi di laurea triennale in ingegneria informatica.

Transcript of Migrazione dei meccanismi di workflow di un sistema informativo assicurativo verso l'ambiente SQL...

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

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

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

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

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

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

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

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

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

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

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

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.

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

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.

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

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.

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

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

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

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

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

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.

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

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

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

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

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

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.

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

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.

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

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.

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

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:

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

19

MessaggiTesti

standard ID

Oggetto

Testo

Allegato1

Allegato2

WkflAutomatismi

ID

Codice

Nome

Note

Query

ID

Descrizione

StringaSQL

Workflow

ID Messaggio

Standard ID Query

Destinatari ID Automatismo

SELECT Nome, Cognome, Email FROM Partner WHERE .....

ALTRE

TABELLE

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

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

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

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.

Tempo

Stato del

servizio

Funzionamento

Riparazione

Istante in cui il servizio

viene ripristinato

Istante in cui il servizio

cessa di funzionare

Tempo tra due

malfunzionamenti

Tempo di

riparazione

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.

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

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.

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

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.

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

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.

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

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.

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

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

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

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

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

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.

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

29

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

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,”[email protected]”,...): 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

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

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.

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

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.

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

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.

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

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.

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

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

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

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

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

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:

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

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.

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

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 + "\r\n" + dettagliEccezione(ex.InnerException);

else return ex.TargetSite.Name + ": " + ex.Message;

}

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

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:\r\n" +

Onlife.dettagliEccezione(ex);

debugInfo += "\r\n\r\nStack delle chiamate:\r\n" +

getInnermostException(ex).StackTrace.ToString();

}

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

41

else

{

debugInfo = "Stack delle chiamate:\r\n" +

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("================================================

\r\n");

}

}

else

{

logTxt.WriteLine(messaggio + " -- Call stack:");

logTxt.WriteLine(debugInfo);

logTxt.WriteLine("================================================

\r\n");

}

}

}

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 è

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

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)

{

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

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

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

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.

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

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

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

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

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

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++;

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

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;

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

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];

}

}

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

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)

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

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;

}

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

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

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

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;

}

}

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

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

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

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

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

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]

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

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

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

58

SET @numDifferenze = @numDifferenze + 1

END

SET @strModificatoStatus = ''

SET @idPartner = NULL

SET @ID = NULL

SET @DataDecorrenza = NULL

SET @DataDecorrenza_onlife = NULL

SET @DataScadenza = NULL

SET @DataScadenza_onlife = NULL

SET @DataSottoscrizione = NULL

SET @DataSottoscrizione_onlife = NULL

SET @RataLorda = NULL

SET @RataLorda_onlife = NULL

SET @Status = NULL

SET @Status_onlife = NULL

SET @PrestazioneIniziale_onlife = NULL

SET @PrestazioneIniziale = NULL

FETCH NEXT FROM sorgDifferenze

INTO @ID, @DataDecorrenza, @DataDecorrenza_onlife,

DataScadenza, @DataScadenza_onlife, @DataSottoscrizione,

@DataSottoscrizione_onlife, @RataLorda, @RataLorda_onlife, @Status,

@Status_onlife, @PrestazioneIniziale_onlife, @PrestazioneIniziale

END

CLOSE sorgDifferenze

DEALLOCATE sorgDifferenze

DECLARE @risultato as nvarchar(50)

SET @risultato = 'Differenze di STATUS: ' + CAST(@numDifferenze as

nvarchar)

EXEC [dbo].[addToLog] @risultato, 'Stored procedure:

ControllaStatusContratti', 5

RETURN @numDifferenze

END

Elaborazione automatica degli incassi

I bonifici da elaborare vengono ricevuti via email in un file nel formato di

Microsoft Excel, strutturato in una maniera predefinita.

L‟elaborazione automatica degli incassi prevede la ricerca di tale file tra le

email ricevute, e la successiva elaborazione della causale di ogni bonifico alla

ricerca di un numero di contratto per cui si è in attesa di pagamento.

Questa funzione è stata realizzata utilizzando OLEDB, una API sviluppata

da Microsoft per accedere a dati provenienti da una grande varietà di fonti

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

59

diverse in maniera uniforme. In questo caso la fonte di dati è direttamente il file

Excel:

string xlsConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source="

+ percorsoFileExcel + ";Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=1\";";

OleDbConnection xlsConnection = new OleDbConnection(xlsConnectionString);

xlsConnection.Open();

Una volta fatte tutte le verifiche sul file sorgente e sui dati caricati, è stato

possibile utilizzare una stored procedure per eseguire le restanti operazioni di

elaborazione del bonifico.

Elaborazione degli estratti conto

Questa funzione deve generare gli estratti conto per gli intermediari di

vendita, deve inviarli ai rispettivi destinatari, e deve generare ed inviare gli

ordini di pagamento a beneficio degli intermediari che ne hanno diritto.

Per creare l‟ordine di pagamento, si è utilizzato il modulo di creazione di

PDF a partire da Form PDF già creato per le altre funzionalità di Onlife.

L‟estratto conto invece è un documento piuttosto complesso da creare,

perchè contiene una tabella creata dinamicamente di dimensioni molto

variabili. Precedentemente veniva creata sfruttando Microsoft Word, ma per le

restrizioni imposte da Allianz questa strada non era percorribile.

Si è quindi deciso di creare una nuova funzione

generaPDFContoIntermediario specifica per questa funzionalità, che utilizza

direttamente la libreria iTextSharp.

Un esempio autoesplicativo del codice creato, tratto dalla funzione in

questione, è il seguente:

//creo il paragrafo iniziale (intestazione)

Paragraph ParagrafoIntro = new Paragraph();

ParagrafoIntro.Font = Times13;

Phrase PhraseIntro = new Phrase();

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

60

PhraseIntro.Add(new Chunk("ONLIFE", Times13Bold));

PhraseIntro.Add(new Chunk(" - Estratto conto in € per", Times13));

PhraseIntro.Add(new Chunk(" " + descrizioneCanale, Times13Bold));

PhraseIntro.Add(new Chunk(" di data", Times13));

PhraseIntro.Add(new Chunk(" " + DateTime.Now.ToString("dd/MM/yyyy"),

Times13Bold));

ParagrafoIntro.SpacingAfter = 5;

ParagrafoIntro.Add(PhraseIntro);

//aggiungo il paragrafo iniziale al documento

document.Add(ParagrafoIntro);

//creo il separatore e lo aggiungo al documento

PdfPTable separatore = new PdfPTable(1);

separatore.WidthPercentage = 100;

separatore.DefaultCell.Border = 1;

separatore.DefaultCell.BorderWidth = 2;

separatore.AddCell(" ");

document.Add(separatore);

Costruire direttamente il documento PDF richiede più lavoro di

programmazione rispetto all‟utilizzo di un editor WYSIWYG, ma consente di

avere un migliore controllo sul risultato prodotto e completa libertà nella

definizione dei contenuti.

Un esempio di documento completo di tutti gli elementi, prodotto dalla

funzione di generazione degli estratti conti, è visibile nella pagina seguente

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

61

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

62

Capitolo 6: Conclusioni

Attualmente il nuovo applicativo batch è in avanzata fase di test. Fin‟ora

ha soddisfatto tutti i requisiti preposti, non sono stati riscontrati problemi di

funzionamento e ed ha soddisfatto gli obiettivi posti dall‟azienda.

È stato deciso di portare separatamente in fase di produzione le singole

funzionalità, in modo da concentrare gli sforzi su una alla volta e quindi

velocizzare il processo. L‟entrata in produzione delle prime funzionalità è atteso

a breve.

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

63

Bibliografia

Microsoft Developer Network. [Online] http://msdn.microsoft.com/.

Felician, Leonardo. Dispense del corso di Sistemi Informativi 2.

Felician, Leonardo. 1995. L'impresa rete. Workflow management e lavoro

cooperativo in azienda. : Franco Angeli, 1995.

Fermeglia, Maurizio. Dispense del corso di complementi di basi di dati.

Gorjan, Mauro. 2006. Onlife: progettazione di un sistema informativo per

l'assicurazione vita su internet. : Università degli studi di Trieste, tesi di laurea

in Ingegneria Informatica, 2006.

Sbroiavacca, Fulvio. Dispense del corso di Sistemi Informativi 1.

Troelsen, Andrew. 2007. Pro C# 2008 and the .NET 3.5 Platform, Fourth

Edition. : Apress, 2007.

Vargas, Enrique. 2000. High Availability Fundamentals. [Online] 2000.

www.sun.com/blueprints/1100/HAFund.pdf.

Vlissides, John, et al. 1994. Design Patterns: Elements of Reusable

Object-Oriented Software. : Addison-Wesley Professional, 1994. ISBN 0-201-

63361-2.