MySail: Guida di riferimento per il...

115
MySail: Guida di riferimento per il Programmatore pag 1 MySail: Guida di riferimento per il programmatore CheckList WorkFlow 4.5 Creato il 19/12/2014 Ultimo aggiornameno di questa guida: 28/06/2016 Vers. sito 40 Versione 1.0 Data 28 Giugno 2016 Autore Fabio Guerrazzi Riservato a Team di Sviluppo e Redattori MySail

Transcript of MySail: Guida di riferimento per il...

MySail: Guida di riferimento per il Programmatore – pag 1

MySail:

Guida di riferimento per il

programmatore

CheckList WorkFlow 4.5

Creato il 19/12/2014

Ultimo aggiornameno di questa guida: 28/06/2016

Vers. sito 40

Versione 1.0

Data 28 Giugno 2016

Autore Fabio Guerrazzi

Riservato a Team di Sviluppo e Redattori MySail

MySail: Guida di riferimento per il Programmatore – pag 2

INDICE

1. STRUTTURA SAILWEB ..................................................................................................................................6

1.1 CODE METRICS (SOLUTION SENZA WEBSITES) .......................................................................................7

1.2 MANTENIBILITÀ DEL CODICE (DA 0 A 100, 0-EASY, 100-COMPLEX) ....................................................8

1.3 INDICE ORDINATO PER NUMERO DI LINEE DI CODICE (PIU BASSO MIGLIOR RISULTATO) ......................9

2. INTRODUZIONE A SAILWEB .......................................................................................................................11

2.1 CARATTERISTICHE PRINCIPALI ...................................................................................................................11

2.2 GENERAZIONE DEL PROGETTO DI START-UP (NON NECESSARIA IN FASE DI MANUTENZIONE MA COME

PROMEMORIA) .........................................................................................................................................................12

3. ASP.NET ................................................................................................................................................... 14

3.1 PERCHÈ ASP.NET 4.5 ..............................................................................................................................14

3.2 COMPATIBILITÀ FRAMEWORK IIS E SERVER ............................................................................................15

3.3 SISTEMA DI AUTENTICAZIONE ...................................................................................................................15

3.4 RUOLI DI BASE E IL LORO UTILIZZO ..........................................................................................................16

3.5 DATABASE MYSAIL ....................................................................................................................................16

3.6 ACCESSO AI DATI DI ASP.NET E MANUTEZIONE POLICIES ....................................................................16

3.7 AGGIUNGERE UN NUOVO RUOLO: ..............................................................................................................17

3.8 AUTENTICAZIONE DI SISTEMA E APPLICATIVA ..........................................................................................17

3.9 STRUTTURA FISICA DEL SITO .....................................................................................................................17

3.10 STRUTTURA LOGICA ...................................................................................................................................19

3.11 JQUERY ........................................................................................................................................................19

3.12 AJAX .............................................................................................................................................................20

3.13 SICUREZZA AJAX ........................................................................................................................................21

3.14 AGGIUNTA DI UNA NUOVA PAGINA ASP.NET 4.5, JQUERY, BOOTSTRAP, CON USO DI AJAX, LINQ TO

SQL ASSOCIATA AD UNA MASTER PAGE ...............................................................................................................21

3.15 SEQUENZA EVENTI - PIPELINE ...................................................................................................................23

3.16 SUDDIVISIONE AREE APPLICATIVE ............................................................................................................23

E SEPARAZIONE CONTESTI .....................................................................................................................................23

3.17 CHECKLIST MANUTENZIONE SITO .............................................................................................................24

4. ABILITAZIONI UTENTI MYSAIL .................................................................................................. 25

4.1 CLIENTE AGENZIA .......................................................................................................................................27

1.1 ADMIN ..........................................................................................................................................................27

4.2 SMALL PARCEL ............................................................................................................................................27

4.3 TELEGRAMMI ...............................................................................................................................................28

4.4 AGENZIA ......................................................................................................................................................28

4.5 IMPRENDITORI AGENZIA ............................................................................................................................28

4.6 REDATTORI AGENZIA (PER STATISTICHE ROY, COMPETENZE, GRAFICI SU SELEZIONE AGENZIA) .......28

4.7 CLIENTI DIREZIONALI ................................................................................................................................28

4.8 ANAGRAFICHE CENTRALIZZATE .................................................................................................................28

4.9 QUALITÀ ......................................................................................................................................................28

4.10 ALTRO ..........................................................................................................................................................29

4.11 UTENTI CON AUTORIZZAZIONI SPECIFICHE .............................................................................................29

TROUBLESHOOTING ................................................................................................................................................30

MySail: Guida di riferimento per il Programmatore – pag 3

5. IMPOSTAZIONE PERMESSI E SETTINGS DEI SINGOLI UTENTI E CONTROLLARLI

DA PROGRAMMA ......................................................................................................................................... 30

5.1 Gestione Permessi ................................................................................................................ 30

5.2 Tabella Permessi, significato delle colonne: ............................................................... 31

5.3 Uso dei permessi e settings da programma ............................................................... 33

5.3.1 UTENTE PRINCIPALE E UTENTE IMPERSONATO ..........................................................................................34

5.3.2 LEGGERE A PROGRAMMA I SETTING DI UN UTENTE ..................................................................................34

5.3.3 Autorizzare / negare accesso alle pagine............................................................... 34

6. SISTEMA ROYALTIES – PER IL PROGRAMMATORE ............................................................ 35

6.1 DOVE STANNO I SORGENTI\BINARIES .......................................................................................................35

6.2 REQUISITI ...................................................................................................................................................35

6.3 PARAMETRI DI ROYBATCH.EXE ..................................................................................................................37

6.4 INDICAZIONI DEI COMMITTENTI RICEVUTE PER MAIL, RIUNIONI, COMUNICAZIONI VERBALI ECC ........40

6.5 PREGRESSO (CASTELLI) ............................................................................................................................40

6.6 COME SONO STATI RIPORTATI I DATI DI EXCEL SUL DB .........................................................................41

6.7 CASI PARTICOLARI / ECCEZIONI ...............................................................................................................41

6.8 CRITERI DI CALCOLO IMPONIBILE ROYALTY .............................................................................................42

6.9 SPECIFICHE TECNICHE ................................................................................................................................43

6.10 QUERY UTILI ...........................................................................................................................................44

6.11 SCRIPT TABELLA ROYALTIES .....................................................................................................................46

(SU SRV_CITY1.SAILNET_REPORT) (MAGGIO 2016) ...................................................................................46

6.12 STORED PROCEDURE [NORMBATCH.ARCHDATI] [DBO].[ROY_LIST_ELEMENT_WEB] (A

MAGGIO 2016) ......................................................................................................................................................47

6.13 ALTRE TABELLE ............................................................................................................................................52

7. SISTEMA ROYALTIES ED ESTRAZIONE MENSILE, PER L’AMMINISTRATORE DEL

SITO .................................................................................................................................................................. 52

7.1 INTRODUZIONE ...........................................................................................................................................52

7.2 ACCESSO .....................................................................................................................................................52

7.3 INSERIRE UN NUOVO CONTRATTO .............................................................................................................53

7.4 CALCOLO/ESTRAZIONE ROY E FATTURE ...................................................................................................57

7.5 LOG .............................................................................................................................................................58

7.6 IMPORTAZIONE FISICA SU GAP .................................................................................................................59

7.6.1 VERIFICA FATTURE PRIMA DI IMPORTAZIONE AL GAP ............................................................................59

7.6.2 VISUALIZZA TRIMESTRE E DETTAGLI ........................................................................................................60

7.6.3 COPIA EXP_SAILNET.MDB SUL REPOSITORY DEL GAP ...........................................................................61

7.6.4 TROUBLESHOOTING ....................................................................................................................................63

8. SVILUPPO DI SAILWEB ................................................................................................................... 64

8.1 INTRODUZIONE ALLA LOGICA DEL SITO ....................................................................................................64

b) cpAjax ........................................................................................................................................ 64

c) ajax.cs ........................................................................................................................................... 64

f) snStorage ..................................................................................................................................... 65

8.2 SAILNETSTORAGE, SAILWEB E CLASSI IN APP_CODE ...........................................................................67

MySail: Guida di riferimento per il Programmatore – pag 4

SailWeb ................................................................................................................................................. 67

SailNetStorage ................................................................................................................................... 67

SQLGrid ................................................................................................................................................. 67

AuthConfig ........................................................................................................................................... 67

BundleConfig ....................................................................................................................................... 67

SWEnvironment ................................................................................................................................. 67

PPAContext .......................................................................................................................................... 68

rkAgenzia ............................................................................................................................................. 68

cpPaginator.......................................................................................................................................... 68

8.3 BUSINNESSLOGIC E BL CITYPOST............................................................................................................68

8.3.1 ISTANZIARE UN MAPPER BUSINNESLOGIC ................................................................................................68

8.3.2 ISTANZIARE UN SERVICE DI CITYPOST.BL ..............................................................................................69

8.3.3 BUSINNES DATA LAYER DI CITYPOST .......................................................................................................70

(BL CPSI CENTRALIZZATO) ..................................................................................................................................70

CONTATTI ................................................................................................................................................................70

PROCESSO ...............................................................................................................................................................70

IMPLEMENTAZIONE .................................................................................................................................................71

TEST 74

DATABASE ...............................................................................................................................................................75

8.3.4 INSTALLAZIONE ED UTILIZZO DEL BUSINNES LAYER ...............................................................................75

PREREQUISITI .........................................................................................................................................................75

INSTALLAZIONE .......................................................................................................................................................76

UTILIZZO .................................................................................................................................................................76

8.4 CLIENT SIDE..............................................................................................................................................76

8.5 FLAGS AJAX PER ESEGUIRE IL PROCESSO ASINCRONO E CONTROLLARNE INIZIO E FINE ......................77

8.6 WEB SERVICE WS.ASHX .....................................................................................................................78

8.6.1 PROGRESSBAR .......................................................................................................................................78

8.7 SERVER SIDE WORKFLOW ........................................................................................................................79

8.8 ORDINE OGGETTI Z-INDEX ..................................................................................................................80

8.9 CLASSI HTML, CSS, JQUERY .......................................................................................................................80

8.10 VISUALIZZARE MESSAGGI SULLA PAGINA .............................................................................................81

8.10.1 CLIENT .................................................................................................................................................81

8.10.2 CURPAGE E DESTPAGE ........................................................................................................................83

8.11 GRIGLIE, GRID, CUSTOM DATAGRID................................................................................................83

8.12 GRIGLIE SQL AUTOMATICHE (LIBEXECSQL) ...........................................................................................87

LIVE UPDATE CELL .................................................................................................................................................90

8.13 EVENTI .........................................................................................................................................................91

9 PUBBLICAZIONE DI SAILWEB ...................................................................................................... 92

9.1 Sito di produzione ................................................................................................................. 92

9.2 Sito Ultimo Funzionante ..................................................................................................... 93

(versione precedente) ..................................................................................................................... 93

9.3 Sito di TEST ............................................................................................................................. 93

MySail: Guida di riferimento per il Programmatore – pag 5

9.4 PUBBLICAZIONE STEP BY STEP ..................................................................................................................94

9.5 VERSIONI DI SAILWEB ..............................................................................................................................97

10 TABELLA PROCESSES ........................................................................................................................ 97

10.1 QUERY SQL SALVATE ...............................................................................................................................98

10.2 MESSAGGI ...................................................................................................................................................98

11 CSV IMPORT/EXPORT ...................................................................................................................... 98

11.1 ESPORTA IN CSV ........................................................................................................................................98

11.2 PROGRAMMARE I SERVICES PER L’EXPORT ...............................................................................................99

11.3 IMPORT CSV (PER ADMIN) .................................................................................................................... 101

SCELTA ORIGINE ................................................................................................................................................. 103

SCELTA DELLA DESTINAZIONE SUL SISTEMA CENTRALE .................................................................................. 104

CARICAMENTO FILE ............................................................................................................................................. 104

VERIFICA VALIDITÀ CSV E ASSOCIAZIONE CAMPI ........................................................................................... 105

CONVALIDA IMPORT ED ESECUZIONE TRASFERIMENTO DATI ........................................................................... 107

CONTROLLO RISULTATI ....................................................................................................................................... 107

12 TELEGRAMMI (PER IL PROGRAMMATORE) .......................................................................... 110

12.1 DESTINATARIO FATTURA DIVERSO DAL MITTENTE ................................................................................ 111

13 SMALL PARCEL (PER IL PROGRAMMATORE) ....................................................................... 111

14 SWSQLMANAGEMENT ..................................................................................................................... 112

15 ADMIN DEL SITO.................................................................... ERRORE. IL SEGNALIBRO NON È DEFINITO.

16 UNIT TEST ................................................................................. ERRORE. IL SEGNALIBRO NON È DEFINITO.

17 WEB SERVICES SAILPOST ................................................. ERRORE. IL SEGNALIBRO NON È DEFINITO.

MySail: Guida di riferimento per il Programmatore – pag 6

1. Struttura SailWeb

MySail: Guida di riferimento per il Programmatore – pag 7

1.1 Code Metrics (Solution Senza WebSites)

Complexity branches ordinati per indice di complessità (valori bassi = migliore)

MySail: Guida di riferimento per il Programmatore – pag 8

1.2 Mantenibilità del codice (da 0 a 100, 0-easy, 100-complex)

MySail: Guida di riferimento per il Programmatore – pag 9

1.3 Indice ordinato per numero di Linee di codice (piu basso miglior risultato)

MySail: Guida di riferimento per il Programmatore – pag 10

MySail: Guida di riferimento per il Programmatore – pag 11

2. Introduzione a SailWeb

Questa guida è il frutto di raccolta note, appunti, wiki e documenti riguardanti il nuovo

FrontEnd Citypost e alcune sue parti BackEnd. E’ il prodotto del lavoro in team da fine 2014.

Il progetto del sito è stato denominato SailWeb, con titolo MySail, sviluppato su target

Framework ASP.NET 4.5. Questa soluzione è stata necessaria in quanto sul cloud Windows

Azure e WebMatrix esistevano basi di creazione WebApplication ASP.NET completi di

autenticazione solo di questa versione.

Ne sono state scaricate e provate altre, e questa ad oggi sembra l’unica che permettesse di

lavorare su un sistema aperto, senza eccessivi User Control Microsoft o di terze parti. In breve,

è risultato quello piu pulito e ordinato. E’ stato scelto ASP.Net classic e non MVC perche i

teams di sviluppo Citypost e TDGroup hanno piu o meno compentenze Microsoft così

distribuite: 5% VB6, 80% ASP Classic, 20% ASPNet 4.0, 30% C#

Le tecniche utilizzate sono state tratte da Professional ASP.NET 4.5 in C # and VB -nelly-

.pdf

Il PDF, di 88Mb e 1.444 pagine, contiente tutto quello che c’è da sapere su ASP.NET.

Suggerisco di consultare questo file prima di qualsiasi ricerca su google perche c’è veramente

tutto

2.1 Caratteristiche principali

La WebApp è stata pensata per suddividere le aree applicative vincolando ai propri dati di

pertinenza gli utenti secondo le proprie caratteristiche, e di globalizzarle per l’assistenza.

L’assistenza vede e gestisce tutto il mondo, i singoli utenti solo le proprie informazioni, le

agenzie amministrano i propri clienti, i redattori del sito le Agenzie

MySail: Guida di riferimento per il Programmatore – pag 12

Il portale è a tema Responsive, ha 4 livelli di ridimensionamento automatico a seconda dello

schermo o dispositivo che lo sta utilizzando e si adatta perfettamente a telefoni e tablet.

Il sistema è modulare, sia il motore di accesso ai database che alle risorse applicative vengono

utilizzate solo se l’utente appartiene a quel contesto. Cioè evita di far caricare al sistema

risorse di cui non ha bisogno.

Il sistema di sicurezza utilizza le piu recenti tecnologie anti-intrusione.

2.2 Generazione del progetto di start-up (non necessaria in fase di

manutenzione ma come promemoria)

Di seguito gli step eseguiti per l’installazione base del sito

- Da Visual Studio 2012 New WebSite

- Framework 4.5

- Project Type Sito Web Form ASP.NET

- Il kit o template di VS installa automaticamente gli assemblies, i componenti grafici,

layout e operativi, su modello del 4.0, come mostrato nell’immagine sottostante

MySail: Guida di riferimento per il Programmatore – pag 13

- Sono stati sostituiti i temi e skin con bootstrap.css, bootstrap.js, Bootstrap è un

prodotto opensource adottato dagli standard Google Inc.

- Gli elementi sono stati allineati al tema cerulean, visibili all’indirizzo

http://bootswatch.com/cerulean/ (La pagina è stata salvata su disco, in caso di

aggiornamento futuri, qui abbiamo la fotografia dello stile in uso a SailWeb)

- Per includere BootStrap e jQeury, Modernizr, si va su Console Getione Pacchetti di

Visual Studio

MySail: Guida di riferimento per il Programmatore – pag 14

- Dalla console NuGet digitare Get-Package –ListAvailable per ottenere l’elenco dei

package disponibili (consiglio di farlo in un momento di inutilizzo del computer perche la

lista è lunghissima, che comunque ho incluse nella cartella di Documentazione)

- Per il sito va eseguito Install-Package BootStrap per caricare la v3.0 di bootstrap

- Va aggiornato jQuery, che il template installa la 1.8, mentre Install-Package jQuery

aggiorna alla 2.1.1

- Va installato Install-Package jQuery-validate

3. ASP.NET

Una volta installato il sito, deve essere configurato il dataprovider di default per la

creazione del db dedicato alle policies ASP.NET. Per farlo è sufficiente indicare nel

Web.Config la stringa di connessione DefaultConnection

<add name="DefaultConnection" connectionString="Data Source=192.168.78.3;Initial

Catalog=SailWebData;Persist Security Info=True;User ID=sa;Password=xxxxxx"

providerName="System.Data.SqlClient"/>

e dalle pagine ASP.Net Management(*) dire che il defaultDataProvider usa la

DefaultConnection.

Al primo avvio del sito, se questi 2 parametri sono stati impostati correttamente, il sistema

crea automaticamente tutte le tabelle che gli servono per l’autenticazione.

Dalla Home della nuova WebApp occorre registrarsi come admin e quindi si è loggati per le

prime prove con questo utente.

(*) da Visual Studio 2013 ASP.Net Management non esiste piu, lo hanno tolto e non si sa

con cosa gestire il Provider, le indicazioni trovate in rete a me non funzionano. Le ho

rifatte a manina, pagina per pagina (gestione utenti, ruoli, associazioni, ecc)

3.1 Perchè ASP.NET 4.5

La ragione per cui è stata adottato il sistema di autenticazione integrato basato sul

Membership è solamente per questioni di sicurezza. Il framework 4.5 integra

System.Web.Security che da questa versione si occupa autonomamente di validare le

richieste processando filtri di sicurezza Anti-XSRF e DoS, fornisce token di sessione e la

chiude nel caso in cui rilevi una condizione di intrusione.

Inoltre il sistema di autenticazione ASP NET permette maggiori garanzie di allineamento

futuro sulle criticità di sicurezza, che riguardino IIS, Windows Server, il Browser o il

Framework stesso.

MySail: Guida di riferimento per il Programmatore – pag 15

3.2 Compatibilità Framework IIS e Server

Nonostante il sito sia sviluppato su Framework 4.5, Windows 2003 IIS 6 con ASP.NET 4.0

supporta il deploy e la pubblicazione senza problemi. Questo perche ASP.NET 4.5 di fatto

non esiste, è il framework ad essere avanzato di versione, e durante la pubblicazione copia

le sue DLL, ma su IIS il pool di Applicazioni resta ASP.NET 4.0

3.3 Sistema di Autenticazione

L’obiettivo principale pensando alle regole di autenticazione è stato quello di gestire un

sistema piu semplice possibile da mantenere in termini di configurazione e

programmazione.

Non è stato facile, in quanto le casistiche sono ampie e gli elementi altrettanto, ma mi sono

basato sul sistema Drupal che ho trovato piu che efficiente. La sfida è stato nel riprodurlo

in ASP NET con il suo framework nativo, senza creare troppe tabelle o configurazioni

specifiche sul web.config.

A ciascun utente è associato uno o piu ruoli.

A ciascun ruolo corrisponde uno o piu permessi.

I permessi vincolano l’accesso a voci di menu, funzioni, pagine, files, cartelle

System.Web.Security espone le sue proprie tabelle Users, Roles, Membership,

Application e UsersInRoles. Io ho aggiunto la tabella Permessi, in cui aggiungo tutte le

pagine o regole che voglio associare ad un ruolo. SWSettings e SWConfig sono

rispettivamente le chiavi delle impostazioni profilo associate a un record di Permessi e i

valori dei settings

All’accesso vengono caricati i propri ruoli e i propri permessi. Nell’esempio che segue, se

l’utente non ha il ruolo Admin non fa il render della voce di menu sulla pagina e per l’utente

finale non esiste fisicamente. (qui siamo sull’html della pagina aspx)

<% if (WebHelper.UserRuoli.Contains("Admin"))

{ %>

<li>

<a id="A2" runat="server" title="Gestisci i permessi"

href="~/Account/Admin.aspx">Admin</a>

</li>

<% }; %>

ATTENZIONE: Quando si crea una nuova pagina, un nuovo menu o una nuova funzionalità,

per default sarà visibile a tutti, Anonimi compresi. Se deve essere vincolata solo a

determinati utenti, creare i records necessari nella tabella Permessi

MySail: Guida di riferimento per il Programmatore – pag 16

3.4 Ruoli di base e il loro utilizzo

Admin, deve aver accesso a tutte le funzioni e pagine del sito, assume il ruolo di Redattore

Redattore. Ha accesso a tutte le funzioni di gestione dati, ad esempio, combinato al ruolo

SailNet vede TUTTE le agenzie, ecc

Agenzia. Ha accesso alle funzioni e pagine dedicate all’agenzia

Cliente. Ha accesso alle funzioni e pagine dedicate ai clienti dell’agenzia

Esempi:

Un utente con ruoli Agenzia e Redattore, vede e gestisce tutte le Agenzie piu i loro clienti.

Un utente con solo il ruolo Agenzia vede esclusivamente la sua Agenzia e amministra i suoi

clienti.

3.5 DataBase MySail

Il Database di produzione in cui risiedono le tabelle dati e autenticazione è SailWebData

sul server 192.168.78.3 Su questo catalog ci sono gli utenti, i permessi, settings, archivio

destinatari abituali, calendario, la chat, contatori di accesso, dati statistici imprenditori

agenzie. Tutte le anagrafiche sono sui server NORMBATCH e sono gestiti internamente o

