• Non ci sono risultati.

CAPITOLO 3 PROGETTAZIONE DEL DW

4.3 SORGENTI INFORMATIVE: APEX

4.3.3 CREAZIONE DEL DATA ENTRY

La parte relativa agli sviluppi del Tool di Data Entry ha avuto una durata di circa un mese e mezzo a partire dal primo mockup consegnato sino al passaggio in produzione dello strumento in seguito alla validazione degli utenti. Partendo dall’Application Builder descritto precedentemente è stata creata una Database Application dal nome ‘Cockpit’ che

39

ha come schema di riferimento DW_APEX, ovvero lo schema in cui sono state create le tabelle precedentemente descritte. Nel Wizard di configurazione del progetto è stata

definita la configurazione di base del tool. Nel dettaglio è stata prevista una pagina di login ed una Home Page ed è stata specificata la necessità di includere dei Tab nella nostra applicazione. In particolare è stata definita una configurazione a due livelli in modo tale da avere il Tab padre che rappresenti il Kpi e da cui è possibile accedere alle pagine di editing dedicate. Quanto descritto ha portato ad avere inizialmente un strumento strutturato come nell’immagine sottostante.

A partire dalla struttura di default sopra rappresentata sono iniziati gli sviluppi per customizzare il prodotto e renderlo in linea con le specifiche dell’utente. A partire dall’application builder è stato possibile editare le pagine create e gestire le varie componenti che andranno a comporre l’applicativo finale.

Figura 14 Login Page

40 Figura 16 Application Builder Cockpit

Al termine del lavoro l’applicazione risulta essere composta dalle seguenti pagine analizzate nel dettaglio di seguito.

4.3.3.1 LOGIN PAGE

La pagina di login è stata la prima sulla quale si è intervenuti per modificare la modalità di accesso. Di seguito verranno esposte una serie di immagini con lo scopo di fornire un quadro generale di come possono essere editate le pagine e come queste interagiscono con le varie componenti presenti nel Tool. La Figura n.17 rappresenta la pagina dedicata al login e verrà presa come campione per spiegare le componenti su cui è possibile intervenire per modificare le pagine.

Figura 17 Login Page

41

➢ Page Rendering: contiene al suo interno le sezioni dedicate alle componenti che andranno a comporre la pagina. In particolare:

o Page: contiene le informazioni riassuntive della pagina e permette di modificare il Template ed inserire codice Javascript/Css/Html.

o Region: consente di definire il contenuto della pagina. Tramite questa sezione viene suddivisa la pagina in base a ciò che viene inserito al suo interno. Nel caso in questione è presente la sola form di Login, ma nelle pagine che analizzeremo in seguito saranno presenti le Tabelle che permetteranno l’inserimento delle informazioni.

Figura 18 Region Options

o Buttons: permette di inserire i bottoni che saranno visibili nella pagina con la possibilità di ancorarli alle region create, oppure di personalizzarli tramite l’utilizzo di codice .Css.

Figura 19 Buttons Options

o Items: permette di inserire una serie di oggetti come Text Field, Text Area ecc.

42 Figura 20 Items Options

o Computations: consente di settare in maniera statica o dinamica i valori degli Items creati all’interno della stessa pagina oppure di pagine differenti.

Figura 21 Computations Options

o Processes: permette di stabilire i processi che devono essere avviati all’interno della pagina.

43

o Dynamic Action: consente la creazione di azioni dinamiche con la possibilità di definirne l’esito in base al verificarsi o meno di un evento definito.

Figura 22 Dynamic Actions Options

➢ Page Processing: racchiude tutti i processi implementati all’interno della pagina. Nel dettaglio:

o Computations: racchiude, come nella sezione precedente, le funzioni per settare i valori delle variabili presenti nella pagina o più in generale nell’applicativo.

o Validation: consente di impostare le operazioni di validazione da compiere. E’ possibile definire la validazione sugli oggetti creati oppure sull’intera pagina.

