MySail: Guida di riferimento per il...
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 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 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-
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$%&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$%&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
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)
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
- 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 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"}
]}