dal BL di Citypost dove possibile

3.6 Accesso ai dati di ASP.NET e manutezione policies

ASP.NET da solo, al momento dell’installazione, crea le tabelle seguenti

di

sistema

Tabella Descrizione

Si Users Raccoglie gli utenti ( campi IdUser e UserName)

Si MemberShip Contiene un record per ogni utente con le proprie

informazioni sull’account (password, email, se è bloccato,

date di accesso, login)

Si Applications Contiene le WebApp (noi ne usiamo una sola, la root del sito,

da investigare l’utilità di uno split su piu app)

Si Profiles Contiene tutte le proprietà estese degli utenti, che sono

definite nel Web.Config

Si Roles Contiene i nomi dei Ruoi (IdRole, RoleName)

Si UsersInRoles Contiene gli idUser e idRoles di abbinamento utenti/ruoli

No Permessi Contiene le pagine, cartelle, funzioni abbinate ai ruoli che in

modo programmatico vengono usate nel codice

Tutte le tabelle di sistema sono normali tabelle SQL Server accessibili con gli strumenti SQL

standard. I dati possono essere interrogati o modificati a mano, ma è opportuno che sia

ASP Net a creare i records, in quanto genera le proprie GUID.

Sul sito ho aggiunto un DHTML per l’accesso ai dati via LinQ e l’ho inserito per praticità,

ma all’avvio della Web Application, il namespace System.Web.Security contiene già questi

Datacontext con tutti i metodi per creazione, validazione, associazione e profilazione utenti.

MySail: Guida di riferimento per il Programmatore – pag 17

Accedendo con Admin sono a disposizione le pagine di amministrazione del sito, degli utenti

e policies. Eseguire da li qualsiasi operazione di manutenzione.

3.7 Aggiungere un nuovo ruolo:

- Dal sito come Admin Sistema->Ruoli, icona Aggiungi ruolo

- Da SSMS Edita la tabella SailWebData.Permessi e aggiungi il ruolo nuovo che puo

accedere alla caratteristica (folder, feature, ecc)

- Da Admin associare il ruolo all’utente da Sistema->Utenti->modifica utente

- Vedi piu avanti Associazione permessi e impostazione settings

3.8 Autenticazione di sistema e applicativa

L’autenticazione ASPNet stabilisce una connessione univoca, sicura, basata su crittografica

e scambio di chiavi di sicurezza, quella applicativa stabilisce il comportamento sull’utilizzo

delle pagine e delle funzioni:

a) I ruoli Admin vengono sempre rediretti sulla Home di root del portale ed hanno la

visibilità di tutte le funzioni di utlitià e sistema, controllo degli utenti, dei ruoli, dei

permessi, stato del sito, analisi ecc. Dovrebbero esistere almeno 2 utenti con questo

ruolo

b) I ruoli Redattore sono gli utenti che prestano assistenza a una o piu aree di lavoro e

vedono tutti gli elementi. Un Redattore Sailnet accede all’elenco di tutte le agenzie ed

ha accesso a tutte le funzioni operative di pertinenza globale o può scegliere di lavorare

come se fosse l’agenzia selezionata. I Redattori dovrebbero essere solo attribuiti al

personale Citypost o SailNet per le analisi e manutenzione della globalità dei contesti.

Un utente Redattore con uno solo dei due ruoi applicativi viene reindirizzato sulla home

contestuale, se ha entrambi gli ambienti viene reindirizzato come un Admin sulla Home

principale da cui puo scegliere.

c) Né Admin né Redattori devono avere ID e PWD applicativa, in quanto gestiscono

elenchi.

d) I ruoli Agenzia non Admin e non Redattore sono le utenze sul territorio, devono

avere ID Anagrafica impostata sul profilo, vengono rediretti sulla Home SailNet

(/SailNet/Default.aspx), vedono e gestiscono solo le informazioni legate alla propria

agenzia e possono impersonare i propri clienti.

e) Il ruolo Anonimo viene assegnato automaticamente all’utente Anonimo di sistema.

Questo particolare utente corrisponde all’identificativo che prendono gli accessi anonimi.

E’ utile per rilevare i tempi di attività e nel caso in futuro vengano abilitate funzioni per

anonimi da trasformare poi in utenti (nello stile e-Commerce dello Shopping cart, per

intenderci)

3.9 Struttura fisica del sito

Le pagine sulla root sono comuni a tutta la WebApp, e corrispondono agli entry point,

richiamabili da url classici.

MySail: Guida di riferimento per il Programmatore – pag 18

Site.Master, Login.Aspx Default.aspx, Contact.aspx, About.aspx corrispondono alla home e

le pagine informative classiche della vetrina iniziale del sito da autente Anonimo, accedibile

a tutti

Site.Master è la master page, e contiene le regioni comuni a tutte le pagine.

Ogni pagina aspx, eccetto ajax.aspx, ha come Masterpage questa o un’altra MasterPage

che a sua volta punta a questa

E’ divisa in 5 sezioni variabili a seconda del contenuto delle pagine.

Su HeadContent viene fatto il rendering html dell’header , script, css, metatag e contenuti

che vanno dal tag <head> al tag </head>

FeaturedContent contiene i pulsanti e/o menu specifici di ogni singola pagina aspx a

seconda delle caratteristiche che deve svolgere.

Toolbar viene utilizzato per i pulsanti specifici di una griglia

MainContent viene utilizzato per il rendering di griglie di dati, <table>, contenuti dinamici.

Sostanzialmente corrisponde al tag <body> della pagina.

MenuSinistro viene utilizzato per i menu specifici per una sotto-webapp

NavBar e Footer sono impostati in modo statico sulla Home e restano invariati per il

periodo che dura la sessione

L’accounting è demandato alle pagine contenute nella sottocartella \Account. Ogni avvio di

sessione viene eseguito il login e reindirizzato sulla home se l’account è in cache ed è valido,

altrimenti si ferma sulla pagina Login.aspx.

MySail: Guida di riferimento per il Programmatore – pag 19

Fig 2. Regioni di rendering html del sito

3.10 Struttura Logica

Per questioni di praticità, compatteza del codice, e performance reali dei tempi di risposta

delle richieste, sono state adottate le seguenti 3 strategie di sviluppo

1) Tutto il layout di stile e grafico è controllato da regole CSS in bootstrap.css

2) Tutte le funzionalità client sono controllate da funzioni jQuery standard e Javascript

personalizzato nel file \Script\citypost.js

3) Tutte le chiamate al server che richiederebbero il refresh della pagina sono chiamate

Ajax e sono totalmente contenute nel file ajax.cs

bootstrap.css

E’ il raccoglitore di regole css piu evoluto e usato nel 2015 per i siti web attualmente in rete.

WordPress, Google, Microsoft, Twitter, sono solo alcuni tra gli utilizzatori. Fornisce

caratteristiche Responsive affidabili e di alta precisione. I temi Responsive sono i siti web

scalabili a seconda delle dimensioni dello schermo, che sia Desktop, telefono o Tablet.

Bootstrap espone una svariata gamma di utilities gia confezionate e pronte all’uso che

integrate con jQuery potenziano e facilitano lo sviluppo di apps di portali web moderni e

dispositivi mobile.

3.11 jQuery

La MasterPage Site.Master istanzia nell’header, carica e poi inizializza citypost.js alla fine del

rendering sul browser. Ovvero, nel dettaglio:

MySail: Guida di riferimento per il Programmatore – pag 20

Nell’header include citypost.js

Esegue il rendering della pagina *.aspx (una qualsiasi) nei rispettivi ContentPlaceHolder

creando tutti i tag html

Inizializza la variabile master e rende visibile jQuery al nostro file js

<script type="text/javascript">

JavaScript:

try {

master.init({

jquery: jQuery

});

}

catch (err) {

ShowErrorMessage(err);

};

</script>

Solo a questo punto (a fine rendering) tutti i tag contenuti nella pagina del browser sono

visibili a jquery e al nostro citypost.js

3.12 Ajax

Base tecnologica: è il sistema per evitare il postbak e refresh dell’intera pagina quando si vuole

aggiornare solo una sua porzione. Il principio è semplice: la chiamata al server è fatta dal

client in Javacript a cui viene detto il tag <div> in cui scrivere il Response.Write da C#

Ajax è il core back-end di questa web application. Concettualmente il sito è strutturato

seguendo questa semplice regola: “Apri la pagina una sola volta caricando dal server tutto il

possibile che ti serve, poi tutto quello che manca dopo lo chiedi ad Ajax dal client “

E’ esattamente ciò che avviene. In questo modo avremo un singolo Page_Load lato C# in cui

aprire le connessioni, definire i datacontext, caricare Listbox statici, definire pulsanti ecc. Tutto

cioè che deve arrivare dal server come prima istanza della pagina si fa nel Page_Load.

Successivamente, se al click su un ListBoxItem, deve essere visualizzata una griglia di dati, si

esegue all’Onclick javascript: cpAjax('<div>’, 'url’)

Dove <div> è l’id del contenitore che riceve l’output, url la la chiamata alla pagina ajax

“/ajax?action=test&ecc ecc”

Il codice c# in ajax.cs farà il parser della querystring in entrata e nel Response.Write scriverà

tutto l’html che serve per la corretta visualizzazione dei dati sulla pagina

Un esempio pratico:

sulla pagina abbiamo un tag div con id pippo che non contiene nulla

<div id="pippo"></div>