44 Figura 23 Validations Options

o Processes: come nella sezione precedente.

o Branches: permette di creare i collegamenti tra le varie pagine

dell’applicativo, con la possibilità di passare i valori delle variabili da una pagina ad un’altra.

Figura 24 Branches Options

➢ Shared Components: racchiude i componenti che possono essere visualizzati in tutte le pagine dell’applicativo. In questa sezione compaiono ad esempio i Tab creati, le configurazioni del Template ed il pulsante per il logout in quanto componenti comuni a tutte le pagine. Per inserire i vari componenti è possibile accedere alla sezione dedicata direttamente dall’Application Builder.

In seguito a questa breve introduzione sull’ambiente all’interno del quale sono stati svolti i lavori, verranno descritte nel concreto le operazioni effettuate. Per la pagina di Login presa in esame, si è provveduto a modificare la modalità di autenticazione, in quanto di default durante la creazione della Database Application viene utilizzata come modalità la stessa tramite la quale si accede al Tool Apex. Attraverso la sezione dedicata alla Security, presente all’interno degli Shared Components, è stata creata una funzione PL/SQL

(linguaggio di programmazione proprietario per Database di Oracle) tramite la quale viene interrogato il Database per verificare che i dati immessi siano presenti nella tabella di Login precedentemente creata. E’ stato creato un nuovo schema di autenticazione, il quale

45

viene richiamato nella pagina di login tramite la funzione ‘apex_authentication.login()’. Tale funzione è stata inserita all’interno della procedura ‘Login’ che, alla pressione del pulsante creato nella form, passa i valori che corrispondono a username e password dell’utente allo schema di autenticazione. Lo schema in questione è stato configurato come rappresentato nella figura sottostante.

Figura 25 Authentication Schema

Nella sezione ‘Source’ visibile nell’immagine, è stata quindi creata una funzione Booleana che ritorna ‘True’ se l’utente e la password inseriti sono presenti nel Database, ‘False’ altrimenti. Inoltre sono stati impostati i reindirizzamenti in caso di Sessione non valida e in caso di Logout. Una volta creato il meccanismo di login, sono stati inseriti due ulteriori

46

processi, il primo ‘Set Username Cookie’ che richiama un’altra funzione nativa di Apex quale ‘apex_authentication.send_login_username_cookie()’ utile per impostare i cookie ed il secondo ‘Clear Page(s) Cache’ implementato per pulire la cache della pagina.

4.3.3.2 HOME PAGE

Terminata la pagina di Login il lavoro è proseguito cercando di impostare una Home Page semplice ed intuitiva, che consentisse agli utenti di accedere alle pagine dedicate ai KPI. La soluzione più semplice da realizzare sarebbe stata quella di lasciare la Home Page bianca e utilizzare i Tab precedentemente configurati per passare alle sezioni di editing, tuttavia ciò avrebbe portato ad avere una pagina vuota e completamente inutilizzata. Per ovviare a questo problema, è stato concordato con gli utenti di inserire al centro della pagina dei bottoni tramite i quali si viene reindirizzati alle pagine dedicate al Data Entry. Questa soluzione ha portato all’inserimento di codice .Css per personalizzare i pulsanti in questione ma anche di codice JavaScript per gestire il posizionamento di quest’ultimi all’interno della Region utilizzata e per rendere invisibili i Tab nella pagina. Il fatto di avere i pulsanti al centro della pagina e i Tab sulla barra superiore avrebbe potuto

provocare infatti incertezza negli utenti, in quanto avrebbero avuto due differenti modalità di accesso alle Form per i Kpi nella stessa pagina. Le immagini che seguiranno saranno rappresentative della Home Page comprensiva dei Kpi definiti per tutte le Wave

programmate.

Analizzando nel dettaglio la pagina è possibile comprendere quanto descritto