Da javascript si chiama cpAjax('pippo’, 'http://192.168.16.200:4560/ajax?action=test’)

nel file Ajax.cs, dopo aver valutato la QueryString action = test, se avessimo questa istruzione

MySail: Guida di riferimento per il Programmatore – pag 21

var action = Request.QueryString["action"];

if (action != null && action == "test")

Response.Write("prova");

all’uscita della call troviamo sulla pagina del browser

<div id="pippo">prova</div>

Questo permette di accedere al server ogni volta che serve senza dover aggiornare tutto il

resto della pagina e intrigarsi con i PostBack e Reloads.

3.13 Sicurezza Ajax

Per evitare che dal browser possa essere inserito manualmente un link operativo, ad esempio

di cancellazione record, è stato previsto un passaggio di chiavi che lega la pagina chiamante al

server che esegue l’operazione. Ogni volta che arriva la pagina sul browser viene generato una

GUID diversa dal suo componente C#. Il client invia questo codice dal browser al server ed

Ajax continua solo se ha trovato corrispondenza. Le chiamate ajax sono attive solo su pagine

che hanno eseguito l’autenticazione, quindi dall’esterno o manualmente non è possibile fargli

eseguire qualcosa, va in errore. Restituisce “ApiKey non valido, ricaricare la pagina”

Al Page_Load della masterpage

// questo è l'id univoco che il client passa a Ajax come APIKEY

// solo chi si è autenticato passa da qui e assicura che da url diretto sulal pagina //

ajax.aspx non funzioni nessuna querystring

// cambia ad ogni pagina, quindi impossibile da sniffare. G0dPjn01 è un <asp:HiddenField />

Session["APiKey"] = System.Guid.NewGuid().ToString();

G0dPjn01.Value = Session["APiKey"].ToString();

In Page_Load di Ajax.cs

// controlli di sicurezza

if (Session["APiKey"] == null) throw new Exception("Apikey nullo, richiesta non convalidata");

if (!AuthConfig.ValidateToken(Response, Pattern.apiKey, Session["APiKey"].ToString()))

3.14 Aggiunta di una nuova pagina ASP.Net 4.5, jQuery, BootStrap, con uso

di Ajax, LinQ to SQL associata ad una master page

Aggiungi un nuovo elemento Web Form ASP.NET di nome test.aspx e seleziona Site.Master

come MasterPage

Il corpo della pagina appena creato si presenta come segue

<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" Runat="Server">

MySail: Guida di riferimento per il Programmatore – pag 22

</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="FeaturedContent" Runat="Server">

</asp:Content>

<asp:Content ID="Content3" ContentPlaceHolderID="ToolBar" Runat="Server">

.. metti qui il DropDownList ..

</asp:Content>

<asp:Content ID="Content4" ContentPlaceHolderID="MainContent" Runat="Server">

.. metti qui il tag Div vuoto ..

</asp:Content>

Aggiungi un ComboBox (DropDownList) nell’area FeaturedContent o ToolBar

<asp:DropDownList ID="cbUsers" runat="server" Width="234px" ClientIDMode="Static">

<asp:ListItem>Utenti</asp:ListItem>

<asp:ListItem>Ruoli</asp:ListItem>

<asp:ListItem>Profili</asp:ListItem>

<asp:ListItem>Applicazioni</asp:ListItem>

</asp:DropDownList>

E nel MainContent

<div id="listTable">

<%-- qui ci va il response ajax --%>

</div>

inserisci nel Page_Load del *.cs

cbUsers.Attributes.Add("onchange", "SelectSecurity(this);");

Crea la function SelectSecurity(this) in citypost.js

function SelectSecurity(item)

{

if (item.value=='Utenti') {

cpAjax('listTable', CreateAjaxCall('ADMIN', 'GetUsers'));

}

}

cpAjax e CreateAjaxCall sono gia fatte, basta richiamarle e fanno tutto da sole

Scrivi il codice dentro il file ajax.aspx.cs che dovrà renderizzare sul tag listTable per

action=GetUsers

if (a == "GetUsers")

{

Response.Write("<select class=\"form-control\">");

AspNetDataContext db = new AspNetDataContext();

var ds = db.Users;

foreach (var r in ds)

{

Response.Write("<option value =\""+ r.UserId.ToString()+"\">"+ r.UserName +

"</option>");

}

MySail: Guida di riferimento per il Programmatore – pag 23

Response.Write("</select>");

}

3.15 Sequenza eventi - Pipeline

Per impostare i breakpoint in fase di sviluppo è importante sapere cosa succede quando un

client accede al sito, quando e cosa fa una parte di codice:

seq File Evento Cosa fa

1 Global.asax Application_Start Viene inizializzata la variabile di

Sessione pubblica, avviato il Logger,

stabilite le connessioni multiutente,

registrati gli scripts MS e Accessi esterni

2 “” Session_Start Controllo autenticazione. Attenzione che

se l’utente è memorizzato nella cache,

se è gia stato caricato in Context.User,

fa tutto aspnet

3 Site.Master.cs Page_Init Check cookies, anti xfr, genera tokens di

sicurezza

4 “” Master_Page_Preload Anti-xfr

5 Default.cs Page_Load Check ruoli e impostazioni

6 Site.Master.cs Page_Load Inizializza le impostazioni di paginazione

Attenzione che Application, Session e Page hanno Lifecycle differenti.

3.16 Suddivisione aree applicative

e separazione contesti

Come è noto, i servizi SailNet/SailPost hanno utenze e contesti completamente diversi. La

caratteristica che condividono è l’assistenza. Questo portale ha lo scopo di unificare le attività

per i Redattori e Admin, e separarle per l’utente finale, che sia un cliente, una agenzia, una

PPA.

Come si ‘dovrebbe’ poter intuire dallo schema sottostante, all’apertura del sito viene richiesta

la pagina di Default.aspx sulla root. A seguito di un flusso di controlli che vengono fatti in fase

di autenticazione si viene rediretti sulla webApp di pertinenza.

MySail: Guida di riferimento per il Programmatore – pag 24

3.17 CheckList Manutenzione sito

Cose da fare e tenere presente quando si crea una nuova pagina o si aggiunge una

caratteristica

Come da prassi è consigliabile individuare la pagina piu simile a quella che deve essere

implementata e farne una copia. Ad ogni modo qualsiasi sia la strategia scelta per aggiungere

cose è importante che ciascun sviluppatore adotti gli stessi strumenti adottati per il resto del

sito.

MasterPage: Nessuna pagina deve essere senza Master Page, a meno che non lo

richieda la caratteristica specifica. Senza MasterPage vengono saltati alcuni controlli di

sicurezza e non ci sono script clients collegati, né funzionalità ajax. Anche una semplice

MySail: Guida di riferimento per il Programmatore – pag 25

pagina informativa deve passare dal Core del sito. I sottositi SailNet ha la sua Master

Page in previsione di accogliere la gestione web di SailNet.

Scripts Bootstrap.css, js, less e tutti i js jQuery non devono MAI essere modificati, in

quanto sono OpenSource e sicuramente verranno aggiornati. Utilizzare files css o js

propri per aggiungere metodi o fare l’override su metodi esistenti

Web.Sitemap ogni nuova pagina creata deve essere aggiunta a questo file. Non tanto

per la funzionalità del sitemap ma per la visualizzazione del breadcrumb. Ogni voce

inserita in questo file verrà mostrata sull’header delle pagine

Web.config: deve avere die ConnectionString. Una DefaultConnection per il motore di

autenticazione asp.net. una DbDatiDefaultConnectionString per l’accesso a CPCONFIG

del BL.

<connectionStrings>

<add name="DbDatiDefaultConnectionString" connectionString="Data

Source=192.168.78.130;Network Library=DBMSSOCN;Initial

Catalog=CPCONFIG;User ID=sa;Password=sql123$%&amp;SQL;"

providerName="System.Data.SqlClient" />

<add name="DefaultConnection" connectionString="Data

Source=192.168.78.131;Network Library=DBMSSOCN;Initial

Catalog=SailWebData;User ID=sa;Password=sql123$%&amp;SQL;"

providerName="System.Data.SqlClient" />

</connectionStrings>

4. Abilitazioni utenti MySail

Questo capitolo spiega come registrare i nuovi utenti e le caratteristiche che devono avere sul

sistema per svolgere un determinato servizio

Per accedere alla pagina di Registrazione Utente, dalla home di Admin, click sul menu laterale

verde

MySail: Guida di riferimento per il Programmatore – pag 26

Il menu laterale

La pagina di registrazione

MySail: Guida di riferimento per il Programmatore – pag 27

Tipi di Utenti

4.1 Cliente Agenzia

Dalla pagina di registrazione creare l’utente di Tipo Cliente, Mettere il Codice Univoco fornito

da SailNet, poi password, nome completo, username, email

NON creare records su LoginDB, ci pensa da solo la registrazione

Il sistema aggiunge da solo i ruoli Cliente e Extranet

Al termine aggiungere a mano le AREE in UtentiAree di LoginDB. Vedi Small Parcel o

Telegrammi sull’abilitazione dei prodotti

Tutte le impostazioni sono modificabili sia da Admin che dall’agenzia di riferimento. Solo Admin

puo aggiungere o eliminare Ruoli

1.1 Admin

User: admin

Password: joshua.00

Ruoli: tutti

La home page di admin è \Admin.aspx, la pagina di sistema \Account\Admin.aspx

4.2 Small Parcel

Abilitare Cliente Agenzia

Aggiungere l’Area Extranet SMPARCEL

Nelle impostazioni Small Parcel verifica che siano abilitate le varie opzioni

MySail: Guida di riferimento per il Programmatore – pag 28

4.3 Telegrammi

Abilitare Cliente Agenzia

Aprire con SQLServerMS SailWebData la Tabella Permessi

Il Record con Nome = TELEXCLI contiene le abilitazioni. Al momento sono definiti utenti

specifici, quando verrà rilasciato basterà inserire il ruolo Clienti e Clienti Direzionali

4.4 Agenzia

Dalla pagina di registrazione creare l’utente di Tipo Agenzia, Mettere il codice univoco fornito

da SailNet,, solo password, nome completo, utente.

NON creare records su LoginDB, ci pensa da solo la registrazione

Il sistema aggiunge da solo i ruoli Agenzia e Extranet (se deve averla)

Al termine se non deve avere Extranet togliere il ruolo da Admin, al contrario, aggiungere a

mano le AREE in UtentiAree di LoginDB

Tutte le impostazioni eccetto Global Settings sono modificabili solo da Admin. L’agenzia le vede

in lettura

La home page delle Agenzie è /SailNet/Default.aspx

4.5 Imprenditori Agenzia

Abilitare Agenzia

Nelle Impostazioni Agenzia spuntare il CheckBox Utente Amministratore Agenzia

4.6 Redattori Agenzia (per statistiche roy, competenze, grafici su selezione

agenzia)

Aggiungere all’utente i ruoli Agenzia e Redattore

4.7 Clienti Direzionali

Aggiungere all’utente il ruolo Cliente Direzionale

4.8 Anagrafiche Centralizzate

Aggiungere all’utente il ruolo Intranet

4.9 Qualità

Dalla pagina di registrazione creare l’utente di Tipo Qualita, non mettere nessun codice

univoco, solo password, nome completo, utente.

MySail: Guida di riferimento per il Programmatore – pag 29

NON creare records su LoginDB, ci pensa da solo a creare il record su LoginDB

Il sistema aggiunge da solo i ruoli Qualita ed Extranet

4.10 Altro

Questo è il tipo di utente generico da utilizzare in fase di registrazione utente. Assegnare

questo tipo se non deve avere nessuna associazione di codici né con SailNet né con Extranet.

Non verrà creato o cercato su LoginDB. Il sistema gli assegna il Ruolo di Intranet. Gestirlo

manualmente se deve fare cose specifiche, agendo sui permessi, settings ecc (vedi il capitolo

dei permessi per l’amministratore)

4.11 Utenti con autorizzazioni Specifiche

Redattori Commerciali e Agenzia, Intranet, Extranet

c.castelli, e.domenici

Controllo Qualità

c.facenza

m.petrone

m.lamaestra

m.cimino

e.carnier

a.gambini

s.canovese

e.landi

PRELIOS

g.cavallaro

i.cellamare

c.lomonaco

l.vannini

s.pedrinazzi

b.bozzolo

m.casati

i.milone

X Test Amministratore di Condominio

[email protected]

Redattore Agenzie

sailadmin \ss$$admin

x test Imprenditore Agenzia

MySail: Guida di riferimento per il Programmatore – pag 30

c.frassini.lu1

x test Cliente Agenzia (no Small Parcel)

[email protected]

x test Cliente Agenzia DEMO

sailtest\sailtest

x test Agenzia Operatore

agdemo

Troubleshooting

Se si danneggiano i ruoi di admin o non si entra piu con admin eseguire queste 2 query sul

192.168.78.131

-- cancella tutti i ruoli di 'admin'

delete FROM [SailWebData].[dbo].[UsersInRoles] where (UserId = '01991CC4-1373-4998-

82B4-840C3B7114A0')

-- gli aggiunge il ruolo Admin. dopodichè fa entrare sul sito e vanno aggiunti dal profilo tutti gli

altri ruoli. TUTTI MENO 'Extranet',

INSERT INTO [SailWebData].[dbo].[UsersInRoles] ([UserId] ,[RoleId]) VALUES ( '01991CC4-

1373-4998-82B4-840C3B7114A0' ,'D0D2EBC2-C4CD-41ED-A451-8FB4CED61B39')

5. Impostazione Permessi e Settings dei singoli utenti e controllarli da

programma

5.1 Gestione Permessi

Per la gesione dei permessi sono coinvolte 3 tabelle di SailWebData sul Sql server *.131 a

Pomezia

- Permessi

- SWSettings

- SWConfig

I Permessi e i settings sono visibili nella pagina Profilo.aspx.

Un permesso per ogni utente, puo avere uno di questi 3 stati:

- Non abilitato e quindi non visibile

- Abilitato e visibile ma non modificabile perche una autorita di contollo superiore ne

gestisce i valori

MySail: Guida di riferimento per il Programmatore – pag 31

- Abilitato ma non visibile (l’autorita di controllo gestisce i valori ma l’utente non puo

vederli nella sua pagina di profilo)

5.2 Tabella Permessi, significato delle colonne:

Pkey: Acronimo per agganciarlo da programma (es: var e =

usr.GetProfileBool(“EXT”)==true);

Nome : descrizione visualizzata nel profilo

Tipo: puo assumere uno dei seguenti valori:

page il nome pagina in Nome è soggetto a vilcoli di accessibilita descritti dai valori

rules e PermissionList

folder la cartella in Nome è soggetto a vilcoli di accessibilita descritti dai valori rules e

PermissionList

feature La PKEY e Descrizione descrivono una caratteristica, attivabile dal Profilo e

gestibile a programma

redirect La pagine in Nome è la home page degli utenti che rientrano nelle condizioni in

rules e PermissionList

settings È identico a feature

Rules:

le regole prese dal codice in AuthConfig.cs di LibCoreMySail

strict i ruoli su permessi devono essere tutti in Roles utente. lutente puo averne di piu, ma quell in permessi devono esserci tutti

MySail: Guida di riferimento per il Programmatore – pag 32

any i ruoli su permessi deve averne almeno uno in Roles dell'utente. all i ruoli su permessi devono essere identici a quelli dell'utente se in rules c'è user, le condizioni di cui sopra sono applicate all'utente. ovviamente se su peressi è specificato piu di un utente 'all' non sara mai soddisfatta, sarebbe una impostazione sbagliata se soddisfa queste condizioni il permesso appartiene al'utente su rules per default il permesso è conecesso (allow), se è specificato 'deny' il permesso è dell'utente ma per il check che non usi tale permesso, gli viene impedito.

Altro schema (stesso significato)

strict (predefinito) significa che questo permesso è abilitato per l'utente se i Ruoli

presenti in colonna PermissionList appartengono all'utente o se specificato Users

l’utente è in PermissoinList

any significa che questo permesso è abilitato per l'utente se tra i Ruoli che ha, almeno

uno è in PermissionList

all significa che questo permesso è abilitato per l'utente se i Ruoli presenti nella

colonna PermissionList corrispondono esattamente ai suoi, non ne deve avere altri

oltre questi

allow (predefinito) Concede il permesso

deny Nega il permesso, cioè inverte il significato risultante di strict,any,all

roles (Predefinito) significa che nella colonna permissionlist sono presenti i ruoli

dell'utente separati da virgola

users significa che nella colonna permissionlist sono presenti usernames separati da

virgola

Strict, any o all puo comparire un valore per volta

Allow,deny puo comparire un valore per volta

Roles,Users puo comparire un valore per volta

strict, allow, roles è un Rules valido

strict,all, users è un Rules non ammesso

le regole prese dal codice in AuthConfig.cs di LibCoreMySail funzione Verify()

rules: mix di 3 possibili parametri separati da virgola 1 allow se passa le condizioni il permesso deve essere concesso 1 deny se passa le condizioni il permesso è negato 2 users PermissioList contine nomi di utenti separati da virgola 2 roles PermissioList contiene ruoli separati da virgole 3 strict i ruoli su permessi devono essere tutti in Roles utente.

l'utente puo averne di piu, ma quell in permessi devono esserci tutti 3 any i ruoli su permessi deve averne almeno uno in Roles dell'utente. 3 all i ruoli su permessi devono essere identici a quelli dell'utente se in rules c'è user, le condizioni di cui sopra sono applicate all'utente. ovviamente se su peressi è specificato piu di un utente 'all' non sara mai soddisfatta, sarebbe una impostazione sbagliata se soddisfa queste condizioni il permesso appartiene al'utente su rules per default il permesso è conecesso (allow), se è specificato 'deny' il permesso è dell'utente ma per il check che non usi tale permesso, gli viene impedito. tip: per fare un permesso globale da concedere a tutti, fai un deny ad anonimo. tutti gli altri hanno il pemesso

MySail: Guida di riferimento per il Programmatore – pag 33

Esempi

strict Agenzia,Extranet tutti gli utenti con ruoli Agenzia e Extranet

any,user f.guerrazzi,e.landi permesso abilitato per questi soli due utenti

all,user f.guerrazzi,e.landi permesso errato, sarà sempre falso

any,user,deny f.guerrazzi,e.landi il permesso è valido per tutti gli utenti eccetto questi

due

per ogni ogni permesso valido, vengono caricati tutti i settings nella tabella SWSettings in cui

PKEYLIst contiene la PKEY del permesso stesso

la PropKey del record di SWSetting ha il suo corrispondente valore per ogni utente in SWConfig

quindi per ogni utente che rientra nei criteri di un permesso, al momento del caricamento

(AuthConfig.ActivateUser) vengono caricati

TREE NODES TABELLA

Permesso 1 Permessi

Setting 1 SWSetting

Valore del Setting+Username SWConfig

Setting 2 SWSetting

Valore del Setting+Username SWConfig

Permesso 2 Permessi

Setting 1 SWSetting

Valore del Setting+Username SWConfig

Setting 2 SWSetting

Valore del Setting+Username SWConfig

Setting 3 SWSetting

Valore del Setting+Username SWConfig

Setting 4 SWSetting

Valore del Setting+Username SWConfig

Permesso 3 Permessi

Setting 1 SWSetting

Valore del Setting+Username SWConfig

5.3 Uso dei permessi e settings da programma

I permessi e i setting hanno un livello di controllo a seconda di quello che è specificato in

owner ovvero una agenzia puo impostare delle opzioni ai propri clienti, l’admin puo impostare

le opzioni delle agenzie.

Per recuperare una impostazione di configurazione a programma occorre sapere di quale

utente si vuole il setting, l’amministratore o l’impersonato.

MySail: Guida di riferimento per il Programmatore – pag 34

5.3.1 Utente principale e utente impersonato

In sessione vengono memorizzati due utenti, sempre disponibili in qualsiasi punto

dell’applicativo.

Al momento del login l’utente viene popolato un oggetto SWUtente salvato in

Session["utente"] e in Session["utente_Selected"]

Quando si impersona un altro utente questo va in Session["utente_Selected"]

Quindi, se si vuole controllare l’utente impersonato o corrente utilizzare

var usr = SailWeb.getSessionUser(Context);

mentre

var usrAdmin = SailWeb.getSessionUser(Context,"utente")

per ottenere l’utente amministratore del login fisico

in questo caso usr è l’amministrato e usrAdmin è l’amministratore.

L’oggetto SWUtente ha una serire di proprietà per recuperare i permessi o settings

5.3.2 Leggere a programma i setting di un utente

var usr = SailWeb.getSessionUser(Context);

var ShowDashBoard = usr.ProfileGetBool("DASHBOARDONSTARTUP", false, "ENV");

vogliamo leggere il valore booleano del SWSetting key DASHBOARDONSTARTUP del permesso

Permessi.PKey "ENV" e se non lo trova come predefinito deve restituire false

utilizzare usr.ProfileGet usr.ProfileGetInt usr.ProfileGetDecimal ecc per recuperare valori

di tipo diverso, come il CodUnivoco usr.ProfileGetDecimal("CODUNIVOCO", 0, "CLI");

altr esempi:

// l'utente deve essere abilitato agli smallParcel o non accede alla pagina

if (!user.ProfileGetBool("SPLCL", false, "SPLCL"))

{

SailWeb.LogIt(Context,"isInExtranetArea: Errore accesso aree Extranet, nessuna

area valida trovata");

throw new Exception("Accesso negato a SmallParcel.aspx, " + user.UserName +

" non dispone dei permessi necessari o la pagina è scaduta.");

}

Oppure, per sapere se può impersonare clienti

usr.ProfileGetBool("IMPUSR", false, "IMPUSR"))

5.3.3 Autorizzare / negare accesso alle pagine

MySail: Guida di riferimento per il Programmatore – pag 35

Per controllare gli accessi alla pagina è possibile negare o vincolare l’accesso alla cartella

impostando nei permessi la folder o la pagina aspx, e poi usare questo codice che fa tutto da

solo

if (AuthConfig.AutorizzaAccessoPagina(Context) == false)

{

SailWeb.AddMessageQueue("Accesso negato","Accesso non convalidato, riprovare

piu tardi",2);

Context.Response.Redirect("/Account/Login.aspx", true);

return;

}

6. Sistema Royalties – per il programmatore

(se devi effettuare l’estrazione mensile vai al capitolo 7, pagina 41)

6.1 Dove stanno i sorgenti\binaries

Tutti I sorgenti e i perogetti stanno sul \\Citypost-RDBMS\Temp\Fabio\Royalties\Luana.rar, in

cui ci sono tutti gli excel di analisi, documenti, scripts, progetti vb6. Il vecchio progetto

CS_Royalties su cui sono nate le roy. Oggi il progetto che effettua l’estrazione, aggiornato a

maggio 2016 è RoyBatch e sta su SVN nella solution 2015_SailWeb.sln . Se è richiesto un

intervento, un controllo, una modifica, per la parte web è tutto concentrato nel file

App_Code\SailNetStorageROY.cs, l’estrazione è nel progetto RoyBatch

6.2 Requisiti

- Sul Server dove gira RoyBatch deve essere installato il driver di MSAccess ACL 64 bit

- Quando dal sito si richiede l’estrazione deve essere attivo il servizio CPWinService

- Sul server deve esistere la cartella E:\siti\Files\Roy

Volume in drive E is E

Volume Serial Number is EEED-5B00

Directory of E:\siti\Files\Roy

25/05/2016 13.58 <DIR> .

25/05/2016 13.58 <DIR> ..

02/05/2016 16.19 5.574.656 Exp_Sailnet.mdb

07/04/2016 13.00 5.574.656 Exp_Sailnet_WEB_ROY.mdb

25/05/2016 13.58 0 files.txt

11/09/2014 08.57 536.256 Handle.exe

03/03/2015 12.48 458 Leggimi.txt

MySail: Guida di riferimento per il Programmatore – pag 36

29/01/2015 10.32 25 lockby.bat

07/01/2016 12.44 <DIR> mdb mandati a GAP

02/05/2016 16.19 5.574.656 royfatt.mdb

23/02/2015 14.17 548.864 royfatt_vuoto.mdb

8 File(s) 17.809.571 bytes

3 Dir(s) 51.830.001.664 bytes free

- Sul server deve esistere la cartella degli eseguibili

Volume in drive E is E

Volume Serial Number is EEED-5B00

Directory of E:\Batch\RoyBatch

25/05/2016 14.01 <DIR> .

25/05/2016 14.01 <DIR> ..

11/08/2015 11.00 587.776 7za.exe

05/05/2016 13.28 648.766 BL.dll

05/05/2016 10.38 13.824 CL.dll

05/05/2016 13.28 1.147.392 Common.dll

11/08/2015 11.00 118.784 ExcelLibrary.dll

25/05/2016 14.01 0 files.txt

02/05/2016 15.57 765 generaroy.bat

05/05/2016 13.29 1.203 help_parametri.txt

11/08/2015 11.00 4.018.176 itextsharp.dll

11/08/2015 11.00 3.152.611 itextsharp.xml

02/05/2016 17.03 106.496 LibBlComuni.dll

05/05/2016 13.28 19.968 LibBlNormalizza.dll

29/02/2016 12.01 12.800 LibCompress.dll

05/05/2016 10.38 85.504 LibComuni.dll

05/05/2016 10.38 7.680 LibCrypting.dll

05/05/2016 10.38 16.384 LibCsvReader.dll

29/02/2016 12.01 72.192 LibCsvTables.dll

29/02/2016 12.01 36.352 LibDatiCitypost.dll

05/05/2016 10.38 23.552 LibDb.dll

28/04/2016 09.00 34.304 LibExecSql.dll

05/05/2016 10.38 91.136 LibForConnection.dll

29/02/2016 12.01 39.936 LibFtp.dll

29/02/2016 12.01 875.520 LibNormalizza.dll

29/02/2016 12.01 29.696 LibOffice.dll

29/02/2016 12.01 33.792 LibPdf.dll

05/05/2016 10.38 38.400 LibPosta.dll

02/05/2016 17.03 36.864 LibProcessi.dll

28/04/2016 09.00 25.600 LibTellus.dll

29/02/2016 12.01 19.968 LibWebService.dll

02/10/2015 12.24 <DIR> log

18/04/2016 09.14 37.376 LumenWorks.Framework.IO.dll

18/04/2016 09.13 83.359 LumenWorks.Framework.IO.xml

11/08/2015 11.00 495.616 Newtonsoft.Json.dll

18/04/2016 09.52 222.432 PostSharp.dll

18/04/2016 09.52 635.179 PostSharp.xml

18/09/2015 14.48 439.808 Renci.SshNet.dll

05/05/2016 13.47 93.696 RoyBatch.exe

05/05/2016 14.17 1.122 RoyBatch.exe.config

05/05/2016 10.14 22.688 RoyBatch.vshost.exe

12/10/2015 11.15 3.036 RoyBatch.vshost.exe.config

30/10/2015 09.19 490 RoyBatch.vshost.exe.manifest

24/02/2015 16.29 3.558 RoyBatch.vshost.exe_BAK.config

MySail: Guida di riferimento per il Programmatore – pag 37

02/10/2015 12.36 <DIR> save

02/05/2016 14.29 <DIR> save_maggio

02/03/2016 14.40 <DIR> save_marzo

04/10/2015 17.28 44 testroy.bat

12/10/2015 11.13 <DIR> v3

42 File(s) 13.333.845 bytes

Dir(s) 51.829.981.184 bytes free

6.3 Parametri di RoyBatch.exe

-v verbose, scrive su console il progresso

-p pausa. si ferma prima di uscire (usare solo se non Š lanciato dal servizio)

-pid:<id

processo>

Avvia processo pid che contiene i parametri e mostra l'avanzamento e

completamento. Se i parametri sono passati qui hanno precedenza su quelli del

db (se eseguito dal *.bat non considera i parametri del db)

-user:<user> utente che richiede il batch

-

anno:<aaaa>

Anno di fatturazione

-

mese:<mm>

mese di fatturazione

-age: <idAge1,idAge2,..> Agenzie da filtrare (elabora solo queste). Con parametro

mancante elabora tutte

-partial:0 0 o mancante esegue tutte le fasi. Da 1 a 5 esegue elaborazione parziale

saltando le fasi prima di questa.

-sim:1 esegue simulazione estraendo dal 1 al 3 gennaio 2013

-check esegue il controllo accessibilita mdb. Se presente questa opzione tutte le altre

operative vengono ignorate

-chkConn esegue il controllo sulla connessione al db. Se presente questa opzione tutte le

altre operative vengono ignorate

-fatt: <data fatt>;dex periodo. data fattura e descrizione periodo nel corpo della

fattura che andra sul gap (es: 31/01/2016;dal 01/01/2016 al 31/01/2016)

Esempi (da generaroy.bat):

@echo off

rem (senza parametri per elenco parametri)

rem roybatch

rem (verifica il driver oledb di access)

rem roybatch -check

rem (verifica l'accesso a SQL e alla tabella processi)

rem roybatch -chkConn

rem esecuzione da riga di comando senza aggiornare il db SailWebData.Processes

rem RoyBatch -v -user:admin -anno:2013 -mese:01 -fatt:31/01/2013;"Periodo dal

01/01/2013 al 31/01/2013" -sim:1

rem con pid e parametri come vengono passati dal servizio CPWinService letti dal db

MySail: Guida di riferimento per il Programmatore – pag 38

rem RoyBatch -v -user:admin -pid:292 -anno:2015 -mese:08 -fatt:'31/08/2015';"Periodo dal

01/08/2015 al 31/08/2015" -sim:0

RoyBatch -p -v -pid:1227 -user:admin -anno:2016 -mese:04 -sim:0 -fatt:'30/04/2016';"'dal

01/04/2016 al 30/04/2016'" -partial:1

pause

Il Core dell’estrazione si trova in RoyBatch.Programs

Storage.RoyClass.executeJob(Shared.Anno, Shared.Mese, Shared.DataFatt, Shared.Periodo,

Shared.Sim, Shared.Partial, Shared.Agenzie);

E in RoyClass

internal void executeJob(int aa, int mm, string DataFatt, string dex, bool simula = false, int Parziale = 0, List<int> Agenzie = null) { try { // qui esegue il codice

Anno = aa; Mese = mm; isSimulazione = simula; DataFatt = DataFatt.Replace("'", ""); DateTime dFatt = new DateTime(); try { dFatt = LocalizationPar.fromStringClientToDate(DataFatt, ""); } catch (Exception ex) { throw new Exception("Errore nella conversione della data fattura da string a datetime: " + ex.Message); } if (isSimulazione) { Anno = 2013; Mese = 1; dex = "Periodo di TEST dal 01/01/2013 al 4/01/2013"; dFatt = DateTime.Now; } Shared.LogIt("Data Fattura: " + dFatt.ToString()); Shared.LogIt("Parziale: " + Parziale.ToString()); //LoggerBl.Debug("Data Fattura: " + dFatt.ToString()); if (Parziale==0) { batchStep("1 di 5 (EstraiMese - riversa Raccomandate su ROY_STORED_TABLE)"); // Shared.LogIt("**** Eseguito Step 1"); EstraiMese(Anno, Mese); } else { batchStep("1 di 5 EstraiMese (**** NON ESEGUITA A CAUSA DELLA PRESENZA DEL PARAMETRO -PARTIAL)");

MySail: Guida di riferimento per il Programmatore – pag 39

} if (Parziale == 0 || Parziale < 2) { batchStep("2 di 5 (Insert_Update_Royalties)"); // Shared.LogIt("**** Eseguito Step 2"); Insert_Update_Royalties(Anno, Mese, Agenzie); } else { batchStep("2 di 5 (**** NON ESEGUITA A CAUSA DELLA PRESENZA DEL PARAMETRO -PARTIAL>2)"); } if (Parziale == 0 || Parziale < 3) { batchStep("3 di 5 (GeneraRoy)"); // Shared.LogIt("**** Eseguito Step 3"); GeneraRoy(Anno, Mese, Agenzie); } else { batchStep("3 di 5 (GeneraRoy) (**** NON ESEGUITA A CAUSA DELLA PRESENZA DEL PARAMETRO -PARTIAL>3)"); } if (Parziale == 0 || Parziale < 4) { batchStep("4 di 5 (GeneraFatture)"); // Shared.LogIt("**** Eseguito Step 4"); GeneraFatture(Anno, Mese, dFatt, dex, Agenzie); } else {

batchStep("4 di 5 (GeneraFatture) (**** NON ESEGUITA A CAUSA DELLA PRESENZA DEL PARAMETRO -PARTIAL>4)"); } if (Parziale == 0 || Parziale < 5) { batchStep("5 di 5 (CopyToDataZoom)"); // Shared.LogIt("**** Eseguito Step 5"); CopyToDataZoom(Anno, Mese); } else { batchStep("5 di 5 (CopyToDataZoom) (**** NON ESEGUITA A CAUSA DELLA PRESENZA DEL PARAMETRO -PARTIAL>5)"); // qui non ci dovrebbe mai arrivare, i valori possono essere da 0 a 5 } batchStep("5 fasi completate. fatture generate su mdb "); SendMailToAdmin("Elaborazione Royalty completata, 5 fasi eseguite. Anno: " + Anno + ", Mese: " + Mese,"RoyBach.exe notifica completamento"); } catch (Exception ex) { SendMailToAdmin("Errore fatturazione roy " + Anno + ", Mese: " + Mese + "Testo del messaggio di errore: " + ex.Message, "RoyBatch: Errore esecuzione processo di estrazione"); batchAbort(ex.Message); throw ex; } batchEnd();

MySail: Guida di riferimento per il Programmatore – pag 40

}

6.4 Indicazioni dei committenti ricevute per mail, riunioni, comunicazioni

verbali ecc

Update 25/11/2014

Fabio

RoyAnniPrec contiene l’import del dettaglio dei dati di excel forniti da Luana il 21 Novembre

2014

Questa tabella serve solo per il conguaglio.

Attenzione che l’import da excel ha generato i dati su RoyAnniPrec e alcuni records in

Royalties. NON TOCCARE LE RIGHE DI ROYALTIES CON TUTTI GLI IMPORTI O % A 0,

SERVONO PROPRIO PER NON FARGLI RICALCOLARE IL PREGRESSO IN AUTOMATICO

Update 19/11/2014

Fabio

E’ stata inserita una nuova colonna nella tabella Royalties, di nome ValoreFatturato

(decimal(2))

Questo campo ospita le somme fatturato reale , mentre TotImponibile costituirà l’importo

soggetto a Royalties, che è lo stesso ma decurtato delle spese di trasporto e recapito e

viaggiante se previsto

Update 18/11/2014

Filippo:

nel caso di vecchio contratto (ovvero RoyDown <> RoyUp) si applicano le roy solo

ai flussi locali, ovvero Agedes = AgeOri oppure (AgeDes <> AgeOri e Comp = 'N')

Nel caso di nuovo contratto (ovvero RoyDown = RoyUp) si applicano le roy mese mese senza

andare a confrontare con il "fatturato" Roy dell'anno precedente:

- locale -> (AgeDes = AgeOri) oppure (AgeDes <> AgeOri e Comp = 'N') da inserire

nell'imponibile ROY prezzo - sconto

- Viaggiante OUT -> (AgeDes <> AgeOri e (Comp = 'S' oppure Comp is null) da inserire

nell'imponibile (prezzo - sconto) - (trasporto + recapitoAg)

Update 12/11/2014

6.5 Pregresso (Castelli)

Dai primi di novembre è sorta la necessità di riportare su db gli importi del fatturato anno

precedente, in quanto fisicamente non ricalcolabili altrimenti ci sarebbe una disparità fra

vecchio e nuovo. Questi valori devono essere presenti da settembre 2014 in poi.

MySail: Guida di riferimento per il Programmatore – pag 41

Dagli excel della tabella sottostante sono stati estratti le rige in celeste, e per agenzia, tipo,

trimestre e anno, è stato ottenuto un record su Royalties con l’importo anno passato. Questi

record sono distinti da tutti gli altri perche hanno “Anno<> 0 And Mese = 0” oppure la colonna

TipoRk = 5

Durante la funzione di “ESTRAZIONE ROYALTY” Il sistema cerca questo record prima di

ricalcolare l’ importo anno precedente, se lo trova applica questo, se no lo ricalcola.

Colonna TipoRk:

- 0 configurazione o dati appena estratti (si distinguono perche mese e anno sono = 0

per la config)

- 1 roy calcolata

- 2 rigo dettaglio fattura, con articolo

- 5 anno precedente da excel

6.6 Come sono stati riportati i dati di Excel sul DB

- Si sono salvati tutti gli xls di luana in CSV

- Si è fatto un programmino di normalizzazione in vb6

6.7 Casi particolari / Eccezioni

Da programma appena ricevuti i dati da sp ROY_LIST_ELEMENT vengono accorpate le agenzie

CASERTA 1/2 e CATANZARO 1/ 2

Nello stesso contesto raggruppa tutti i servizi (tipo 3) in NON TRACCIATO, (tipo 1)

foreach (var g in ListaRacc)

{

if (g.AgeOri == 81010) g.AgeOri = 81110; // da CASERTA 2 a CASERTA 1

if (g.AgeDes == 81010) g.AgeDes = 81110;

if (g.AgeOri == 88100) g.AgeOri = 88101; // da CATANZARO 2 a CATANZARO 1

MySail: Guida di riferimento per il Programmatore – pag 42

if (g.AgeDes == 88100) g.AgeDes = 88101;

if (g.TipoTracer == 3) g.TipoTracer = 1;

}

AGENZIA LUCCA 2 è presente sull’excel ma non è sul db, non è stato inserito, non essendo

sul db non avrà nemmeno le roy calcolate.

- Il nuovo sistema suddivide i tipi di articolo in 2 tipi, 1 NON TRACCIATI, 2 sono i

TRACCIATI. Dall’excel

- Essendo stato fatturato con vecchio sistema fino ad agosto 2014, gli importi anno

precedente devono essere presenti fino ad agosto 2015.

6.8 Criteri di calcolo Imponibile Royalty

// Applica tutte le eccezioni note, prima di creare o aggiornare il record Royalties

(ListaRacc è la ROY_STORED_TABLE)

foreach (var g in ListaRacc)

{

if (g.AgeOri == 81010) g.AgeOri = 81110; // accorpa CASERTA 2 con CASERTA

1

if (g.AgeDes == 81010) g.AgeDes = 81110;

if (g.AgeOri == 88100) g.AgeOri = 88101; // accorpa CATANZARO 2 con

CATANZARO 1

if (g.AgeDes == 88100) g.AgeDes = 88101;

if (g.TipoTracer == 3) g.TipoTracer = 1; // raggruppa tutto su NON TRACCIATO

(è stato cambiato nella stored, arrivano gia tutti con 1, si lascia comunque)

// cambia il flag competenza, assegna V per viaggiante L per locale o N a seconda dei casi

// il codice sottostante doddisfa le seguenti condizioni:

// nel caso di vecchio contratto (ovvero RoyDown <> RoyUp) si applicano le roy solo

// ai flussi locali, ovvero Agedes = AgeOri oppure (AgeDes <> AgeOri e Comp = 'N')

//Nel caso di nuovo contratto (ovvero RoyDown = RoyUp) si applicano le roy mese mese senza

andare a confrontare con il "fatturato" Roy dell'anno precedente:

- locale -> (AgeDes = AgeOri) oppure (AgeDes <> AgeOri e Comp = 'N') da inserire

nell'imponibile ROY prezzo - sconto

- Viaggiante OUT -> (AgeDes <> AgeOri e (Comp = 'S' oppure Comp is null) da inserire

nell'imponibile (prezzo - sconto) - (trasporto + recapitoAg)

bool locale = g.AgeOri == g.AgeDes || (g.AgeOri != g.AgeDes && g.comp ==

"N");

g.comp = "V";

if (locale) g.comp = "L";

int ag = g.AgeOri?? 0;

if (g.comp == "V") // esclu dei casi in cui non deve calcolare la viaggiante

{

if (!ages.Contains(ag)) // true = è tra le configurazioni con % identica =

nuovo contratto

g.comp = "N"; // se arriva qui è un vecchio contratto ed è una viaggiante,

non deve calcolare imponibile quindi si imposta il flag a N

MySail: Guida di riferimento per il Programmatore – pag 43

if (ag == 100303) g.comp = "N"; // MILANO 1 non DEVE calcolare la

viaggiante

}

}

[..]

..Poi quando legge il singolo record di ROY_STORED_TABLE, accumula l’importo se è (L)ocale o

(V)iaggiante, altrimenti 0

decimal importo = 0;

decimal price = Convert.ToDecimal(Prezzo);

decimal discount = Convert.ToDecimal(Sconto);

if (comp == "L")

importo = (price - ScontaPrezzo(discount, price)) * Convert.ToDecimal(Qta);

if (comp == "V")

importo = (price - (ScontaPrezzo(discount, price) - Convert.ToDecimal(Trasporto) -

Convert.ToDecimal(RecapitoAg))) * Convert.ToDecimal(Qta);

return importo;

6.9 Specifiche tecniche

Il sistema carica la tabella delle royalties in archivio, parte di questi records sono i saldi delle

elaborazioni (tipork= 5) e parte sono di configurazione. La configurazione è definita da tutti gli

elementi che hanno mese = 0

La colonna Tipo:

0- Tutti i tipi

1- NON TRACCIATO

2- TRACCIATO

Percentuali applicate

RoyUp % da applicare se l’imponibile del mese SUPERA l’imponibile dell’anno

precedente

RoyDown % da applicare se E’ INFERIORE all’imponibile dell’anno precedente

Quando si elabora il mese di una agenzia va a prendere le sue specifiche percentuali di calcolo.

Da Aprile 2016 TUTTE le agenzie devono essere presenti in configurazione. Se durante

l’estrazione viene trovato del lavorato e l’agenzia non viene trovata in configurazione il sistema

si ferma con un messaggio di errore “Agenzia non configurata per le Roy”. Questo impedisce di

MySail: Guida di riferimento per il Programmatore – pag 44

avere contratti fuori controllo, di cui il sistema non riesce ad associare le percentuali. Tutte le

agenzie devono essere contrattualizzate con le proprie percentuali in configurazione.

Per applicare una nuova percentuale ad una agenzia:

- Individuare il CodUnivoco dell’agenzia su AnagraficoClienti

- Aggiungere manualmente un record a Royalties

- Lasciare tutti i campi a 0 eccetto AgeOri, RoyUp, RoyDown. IDArticolo deve essere

lasciato null

Per applicare una percentuale specifica ad un tipo (TRACCIATO, NON TRACCIATO):

- Eseguire le stesse indicazioni per impostare una agenzia aggiungendo il tipo. Quando

l’applicazione trova che c’è un record agenzia-tipo applica queste percentuali specifiche

Per applicare una percentuale ad un singolo articolo:

- Non è implementato, ma basta fargli cercare IdArticolo con tutto il resto a 0

6.10 QUERY UTILI

Su SRV_CITY1.SailNet_Report

Imposta una agenzia per le simulazioni, rk fisso 751760

update royalties set UniAge= -168 where IDRoy = 751760

Select delle royalties di ANCONA1 per il 3° trimestre 2014

select top 1000 * from royalties where uniage = 168 and anno = 2014 and trimestre = 3 and

idArticolo is null

Criteri di calcolo Royalty:

- Il numero di elementi da conteggiare viene stabilito ed estratto dalla SP sotto riportata,

per i criteri si selezione e assegnazione a TRACCIATO o NON TRACCIATO consultare il

codice SQL, perche descriverla è piu complicato che leggerla

- Da programma viene poi calcolato l’imponibile per ogni rigo assegnando un prezzo con

la seguente formula:

public decimal fatturato()

{

decimal importo = 0;

decimal price = Convert.ToDecimal(Prezzo);

decimal discount = Convert.ToDecimal(Sconto);

MySail: Guida di riferimento per il Programmatore – pag 45

bool competenze = (comp == null || comp == "S");

if (AgeOri == AgeDes || !competenze)

{

// calcolo 1

// il prezzo è calcolato con (Prezzo - sconto se UniAgeOri ==

UniAgeDes) * NrColli

importo = (price - ScontaPrezzo(discount, price)) *

Convert.ToDecimal(Qta);

}

else

{

// altrimenti con (Prezzo - sconto - Trasporto - recapitoAg) * NrColli

[gli ultimi due sono i costi di viaggiante]

importo = (price - (ScontaPrezzo(discount, price) -

Convert.ToDecimal(Trasporto) - Convert.ToDecimal(RecapitoAg))) *

Convert.ToDecimal(Qta);

}

return importo;

}

private decimal ScontaPrezzo(decimal sconto, decimal prezzo)

{

if (sconto == 0 || prezzo == 0) return 0;

return (prezzo * sconto) / 100;

}

}

- Successivamente, se il progressivo del mese è inferiore al totale dell’anno precedente

calcola il valore della royalty sulla 1° %, altrimenti sulla 2°

public decimal CalcolaRoyalty(decimal progr)

{

RoyImpDown = 0; // li azzero perche potrebbero essere in Update

RoyImpUp = 0;

RoyValDown = 0;

RoyValUp = 0;

progr += TotImponibile; // somma l'imponibile del mese al progressivo

decimal r = progr - TotImpAnnoPrec;

if (r < 0) // totale del mese sotto quello dell'anno precedente, va sulla %

piu alta

{

RoyImpDown = r * -1;

RoyImpUp = 0;

if (Roydown > 0 || RoyImpDown > 0)

RoyValDown = (RoyImpDown * Convert.ToDecimal(Roydown)) /

100;

}

else // viene divisa sulle 2 %

{

MySail: Guida di riferimento per il Programmatore – pag 46

RoyImpDown = TotImpAnnoPrec;

RoyImpUp = r;

if (Roydown > 0 || RoyImpDown > 0)

RoyValDown = (RoyImpDown * Convert.ToDecimal(Roydown)) /

100;

if (Royup > 0 || RoyImpUp > 0)

RoyValUp = (RoyImpUp * Convert.ToDecimal(Royup)) / 100;

}

ProgrMese = progr; // scrive il progressivo in tabella per semplicita di

reportistica

TotRoyalty = RoyValUp + RoyValDown;

return progr;

}

6.11 Script Tabella Royalties

(Su SRV_CITY1.SailNet_Report) (maggio 2016)

USE [Sailnet_Report]

GO

/****** Object: Table [dbo].[Royalties] Script Date: 25/05/2016 11:00:32 ******/

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

SET ANSI_PADDING ON

GO

CREATE TABLE [dbo].[Royalties](

[IDRoy] [int] IDENTITY(1,1) NOT NULL,

[UniAge] [int] NOT NULL,

[Anno] [int] NOT NULL,

[Mese] [int] NOT NULL,

[Tipo] [int] NOT NULL,

[IDArticolo] [varchar](20) NULL,

[NumElementi] [int] NOT NULL,

[Roydown] [float] NOT NULL,

[Royup] [float] NOT NULL,

[TotImpAnnoPrec] [decimal](18, 2) NOT NULL,

[TotImponibile] [decimal](18, 2) NOT NULL,

[ValoreFatturato] [decimal](18, 2) NULL,

[ProgrMese] [decimal](18, 2) NULL,

[RoyImpUp] [decimal](18, 2) NOT NULL,

[RoyImpDown] [decimal](18, 2) NOT NULL,

[RoyValUp] [decimal](18, 2) NOT NULL,

[RoyValDown] [decimal](18, 2) NOT NULL,

[TotRoyalty] [decimal](18, 2) NOT NULL,

[TipoRk] [int] NOT NULL,

MySail: Guida di riferimento per il Programmatore – pag 47

[Trimestre] [int] NULL,

[Note] [nvarchar](250) NULL,

CONSTRAINT [PK_Royalties] PRIMARY KEY CLUSTERED

(

[IDRoy] ASC

)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,

ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

) ON [PRIMARY]

GO

SET ANSI_PADDING OFF

GO

6.12 Stored Procedure [NORMBATCH.ArchDati]

[dbo].[ROY_LIST_ELEMENT_WEB] (a maggio 2016)

USE [ArcDati]

GO

/****** Object: StoredProcedure [dbo].[ROY_LIST_ELEMENT_WEB] Script Date:

25/05/2016 11:03:09 ******/

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

-- =============================================

-- Author: <Ivo, Emanuele,Fabio>

-- Create date: <Ottobre 2014>

-- Update date: <Gennaio 2014>

-- Description: <Estrae il lavorato fisico da raccomandate e corpodistage>

-- Versione WEB cpw.4.5

--

-- temp Tables:

-- @TableRecords = Output

-- @TableIdDistinte = Lista IdDistinta nel periodo

-- @TableConCorpo = CorpoDistaAge compreso idAgenzia e Data di testata

--

--

--

-- 12/01/15 FG

-- Aggiunto idEstrazione e parametro idEstraz.

-- se il parametro è passato deve prima eliminare i records con questo id e poi riottenerli

-- =============================================

CREATE PROCEDURE [dbo].[ROY_LIST_ELEMENT_WEB]

@DEBUG INT = 0,

@DataFrom DateTime,

@DataTo DateTime,

@Estrazione int = 0

MySail: Guida di riferimento per il Programmatore – pag 48

AS

BEGIN

--DECLARE @Estrazione INT = 0

DECLARE @AgeId INT = 0 -- per debug di una singola agenzia, se è 0 estrae tutto

(FG 11/2014)

DECLARE @SoloPRINT INT =0

IF (@DEBUG = 1)

BEGIN

SET @SoloPRINT = 1

SET @DEBUG = 0

END

IF (@SoloPRINT = 1)

Print 'Inizio ' +Convert(Varchar(20), GetDate(), 100)

DECLARE @TableRecords TABLE (

[IdDistinta] [int],

[DataDistinta] [datetime] ,

[IdRecord] [int] ,

[NrRigoCorpo] [int],

[Tracer] [varchar](20),

[DataRaccom] [datetime] ,

[IdArticolo] [varchar](20),

[Qta] [int],

[Vettore] [int],

[Prezzo] [money],

[CodIva] [int] ,

[Sconto] [real] ,

[Trasporto] [money] ,

[RecapitoAg] [money],

DaCorpoDistAge int,

IdCorpoDistAge int,

[TipoTracer] tinyint,

[AgeOri] int,

[AgeDes] int,

[comp] [varchar](1),

[DataCreazione] [DateTime],

[idEstrazione] int

)

-- 04/01/2016 [fabio] da 'dbo.CorpoDistAge.IdVettore <> 2' a

'dbo.CorpoDistAge.IdVettore not in (2,4,5)'

-- 12/01/2015 [fabio], aggiunto id estrazione per eventuali rielaborazioni

-- 07/MAGGIO/2015 [fabio], tolta cancellazione id estrazione in automatico

-- 02/luglio/2015 [fabio] deve sempre mettere un id estrazione diverso..

SET @Estrazione = (SELECT (MAX(idEstrazione) + 1) from ROY_STORED_TABLE)

-- se è passato

/*IF (@Estrazione = 0)

SET @Estrazione = (SELECT (MAX(idEstrazione) + 1) from ROY_STORED_TABLE)

ELSE

IF (@SoloPRINT = 0) DELETE FROM ROY_STORED_TABLE WHERE idEstrazione =

@Estrazione

*/

MySail: Guida di riferimento per il Programmatore – pag 49

DECLARE @TableIdDistinte TABLE (IdDistinta int, Data datetime)

INSERT INTO @TableIdDistinte (IdDistinta, Data)

SELECT [t0].[IdDistinta], [t0].Data

FROM ([DistinteAgenzia] AS [t0] WITH (NOLOCK READUNCOMMITTED) inner join

anagraficheagenzia AS A1 WITH (NOLOCK READUNCOMMITTED)

ON t0.idforn=A1.idanagrafica)

left join anagraficaclienti AS A2 WITH (NOLOCK READUNCOMMITTED)

ON A1.codunivoco=A2.codunivoco

WHERE ([t0].[Data] >= @DataFrom) AND ([t0].[Data] <= @DataTo)

AND

(A2.clientedir<>1 or A2.clientedir is null)

AND

A1.CodUnivoco not in (100209, 100409)

IF (@DEBUG = 1)

SELECT * from @TableIdDistinte

IF (@SoloPRINT = 1)

Print '@TableIdDistinte estratte ' +Convert(Varchar(20), GetDate(), 100)

DECLARE @TableConCorpo TABLE (

[IdDistinta] [int],

[DataDistinta] [datetime] ,

[IdRecord] [int] ,

[NrRigoCorpo] [int] ,

[IDArticolo] [varchar](20),

[Qta] [real] ,

[Costo] [money] ,

[Sconto] [money],

[Iva] [int] ,

[Vettore] [int] ,

[AgeOri] [int] ,

[TipoArticoloCorpo] [Int]

)

INSERT INTO @TableConCorpo (IdDistinta,

[DataDistinta],[IdRecord],[NrRigoCorpo],[IDArticolo],[Qta],[Costo],[Sconto],[Iva],[Vettore],[A

geOri],[TipoArticoloCorpo])

SELECT dbo.DistinteAgenzia.IdDistinta, dbo.DistinteAgenzia.Data,

dbo.CorpoDistAge.IdRigo as [IdRecord],

dbo.CorpoDistAge.NRigo AS [NrRigoCorpo],

dbo.CorpoDistAge.IDArticolo,

dbo.CorpoDistAge.Qta, dbo.CorpoDistAge.Costo, dbo.CorpoDistAge.Sconto,

dbo.CorpoDistAge.Iva, dbo.CorpoDistAge.IdVettore AS

Vettore, dbo.DistinteAgenzia.CodUniAge,

dbo.CorpoDistAge.tipoarticolo

FROM @TableIdDistinte AS TMP INNER JOIN dbo.DistinteAgenzia WITH (NOLOCK

READUNCOMMITTED) ON dbo.DistinteAgenzia.IdDistinta = TMP.IdDistinta

INNER JOIN dbo.CorpoDistAge WITH (NOLOCK READUNCOMMITTED) ON

dbo.DistinteAgenzia.IdDistinta = dbo.CorpoDistAge.IdDistinta

WHERE --(@AgeId<>0 AND dbo.DistinteAgenzia.CodUniAge=@AgeId) OR

@AgeId=0

dbo.CorpoDistAge.IdVettore not in (2,4,5)

IF (@DEBUG = 1)

SELECT * from @TableConCorpo

MySail: Guida di riferimento per il Programmatore – pag 50

IF (@SoloPRINT = 1)

Print '@TableConCorpo estratte ' +Convert(Varchar(20), GetDate(), 100)

-- Tracer= 1- NON TRACCIATO, 2- TRACCIATO,

INSERT INTO

@TableRecords([IdDistinta],[DataDistinta],IdRecord,[NrRigoCorpo],[Tracer],[DataRaccom],[Id

Articolo],[Qta],

[Vettore],[Prezzo],[CodIva],[Sconto],[Trasporto],[RecapitoAg],

DaCorpoDistAge, IdCorpoDistAge,

TipoTracer,

AgeOri,AgeDes,comp,[DataCreazione], idEstrazione)

select RCC.IdDistAge, TMP.[Data],RCC.IdRaccom AS [IdRecord],

[RigoDistAge],RCC.CodRaccom AS [Tracer], RCC.Data AS DataRaccom,

RCC.[IDArticolo],RCC.NrColli as [Qta],

RCC.[Vettore],RCC.[Prezzo],RCC.CodIva as

Iva,RCC.[Sconto],RCC.[Trasporto],RCC.[RecapitoAg], 0 as DaCorpoDistAge, null AS

IdCorpoDistAge,

(CASE WHEN ART.Tracer = 0 THEN

1

WHEN ART.Tracer = 1

THEN 2

ELSE 1

END

)

AS TipoTracer

,

RCC.[UniAgeOri],RCC.[UniAgeDes],

AgenzieViagg.competenze,

GETDATE(), @Estrazione

FROM ((Raccomandate AS RCC WITH (NOLOCK READUNCOMMITTED) left join

anagraficaclienti AS a WITH (NOLOCK READUNCOMMITTED) on

rcc.idmittunivoco=a.codunivoco)

left JOIN dbo.agenzietoagenzie As AgenzieViagg WITH (NOLOCK

READUNCOMMITTED)

ON (RCC.uniageori=agenzieViagg.agenziaori and

RCC.uniagedes=agenzieViagg.agenziades))

LEFT JOIN @TableIdDistinte AS TMP ON TMP.IdDistinta = RCC.IdDistAge

INNER JOIN Articoli AS ART WITH (NOLOCK READUNCOMMITTED) ON

RCC.[IDArticolo] = ART.IDArticolo

WHERE rcc.vettore not in (2,4,5) and (a.clientedir<>1 or a.clientedir is null)

AND rcc.idarticolo not like 'PPTE%' AND -- per non prendere prioritarie estere,

condizione uniagedes<>100403 è meglio ???

(

(TMP.IdDistinta is null and (RCC.Data between @DataFrom AND

DATEADD(hh, 23,@DataTo)))

OR

TMP.IdDistinta is Not null

)

AND

RCC.IdMittUnivoco not in (100209, 100409)

-- AND ( (@AgeId<>0 AND AgeOri=@AgeId) OR @AgeId=0 )

--DELETE From @TableConCorpo

--WHERE IdRecord IN (Select IdCorpoDistAge FROM @TableRecords)

MySail: Guida di riferimento per il Programmatore – pag 51

INSERT INTO

@TableRecords([IdDistinta],[DataDistinta],IdRecord,[NrRigoCorpo],[Tracer],[DataRaccom],[Id

Articolo],[Qta],

[Vettore],[Prezzo],[CodIva],[Sconto],[Trasporto],[RecapitoAg],DaCorpoDistAge,

IdCorpoDistAge,

AgeOri, AgeDes,TipoTracer,[DataCreazione], idEstrazione)

select IdDistinta, [DataDistinta],[IdRecord], [NrRigoCorpo],'' AS [Tracer],[DataDistinta]

AS[DataRaccom], [IDArticolo],[Qta],

[Vettore],[Costo] AS Prezzo,[Iva],[Sconto], 0, 0, 1 as

DaCorpoDistAge, IdRecord AS IdCorpoDistAge,

AgeOri, AgeOri, 1,GetDate(),@Estrazione

FROM @TableConCorpo

WHERE [TipoArticoloCorpo] = 0

IF (@DEBUG = 1)

SELECT * from @TableRecords

IF (@SoloPRINT = 1)

Print 'Prima di select finale ' +Convert(Varchar(20), GetDate(), 100)

-- Voluta da castelli il 14/11/14 per produzione dettaglio articolo per articolo da

spedire in xls alle agenzie

-- NB ogni estrazione accoda, se vengono rifatte estrazioni identiche vanno eliminate le

precedenti a mano (FG)

DECLARE @cnt int = 0

IF (@SoloPRINT = 0)

BEGIN

INSERT INTO ROY_STORED_TABLE

SELECT *

FROM @TableRecords

END

-- ELSE

--SET @cnt = (SELECT COUNT(*) FROM @TableRecords)

-- Print 'Record estratti (DEBUG): ' + @cnt

-- DROP TABLE ROY_STORED_TABLE

--SELECT *

-- INTO ROY_STORED_TABLE

--from @TableRecords

-- SELECT *

-- from @TableRecords

END

GO

MySail: Guida di riferimento per il Programmatore – pag 52

6.13 Altre tabelle

Su SRV_CITY1.SailNet_Report risiede la tabella ufficiale delle ROY Royalties

RoyAnniPrec in cui sono presenti tutti i totali dell’anno 2013, di riferimento per il 2014, anno

di passaggio da manuale a informatico. Su questa tabella sono stati riportati i totali calcolati

dagli excel di Luana. Per gli anni successivi la Royalties stessa contiene gli importi dell’anno

precedente. Cio significa che dopo l’attivazione questa tabella non serve piu, ma si tiene come

storico dei calcoli effettuati.

RoyRiepilogo è stata utilizzata per le verifiche incrociate del calcolo dei conguagli a settembre

2014, data in cui sono state inviate le fatture di conguaglio alle agenzie. Si tiene come storico

dei calcoli effettuati.

7. Sistema Royalties ed estrazione mensile, per l’amministratore del sito

Tempo medio per eseguire l’attività: 40 minuti (circa 20 minuti l’estrazione)

7.1 Introduzione

Gli screenshoot di questa giuda sono della prima versione ancora da pubblicare, per quello

appaiono in celeste twitter. Oggi i colori cambiano ma le funzioni sono identiche

7.2 Accesso

Vai al link http://net.sailpost.it

Accedi come Admin o con utente sailadmin, password ss$$admin

Click sul Menu Royalties

MySail: Guida di riferimento per il Programmatore – pag 53

Oppure, se sei Admin

7.3 Inserire un nuovo contratto

Da Maggio 2016 è stata cambiata la politica di configurazione ROY. Fino a questo momento,

per le agenzie che non erano configurate sul sistema il programma assumeva che avessero

percentuali vecchie

TRACCIATO 9.60% 4.00%

NON TRACCIATO 8.00% 2.80%

Per le agenzie con nuovo contratto (12% fisso su tutto) veniva inserito un record in

configurazione come spiegato piu avanti.

MySail: Guida di riferimento per il Programmatore – pag 54

Da Maggio 2016 invece, TUTTE le agenzie DEVONO avere la loro configurazione, 2 records per

i vecchi contratti, uno solo per i nuovi.

In questo modo il sistema è in grado di capire da solo se sta calcolando delle royalties ad

agenzie non censite. Se durante l’estrazione RoyBatch trova una agenzia che non ha un record

di configurazione significa che ci siamo dimenticati di attivargli le ROY e non si corre il rischio

che prenda percentuali da vecchio contratto. Il sistema da errore “AGENZIA NON

CONFIGURATA”

Per questo motivo chi amministra le ROY deve essere inserito nella mailing List

dell’amministrazione ed essere al corrente costantemente dei nuovi contratti o delle variazioni

che riguardano ROY.

Per aggiungere un nuovo contratto si possono seguire 2 strate, via web o via SQL

Metodo 1: via Web. - Seleziona l’agenzia da inserire per ottenere il suo codice

MySail: Guida di riferimento per il Programmatore – pag 55

- Premi Configurazione

- Scorri l’elenco e controlla che il codice non sia gia inserito

- Premi il pulsante Nuovo e inserisci i dati nel form che segue

MySail: Guida di riferimento per il Programmatore – pag 56

Se stai aggiungendo o modificando un contratto fatti dire dall’amministrazione o da Filippo se

va esclusa la Viaggiante. Come predefinito viene inclusa. Pe rescluderla selezionare il check

Metodo 2: Via Management Studio In alternativa alla configurazione via web vai su SQL Server SRV_CITY1.SailNetReport.dbo.Royalties e

fai una select per mese = 0 e anno = 0, sono tutti record di configurazione, in edit modificali o

aggiungi records copiando da altri esistenti

MySail: Guida di riferimento per il Programmatore – pag 57

7.4 Calcolo/Estrazione Roy e Fatture

- Assicurati che sulla 192.168.78.3 stia girando il servizio CPWinService. Nel caso lo trovassi

spento avvialo e ristoppalo alla fine del processo, in quanto al momento viene utilizzato solo

per le Roy, non ha senso tenerlo sempre attivo. (prima serviva anche AlignUser.exe,

DataGenerator.exe che non sono piu utilizzati)

- Seleziona dai combo Anno e Mese da elaborare (tutti gli altri combo vengono ignorati)

- Premi il pulsante FATTURAZIONE, viene mostrata la pagina sottostante

Questa pagina contiene l’esito delle verifiche sulle risorse necessarie per l’elaborazione delle

roy. Path, driver ODBC, files access. Inoltre mostra il periodo scelto e l’ultima fatturazione

eseguita. Se i dati a video sono coerenti e non ci sono segnalazioni proseguire come segue:

- Imposta la Data Fattura di fine mese che comparirà nella intestazione del GAP (es

31/01/2017)

- Imposta Periodo di Fatturazione che sarà messo in fattura come primo rigo di

annotazione (es: “dal 01/01/2017 al 31/01/2017”)

- Premi Avvia Elaborazione. Un messaggio chiederà conferma per proseguire

A questo punto inizia il processo di estrazione vero e proprio che bloccherà il browser per

qualche secondo. Viene scritta sul DB una nuova riga Coda Lavori in cui è possibile seguire i 5

steps:

1) Esecuzione stored ROY_STORED_TABLE_WEB e raccolta dati da Raccomandate a

ROY_STORED_TABLE di NORMBATCH.

2) Ottiene i records in SRV_CITY1.Sailnet_Report.Royalties per la visualizzazione

trimestrale

MySail: Guida di riferimento per il Programmatore – pag 58

3) Ottiene I records di Fattura su in SRV_CITY1.Sailnet_Report.Royalties

4) Copia fatture da in SRV_CITY1.Sailnet_Report.Royalties all’mdb Exp_Sailnet.mdb

5) Trasferisce I totali fatture da SRV_CITY1.Sailnet_Report.Royalties a

[ArcDati].[dbo].[ROYALTIES_DATAZOOM] per il passaggio a DataZoom

Attendere il completamento del 5° step seguendo l’andamento delle notifiche code lavori

Dal qui verifichi l’avanzamento dell’elaborazione. Il tempo richiesto di media è di una ventina

di minuti, e termina quando la colonna stato riporta “Completato”

7.5 LOG

Segui come sta andando tenendo aperto il log del BL in E:\Logs\logdel_2016_06_06.log e

vedi l’avanzamento su cosa ci scrive. (attenzione, il file di LOG non è quello del sito, ma quello

del BL)

MySail: Guida di riferimento per il Programmatore – pag 59

Se il processo di estrazione si interrompe viene mostrato il messaggio che ha generato l’errore

in MsgCompletamento con stato Interrotto.

In alternativa all’esecuzione via web puoi lanciarlo a mano con tutti i parametri che gli

servono, vedi il significato dei parametri di RoyBatch.exe nel capitolo 6.3 pagina 36

7.6 Importazione fisica su GAP

Al termine di tutto il processo va fatta la copia manuale del file Exp_Sailnet.mdb sul

repository da cui GAP acquisisce tutte le fatture. Segui scrupolosamente gli step

sottostanti

7.6.1 Verifica Fatture prima di importazione al GAP

Questi controllo post elaborazione consentono di verificare a video se l’estrazione appena

eseguita è coerente che l’estrazione dei mesi precedenti. Da qui si potranno valutare se le

oscillazioni di importi sono coerenti con l’andamento di una data agenzia

- Premi sul menu Royalties

- Seleziona Anno e Mese

- Premi il pulsante “LISTA FATTURE”, viene mostrato l’elenco e totale fatturato per tutte

le agenzie

MySail: Guida di riferimento per il Programmatore – pag 60

7.6.2 Visualizza Trimestre e Dettagli

- Premi Menu Royalties

- Seleziona l’Agenzia, anno e il trimestre di interesse e premi Trimestre

MySail: Guida di riferimento per il Programmatore – pag 61

7.6.3 Copia Exp_Sailnet.mdb sul repository del GAP

- Assicurati con l’assistenza Sailpost (ilo, bruzio, cosmo) che non ci siano in corso altri

import a GAP

- Vai sul path di rete \\citypost-rdbms\DBSERVER\GAP\DatiEsterni, cerca

Exp_Sailnet.mdb e rinominalo in Exp_Sailnet_ORI.mdb

- Collegati in RDP sulla 192.168.78.3

- Copia il file come mostrato in figura

MySail: Guida di riferimento per il Programmatore – pag 62

- Incolla il file sul path di rete \\citypost-rdbms\DBSERVER\GAP\DatiEsterni

- Comunica all’amministrazione (Tina) che puo procede con l’import

[email protected]

- Quando ha importato occorre salvare il file appena importato e ripristinare quello

dell’assistenza

o Rinomina Exp_Sailnet.mdb in Exp_Sailnet_ROY_AAAA_MM.mdb

o Rinomina Exp_Sailnet_ORI.mdb in Exp_Sailnet.mdb

A questo punto tutto il ciclo è completato.

MySail: Guida di riferimento per il Programmatore – pag 63

7.6.4 Troubleshooting

Nel log il processo è andato in Timedout

Soluzione

se lo step 1 di estrazione ROY_STORED_TABLE_WEB è stato completato collegati in RDP sulla

3 ed esegui RoyBatch a mano (usa il *bat) con il parametro –Partial:1. Il processo riparte

dalla generazione Roy e salta l’estrazione.

Cosa succede se eseguo piu volte il processo?

Soluzione

Nulla. Se devi ripartire da zero però devi vedere il n° estrazione ultimo MAX(idEstrazione) di

ROY_STORED_TABLE su NORMBATCH e cancellarlo a mano. Una estrazione genera su questa

tabella circa 200mila records, cancellali tutti per ripartire da zero, altrimenti se sai che

l’estrazione è andata a buon fine esegui RoyBatch a mano (usa il *bat) con il parametro –

Partial:1. Il processo riparte dalla generazione Roy e salta l’estrazione.

ERRORE: L'Agenzia con CodUnivoco XXXXX NON E' STATA TROVATA NELLA

CONFIGURAZIONE PER IL RECUPERO DELLE PERCENTUALI DA APPLICARE

Causa

Nell’estrazione sono stati trovati record di questa agenzia in ROY_STORED_TABLE ma non c’è

nella configurazione

Soluzione

Lo step 1 è completato, non deve essere rifatto, ma va configurata l’agenzia che manca e far

ripartire il processo dallo step 2

- Vai su NORMBATCH.AnagraficaClienti e cerca la tipologia dell’agenzia (es 95041

AGENZIA CATANIA 4)

- Vai su SAILWEB131.SailWebData.Processes e seleziona l’ID = 1771 (lo vedi dalla coda

lavori qui sotto)

- Stoppa CPWinService sulla 3

- Cambia l’id 1771 aggiungendo –Partial:1 nel parametri in modo che salti l’estrazione

- Cambia la colonna stato in 0 (da eseguire)

- Avvia CPWinService sulla 3 e verifica l’avanzamento, potrebbe trovare altre agenzie non

configurate o arrivare in fondo ai 5 step1771

MySail: Guida di riferimento per il Programmatore – pag 64

Errore fatturazione roy 2016, Mese: 5Testo del messaggio di errore: Connection

Timeout Expired. The timeout period elapsed while attempting to consume the pre-

login handshake acknowledgement. This could be because the pre-login handshake

failed or the server was unable to respond back in time. The duration spent while

attempting to connect to this server was - [Pre-Login] initialization=3010;

handshake=11989;

Causa

Uno dei server non risponde e va in timed out

Soluzione

Poiché non si puo sapere esattamente in che punto si è fermata l’elaborazione, si fa ripartire

dalla 2 (vedi Issue precendente) con -Partial:1. Tutte le elaborazioni possono essere ripetute

eccetto la prima, nel qual caso deve essere cancellato tutto il Max(idestrazione) di

Roy_Stored_table. Tutte le altre possono essere ripetute, la prima volta vanno in insert, la

seconda in update

8. Sviluppo di SailWeb

“La via più breve per trovare qualcosa sul codice del progetto è aprire LibCoreMySail.dll

AsyncHelper e cercare tra i case. Molto probabilmente quello che cerchi passa da qui.”

8.1 Introduzione alla logica del sito

Il sito fa uso massiccio di Ajax.

in uno scenario tipico, il flusso di chiamate è il seguente

a) click pulsante sulla pagina con onClick ad una funzione js che esegue cpAjax

cpAjax('ajax-default', CreateAjaxCall('GRID', 'FREESQLCACHE'));

b) cpAjax apre un thread asincrono sulla pagina ajax.aspx

c) ajax.cs splitta l'url creando l'oggetto PatternUrl, che contiene tutte le informazioni

validate e pronte al parsing della request + altre informazioni custom. Ciò significa che

la nostra Request che portiamo in giro sul sito è la request http piu tutte le informazioni

MySail: Guida di riferimento per il Programmatore – pag 65

che ci servono per il contesto di questa web app (filtri, nome di tabelle, parametri client

ecc)

d) ajax.cs quindi avvia AsyncHelper.ProcessAsyncRequest, in cui sono concentrate tutte

le Action Key, per ognuna di esse esegue la funzione di validazione e rendering. Un

utilizzo tipico è snStorage.render<qualche cosa> o SailWeb.render<qualche

cosa>

e) in snStorage viene generato il codice html e scritto sul Response.Write.

f) snStorage rappresenta il layer di comunicazione e trasferimento dati tra server e

client. in alcuni casi fa accesso diretto al DB,ne legge il contenuto e lo scrive sulla

pagina.

Nella maggior parte dei casi istanzia il BL o BusinnesLogic carica e pagina i dati per le

griglie

g) snStorage usa TemplateHelper per il rendering e il layout dei dati.