precedentemente. Dall’immagine si nota come i pulsanti siano posizionati al centro della Region che li comprende e come siano organizzati in maniera tale che ne vengano

47

posizionati massimo 4 per riga. Inoltre, come anticipato, non sono presenti Tab nella Barra principale, se non quello che rappresenta la Home Page. Di seguito verrà rappresentata la sezione di editing che riguarda la pagina, da cui è possibile comprendere le operazioni svolte.

Figura 27 Home Page editor

Nella sezione Regions è stato creato uno spazio di tipo ‘HTML’ di nome ‘Select KPI’, il quale ospiterà i pulsanti visibili nella sezione subito sotto. I pulsanti in oggetto hanno tutti la stessa struttura di base interna che varia naturalmente in relazione al KPI a cui fanno riferimento.

48

Dall’immagine è possibile vedere come nella sezione ‘Attributes’ sia stata specificata la classe .Css da cui vengono ereditate le impostazioni del layout e nella sezione

‘Conditions’ è stata impostata come condizione da soddisfare affinché il componente sia processato, ‘Exists(SQL query returns at least one row)’. Tale condizione permette di eseguire una query nel DB per verificare che l’utente con cui si è effettuato il Login sia abilitato o meno ad editare un determinato Kpi. La query in questione è la seguente:

“ select 1 from DW_APEX.WORKFLOW_MAPPING W WHERE UPPER(W.USERNAME) = v('APP_USER') AND W.KPI = 'TOTAL PRICE SAVING ACTUAL' ”

La tabella interrogata corrisponde a quella descritta nella parte iniziale del capitolo e dove sono stati inseriti gli utenti e i Kpi che questi ultimi possono modificare. In tal modo, qualora l’utente loggato, individuato tramite la funzione “v(‘APP_USER’)” di Apex, risulti essere abilitato ad editare il KPI in questione(TOTAL PRICE SAVING nell’esempio sopra), la query ritorna 1 come risultato rendendo visibile il pulsante. La query descritta è la medesima in ogni pulsante creato con il solo nome del KPI che la differenzia in base al bottone. Il codice Javascript è stato inserito all’interno della sezione dedicata alle

‘Dynamic Actions’, in cui troviamo due differenti azioni. La prima riguarda la gestione della visualizzazione dei pulsanti e prende il nome di ‘Display button’. L’azione è stata configurata in modo tale da essere lanciata all’apertura della pagina ed esegue il seguente codice:

If ($('#R7063331821297945 > div.uRegionContent.clearfix > table > tbody > tr > td:first > input').length > 4) { $('#R7063331821297945 > div.uRegionContent.clearfix > table > tbody > tr > td:first >

input').each(function(index,element){

$(element).parent().css('text-align','center');

var trCount = $('#R7063331821297945 > div.uRegionContent.clearfix > table > tbody > tr').length; var firstRowLength = $('#R7063331821297945 > div.uRegionContent.clearfix > table > tbody > tr:first > td > input').length;

var lastRowLength = $('#R7063331821297945 > div.uRegionContent.clearfix > table > tbody > tr:last > td > input').length;

if (firstRowLength > 4) {

if ((trCount > 1 && lastRowLength == 4) || (trCount == 1 && lastRowLength >= 4)) { var tr = $('<tr></tr>');

var td = $('<td></td>'); td.css('text-align','center'); tr.append(td);

$('#R7063331821297945 > div.uRegionContent.clearfix > table > tbody').append(tr); }

$(element).appendTo('#R7063331821297945 > div.uRegionContent.clearfix > table > tbody > tr:last > td'); }

}); }

49

Il codice raffigurato è il risultato di una serie di test effettuati per comprendere il