i templates sono semplici files html contenenti tag statici e variabili passate da

snStorage

i campi variabili aprendo un file template sono tutti i valori racchiusi tra “%%”

Quando usi i template in Visual Studio tieni aperto codice e Template insieme

stack di chiamate pseudo code 1

[ Button_click ]

funzione click nel js della pagina

funzione cpAjax(<action key>) in citypost.js (<--qui stacca il thread)

apre ajax.aspx

parse della querystring su PatternUrl

parse della <action key> in ProcessAsyncRequest

individua l'action key

SailWeb.snStorage.renderXXXX(<action key>)

apre il mapper, inizializza i dati e corpo di paginazione

carica il buffer di dati richiesti

SailWeb.TemplateHelper HEADER, scrive l'header della

griglia

scorre i records

SailWeb.TemplateHelper ROW, scrive la riga della griglia

end loop

SailWeb.TemplateHelper FOOTER, scrive i totali e footer

della griglia

stack di chiamate pseudo code 2

[ Button_click ]

citypost.js -> cpAjax(<action key>)

open ajax.aspx

ajax.cs .. <- getPatternUrl()

AsyncHelper.cs-> ProcessAsyncRequest(<action key>)

..

switch case action key

SailWeb.snStorage.renderXXXXXXX(param)

MySail: Guida di riferimento per il Programmatore – pag 66

open mapper

read and get buffered page

records

..

SailWeb.TemplateHelper(<template

file>)

while buffer end->

response.write(record)

Questo stack di chiamate è identico e ridondante in tutto il sito

MySail: Guida di riferimento per il Programmatore – pag 67

8.2 SailNetStorage, SailWeb e classi in App_Code

SailWeb classe statica, funge da CORE statico, e contiene tutte le funzioni comuni a tutti gli

utenti che non accedono a BL o dati, non fanno transazioni. Solitamente raggruppa tutti i

rendering html

SailNetStorage è una classe non statica ma dichiarata statica in SailWeb. Era nata con scopi

diversi , doveva agganciare il mondo SailNet, un altra CityPostStorage idem, ecc.

E' rimasta come interfaccia tra sito e BL/Dati. Questo oggetto raccoglie tutte le funzioni che

fanno accesso ai dati

le sottoclassi RoyMember e Administrator, sono istanziate solo se i ruoli ne hanno bisogno e

gli oggetti prendono posto in memoria solo se qualcuno richiede le roy o funzioni di

amministrazione

SQLGrid classe statica, contiene tutte le funzioni di rendering e di controllo che riguardano

LibExecSQL, ovvero tutto il core delle T-SQL to SailWeb Grid è concentrato in questa classe.

AuthConfig classe statica, contiene tutte le funzioni di controllo utenze, login, impersonate,

creazione, cancellazione utenti.

BundleConfig classe non statica con una sola funzione statica. È una classe di sistema

generata dal wizard di creazione nuovo sito web, serve a modernizr per raccogliere i css e js

per asp.net

SWEnvironment classe statica per il rendering dello stato del sito

MySail: Guida di riferimento per il Programmatore – pag 68

PPAContext classe statica che contiene tutte le funzioni di gestione PPA

rkAgenzia non-static class, contiene il record minimo delle tipologie agenzia, le carica tutte

all’avvio del pool, per le decodifiche al volo successive.

cpPaginator non-static, contiene tutte le definizioni e i metodi per la paginazione delle griglie,

fa il rendering, contiene i filtri per le select LinQ SearchDynamic

8.3 BusinnessLogic e BL CityPost

Per una corretta programmazione il sito NON deve referenziare mai nessuna connessione

diretta, ma passare da layer dati esterni. Come primo oggetto BL fu implementato

BusinnesLogic, che è stato integrato a fine 2015 in CityPost.BL.

Al momento (maggio 2016) restano 2 o 3 mappers ancora attivi in BusinnesLogic, tutti gli altri

sono integrati come Services e Persister nel nuovo.

Ciò che è rimasto sono gli utenti, i telegrammi, i parcel e i destinatari abituali.

Su BusinnesLogic non deve essere implementato piu nulla. Ad ogni modo resta utilizzabile

l’esistente.

8.3.1 Istanziare un mapper BusinnesLogic

using BusinnessLogic.Entity.Helpers;

using BusinnessLogic.Entity.SailNet;

using BusinnessLogic.Entity.Utenti;

using BusinnessLogic.Mappers;

[..]

using (var Mapper = new TelexMapper()) {

var usr = SailWeb.getSessionUser(Context);

var curRequest = SailWeb.getRequest(Context);

var Buffer = new List<_Telex>();

// questo è il primo punto nel progetto in cui sono state implementati

// filtri multipli con range di date dinamiche (21/05/216)

try

{

curRequest.Pager.Filters.AddChild("SmallTelegrammi", "CodiceMittSailPost",

"string","= " + CodUnivoco);

curRequest.Pager.Filters.AddChild("SmallTelegrammi", "DataAccettazione",

"Date", ">= " + fts[0]);

curRequest.Pager.Filters.AddChild("SmallTelegrammi", "DataAccettazione",

"Date", "<= " + fts[1]);

curRequest.Pager.Filters.AddChild("SmallTelegrammi", "Nome", "String", "% " +

fts[2]);

curRequest.Pager.Filters.AddChild("SmallTelegrammi", "mttNome", "String", "%

" + fts[3]);

curRequest.Pager.Filters.AddChild("SmallTelegrammi", "UserName", "String", "%

" + fts[4]);

}

MySail: Guida di riferimento per il Programmatore – pag 69

catch

{

// se un indice di ft non è presente è inutile che cerchi gli altri, va bene che salti

qui

}

curRequest.Pager.Filters.GenerateFilterFromChild();

curRequest.Pager.Filters.valueTo = "*ALL*"; // vede tutto il codUnivoco

curRequest.Pager.Filters.InitValue = CodUnivoco;

if (viewMode == "*USER*") curRequest.Pager.Filters.valueTo = usr.UserName;

curRequest.Pager.Filters.valueFrom = righe;

if (SQLGrid.ExportToCSV(Response, curRequest, Mapper)) return;

// massimo righe restituite dal bl, se 0 tutte quelle che trova appartenenti a

CodUnivoco

Mapper.Initialize(curRequest.Pager.Current, curRequest.Pager.MaxItems,

curRequest.Pager.Filters);

curRequest.Pager.SetupTotalPages(Mapper.Count);

Buffer = Mapper.GetListTelexPerCodUnivoco(CodUnivoco);

Ecc ..

} // dispose del mapper

8.3.2 Istanziare un Service di CityPost.BL

using Citypost.BL.DerivedServices;

using Citypost.BL.Services;

using Citypost.Common;

using Citypost.Common.DataShapes;

using Citypost.Common.DataShapes.DBML;

using LibBlComuni;

using LibExecSql;

using LibForConnection;

[..]

using (var sm = new SwStatService()) {

sm.Initialize();

var rk = new SWDataStat();

rk.data = DateTime.Now;

rk.data2 = rk.data;

rk.AA = rk.data.Value.Year;

rk.MM = rk.data.Value.Month;

rk.DD = rk.data.Value.Day;

rk.CodUnivoco = usr.CodUnivoco;

rk.Descrizione = trc;

rk.Nome = "SmallParcel";

rk.Keyword = "BRD";

sm.AddCutOffDataStat(rk);

MySail: Guida di riferimento per il Programmatore – pag 70

}

8.3.3 Businnes Data Layer di Citypost

(BL CPSI centralizzato)

Nel seguito valgono le seguenti abbreviazioni:

SI: Sistema informativo

PL: Presentation Layer

BL: Business Layer

DAL: Data Access Layer

ORM: Object Relational Mapping

DTO: Data Transfer Object

LINQ: Language-Integrated Query

EF: Entity Framework

MVC: Model View Controller

Contatti

Responsabile sviluppo: Samuele Dembele

Responsabile sviluppo: Ivo Montanelli

Assistenza tecnica: Sviluppo CityPost

Processo

Si tratta di separare in strati logici (Layers) il sistema informativo intero.

La tipica suddivisione prevede tre strati logici diversi:

o Accesso ai dati (DAL): è lo strato che si occupa della lettura/scrittura dati (persistenza)

tipicamente su un database.

o Logica di business (BL): è lo strato oggetto di questo lavoro. Racchiude tutta la logica

applicativa del SI e fornisce oggetti e metodi controllati per implementare questa logica.

o Strato di presentazione (PL): è la parte dell'interfaccia rivolta all'utente finale. Può

essere una apllicazione web, windows form e anche console.

I pricipali vantaggi di questa architetura sono:

MySail: Guida di riferimento per il Programmatore – pag 71

o Le modifiche implementative/migliorie di ogni strato non impattano sugli altri strati

purché venga rispettata l'interfaccia di comunicazione tra gli strati stessi

o Possibilità di mettere dei team di lavoro diversi su ogni strato in contemporanea

o Di solito si ottengono applicazioni client più leggere e modificabili

Implementazione

DAL

La prima cosa realizzata è un repository dei modelli dati. Cioè un unico posto in cui siano

definiti gli oggetti del "mondo" del nostro SI. Alcuni esempi sono l'oggetto Utente del SI,

l'oggetto Soggetto che può essere un cliente piuttosto che un'agenzia. Questi oggetti sono

tutti definiti nel progetto Citypost.Common il cui nome parla molto più di ogni spiegazione.

I metodi che lavorano su questi oggetti sono il BL (Citypost.BL). Può essere necessario

definirsi una struttura dati anche lato client, ma si tratta di strutture ausiliari e non principali.

Ad ora sono stati formalizzati soltanto gli oggetti Utente, Cliente e alcuni oggetti di servizio

(tipicamente legati alle tabelle di decodifica del db).

La parte di lavoro (consistente) da fare ancora è quella di formalizzare tutti gli altri oggetti

necessari ad implementare le logiche che man mano verranno richieste.

Le classi per formalizzare gli oggetti devono essere solo contenitori con properties get/set.

Cioè sono semplici DTO e non oggetti complessi come Datatables,DataSets o peggio interi

oggetti di business. Infatti devono essere il più leggeri possibile visto che sono responsabili del

trasporto dati.

Gli strumenti accettati nel nostro BL per questa attività sono: LINQ, EF oppure DTO fatti "a

mano".

È fuori tema discutere qui quali di questi ORM sia il migliore, se c'è. Per chi è interessato, qui

trovate un confronto tra i DTO fatti con puro ADO.NET e EF ADO.NET VS EF Performance

Certo è che vale la massima "chi fa per sé...." poiché gli ORM ufficiali aggiungono normalmente

un po di cose loro e impogono che a ogni modifica venga rigenerata la classe.

È per questo che sia LINQ che EF non hanno bisogno di particolari meccanismi per gestire la

persistenza (ce l'hanno on board) e invece i DTO fatti a mano hanno bisogno di un oggetto

Persister per salvare e leggere dal db.

Il nostro Accesso ai dati sarà dunque DAL = Citypost.Common per i dati + LibDb per

ADO.NET via driver nativo Sql Server o OleDb + LINQ/EF. Anche i file dbml di LINQ dovranno

risiedere in Citypost.Common.

BL

Se chiamiamo OBJ un oggetto qualsiasi (DTO, classe LINQ e EF) lo si espone come OBJ,

List<OBJ>, DataPage<OBJ> dove la DataPage è una struttura appositamente pensata per

le applicazioni web. Naturalmente ci deve essere la possibilità di esporre dati semplici come un

intero o una stringa.

public class DataPage<T>

MySail: Guida di riferimento per il Programmatore – pag 72

{

public List<T> Data = new List<T>();

public int RecordCount = 0;

public int PageSize = 20;

public int PageIndex = 0;

public int PageCount { get{ return (RecordCount ==0 || PageSize==0) ? 0 : (RecordCount

+ PageSize - 1) / PageSize;}}

}

Il BL visto da Visual Studio:

Il BL eroga servizi per ogni OBJ. Dietro le quinte vengono usate le classi sotto Persistance e

Rules, ma le classi di interesse per l'utente del BL sono le classi sotto Services.

Infatti le classi di supporto servono "soltanto" a gestire il tutto in modo object oriented. Gli

oggetti del mondo del SI sono solo le classi sotto Services.

Generalmente ogni cartella contiene la classe d'interfaccia che bisogna rispettare per creare un

oggetto di un certo tipo.

IDataMapper: è l'interfaccia che deve rispettare una classe Mapper. Se non si fornisce una

specifica classe mapper viene usata la GenericMapper.

Le classi generate con LINQ/EF NON hanno bisogno della classe mapper in quanto hanno tutto

on board.

interface IDataMapper {

// Main method that populates dto with data

Object GetData(IDataReader reader, string subClass = "" );

// Gets the num results returned. Needed for data paging.

int GetRecordCount(IDataReader reader);

}

IModelDbDao: è la classe che definisce in quale formato devono essere restituiti i dati per

l'accesso via ADO.NET. Le due classi che le implementano sono la classe di accesso che lavora

con il driver Sql Server nativo (LibSqlDao) e quella che accede via OleDb (LibOleDbDao).

MySail: Guida di riferimento per il Programmatore – pag 73

Le classi che definiscono la Business logic (Services) sono quelle che andranno implementate per ogni OBJ complesso.

Tutte hanno a comune la classe ServiceBase che contiene oggetti e servizi di utilità per tutte le

classi derivate:

public abstract class ServiceBase : IDisposable

{

private static bool _InitDone = false;

// SharedSqlDao

private LibSqlDao _sharedCPSIDao = null;

private LibSqlDao _sharedDBLOGDao = null;

private LibSqlDao _sharedGAPDao = null;

private LibSqlDao _sharedLOGINDBDao = null;

private LibSqlDao _sharedNORMARCDATIDao = null;

private LibSqlDao _sharedSAILREPORTDao = null;

private LibSqlDao _sharedSRVCTARCDATIDao = null;

Dictionary<DataSourcesNames, DataSourcesDTO> AllDataSources;

private static List<Applicazione> _allApps = null;

public List<Applicazione> AllApps {

get {

if (_allApps == null) {

string query = @"SELECT * FROM

[dbo].[TbSecApplications]";

IDbCommand command =

_sharedCPSIDao.CreateCommand(query);

_allApps=_sharedCPSIDao.GetEnumerable<Applicazione>(command).ToList();

}

return _allApps;

MySail: Guida di riferimento per il Programmatore – pag 74

}

}

Da notare l'uso del paradigma Singleton per la lista delle applicazioni. Questo permette di

ottenere un caricamento dei dati "on demand" soltanto la prima volta che servono.

In effetti è assolutamente improbabile che la lista delle applicazioni del SI cambi durante la

vita di una singola istanza del BL.

Si possono notare all'inizio della classe le variabili che definiscono tutte le fonti dati

potenzialmente accedute dal BL. Questa lista sarà soggetta a notevoli modifiche...

La scelta per l'accesso ADO.NET è quella del driver nativo di Sql Server

La classe DynamicLibrary serve a gestire le query dinamiche di LINQ ed è l'unica che non

fornisce direttamente dei servizi.

Il linguaggio utilizzato per esprimere la logica di business è semplicemente sql per gli oggetti gestiti da ADO.NET e le query LINQ per gli oggetti definiti nei file .dbml.

Esempio di metodo con sql

public UtenteDTO DoLogin(string userName, string passWord) {

string query = @"SELECT u.*, d.IdPRA

FROM [dbo].[TbSecUtenti] u inner join

[dbo].[TbSecProfiliPerRuoliApp] d

on u.GuidUtente = d.GuidUtente and d.AppAttiva = 1 and

d.ProfiloAttivo = 1

WHERE u.UsrName = @UsrName

and u.Pswd = @Pswd";

LibSqlDao dao = SharedSqlDao;

IDbCommand command = dao.CreateCommand(query);

dao.AddParameter(command, "@UsrName", userName);

dao.AddParameter(command, "@Pswd", passWord);

return dao.GetSingle<UtenteDTO>(command);

}

Esempio di metodo con LINQ

public List<Buste> GetBusteByCap(string cap, int quante, BusteSortOption order) {

string where = "Cap == " + Quota(cap).Replace('\'', '"');

string ordby = GetOrderBy(order);

return BustePersister.Bustes.Where

(where)

.Take(quante)

.OrderBy(ordby).ToList();

}

N.B. gli esempi non corrispondono all'attuale implementazione.

Test

Per i test ho utilizzato un programma di console (TestBLConsole) per le operazioni più banali.

Per i test riguardanti la paginazione dei dati, l'ordinamento ecc... è stato utilizzato una web

app fatta con ASP.NET MVC V4 (TestBLMVC).

La scelta del framework MVC è stata dettata da alcune considerazioni:

MySail: Guida di riferimento per il Programmatore – pag 75

o Questo lavoro, dopo vari studi, si basa su un lavoro reale testato appunto con una web

app MVC

o La "separation of concern" del pattern MVC, fa si che la parte Model sia esattamente il

BL

o L'architettura MVC consente di ottenere un'ottima scalabilità e si presta bene a

l'aggiunta di funzionalità da testare per complesse che siano

o La parte di presentation (View) può essere gestita da personale dedicato al markup

poiché contiene solo html e script di tipo razor/aspx

Riferimenti:

ASP.NET MVC Overview

Difference betweeen ASP.NET WebForms and ASP.NET MVC

Comparing Web Forms And ASP.NET MVC

DataBase

CPSI su Pomezia 192.168.78.130 CPCONFIG. CPCONFIG propaga l’accesso DTO o DBML a

tutti catalog del mondo Citypost (circa una trentina)

8.3.4 Installazione ed utilizzo del Businnes Layer

Prerequisiti

Il Business Layer (di seguito BL) gira con il .NET Framework 4.0 full e non il "Client profile"

poiché abbiamo bisogno di componenti presenti solo dalla versione 4.0 full in poi.

Per essere correttamente compilato ha bisogno di alcune librerie nostre e di un prodotto di

terze parti che sarebbe PostSharp

Nostre librerie:

o LibComuni: Libreria di utilità di uso comune praticamente ovunque.

o LibDb: Si occupa dell'accesso a DB.

o Citypost.Common: Il repository di tutte le classi dati. o Citypost.CL: Il nostro cahing layer.

Librerie di terze parti:

o Manager di pacchetti Nuget download. Serve per installare i plugin di PostSharp e altri

pacchetti necessari per lo sviluppo web.

MySail: Guida di riferimento per il Programmatore – pag 76

o Libreria PostSharp per fare AOP (Aspect Oriented Programming) download. La

utilizziamo per fare caching su tutti i metodi che non siano nella classe base di servizio (BlServiceBase).

Installazione

La prima cosa da fare è installare Nuget, dopodichè si può installare il pacchetto Postsharp.

Successivamente è possibile installare i plugin per Visual Studio dal manager di pachetti Nuget.

A questo punto basta aggiungere le nostre librerie come progetti (aggiungi progetto esistente)

alla soluzione et voilà!

Utilizzo

Fare la login:

using (var userService = new UtenteService()) {

var mioUt = userService.DoLogin("UserName", "Password");

if (mioUt != null) {

...

string myUrl =

userService.GetUtenteDefaultApp(mioUt.DefaultAppId).AppUrl;

...

List<AttivitaDTO> activities = mioUt.ListaAttivita;

...

}

}

..inserire altri esempi..

8.4 CLIENT side

Il core jQuery lato client si trova nel file citypost.js

usa la pagina ajax.aspx per passare la richiesta al server

l'url e i parametri viene costruito in citypost.js dalla funzione cpAjax

cpAjax accetta 2 parametri

1- string, id del div contenitore su cui viene scritto il Response.Write("..") dal server

2- url della pagina con tutti i parametri necessari alla funzione specifica

Sintassi:

cpAjax(uno, due);

Il parametro uno corrisponde a un tag <div> su cui si desidera renderizzare l’html prodotto

dal server durante il Response.Write("..")

il parametro due viene costruito dinamicamente dalla funzione CreateAjaxCall(SystemArea,

Action)

CreateAjaxCall accetta due parametri

1 - key string del contesto. Non è realmente utilizzato, ma fornisce al server il contesto della

chiamata, ad esempio se è di sistema, se è una richiesta di gridding ecc.

2 - string key Action contiene tutti gli elementi per informare il server all'esecuzione di una

specifica funzione e tutti i suoi parametri separati da ;

MySail: Guida di riferimento per il Programmatore – pag 77

CreateAjaxCall per prima cosa recupara la root del sito , poi ci aggiunge la pagina

/ajax.aspx piu tutti i parametri della querystring.

var p = GetBaseSitePath();

p += "/ajax.aspx?System=" +

SystemArea + "&Action=" +

Action + "&page=1&filtro=&orderby=&rows=" + rows +

"&CSV=" ;

Action contiene stringhe separate dal carattere ;

Il primo elemento è la action vera e propria, tutto il resto sono parametri.

Esempio:

var url = CreateAjaxCall('GRID', 'FREESQLCACHE');

watchdog(url);

cpAjax('ajax-default', url);

SendMessage("FreeMem", "Cache eliminata, memoria fisica riallocata", "", 0);

Componenti della querystring

&Action = <string key + parametri>

&page=<pagina corrente>

&filtro= <string filtro da applicare alla tabella di pertinenza>

&orderby= <nome del campo sul db su cui ordinare>

&rows= <numero di righe visuallizzabili sulla griglia>

&CSV=1 <se valorizzato a 1, riesegue il get dei dati della griglia ma si scrive su csv e non a

video)

&ApiKey <GUID univoco generato al loading della master.page. il server sa sempre che la

chiamata è stata fatta da funzioni applicative. in questo modo impedisce l'esecuziona ajax

direttamente da url>

8.5 Flags Ajax per eseguire il processo asincrono e controllarne inizio e fine

una chiamata ajax essendo di per se asincrona, avvia un thread separato e restituisce

immediatamente il controllo al brwoser. Per default viene visualizzato un div a schermo intero

semitrasparente con uno spinning java animato che impedisce di far compiere altre azioni

agli utenti web fino a quando tutto il response non è stato generato e la call ajax completata.

Il lifecycle della chiamata inizia dalla call cpAjax e termina autonomamente quando ha finito di

scrivere il response.

non tutte le chiamate devono essere cosi. si puo avere la necessita di fare una richiesta in

background, e farli fare cose diverse al suo completamento a seconda dell'action passata.

per pilotare tutte queste condizioni si usano delle variabili come flags, presenti nel js

SWAjax.js:

AjaxNoWait= true non blocca il browser, non viene visualizzato lo spinning java, l’utente non si

accorge che in background sta girando qualcosa.

MySail: Guida di riferimento per il Programmatore – pag 78

AjaxCompletedExecCode = x ; un codice numerico che fa eseguire una specifica funzione al

completamento della richiesta ajax

AjaxRefresh = true; fa il reload completo della pagina al completamento della chiamata.

Questo flag è utile se non si sta scrivendo qualcosa a video ma ad esempio su un db e lo scopo

è visualizzare la modifica dopo averla applicata.

uso il sistema seguente se cambia qualcosa a video (edit, cancellazone di un elemento di una

grid), e aggiorna il contenuto esattamente com'era

AjaxCompletedExecCode = 1;

AjaxBackupCall(); <-- salva url e div

cpAjax(preDiv, CreateAjaxCall('SYS', 'unlockuser;' + user)) <- nuova chiamata

AjaxLastCall(); <- richama url e div salvato, riesegue la cpAjax con i due parametri

salvati

.. sblocca un utente e cambia l'icona del pulsante

Oppure, altro metodo

AjaxCompletedExecCode = 1;

AjaxRefresh=true;

AjaxNoWait=true

cpAjax(preDiv, CreateAjaxCall('SYS', 'unlockuser;' + user))

.. sblocca un utente e ricarica la pagina

Tutti i flag impostati prima di una chiamata vengono resettati al termine del loro utilizzo.

Non c’è bisogno di chiudere il pannello spinner java StartStatus(“esecuzione di qualcosa in

corso..”) con StopStatus(). Lo stop avviene da solo al termine della chiamata.

8.6 WEB SERVICE WS.ASHX

L'unica ragione per cui esiste un web service in questo progetto è dovuto al fatto che è l'unico

modo per visualizzare la progressbar.

poiché deve essere asincrono esattamente come ajax e ajax non puo avere 2 istanze

contemporanee (le puo avere ma il driver sembrerebbe ubriaco, ovvero è un casino debuggarlo

perche non sai chi sta facendo cosa), il ws consente di avere thread asincroni. paralleli senza

che bisticcino

ciò non toglie che un domani, se si rende necessario un get/set di passaggio json da e verso

l'esterno, l'elemento esiste e si puo implementare. al momento non serve , come gia detto, il

WS gestisce solo la PB

8.6.1 PROGRESSBAR

MySail: Guida di riferimento per il Programmatore – pag 79

La ProgressBar è prevista solo nel caso di chiamate ajax. Non si puo usare su POST, non è

implementato. Nella funzione js di cui si vuole una PB durante l'elaborazione ajax, basta

aggiungere

function ShowUsers(context) {

StartProgress("Elenco Utenti");

var url = CreateAjaxCall('GRID', 'persone;full');

cpAjax('listTable', url);

}

in c# dove elabori PERSONE incrementa SailWeb.Percentage += 1;

e ogni mezzo secondo viene letto il valore e messo sulla progressbar della pagina. fa tutto da

solo, chiude e nasconde i tag cpAjax quando ha finito.

Per questo polling ogni 0.5s viene fatta una chiamata WS, in quanto il sistema ha gia in pancia

una chiamata asincrona ajax, non ne puo fare due contemroranemanete. il servizio puo girare

in parallelo, è un altro thread

purtroppo non si puo fare in POST su un form asp.net. se fai click su un button runat="server"

dovresti prima ricaricare la pagina, avviare l'attesa, la progressbar. Non si po fa

ho provato e toccherebbe fa dei giri IsPostBack, QueryString, esecuzione di script client, che lo

rendono ingestibile

8.7 SERVER side workflow

Ajax.cs

supponendo che come action gli venga passato "DECODAGE;10030"

1) verifica subito se l'apikey corrisponde a quella generata sulla master.page

2) crea l’oggetto PatternUrl interpretando la querystring

3) esegue AsyncHelper.ProcessAsyncRequest(Context, Pattern);

AsyncHelper.cs esegue

1) interpreta la action "DECODAGE", inzializza idAge

2) esegue SailWeb.snStorage.renderAgenzia(Response, idAge);

renderAgenzia esegue

1) Istanzia il mapper di AnagraficaClienti

2) esegue AgeCurrentmyBL = anagMapper.GetByCodUnivoco(idAge);

TemplateHelper.cs

1) esegue WriteDecodificaAgenzia(Response, "/Templates/Anagrafiche/agedecodifica.html",

AgeCurrentmyBL);

il template contiene tag html fissi e variabili “%....%” sostituite dai valori di

AgeBurrentmyBL

MySail: Guida di riferimento per il Programmatore – pag 80

8.8 ORDINE OGGETTI z-index