comportamento del Tool per il posizionamento dei pulsanti. Analizzando l’applicativo in Debug si è dedotto che i bottoni vengono prima inseriti all’interno della pagina e poi vengono riposizionati seguendo uno schema tabellare a partire dall’ultimo pulsante inserito che viene riposizionato a partire dalla parte sinistra della prima riga della Region. In base a questo meccanismo quindi è stato creato il codice precedente che gestisce il processo analizzato permettendo di allineare i pulsanti al centro della pagina e disponendoli in modo tale che ne vengano visualizzati 4 per riga.

La seconda azione implementata che prende il nome ‘hiddenTab’, viene lanciata anche essa all’avvio della pagina e modifica tramite codice Javascript le proprietà .Css dei Tab, rendendoli invisibili. Quest’azione è stata resa necessaria in quanto non è stato possibile impostare i Tab in modo tale che fossero visibili solo nelle pagine di editing e non nella Home Page.

Il documento .Css che gestisce il layout dei bottoni è stato inserito come file esterno attraverso la sezione ‘Shared Components’ ed è stato richiamato all’interno dell’header del template utilizzato.

4.3.3.3 DATA ENTRY TOTAL PRICE SAVING

La creazione della pagina dedicata al Data Entry è stata la parte del lavoro, relativamente al Tool Apex, che ha occupato la maggior parte del tempo. In linea generale le difficoltà incontrate sono attribuibili alle numerose richieste di customizzazione richieste dagli utenti ed il motivo di tali difficoltà è dovuto alla rigidità del tool utilizzato. Apex infatti, se da una parte è uno strumento molto potente e di semplice utilizzo, dall’altra è difficilmente personalizzabile e ciò ha portato a dover utilizzare una serie di tecniche non presenti all’interno delle componenti native. Tutto questo ha portato ad avere numerosi incontri con la committenza ed ha provocato anche un allungamento dei tempi di rilascio a causa del cambiamento di molte specifiche che erano state preventivate quindi come ottenibili tramite componenti native di Apex ma che in realtà non avrebbero potuto essererlo. Gli sviluppi sono partiti dalla definizione del componente da inserire nella Region e subito si sono incontrate le prime difficoltà. L’obiettivo finale in questa fase era quello di ottenere una Tabella che rispecchiasse il Kpi in oggetto, su cui gli utenti avrebbero potuto compiere operazioni di inserimento e di modifica ma non di cancellazione in quanto non consentite

50

da specifiche. Il componente di Apex che assolve a tale funzione è la ‘Table Form’ raggiungibile dal componente ‘Form’ della sezione Region. Durante la fase di

configurazione del componente vengono richieste una serie di informazioni utili per il corretto funzionamento della form quali:

• Schema: DB Schema su cui è presente la tabella da utilizzare per l’inserimento dei dati.

• Table: Tabella da utilizzare

• Allowed Operations: operazioni consenti nella form. Nel nostro caso esclusivamente inserimento e modifica.

• Primary Key: definizione della PK per la gestione delle operazioni di inserimento e modifica

• Updateable Columns: definizione delle colonne su cui sarà possibili effettuare modifiche.

• Buttons and Branching : definizione dei pulsanti presenti all’interno della Region. Di default sono presenti ‘Cancel’, ‘Add Row’ e ‘Submit’. Il primo annulla le operazioni compiute e porta la tabella nuovamente allo stato in cui è nel Database. Il secondo permette l’inserimento di una nuova riga su cui è possibile effettuare modifiche. Il terzo compie l’operazione di inserimento nel Db.

La prima difficoltà individuata è riconducibile alla definizione della Primary Key. Il tool infatti consente di indicare al massimo due colonne per la definizione della Key, oppure di delegare la gestione al Database tramite il Row_id. Tuttavia, avendo definito con gli utenti i campi da utilizzare come chiave ed essendo impossibilitati ad inserire un numero maggiore di 2 campi all’interno del vincolo, si è dovuto pensare ad un metodo alternativo di gestire il flusso delle informazioni. La soluzione adottata è stata quella di creare una View della tabella ‘PURCH_SAVING_ACTUAL’ che contenesse in aggiunta il campo ‘View_Id’ come concatenazione dei campi utilizzati come Primary Key. La query