(piu alto il numero, piu è vicino all'osservatore)

Questo è un aspetto DELICATO, sono un mare e con tanti oggetti che si sovrappongono sulla

pagina è facile perdere il controllo

z-index classe/id pagina descr. oggetto

0 il background (container, container-

fluid, logo, breadcrumb..)

1000 (10) sidebar Site.Master pulsante del menu sinistro

1030 navbar-fixed Site.Master barra in alto arancione con user

online, user logged, contatti

99999 preloader Site.Master rotellina animata di java, deve stare

il piu alto in assoluto

1090 id="process-modal" JobPopup.html popup form "nuovo messaggio"

(render in Messaggi.aspx)

1100 id="pdfModal" PopupPDF.html renderizzata dove richiesta (call via

ajax in citypost.js)

1090 id="checkoutModal" PopupTracer.html

2001 modal devoops.css bootbox

1040 modal Bootstrap.css (overrided da devoops.css)

1070 id="popModal" popGapTracers.html Popup elenco tracers sulle pagine

competenze

100 ui-front SmallParcel.aspx e

altre

autocomplete jquery-ui

3000

!important;

expanded WinMove di

devoops

draggable windows

1999 box

2001 (98) .main-menu

.dropdown-menu

Devoops.css i combo devono stare davanti alle

window, le window dietro a ui-front

= 100

8.9 Classi html, css, jquery

Classi html proprietare di mysail, create per questo sito. Le css sono tutte incluse in

\00.local\Content\style.css. Non riporto qui tutte le classi di stile, consultare il css, le

customizzazioni sono tutte li dentro. Bootstrap e versioni future non hanno bisogno di

modifiche, le classi personalizzate vengono sostituite in override

Classe Usata (un

esempio)

Tipo Descrizione

maxchar1500 Jobpopup.html js Usare negli input per limitare l’immissione di testo che

non superi 1500 caratteri, limite (di 2024) delle

chiamate ajax tra url e parametri

MySail: Guida di riferimento per il Programmatore – pag 81

8.10 Visualizzare MESSAGGI sulla pagina

In aggiunta alla modalità standard di Logging di Log4Sail, è stato adottato un metodo per la

gestione dei messaggi in modo tale che durante la programmazione possano essere inviati al

browser in 3 modi differenti a seconda dei contesti server o client, senza che sia necessario

nessun refresh della pagina.

Client, Server http, ajax

Su site.master sono stati inseriti 3 tag div nascosti di colore diverso

8.10.1 CLIENT

Questi 3 elementi, quando viene cariata la pagina, sono nascosti di default.

La function sul client (in citypost.js) che li rende visibili è la SendMessage.

Da qualsiasi parte del sito in cui ci sia la necessità di informare l’utente attraverso un

messaggio, la chiamata viene fatta a questa function sul client.

Se stiamo programmando sul contesto client è piuttosto semplice perche la chiamata è diretta.

SendMessage("FreeMem", "Cache eliminata, memoria fisica riallocata", "", 0);

l’ultimo parametro descrive il colore

0: info,verde

1: warning, beige

2: danger,rosso

Dal server in C# invece possiamo trovarci in due contesti diversi:

- nel PostBack di una qualsiasi pagina aspx (es Page_Load)

- nel rendering di codice html all’interno di una chiamata asincrona AJAX

Nel primo caso basta aggiungere uno o piu messaggi alla coda attraverso il metodo

predisposto

Server Http

MySail: Guida di riferimento per il Programmatore – pag 82

il principio è il seguente: tutti i messaggi e di qualsiasi natura vengono aggiunti a una coda

messaggi del server e sparati a video da js.

un ciclo di funzioni sparse per il sito può generare eccezioni e messaggi a volontà, vengono

scritti a video dalla masterpage una volta sola alla fine del caricamento di ogni pagina aspx

poichè dalla masterpage ci passa ad ogni cambio pagina, in fondo usa questa funzione

<% SailWeb.renderServerMessage(Response); %>

Dove scrive i tag e mostra il messaggio renderizzato a seconda del contento della Queue

Per aggiungere messaggi alla coda si usa la sintassi che segue:

string Message = "Credenziali applicative non valide. Contattare l'assistenza";

SailWeb.AddMessageQueue("Avviso autenticazione!", Message, 2);

Esempio:

AddMessageQueue("pippo è il cugino di topolino", 1);

AddMessageQueue("ma attenzione, topolino è sposato con minnie", 2);

aggiunge i messaggio alla coda sul server, e quando passa dalla masterpage, nell'html ci

scrive:

..

<script>

SendMessage('pippo è il cugino di topolino',1);

SendMessage('ma attenzione, topolino è sposato con minnie’,2);

</script>

..

cosi il browser invia i due messaggi come se fossero parte della pagina html in corso.

una volta scritti a video la coda viene cancellata, quindi sono importanti CurPage e DestPage

AJAX

Nel secondo caso, non essendo in corso un ‘Loading’ della pagina, il SendMessage viene

eseguito al completamento della funzione Ajax richiesta, ed è suffciente informare il metodo

renderServerMessage true che la chiamata è asincrona. Inoltre le funzioni Ajax non avendo

completamento di pagina, non c'è OnLoad e non c'è un termine di caricamento, quindi non può

usare la SendMessage.

SailWeb.AddMessageQueue("Errore sicurezza", "La chiamata ajax non superato la convalida di

sicurezza", 1);

SailWeb.renderServerMessage(Response, true);

Da C# i messaggi possono essere inviati alla coda in qualsiasi momento e in numero illimitato.

La prima volta che viene ricaricata Site.Master saranno visualizzati ed eliminati dalla coda.

MySail: Guida di riferimento per il Programmatore – pag 83

8.10.2 CurPage e DestPage

per effetto di redirect o per altre mille ragioni, è possbile che il codice C# stia processando una

determinata pagina ma i messaggi devono essere visualizzati su una differente. O meglio, se

carico un messaggio nella coda

SailWeb.AddMessageQueue("Errore sicurezza", "La chiamata ajax non superato la convalida di

sicurezza", 1);

può verificarsi che la prima pagina che completa il caricamento e quindi lo svuotamento della

coda, non sia la stessa pagina da cui è stato aggiunto il messaggio.

per assicurarsi che la coda messaggi non sia sparata e cancellata su una pagina di transito, va

passato il parametro DestinationPage

Ogni nuova pagina che si aggiunge, quindi, deve avere una tag o acronimo univoco che la

identifica, come ad esempio la default della root

SailWeb.CurPage="DEFAULT";

e se vuoi che i messaggi siano scritti al rendering di una pagina specifica gli passi l'id (in

questo caso "DEFAULT";

SailWeb.AddMessageQueue("Errore sicurezza", ex, 2, "DEFAULT");

SE NON GLI PASSI NULLA FA IL RENDERING E SCARICA LA CODA SULLA PRIMA PAGINA CHE

CARICA LA MASTER.. a video non si vede nulla

8.11 GRIGLIE, GRID, Custom DATAGRID

Le griglie di dati o di collection list, sono oggetti renderizzati dal server in Ajax e il lato client

di beautify è gestito dallo script SailPostGrid.js

Il sistema di griglie SailWeb sono interamente pensate e customizzate su questo sito per

Citypost, non si trova nulla di simile in rete e sono estremamente veloci, versatili e piuttosto

semplici da implementare.

Sono state ripensate perche quello che si trova è basato su richeste Json/xml, mentre

l’obbiettivo era quello di avere uno strumento su cui posso controllare la renderizzazione,

colore, font, contenuto, eventi, di una singola cella sia sul lato server che sul lato client e

soprattutto volevo essere io, programmatore, a decidere quante griglie visualizzare, dove, in

che stile.

L’unico limite è che non si possono usare in PostBack. Per fare questo è necessario usare un

controllo DataGridView di Asp.Net. Un esempio si trova nella pagina ActivityLog.Aspx

Il workflow di una griglia è questo.

MySail: Guida di riferimento per il Programmatore – pag 84

1) Si prepara il div nel punto in cui si vuole visualizzare la griglia di dati

<div class="row panel panel-default wow fadeIn" data-wow-offset="200">

<div class="col-md-12">

<div class="row repad">

<div id="table-container" class="sw-grid"></div>

</div>

</div>

</div>

2) Click sul pulsante di richiesta grid

<button type="button" onclick="javascript: ShowUsers();" title="Elenco Utenti" class="btn

btn-lg btn-outline btn-primary">Utenti</button>

Oppure, se deve essere caricata alla fine del caricamento pagina

<script>

$(document).ready(function () {

ShowUsers();

}

</script>

3) Esegue lo script

function ShowUsers() {

StartProgress("Elenco Utenti");

cpAjax('table-container', CreateAjaxCall('GRID', "PERSONE;FULL));

}

4) Entra I Ajax.cs, crea l’oggetto PatternUrl della richiesta, passa il controllo ad

AsyncHelper

Ajax.cs

var Pattern = SailWeb.GetPatternUrl(Context); // categorizza tutte le info passate da url

AsyncHelper.ProcessAsyncRequest(Context, Pattern);

5) Entra in AsyncHelper dove valuta tutte le action e fa il parsing di parametri

AsyncHelper

string[] vars = Pattern.actionstring.Split(';');

switch (Pattern.Command.ToUpper()) {

case "PERSONE":

if (vars[1] == "full") {

SailWeb.snStorage.AdminClass.renderBLUsers2(Response);

SailWeb.LogIt(Context, "Richiesta grid utenti registrati sul sito");

}

break;

}

MySail: Guida di riferimento per il Programmatore – pag 85

Sul file SailNetStorageADMIN.cs , classe SailNetStorage, classe Admin funzione

renderBLUsers2

Get richiesta corrente (con il numero di pagina selezionata, I filtri, ecc)

var curRequest = SailWeb.getRequest(HttpContext.Current);

6) Inizializza il mapper dati e scrive buttons e tutti gli altri tag della paginazione in alto

var UserMapper = new SWUserMapper();

UserMapper.Initialize("aspnet");

curRequest.Pager.SetupTotalPages(UserMapper.Count);

UserMapper.CurPage = curRequest.Pager.Current;

curRequest.Pager.WriteHtml(Response)

7) Inizializza il template e carica l’header

8)

string tpl = "/Templates/Admin/GridUtenti.html";

parm = new Hashtable();

parm.Add("%Title%", "Elenco Utenti");

parm.Add("%fa-icon%", "fa-user");

TemplateHelper.WriteGridGen(Response, "HEADER", fil, parm);

9) Applica i filtri (curRequest.Pager.Filters) e legge la quantità di righe impostate nella

request (PatternUrl)

var utenti = new List<SWUtente>();

utenti = UserMapper.getGridUsersMini(curRequest);

10) Scrive le righe controllandone una alla volta

foreach (var p in utenti) {

parm = new Hashtable();

parm.Add("%idRow%", row);

parm.Add("%UserSel%", butSel);

parm.Add("%UserEdit%", butEdit);

parm.Add("%UserDelete%", butDel);

parm.Add("%UserLock%", butLock);

parm.Add("%UserName%", p.UserName);

parm.Add("%LastActivityDate%", p.LastActivityDate);

MySail: Guida di riferimento per il Programmatore – pag 86

TemplateHelper.WriteGridGen(Response, "ROW", fil, parm);

}

11) Scrive il footer e chiude la griglia

TemplateHelper.WriteGridGen(Response, "FOOTER", fil, null);

12) Al completamento del caricamento SailPostGrid.js aggiunge , tutti i controlli

client per l’input dei criteri di selezione (filtri) e di ordinamento. Se sulla griglia si

cambia pagina (click su un numero) se si cambia il numero di righe da visualizzare, si

richiede l’export in csv, viene rifatta esattamente la stessa richiesta di gridding

originale, con le varianti appena impostate. Il tutto è automatico. L’unica cosa che va

fatta è controllare e gestire i filtri in modo che il risultato sia coerente con quanto

richiesto. Lato Server i filtri sul DB vanno gestiti a mano.

Il risultato sulla pagina è il seguente

Requisiti:

- il contenitore ajax DEVE avere la classe sw-grid <div id="table-container" class="sw-

grid"></div>

- la table nel template DEVE avere la classe sw-table-filtered

MySail: Guida di riferimento per il Programmatore – pag 87

- Nel template deve essere definita almeno una colonna di intestazione con le indicazioni sul

filtro

Template GridUtentiMini.html

<table id="ft-usrs" class="sw-table-filtered table table-condensed table-bordered table-striped

table-hover table-responsive no-border-bottom">

<thead>

<th>*</th>

<th id="username-users" class="enable-filter" data-dbfield="UserName" data-

type="string"

data-table="users" Title="Ordina per Nome Utente" >UserName</th>

</thead>

8.12 Griglie SQL automatiche (LibExecSql)

Da metà settembre 2015 sono state introdotte griglie dinamiche, punto assoluto di forza di

questo strumento. Da una semplice o complessa select in puro T-SQL,o da una vista, o da una

Stored, il sito genera la grid con tutti i parametri per il filtro, ordinamento, paginazione. Fa

tutto da solo, crea ordinamento e filtri senza bisogno di toccare una riga di codice, funzionano i

filtri e ordinamento su tutte le colonne.

La differenza tra queste griglie e quelle generate a programma leggendo i dati dal BL, è che in

questo caso c’è accesso diretto al db, quindi con un po di Reflection si puo recuperare sempre

lo stesso tipo di strutture. Da un oggetto restituito dal BL al momento non c’è automatismo e

tutti i filtri vanno implementati a mano.

Il workflow è descritto nello pseudo-code che segue

call cpAjax con action QUERY4

AsyncHelper case “QUERY4”

SQLGrid.renderSQLRequest(..)

Parsing server e catalog

Parsing query SQL

Set TimedOut=0; Connect

Execute query Command

Reflection del Reader e creazione SQLData structure con i campi

Copy da reader a SQLRow

Adding SQLRow to SQLData

Return SQLData

Se non esiste crea cartella \Templates\Dynamic\output\<nomeutente>

Crea il template dal MetaData di SQLData e salva su disco un nome di file

random guid

TemplateHelper.WriteGridGen(.."HEADER"..)

foreach { TemplateHelper.WriteGridGen(.."ROW"..) }

TemplateHelper.WriteGridGen(.."FOOTER"..)

Dettaglio:

Questo è il parsing delle richieste che viene fatto da AsyncHelper a seguito di una richiesta

client cpAjax(..)

case "QUERY4":

if (vars.Length > 2)

if (vars[2] == "FREECACHE") SailWeb.SvuotaCache(Context, true);

MySail: Guida di riferimento per il Programmatore – pag 88

SailWeb.LogIt(Context, "Richiesta parsing sql parametrica di tipo 4: " +

vars[1].Substring(0, 15) + ".."); // parametrica @

SQLGrid.renderSQLRequest(Context, vars[1], 4);

break;

case "QUERY3":

SailWeb.LogIt(Context, "Richiesta parsing sql tipo 3 " + vars[1]); // nella

query c'è server e catalog {server.catalog}

SQLGrid.renderSQLRequest(Context, vars[1]);

break;

case "QUERY2":

SailWeb.LogIt(Context, "Richiesta parsing sql di tipo 2 ");

SQLGrid.renderSQLRequest(Context, vars[1], vars[2], vars[3]);

break;

Avvertenze: server è un nome di DataSource della tabella TbDsDataSource di CPSICONFIG