utilizzata è visibile nell’immagine

51 CREATE OR REPLACE FORCE VIEW "DW_APEX"."PURCH_SAVING_A_V"

("VIEW_ID", "MANDT", "ID_YEAR", "ID_MONTH", "AREA", "BU", "REGION", "COUNTRY",

"COMPANY_CODE", "PLANT", PRICE_SAVING_ACTUAL", "DW_DT_INS", "DW_DT_UPD", "USERNAME", "DW_VALIDITY") AS

SELECT

COUNTRY || '.' || AREA || '.' || SUBSTR(TO_CHAR(MONTH_ID),0,4) || '.' ||

SUBSTR(TO_CHAR(MONTH_ID),5,2) || '.' || MANDT || '.' || BU || '.' || REGION || '.' || COMPANY_CODE || '.' || PLANT VIEW_ID, MANDT, SUBSTR(TO_CHAR(MONTH_ID),0,4) ID_YEAR, SUBSTR(TO_CHAR(MONTH_ID),5,2) ID_MONTH, AREA, BU, REGION, COUNTRY, COMPANY_CODE, PLANT, PRICE_SAVING_ACTUAL, DW_DT_INS, DW_DT_UPD, USERNAME, DW_VALIDITY FROM DW_APEX.PURCH_SAVING_A;

Figura 29 Query creazione View

La creazione della View ha consentito di utilizzare il campo ‘View_Id’ come PK ed inoltre ha permesso una migliore visualizzazione della data nella form del Data Entry. Come è possibile vedere dal codice infatti, il campo MONTH_ID è stato scomposto per separare il valore che indica l’anno da quello che indica il mese.

Definita la View come tabella alla base della Form, sono stati definiti dei Trigger per gestire le operazioni di Insert/Update all’interno della Tabella ‘PURCH_SAVING_A’, la quale sarà utilizzata come sorgente informativa durante le operazioni di ETL. I Trigger sono degli oggetti collegati ad una tabella che vengono eseguiti al verificarsi di un determinato evento. Gli eventi utilizzati nel caso in questione sono due:

52

• BEFORE INSERT • BEFORE UPDATE

In sostanza, ogni qual volta vi sia un’operazione di insert o update all’interno della tabella, vengono lanciati i Trigger sotto rappresentati.

➢ PURCH_SAVING_A_USER o Codice:

o Descrizione: il trigger valorizza il campo USERNAME ad ogni operazione di Insert/Update all’interno della Tabella. Il codice rappresentato viene eseguito per ogni riga interessata ed valorizza un campo su cui l’utente non è abilitato alla modifica. L’esecuzione è vincolata alla variabili ‘PAGEID’ che viene creata e valorizzata a 0 solo nella pagina del Data Entry. Questa soluzione è stata adottata per differenziare le operazioni effettuate nella pagina di inserimento da quelle effettuate dalla pagina dedicata

all’approvazione.

➢ PURCH_SAVING_A_INSERT_TIME o Codice:

create or replace TRIGGER "DW_APEX"."PURCH_SAVING_A_USER" BEFORE

insert or update on DW_APEX.PURCH_SAVING_A for each row

begin

if (v('PAGEID')=0) THEN

:NEW.USERNAME := v('APP_USER'); end if;

53

o Descrizione: il trigger valorizza i campi DW_DT_INS e DW_DT_UPD ad ogni operazione di Insert/Update all’interno della Tabella. Il codice

rappresentato viene eseguito per ogni riga interessata e valorizza campi su cui l’utente non è abilitato alla modifica tramite la funzione SYSDATE ➢ PURCH_SAVING_A_MANDT

o Codice:

o Descrizione: Il Trigger valorizza il campo MANDT con il valore 210 ad ogni operazione di insert all’interno della tabella. Tale valore deriva dalle specifiche e rappresenta il codice dell’area mandato che corrisponde a ‘Consumer’.

➢ PURCH_SAVING_A_UPDATE_TIME o Codice:

create or replace TRIGGER "DW_APEX"."PURCH_SAVING_A_INSERT_TIME" BEFORE

insert on DW_APEX."PURCH_SAVING_A" for each row

begin

:NEW.DW_DT_INS := SYSDATE; :NEW.DW_DT_UPD := SYSDATE; end;

create or replace TRIGGER "DW_APEX"."PURCH_SAVING_A_MANDT" BEFORE

insert on DW_APEX.PURCH_SAVING_A for each row

begin

:new.MANDT := '210'; end;

54

o Descrizione: il Trigger aggiorna il campo DW_DT_UPD ad ogni operazione di update all’interno della tabella.

➢ PURCH_SAVING_A_VALIDITY o Codice:

create or replace TRIGGER "DW_APEX"."PURCH_SAVING_A_UPDATE_TIME" BEFORE

update on DW_APEX.PURCH_SAVING_A for each row

begin

:NEW.DW_DT_UPD := SYSDATE; end;

create or replace TRIGGER "DW_APEX"."PURCH_SAVING_A_VALIDITY" BEFORE

insert or update on DW_APEX.PURCH_SAVING_A for each row

BEGIN DECLARE

v_privilegi number(1); BEGIN

v_privilegi :=0;

SELECT PRIVILEGI INTO v_privilegi

FROM USERLOGIN WHERE LOWER(USERNAME) = LOWER(v('APP_USER')); If ( v_privilegi = 0 ) THEN

:new.DW_VALIDITY := 0; ELSE

if(v_privilegi = 1 AND (:new.DW_VALIDITY < 2 OR :new.DW_VALIDITY IS NULL )) THEN :new.DW_VALIDITY:= 1; end if; END IF; END; END;

55

o Descrizione: il Trigger valorizza il campo DW_VALIDITY ad ogni operazione di Insert/Update. Il campo in questione definisce la validità o meno della riga inserita. Il campo valorizzato con:

▪ 0: indica che l’istanza è nello stato ‘In attesa di approvazione’ ▪ 1: indica che l’istanza è nello stato ‘Approvata’

▪ 2: indica che l’istanza è nello stato ‘Rigettata’

La valorizzazione è legata ai privilegi utente, che vengono selezionati tramite la query rappresentata. In questo modo vengono distinte due differenti strade:

▪ Utente standard: il campo DW_VALIDITY viene valorizzato a 0. ▪ Utente Approvatore: il campo DW_VALIDITY viene valorizzato a 1

se dall’Applicazione il valore di partenza dello stesso campo è ‘Null’ o minore di 2. Questa condizione è stata inserita affinché il trigger non intervenga quando un’istanza viene rigettata

dall’approvatore e quindi ha il campo DW_VALIDITY = 2 I Trigger rappresentati vengono eseguiti ad ogni operazione effettuata sulla tabella

PURCH_SAVING_A’. Tuttavia, come spiegato sopra, la tabella sulla quale si basa la

form risulta essere la view precedentemente creata e ciò ha reso necessario la creazione di un ulteriore Trigger affinché le operazioni di Insert/Update venissero dirottate verso la tabella di origine. Per assolvere a tale compito è stato creato quindi un Trigger INSTEAD OF, il quale definito su una vista, consente di inserire/modificare/cancellare i dati di una o più tabelle di base. Il codice implementato, visibile in Appendice, assolve a diverse funzioni.

1. Verifica dei permessi utente => Come da specifiche, ogni utente è abilitato a poter inserire/modificare i KPI e più nel dettaglio le Aree per il quale è autorizzato. Il controllo che viene effettuato quindi, non fa altro che verificare che le righe inserite dall’utente si riferiscano ad un’area e ad un KPI presente all’interno della tabella

Documenti correlati