(della connectionstring <add name="DbDatiDefaultConnectionString" connectionString=..>

Il catalog non serve piu, in quanto CPSI ha definito entrambi nei DataSource. Va indicato per

compatibilita con le vecchie funzioni, ma non è valutato. Probabilmente passare come

Server.Catalog NORMARCDATI.pluto apre comunque il catalog ArcDati.

nel parsing di tipo QUERY2 sono richiesti 3 parametri: server, catalog e la query.

nel parsing di tipo QUERY3 è richiesto un solo parametro. server e catalog sono nella stringa

sql racchiuse tra graffe, es: "{NORMBATCH.ArcDati} select * from AnagraficaClienti"

La QUERY3 è utilizzata dalle pagine aspx in SWSQLManagement.aspx e nella Admin.aspx sotto

Account

function EsempioQuery3 () {

StartProgress("Elenco anagrafico, attendere..");

var q = "{NORMBATCH.ArcDati} select * from AnagraficaClienti";

cpAjax('table-container', CreateAjaxCall('GRID', 'QUERY3;' + q));

}

Il parsing di tipo QUERY4 è quello piu evoluto e completo:

var queryModel;

queryModel = "@database:SAILWEB131.SailWebData @tableid:ft-rub1 @template:null

@title:Rubrica Destinatari";

queryModel += "@button:mode=checkbox,id=%ID%";

queryModel += "@hiddencolumns:ID"; // separa le colonne da virgola se devi

aggiungerne piu di una

queryModel += "@footerstat:true";

queryModel += "@buttonfooter:mode=button,id=btnCheck, class=btn btn-primary,

callback=CheckSelections('%tableid%'), title=Check Selezioni";

queryModel += "@buttonfooter:mode=button,id=btnImport, class=btn btn-primary,

callback=GotoRubrica(), title=Importa da CSV";

queryModel += "@buttonfooter:mode=button,id=btnDelete, class=btn btn-primary,

callback=DeleteSelectedItems('%tableid%'), title=Elimina selezioni";

MySail: Guida di riferimento per il Programmatore – pag 89

// set query

queryModel += "@query: select ID,

Nome,Peso,Tel1,Cap,Via,Localita,Provincia,Civico,Interno, Presso,Scala,Tipo,RifCSV from

AnagraficaFullView where tipo = 'DESTINATARIO' and CodUnivoco = " + CodUnivoco;

var url = CreateAjaxCall('GRID', 'QUERY4;' + queryModel);

cpAjax('rubrica-content', url);

keyword

Nome Tipo di dati e parametri Descrizione

@database <datasource di

CPSICONFIG>.catalog

Informa l’executor su quale db accedere. La

query finale puo essere in join con altri mille

DB linkati. Questo è il master principale dove

viene eseguita fisicamente la query

@tableid string È l’id da assegnare alla table generata nel

caso si voglia raggiungere con jquery dopo

averla renderizzata

@template Path e nome template es

\Template\MioResult.html

Template da utilizzare. Molto utile se si vuole

arricchire il layout del template generato *

@title Titolo Titolo che verra sull’intestazione della grid

@query Select su tabella, stored, vista Quersy da eseguire sul db **

@button

checkbox

@button:mode=checkbox,

id=%ID%

Aggiunge in ogni riga un checkbox, e pone

come ID il valore della colonna racchiusa tra

% es: mode=checkbox, id=ck-

row%CodUnivoco% sarà agganciabile da

jquery con $(‘#ck-row-98793845’).checked

(vedi esempi sul progetto su come controllare

i checkbox)

@button

custom

@button:mode=fa-male,

Title=Impersona Cliente,

callback=ImpersonateUser('%u

sername%')

Aggiunge l’icona di font-awesome icon fa-

male (quindi una qualsiasi icona) mette nell’

OnClick=ImpersonateUser('%username%')

dove UserName è una colonna della SELECT

***

@button edit "@button:mode=edit,

Title=Modifica,

callback=EditSede('%IdSede%'

) "

Aggiunge l’icona di edit e mette e nell’

OnClick=ImpersonateUser('%username%')

dove UserName è una colonna della SELECT

***

@button

select

"@button:mode=select,

Title=Seleziona,

callback=SelezionaSede('%IdS

ede%') "

Aggiunge un pulsante con icona di select per

ogni riga e nell’

OnClick=SelezionaSede('%IdSede%') dove

IdSede è una colonna della SELECT ***

@button

delete

"@button:mode=delete,

Title=Elimina,

callback=DelSede('%IdSede%'

) "

Aggiunge un pulsante con icona gomma per

ogni riga e nell’ OnClick=

DelSede('%IdSede%') dove UserName è una

colonna della SELECT ***

@hiddencolu

mns

Nome di colonna da

nascondere ***

Indicare separati da virgola, i nomi di colonne

da nascondere. Un altro metodo è copiare il

template e mettere hidden nelle colonne da

nascondere. @hiddencolumns lo fa durante la

generazion del template

@footerstat "@footerstat:true" Abilita la visualizzazione statistica del

consumo risorse per l’esecuzione della query

(indicato solo per debug, non metterlo true in

MySail: Guida di riferimento per il Programmatore – pag 90

produzione)

@buttonfoot

er

mode=button id=btnCheck,

class=btn btn-lg btn-outline

btn-primary,

callback=CheckSelections('%ta

bleid%'), title=Check Selezioni

Aggiunge un pulsante alla fine della griglia.

Non ci sono limiti di numero di pulsanti.

* per ottenere il template di base non va scritto nulla, si prende quello che genera lui la prima

volta in (\Templates\Dynamic\output\<nomeutente>\<guid random>.html). Svuota la cache,

esegui la query con template @null, prendi il file generato, cambiagli nome e posizione e usalo

come @template. Arricchiscilo a piacere

** Il timeout della query è illimitato, se la query richiede due ore, il processo ajax sta fermo

per 2 ore.

*** i nomi delle colonne devono rigorosamente rispettare le maiuscole e minuscole definite

nella select

Questi metodi istanziano il mapper SQLMapper e una serie di oggetti da cui ricavano tabella,

schematable, datatable, rows, cells e tutto quello che serve di una query,

suggerisco di dare un occhiata a queste classi in LibExecSql

SQLData

SQLRow

SQLRequest

Live Update Cell (salva da griglia)

E’ una caratteristica molto utile che permette di editare una cella di una grid da una lista di

valori in un DropDown bootstrap. Al cambio valore sulla cella viene automaticamente salvata

sul DB

In abbinamento con la classe SWObjects in C# e SailpostGrid.js lato client, si puo impostare

questa caratteristica durante il popolamento grid

in citypost.js

la function DD_MakeSelection(span_id, text)

Imposta il testo del button DropDown ed se ci sono le condizioni aggiorna direttamente il

record in tabella

campi:

span_id = id dello span

text = nuovo valore

MySail: Guida di riferimento per il Programmatore – pag 91

per i requisiti per l'update automatico del db vedi SailpostGrid.js LiveUpdateOnGrid

lo span_id deve essere composto da cell-xxx (id del record sul db da aggiornare)

lo span_id puo contenere altri valori separati dal trattino, l'importante è che inzi con cell e

finisca con l'id

cell-grp-12232 valido

cell-12232 valido

cell-grp-fix-12232 valido

grp-cell-12232 NON valido

se l'id è valido esegue LiveUpdateOnGrid e salva

8.13 Eventi

Gli eventi in asp.net non hanno lo stesso comportamento degli eventi di una window form,

questo è evidente da subito.

In una window form quando viene intercettato ed eseguito un evento, è solo lui che ha il

controllo del puntatore di flusso, il thread è fermo in attesa della conclusione di quell’evento. In

asp.net, quando viene scatenato un evento come Login_Click(object sender), viene di fatto

fatta un richiesta al server, viene quindi caricata tutta la pagina e poi processato l’evento. Ciò

significa che in debug si vedono sollevare un mare di eventi prima del nostro Click. E’ utile

saperlo per evitare spiacevoli sorprese. Per questo motivo secondo me è preferibile usare

button client con chiamate ajax, perche viene eseguito solo il codice di cui prevediamo e

controlliamo tutto il flusso dall’inizio alla fine. Un evento server al contrario, attiva il framework

asp.net in POST sulla pagina. Questo determina il valore isPostBack True, se il caricamento è

dovuto ad una submit, o False se si tratta del caricamento per richiesta di visualizzazione

pagina.

Workflow

Caso 1

Dalla pagina di Default.aspx si richiama una pagina Contacts.aspx da un tag client

<a href="javascript:window.location.href=’Contacts.aspx’;"

id="btnRedirectClient">Contatti</a>

Load master page

Page_Load di Contacts.cs

IsPostback = False

render Contacts.aspx

La pagina contacts.aspx è visualizzata sul browser

Caso 2

MySail: Guida di riferimento per il Programmatore – pag 92

Dalla pagina di Default.aspx si richiama una pagina Contacts.aspx da un tag server

<asp:LinkButton

<asp:LinkButton ID="Linkbt" runat="server"

OnClick="GoContacts_Click">Contatti</asp:LinkButton>

protected void GoContacts_Click(object sender, EventArgs e)

{

SailWeb.LogIt(Context, "Vai a lla pagina dei contatti");

try

{

Context.Response.Redirect("Contacts.aspx", true);

}

catch (Exception ex)

{

SailWeb.LogIt(Context, ex);

}

}

Load master page

Page_Load Default.cs

isPostBack= True

render Default.aspx

GoContacts_Click

Load master page

Page_Load Contacts.cs

isPostBack= False

render Contacts.aspx

La pagina contacts.aspx è visualizzata sul browser

9 Pubblicazione di SailWeb

Nell’infrastruttura Citypost si sono dedicate 3 posizioni su cui pubblicare il sito, gli scopi sono

diversi a seconda delle necessita

9.1 Sito di produzione

Descrizione: Sito ad accesso pubblico ufficiale dove accedono Agenzie, Clienti, Clienti

Direzionali, ecc..

Server 192.168.78.3

Nome Sito IIS: SailWeb

Pool di Applicazioni: SailWeb

Porta: 80

MySail: Guida di riferimento per il Programmatore – pag 93

URL pubblico: http://net.sailpost.it

URL privato: http://198.168.78.3

SSL: Si https://net.sailpost.it

Path FileSystem: E:\Siti\SailWeb

Log: E:\Log

9.2 Sito Ultimo Funzionante

(versione precedente)

Descrizione: Versione di produzione che funzionava prima dell’ultima pubblicazione, è una

sorta di backup, se qualcosa va storto sull’ultima pubblicazione o si fanno puntare tutti a

questo sito o da qui si prende tutto il contentuto da rimettere in \SailWeb

Server 192.168.78.3

Nome Sito IIS: SailWebUltimo

Pool di Applicazioni: SailWebUltimo

Porta: 8082

URL pubblico: http://net.sailpost.it:8082

URL privato: http://198.168.78.3:8082

SSL: Si https://net.sailpost.it:8082

Path FileSystem: E:\Siti\SailWebUltimo

Log: E:\SWLog8082

9.3 Sito di TEST

Descrizione: Sito su cui effettuare i test di laboratorio, verifica. E’ pubblico, si accede anche

dall’esterno

Server 192.168.78.6

Nome Sito IIS: SailWeb

Pool di Applicazioni: SailWeb

Porta: 8082

URL pubblico: http://156.54.97.110:8082/Account/Login.aspx

URL privato: http://198.168.78.6:8082

SSL: No

Path FileSystem: E:\Siti\SailWeb

Log: E:\Log

MySail: Guida di riferimento per il Programmatore – pag 94

9.4 Pubblicazione Step by Step

Tempo medio per eseguire l’attività: 20 minuti

- Esegui l’UPDATE di SVN

- Segnati la versione attuale del sito in produzione (es 295 del 22/5/16 16:21), la

trovi a video

- Compila il sito

- Crea o usa una cartella dove pubblicare da visual studio. In questo esempio ho usato

c:\0\SVN_PUBBLICAZIONI_VS\PubblicazioniLocali\Profilo per TEST 6. in

questa cartella ci vanno sia le pubblicazioni di test che di produzione, si spostano in una

delle 3 posizioni descritte in precedenza, ma la pubblicazione locale si fa sempre sulla

stessa cartella. Conviene quindi dargli un nome piu indicato, per non confondersi

sull’utilizzo.

- Assicurati che in questa cartella non ci sia una precedente \Sail.Web se si, cancellala

- Da Visual Studio Mouse Destro->Publish Web App

- Dalla finestra di pubblicazione crea un nuovo profilo indicandogli nella Connection

FileSystem e la tua cartella

- Click Publish

- Al termine vai sulla cartella e impacchettala

MySail: Guida di riferimento per il Programmatore – pag 95

- Cambia nome al *.rar in SailWebxxx dove xxx è il nuovo numero di versione (es

SailWeb296)

- Se hai un path di rete connesso tipo questi, ci copi il file

- Se no collegati in RDP alla macchina dove vuoi pubblicare

- Decomprimi il file in una nuova cartella

MySail: Guida di riferimento per il Programmatore – pag 96

- Stoppa il Sito e il Pool di Applicazioni SailWeb

- Elimina tutti i files dalla cartella di destinazione effettiva (es SailWeb) MENO il

web.config

- Dalla SailWeb296 taglia tutti i files MENO il web.config

- Spostali da SailWeb296 a SailWeb

- Apri il Web.Config di SailWeb con Notepad++

- Alla linea del Setting key Versione, aggiornalo con la descrizione corretta (n°

d/m/yyyy hh:mm)

MySail: Guida di riferimento per il Programmatore – pag 97

Questa operazione può sembrare banale ma non lo è, il numero di versione fa si che vengano

ricaricati tutti i css e js in cache sui browser dei clients. Ogni pubblicazione deve essere diverso

altrimenti non vengono caricate le modifiche

- Avvia il Sito *

- Avvia il Pool *

- Prova ad accedere

- Cancella la cartella SailWeb269 e il rar

- Chiudi l’RPD

* Avvia prima il Sito e poi il Pool. Se vedi nel log, la Global.Asax.Application_Start scrive una

serie di informazioni. Se avvi prima il Pool del Sito, il Log manca dello starting del pool,

trovandolo gia attivo. Per questo è consigliabile sempre rispettare questa sequenza.

9.5 Versioni di SailWeb

Nota sulle versioni SailWeb: Il numero 296 sta per versione 2 + pubblicazione numero 96. La

versione 1 è stata quella offline, prima della messa in esercizio ufficiale, che era celeste. E’

possibile controllare tutte le pubblicazioni interrogando la tabella Process con stato = 5693.

Ogni volta che si avvia il pool va a controllare se non esiste la versione e aggiunge un record,

cosi possiamo risalire a date di tutte le pubblicazioni avvenute

SELECT info,datastart FROM [SailWebData].[dbo].[Processes] where stato = 5693

10 Tabella Processes

MySail: Guida di riferimento per il Programmatore – pag 98

10.1 Query SQL Salvate

Sono le query che vengono salvate dalla funzione Salva Public della pagina

SWSQLManagement.aspx

SELECT [id],[Info],[idUser],[Descrizione],[Tipo],[Contenuto],[Stato] FROM

[SailWebData].[dbo].[Processes] where tipo = 'sql' and stato = 500

Risultato

10.2 Messaggi

SELECT [id],[Info],[idUser],[Descrizione],[Tipo],[Contenuto],[Stato],DataStart FROM

[SailWebData].[dbo].[Processes] where tipo = 'msg' order by DataStart desc

11 CSV Import/Export

Da Sailweb l’esportazione in CSV è attiva su tutte le griglie cliccando sul pulsante sulla

riga della paginazione. Per l’import invece è stata definita una pagina a se stante, dalla quale è

possibile caricare CSV con destinazione diversa a seconda di dove si vogliono importare i dati.

Questo contenitore è la RUBRICA di SailWeb

11.1 Esporta in CSV

l’esportazione in CSV è attiva su tutte le griglie cliccando sul pulsante sulla riga della

paginazione. Per le griglie generate da T-SQL di tipo QUERY4, il pulsante genera

automaticamente il CSV, mentre per le griglie customizzate occorre fare una semplice

implementazione, non è difficile, questa guida fornisce l’esempio di un nuovo oggetto da

esportare in CSV.

MySail: Guida di riferimento per il Programmatore – pag 99

Premendo il pulsante il sistema legge l’intero set di dati (tutte le pagine) e lo scrive in un

csv mostrando questo pulsante di download , su cui è visibile la dimensione

del file generato.

11.2 Programmare i Services per l’export

Perche un nuovo service esporti in csv sfruttando il pulsante della griglia, occorre

implementare alcuni passaggi, piuttosto semplici.

Quando l’utente clicca ul pulsante il sistema riesegue la stessa chiamata ajax con l’unica

differenza del parametro CSV = 1 anziche 0

nel momento in cui apre il mapper prima della get dei dati da mettere in griglia, incolla questo

codice

using (var Mapper = new SWUserMapper()) {

var curRequest = SailWeb.getRequest(HttpContext.Current);

if (SQLGrid.ExportToCSV(Response, curRequest, Mapper)) return; //<- QUI!!

um.Initialize(curRequest.Pager.Current, curRequest.Pager.MaxItems,

curRequest.Pager.Filters);

curRequest.Pager.SetupTotalPages(um.Count);

Archivio = um.getGridLogindb();

esegue SQLGrid.ExportToCSV(Response, curRequest, Mapper)) ed esce se CSV=1 e riesce a

generare il file da scaricare.

In SQLGrid.ExportToCSV va aggiunto il Mapper del Service desiderato (copia questo e

sostituiscilo con il nuovo Mapper

if (Mapper is SWUserMapper) {

var mp2 = (SWUserMapper)Mapper;

mp2.Export(fc, curRequest.Pager.Filters);

}

Dopodichè sull’oggetto mapper va implementata la funzione Export, che è identica per tutti i

mappers, basta copiarne una, cerca Export in tutto LibCoreMySail o in BusinnesLogic. (ce ne

sono anche nel BL, ma sono identici

Copia esattamente questo, sostiuendo SWUtente con il tuo Entity, Persister o DataShape

public void Export(string fc, SqlDynamicFilter Filter) {

CSVName = fc;

Initialize(1, 200000, Filter);

var Buffer = new List<SWUtente>();

MySail: Guida di riferimento per il Programmatore – pag 100

Buffer = getGridLogindb();

foreach (var p in Buffer) {

p.ToCSV(CSVName);

}

CSVName = "";

}

Ora, per finire, vanno implementati i membri di p.ToCSV, che sta nell’EntityBase

public void ToCSV(string file)

{

bool isnew = !File.Exists(file);

using (var sw = new StreamWriter(file, true))

{

if (isnew)

{

if (!String.IsNullOrEmpty(CSVDataBase))

{

sw.WriteLine(LogIt("term;Server;Catalog;Table;" + ToCSVLineHeader(";")));

// sul log ci va l'header per segnalare l'inizio dell'export, le righe non ci vanno

sw.WriteLine(WriteIt(ToCSVLine(";")));

}

else

{

sw.WriteLine(ToCSVLineHeader(";"));

sw.WriteLine(WriteIt(ToCSVLine(";")));

}

}

else

{

if (!String.IsNullOrEmpty(CSVDataBase))

sw.WriteLine(WriteIt(MoreCSVData + ";" + CSVDataBase + ToCSVLine(";")));

else

sw.WriteLine(WriteIt(ToCSVLine(";")));

}

}

Questa non va copiata, c’è gia e funziona. Ci serve solo perche sulla nostra Entity mancano

ToCSVLine e ToCSVLineHeader

Eccole qua. Basta sostituire il return con il valore dei campi separati da sep e dall’intestazione

dei campi

public override string ToCSVLine(string sep) {

string st = Userid + sep +

UserName + sep +

Password + sep +

NomeCompleto + sep +

mail + sep +

MaxRows + sep +

LastActivityDate + sep +

LastLoginDate + sep +

CreateDate + sep;

MySail: Guida di riferimento per il Programmatore – pag 101

string h = "";

foreach (long i in ClientiAgenzia) {

h += i.ToString() + " ";

}

st += h + sep;

h = "";

foreach (string i in Ruoli) {

h += i.ToString() + " ";

}

st += h + sep;

h = "";

foreach (var i in Abilitazioni) {

h += i.ToString() + "|";

}

st += h + sep;

h = "";

foreach (string i in ExtranetAree) {

h += i.ToString() + " ";

}

st += h + sep;

return st;

}

public override string ToCSVLineHeader(string sep) {

return "Userid" + sep +

"UserName" + sep +

"Password" + sep +

"NomeCompleto" + sep +

"mail" + sep +

"MaxRows" + sep +

"LastActivityDate" + sep +

"LastLoginDate" + sep +

"CreateDate" + sep +

"ClientiAgenzia" + sep +

"Ruoli" + sep +

"Permessi" + sep +

"ExtranetAree";

}

11.3 Import CSV (per Admin)

Il sitema di Import da CSV permette di caricare 3 tipi di dati sul sistema centralizzato

DESTINATARI

MITTENTI

RUBRICA TELEFONICA

Per accedere alla pagina, click sull’etichetta verde del menu laterale destro

MySail: Guida di riferimento per il Programmatore – pag 102

Si accede alla pagina che segue

MySail: Guida di riferimento per il Programmatore – pag 103

Primo step, scegliere quale tipo di CSV si sta importando e dove si vuole caricare

Scelta Origine

MySail: Guida di riferimento per il Programmatore – pag 104

Scelta della destinazione sul Sistema Centrale

Caricamento File

Trascinare il file dalla cartella locale e rilasciare il mouse all’interno del rettangolo tratteggiato

MySail: Guida di riferimento per il Programmatore – pag 105

Verifica Validità CSV e associazione campi

Al termide del caricamento si presenta la seguente sottopagina: Da questa occorre verificare la

correttezza delle associazioni effettuate e la eventuale mancanza di associazioni dei campi

obbligatori.

Informazioni CSV: Indica il n° di colonne rilevate, la quantità di righe contenute, il

Cod.Univoco dell’utente connesso e le associazioni obbligatorie che sono richieste per poter

proseguire.

Corpo della scheda:

In verticale da sinistra a destra possiamo vedere:

Le colonne del CSV

L’elenco dei campi selezionabili per l’associazione del DataBase sul sistema.

Dalla Riga 1 alla riga 5, i dati estesi in orizzontale per verificare la correttezza dei dati

della colonna. Per una intestazione CAP, ad esempio, ci aspettiamo di trovare numeri di

5 cifre. Se così non fosse occorre rivedere il contenuto del CSV e correggerlo

Schema Associazione Campi

MySail: Guida di riferimento per il Programmatore – pag 106

L’elenco dei campi da associare è una combobox contenente i nomi disponibili. Le voci in rosso

sono i campi obbligatori.

MySail: Guida di riferimento per il Programmatore – pag 107

Convalida Import ed esecuzione trasferimento dati

Una volta verificate e completate le associazioni premere il pulsante

Controllo risultati

AL termine dell’import un ultima scheda riporta il risultato dell’eleborazione, quante righe ha

copiato, quante ne ha scartate, se ci sono stati errori bloccanti o meno

Su questa scheda vengono evidenziati:

Errori bloccanti, che hanno impedito il trasferimento. A causa del formato errato,

associazioni non complete, errore di lettura file csv ecc.. In questo caso non viene

copiato nessuna riga del CSV e l’importazione si è fermata

Errori di avvertimento (come mostrato in figura) che non hanno impedito il

trasferimento, ma evidenziali le righe del CSV scartate che non sono risultate conformi.

ToolBars:

Torna a questa pagina da qualsiasi punto di importazione

MySail: Guida di riferimento per il Programmatore – pag 108

Rileggi l’ultimo CSV caricato (evita di ripetere Uploads)

Gestisci la rubrica selezionata in Selezione Destinazione

Modifica l’ultimo CSV caricato, permette l’edit direttamente dal sito

Scarica CSV preformattato. Scarica sul vostro PC locale un modello di CSV

precompilato con 3 o 4 righe di esempio contenente l’intestazione corretta per

l’associazione automatica di tutti i campi. Si consiglia di utilizzare questo modello

per accellerare il processo di associazione campi/dati

Guida in linea (apre la guida alla gestione delle rubriche destinatari/telefoniche e

trattamento CSV in generale)

Guida in linea (apre la guida alla gestione delle rubriche destinatari/telefoniche e

trattamento CSV in generale)

Gestione Rubriche

Mostra l’elenco della tabella selezionata nel combobx Seleziona Destinazione

Da questo elenco è possibile selezionare uno o piu elementi da eliminare

MySail: Guida di riferimento per il Programmatore – pag 109

Mofifica l’ultimo CSV caricato. Legge il file caricato sul server e lo presenta su un campo

modificabile sulla pagina Maintenance.aspx?q=CSV

Premere Salva al termine delle modifiche, torna indietro per tornare ala home Import CSV

Identificazione Lotti di Caricamanto

Nella visualizzazione Elenco Rubrica l’ultima colonna identifica il lotto del CSV. Si tratta di un

codice alfanumerico generato con caratteri casuali al momento della scrittura sul DataBase ed

è identico per tutte le righe di un singolo CSV. In questo modo è possibile a posteriori

identificare tutte le righe aggiunte in un determinato set di caricamento da CSV

MySail: Guida di riferimento per il Programmatore – pag 110

12 Telegrammi (per il programmatore)

I Telegrammi, come i Parcel, sono derivati da back-end gia operativo del sistema di

archiviazione spedizioni via SENDABOX e PARMAREC per i telex.

Tutto il meccanismo Back-End si basa sul motore ArchiviaMpx, nato come applicazione

Windows con pannelli di controllo dei flussi, poi trasformati in Libreria monoutente

LibArchiviaMpx.dll, resa infine multiutenza da LibForConnection adottata a fine 2015.

Il sistema di archiviazione si basa su un flusso di dati che dall’input genera un CSV, dal quale

Mpx raccoglie le informazioni e le scrive sul DataBase.

E’ importate sapere queste informazioni perche molti campi a video si chiamano in un modo e

sul db sono scritti su colonne senza corrispondenza di nome. Questo perché si è dovuto

mantenere integra una struttura di tabelle e colonne di ampiezza definita, per compatibilità con

il vecchio.

Eris e Ivo conoscono il dettaglio di questi abbinamenti video/db, e non sarebbe male annotarli.

Detto cio, i telegrammi mysail concettualmente seguono questo workflow

Workflow Telex

Data entry dell’utente

Click su Invia

In PostBack True passa i dati da video a un oggetto _Telex di BusinnessLogic.

Il Mapper di BusinnesLogic trasferisce dall’oggetto _Telex a ClasseTelegrammi di

LibArchiviaMpx

Il sito scrive in sessione il _Telex con stato In Acquisizione

LibArchiviaMpx scrive ClasseTelegrammi su un csv nell’area ftp.

Il processo CheckFtp schedulato ogni 10 secondi, appena trova un csv sul ftp aggiunge un

record nella tabella dei processi WF_Processes di DbLog.

Un altro processo CW_EseguiProcessi schedulato ogni 10 secondi, appena trova una riga su db

avvia ArchiviaMpx windows app, con i parametri che trova sul record.

ArchiviaMpx win app scarica il csv da ftp e Archivia il telex su dbServer.BusteWeb_Sara.Buste

e sue estensioni (Flussi, ftpExtendBuste, ecc) e fa lo shutdown di se stesso.

In questa attesa di scambio dati e processi schedulati, a video si vede il telex in stato In

Acquisizione e resta tale fino a quando tutto il ciclo non è terminato.

MySail: Guida di riferimento per il Programmatore – pag 111

Se sono richiesti piu destinatari, il ciclo è ripetuto tante volte quanti sono i telex da produrre.

L’elemento sulla griglia cambia stato in In Elaborazione quando un ciclo è terminato.

Il Cut-Off dei telex che avviene a ore prestabilite (da lunedi a venerdi 2 volte al giorno alle ore

8:00 e 14:00) è una schedulazione di un *.bat che avvia un’altra istanza di ArchiviaMpx win

app che cambia stato del telex in Inviato , produce il file PDF, genera l’xls da caricare su

sailnet e genera la mail per l’agenzia.

A questo punto il telex entra nel circuito di spedizione e dall’interrogazione del tracking online

con il numero di tracer è possibile controllarne l’esito di consegna.

12.1 Centri di Costo

I centri di costo sui telex sono individuali per ogni utilizzatore. Al momento sono configurati solo quelli di

PRELIOS, tutti gli altri non vedono CDC.

Per abilitare i CDC a chi ne fa richiesta procedere come segue:

- Editare 200 righe della tabella TABELLE sul 131

- Vedi come è fatto PRELIOS e ripeti la stessa cosa per il nuovo utente. Il record con CDCxxxxx (dove

xxxx è il CodUnivoco) raggruppa i CDC di un utente

- Inserire l’intestazione con IDPadre = 0 e Descrizione CDCxxxxxx

- Inserire le righe per ogni centro di costo, con IDPadre quello precedente e come descrizione il

Codice Centro di Costo

finito

12.2 Destinatario fattura diverso dal mittente

In fase di creazione telegrammi è possibile indicare un destinatario fattura

(da completare con la descrizione tabella e sp Condomini)

13 Small Parcel (per il programmatore)

MySail: Guida di riferimento per il Programmatore – pag 112

14 SWSQLManagement

15 Admin, Amministratore del sito

Per cambiare nome utente e/email

Sulla pagina di admin premi il pulsante

Indica il nome esistente su SailWeb

Il nuovo nome utente non è obbligatorio, se manca, aggiorna solo la mail

La nuova mail non è obbligatoria, se manca, aggiorna solo l’UserName.

L’username nuovo viene riportato anche sui SWSettings

16 Unit Test

E’ stato predisposto un progetto Unit Test per SailWeb ma può e dovrebbe essere usato per tutto il mondo

Citypost.

MySail: Guida di riferimento per il Programmatore – pag 113

Il progetto è SailWeb.UnitTest e funge da raccoglitore di prototipi, funzioni una-tantum, funzioni di

verifica di blocchi di codice in produzione.

È diviso in settori separati.

UnitTestIIS

È il modulo da cui testare le funzionalità web. Qualsiasi metodo di test venga lanciato, l’init della classe

istanzia un WebServer fake (mock), da cui è possibile gestire Session, Context, Application Pool, Request e

Response, senza aver avviato né IIS né CassiniDev, né nessun altro web server fisico.

UnitTestGridding

È il modulo di prototipi funzionalità di LibSQLExec per le grid dinamiche da query SQL

UnitTestPPA

È il modulo di prototipi funzionalità per l’accesso ai Plichi e PPA

UnitTestSystem

È il modulo di prototipi funzionalità generiche e astratti.

17 Web Services SailPost

Ivo, mail a sviluppo del 07/06/2016

Ho creato il servizio che ritorna l’ultimo esito scaricato da SailNet

Ho aggiornato solo

\\192.168.78.2\siti\SAILNET_SERVICES_8080, quindi il servizio da chiamare è

http://svc.sailpost.it:8080/SailpostServices.ashx/SAIL_TRACKING

la richiesta può essere fatta sia come Json, che come Xml. La risposta manterrà la stessa serializzazione (a

meno di eccezioni che risponde sempre Json)

chiamata (POST): <WS_RequestTracking xmlns="http://schemas.datacontract.org/2004/07/LibDatiCitypost"

xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <ListaTracking>

<Tracking><Action/><CodiceCli>0</CodiceCli><Hidden>false</Hidden><Rif1/><Rif2/><Rif3/><Track>08005210150

000768</Track></Tracking>

<Tracking><Action/><CodiceCli>0</CodiceCli><Hidden>false</Hidden><Rif1/><Rif2/><Rif3/><Track>20017410150

003625</Track></Tracking>

</ListaTracking>

<SoloUltimoMovimento>true</SoloUltimoMovimento>

MySail: Guida di riferimento per il Programmatore – pag 114

</WS_RequestTracking>

oppure (in forma ridotta): <WS_RequestTracking xmlns="http://schemas.datacontract.org/2004/07/LibDatiCitypost">

<ListaTracking>

<Tracking><Track>08005210150000768</Track></Tracking>

<Tracking><Track>20017410150003625</Track></Tracking>

</ListaTracking>

<SoloUltimoMovimento>true</SoloUltimoMovimento>

</WS_RequestTracking>

La cui risposta è (sempre): <WS_ResponseOnlyLastMovTracking xmlns="http://schemas.datacontract.org/2004/07/LibDatiCitypost"

xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

<ListaTracking>

<WS_TrackingRecord><Data>2015-09-25T11:00:00</Data><Desc>Consegnato in

agenzia</Desc><IdStato>902</IdStato><Track>08005210150000768</Track></WS_TrackingRecord>

<WS_TrackingRecord><Data>2015-08-03T13:01:00</Data><Desc>In

giacenza</Desc><IdStato>60</IdStato><Track>20017410150003625</Track></WS_TrackingRecord>

</ListaTracking>

</WS_ResponseOnlyLastMovTracking>

Versione Json: {"ListaTracking":[

{"Track":"08005210150000768","Action":"","Hidden":false,"CodiceCli":0,"Rif1":"","Rif2":"","Rif3":""}

{"Track":"20017410150003625","Action":"","Hidden":false,"CodiceCli":0,"Rif1":"","Rif2":"","Rif3":""}

],"SoloUltimoMovimento":true}

oppure (in forma ridotta): {"ListaTracking":[{"Track":"08005210150000768"},{"Track":"20017410150003625"}]}

La cui risposta è (sempre): {"ListaTracking":

[

{"Track":"08005210150000768","Data":"\/Date(1443171600000+0200)\/","IdStato":902,"Desc":"Consegnato in

agenzia"},

{"Track":"20017410150003625","Data":"\/Date(1438599660000+0200)\/","IdStato":60,"Desc":"In giacenza"}

]}

MySail: Guida di riferimento per il Programmatore – pag 115