Digital Team Board and CIC Board
Di seguito il documento di specifica di Franke:
La struttura delle location prevederà:
- Azienda → Area → Plant
- Team (Reparti) → Luoghi e linee di produzione
Al fine di importare le location da un database di un determinato stabilimento per aggiungerle ai relativi TEAM, si procede come segue:
- Si seleziona la lista delle ubicazioni che si vogliono importare dallo stabilimento
- Si richiama la setcentubi dell'agente centubi
Per il p.to 1 è necessario usare l'agentdb definito nella tabella dbubi in corrispondenza dello stabilimento (tiposet='S') relativo all'elemento selezionato. Cosi si può estrarre la lista di tutte le linee di produzione ordinate in modo alfabetico. Successivamente si può richiamare la seguente per inviare al centubi che copierà i dati:
Safety Pages
Selezionando un elemento della gerarchia a partire dal Team (Reparto) in poi viene abilitata una delle funzioni di inserimento dati presenti ai paragrafi:
- 1.2.2, 1.2.3, 1.2.4
Strutture dati
Le strutture dati utilizzate sono quelle relativa al sistema EEM ovvero:
- objiter: ogni oggetto della safety è un objiter abbiamo i seguenti tipi di oggetti:
- Near Miss (N)
- Accident (A)
- Long time 5S (S)
- Long time TMP (J)
- Short time 5S/TMP (Y)
- Audit Checklist (P)
- project: ogni oggetto trova i dati di dettaglio nel project
- objteam: team interessato dall'attività
Per quanto riguarda oggetti di tipo N, A, S, J, Y viene considerato il project solo come definizione di eventi e attività da svolgere; un'attività è svolta quando l'objiter.state='A' (approvato/chiuso).
Mentre per quanto riguarda il tipo P, si dovrà generare la checklist (clista) e registrare l'esito del voto direttamente in curans.
Near Miss, Accident, Long time 5S, Long time TMP sono gestiti dalla pagina al paragrafo 1.2.4, mentre Short time 5S/TPM sono gestiti dalla pagina 1.2.2. I flussi operativi sono esattamente gli stessi, ma quando si crea un progetto con la 1.2.2 si dovrà assegnare anche un project.codequip.
Una struttura completa del database la troviamo ai seguenti paragrafi:
Near Miss, Accident, long time S5 e TPM, short time TPM
Il flusso generale della gestione dei suddetti objects è il seguente:
- newobjiter (tipo=N,A,S,J,Y): crea il nuovo objiter e restituisce il codice
- insert into project (codice,descrizio,codubi): inserisce in project con la descrizio ed il codubi (vedi sotto le query da svolgere)
- initteam: inizializza il team, nel caso specifico individua "chi" dovrà eseguire l'eventuale contromisura
- sendobjiter: pianifica l'objiter per lo svolgimento
- approve: dichiara lo svolgimento eseguito dell'objiter
L'inserimento del progetto deve procedere svolgendo esattamente le seguenti query, sostituendo opportunamente il codice del progetto con il codice del objiter create (le tre query vanno fatte in un colpo solo):
INSERT INTO PROJECT (codice,descrizio,codubi) VALUES (8,'descrizione di prova','000000098'); -- (alloca il progetto) INSERT INTO PRJMATGAP (CODPRJ,CODGRP,CODAREA,CODPROC) VALUES (7,1,1,1); -- (necessario per la gestione delle checklist) INSERT INTO PRJCAT (codprj,codcat) SELECT 7,category.codice FROM category; -- (necessario per la gestione delle checklist)
Le tabelle coinvolte dai movimenti sono le seguenti:
- objiter: contiene la tipologia ed i riferimenti principali
- project: contiene alcune informazioni di dettaglio (descrizio, codubi, altro…)
- objteam: contiene il team (chi) che deve svolgere; il team avrà objteam.tipo=A
- iter: contiene le date di previsto svolgimento (tmsend) ed infine di svolgimento (tmfeed)
L'objiter cambia stato in funzione delle operazioni:
- appena inserito è in objiter.state=N
- dopo la sendobjiter è in objiter.state=S
- dopo l'approve è in objiter.state=A (stato di chiusura dell'operazione)
Di seguito le chiamate da effettuare ad i rispettivi agenti:
- newobjiter (nel nume va il tm di creazione dell'oggetto, se 0 prende il tm attuale)
- initteam: nel caso di modifica del team è sufficiente reinviare il team con nume=1 (il team verrà cancellato e ripristinato, al limite si fa una select dell'owner e si invia anche l'owner; in tal caso si dovrà aggiungere un campo al rec con il nome "owners" e mettere il codoper opportuno)
- sendobjiter (nel nume va il tm di creazione dell'oggetto, se 0 prende il tm attuale)
- approve (nel nume va il tm di creazione dell'oggetto, se 0 prende il tm attuale)
La seguente immagine illustra il flusso dall'inizializzazione del team alla chiusura dell'oggetto nella grafica proposta da Franke.
Mentre i short time TPM/5S sono gestiti dalla seguente ove è indicato il flusso:
Short time TPM/5S REJECT
Dallo schema del short time TPM/5S è evidente come in corrispodenza di una determinata riga, vi sia una ripianificazione di una attività.
In questo caso specifico, l'operatore deve avere la possibilità di eseguire i seguenti passi:
- reject: una reject in corrispondenza della ITER che non è stata svolta
- sendobjiter: una sendobjiter per creare la nuova ITER da svolgere
La prima sendobjiter crea il primo iter con lo stato = 'N' (vedi sotto).
A partire dal calendario possiamo prevedere le seguenti funzionalità:
- conferma svolgimento (approve)
- attività non svolta (reject)
La conferma corrisponde alla chiamata approve già vista sopra, mentre la reject è la seguente.
Funziona esattamente come la approve ma l'effetto su iter è il seguente.
- su iter
- su objiter
Se rigettiamo una attività, abbiamo la possibilità di riprogrammarla richiamando nuovamente la sendobjiter con una nuova data. Effettuando questa operazione otteniamo quanto segue:
- su iter
- su objiter
Si può iterare questo flusso finchè si rigetta definitivamente (objiter resta nello stato R) oppure si approva (objiter nello stato A).
Interrogando la tabella iter si può ricavare una sorta di calendario delle varie pianificazioni effettuate.
Short time TPM/5S Eventi periodici
E' possibile pianificare eventi con una cadenza periodica a tal fine si stabilisce:
- data di inizio pianificazione (project.tmstart)
- data di fine pianificazione (project.tmend)
- tipo di periodo (project.tipoper): W=settimanale, D=giornaliero
- durata del periodo in unita' di tipoper (project.n): ogni 2 giorni ⇒ tipoper=D, n=2
In questo caso si dovranno utilizzare apposite chiamate per gestire gli objiter periodici che sono le seguenti:
- pianificazione: sendobjiterperiodic
- annulla piano: undosendobjiterperiodic
- approve di una iter: approveiterperiodic
- reject di una iter: rejectiterperiodic
- undo di una iter: undoiter (con nume=1)
Di seguito la sendobjiterperiodic.
Di seguito la undosendobjiterperiodic.
Mentre le altre chiamate sono identiche alle rispettive per il caso di eventi non periodici, con l'aggiunta del codice dell'iterazione nel rec nel campo coditer.
Se si rettifica la periodicità del piano è necessario innanzitutto esegure una undosendobjiterperiodic
Gestione delle checklist (S5 - AUDIT)
Il flusso generale della gestione del suddetto object è il seguente:
- newobjiter (tipo=P): crea il nuovo objiter e restituisce il codice
- insert into project (codice,descrizio,codubi): inserisce in project con la descrizio ed il codubi (vedi sotto le query da svolgere)
- initteam: inizializza il team, nel caso specifico individua "chi" dovrà eseguire la compilazione
- generate: genera la checklist
- answer: registra la risposta di ogni elemento della checklist
- approve (da valutare se lo gestiremo): dichiara lo svolgimento eseguito dell'objiter
L'inserimento del progetto deve procedere svolgendo esattamente le seguenti query, sostituendo opportunamente il codice del progetto con il codice del objiter create (le tre query vanno fatte in un colpo solo):
INSERT INTO PROJECT (codice,descrizio,codubi) VALUES (8,'descrizione di prova','000000098'); -- (alloca il progetto) INSERT INTO PRJMATGAP (CODPRJ,CODGRP,CODAREA,CODPROC) VALUES (7,1,1,1); -- (necessario per la gestione delle checklist) INSERT INTO PRJCAT (codprj,codcat) SELECT 7,category.codice FROM category; -- (necessario per la gestione delle checklist)
Le tabelle coinvolte dai movimenti sono le seguenti:
- objiter: contiene la tipologia ed i riferimenti principali
- project: contiene alcune informazioni di dettaglio (descrizio, codubi, altro…)
- objteam: contiene il team (chi) che deve svolgere; il team avrà objteam.tipo=A
- iter: contiene le date di previsto svolgimento (tmsend) ed infine di svolgimento (tmfeed)
- prjtask: tabella intermedia dei task che collega l'istanza di checklist al progetto
- clista: contiene le checklist e le risposte correnti
- answer: contiene i commenti di ogni singola risposta e l'esito della risposta
Di seguito uno schema commentato della pagina degli Audit.
I passi 1, 2, 3, 6 sono svolti come indicato nel paragrafo precedente, mentre i passi 4, 5 come segue:
- generate
- answer
Green Cross
Le Green Cross prevedono la visualizzazione di eventi di tipo:
- near miss (objiter.tipo='N'): colore giallo
- accident (objiter.tipo='A'): colore rosso
Oltre alla visualizzazione giornaliera dei dati viene anche indicata la data ed il luogo dell'ultimo incidente e dell'ultimo near miss (tabella a destra).
Al fine di avere un valore iniziale relativamente alla data ultimo incidente e data ultimo near miss, utilizziamo due campi aggiuntivi di ubicaz:
- ubicaz.tminc: tm dell'ultimo incidente
- ubicaz.tmnm: tm ultimo near miss
ALTER TABLE ubicaz ADD COLUMN tminc FLOAT, ADD COLUMN tmnm FLOAT; comment ON COLUMN ubicaz.tminc IS 'tm dell''ultimo incidente'; comment ON COLUMN ubicaz.tmnm IS 'tm dell''ultimo near miss';
L'AgenteDigCIC si occuperà di considerare questi valori, insieme a quelli derivanti dagli objiter creati, per fornire i dati alla GUI secondo gli schemi descritti di seguito.
La chiamata per ottenere i dati delle green cross è la seguente (greencross).
L'agente elabora le greencross di ogni location sottostante e restituisce la seguente lista.
Quality
Action plan Quality
L'Action plan Quality ha la medesima impostazione degli Action plan definiti per la safety in particolare per la Near Miss, Accident, long time S5 e TPM, short time TPM. Il flusso è il medesimo definito per i tipi N,A,S,J; aggiungiamo un nuovo tipo che chiamiamo Q. Il resto del processo è esattamente lo stesso come pure la pagina cui si fa riferimento (vedi sotto).
Grafici della qualità
Vengono definite 2 strutture basate su grafici per visualizzare i dati della qualità:
- la prima visualizza, in un grafico a barre, la frazione di scarti/ripassi per ogni mese; inoltre, per ogni settimana, presenta una tabella, ove le colonne sono i giorni della settimana (lun, mar, …) e le righe sono le macchine appartenenti al team; ogni cella contiene il numero di pezzi giornaliero di scarti/ripassi (2 tabelle)
- la seconda visualizza il Pareto delle cause/numero di scarti/ripassi; in un unico grafico vengono affiancate sia le barre dei ripassi che quelle degli scarti con colore differente
Q1
Al fine di gestire le soglie di scarti/ripassi per location-turno (presenti nelle tabelle settimanali) viene creata la relazione ubiturso (soglie ubicaz-turnidet). Di seguito il file contenente la struttura e lo schema ER.
Al fine di inserire i dati nella ubiturso, l'utente potrà selezionare l'icona indicata sotto solo in corrispondenza di una specifica location di tipo linea di produzione.
I dati relativi al report Q1 possono essere richiesti all'AgentDigCICSup attraverso la seguente chiamata:
Ove in p1, troviamo il codice della location a partire dalla quale si desidera sviluppare il report e l'anno di riferimento. L'agente ritorna un REC contenente 3 campi che sono oggetti JSON:
- mensile: grafico dei dati mensili
- settimanale_scarti: tabella settimanale degli scarti contenente tutte le settimane dell'anno
- settimanale_ripassi: tabella settimanale dei ripassi contenente tutte le settimane dell'anno
Di seguito il JSON di "mensile".
Di seguito il JSON di "settimanale_scarti" (il JSON di settimanale_ripassi è uguale).
@
Nel JSON Settimanale è stato integrato un campo aggiuntivo per ubicazione-turno che si chiama "soglia"; tale campo rappresenta la soglia giornaliera in termini di numero di scarti o ripassi (ubiturso.nsca, ubiturso.nrip).
Q2
E' possibile estrarre la statistica Q2 tramite l'AgentDigCICSup con la seguente richiesta, riferita ad una specifica codubi e ad un intervallo temporale.
La risposta è un rec contenente per ogni causale identificata di scarto il numero di scarti (scarti) ed il numero di ripassi (ripassi), oltre al codice e descrizione della causale di scarto/ripasso.
Quality Alarms
Di seguito lo schema da realizzare per i quality alarms.
Verrà inserito come objiter di tipo X, e viene allocata una nuova tabella relazionata alla project secondo il seguente schema.
L'oggetto non sarà soggetto ad iterazioni e non richiede la costruzione del team. Il seguente file crea la actionplan:
Costs
Il modulo Costs presenta le seguenti funzioni:
- C1 - OEE
- C2 - STOPPAGE
- C3 - CHANGEOVER
- C4 - ACTION PLAN
Il modulo C4 - Action Plan sarà gestito come gli altri action plan con tipo='O'.
C1 - OEE
Al fine di realizzare il grafico C1 sarà necessario attivare per lo specifico plant il calcolo dell'OEE per turno per ogni location del plant. In particolare si dovrà tenere in conto la seguente raccomandazione da verificare prima dell'avviamento:
- LE LINEE DEL PLANT SONO SOGGETTE A CAMBIO DEL TURNO: in tal caso si dovrà prevedere, al momento del caricamento del plant, la possibilità di modificare il turno in OEECONF per le linee (da sviluppare solo durante l'eventual estensione)
Il grafico sopra ha il medesimo schema del grafico Q1 della qualità. A sx abbiamo l'andamento mensile totale, mentre a dx abbiamo calendari settimanali per macchina/turno ove sono indicati i valori dell'OEE e le relative soglie.
I dati sono forniti allo stesso modo dall'AgentDigCICSup attraverso la seguente chiamata.
L'agente risponde con un rec contenete i due campi seguenti:
- mensile: array JSON con la lista dei mesi dell'anno e l'OEE + soglia di ogni mese
- oee_settimana: array JSON contenente le settimane dell'anno (woy=1..53) ed un campo data
- il campo data a sua volta contiene un array JSON come segue
C2 - STOPPAGES
Si tratta di un semplice Pareto delle fermate accessibile da qualsiasi livello della gerarchia. Per ottenere i dati è sufficiente inoltrare all'AgentDigCICSup, la seguente chiamata.
L'agente risponde con la seguente semplice struttura (rec).
C3 - Changeover
La pagina del Changover dovrà presentare un blocco dati per ogni linea appartenente ad un determinato Team; in un pagina si dovranno presentare massimo 4 linee alla volta, con la possibilità di poter scorrere manualmente oppure automaticamente.
I dati saranno prodotti dall'AgentDigCICSup, in base al codice del Team (codubi) ed ad un intervallo temporale (tmin, tmfi). L'agente produce un rec contenente tutti i dati ordinati per codubi delle linee di produzione e per tm.
Di seguito uno schema dell'interfaccia.
I dati presenti in ogni blocchetto macchina sono i seguenti:
- nome della linea/macchina
- numero di eventi di changeover (numero di righe del rec ritornato riferiti alla linea)
- quantità media ordini del periodo (presente nella colonna qtameop del rec dell'agente)
- durata totale changover (somma dei tmdiff presenti nel rec per la linea)
- durata media changeover (media dei tmdiff presenti nel rec per la linea)
- mediana della durata di changeover (mediana dei tmdiff presenti nel rec per la linea)
- grafico
- serie 1: x = tm del rec per la linea, y = tmdiff del rec per la linea
- serie 2: y = media
- serie 3: y = mediana
- dati aggiuntivi: data inizio, fine, codice e descrizione dell'articolo in lavorazione (questi ultimi si trovano nel rec per la linea, come JSON nel campo "catego" della riga corrispondente)
Di seguito la richiesta da inviare all'AgentDigCICSup.
La risposta dell'agente è la seguente.
Delivery
Il modulo Delivery presenta le seguenti funzioni:
- D1 - Order achievement
- D2 - Pareto Order achievement / losses
- D3 - ???
- D4 - ACTION PLAN
Il modulo D4 - Action Plan sarà gestito come gli altri action plan con tipo='D'.
D1 - Order Achievement
La logica di funzionamento di questa tabella è la medesima della tabella dell'OEE in C1; l'unica differenza è che le soglie sono soglie giornaliere e per macchina/turno. Questo sarà gestito nel rec ritornato dall'agente.
La chiamata all'agente restituisce direttamente un rec con la coppia:
- woy: numero della settimana dell'anno (per tutto l'anno)
- data: JSON contenente i dati della settimana
La richiesta all'AgentDigCICSup è la seguente.
La risposta dell'agente ha la medesima struttura della parte "settimanale" del report C1. Da notare che in ogni giorno della settimana (0, 1, .., 6), questa volta troviamo due numeri interi divisi da una virgola:
- il primo numero intero è il numero di pezzi prodotto nel turno
- il secondo numero intero è il target del turno in base al takt time delle lavorazioni effettuate
D2 - Pareto Order achievement / losses
Semplice pareto delle cause di speed-losses, riferito ad uno specifico Team (codubi in generale) ed ad uno specifico intervallo temporale (tmin, tmfi).
A tale scopo si può chiedere all'AgentDigCICSup la seguente ask.
A cui l'agente risponde fornendo la lista delle cause di speedlosses riscontrate nel periodo (INRA) con la somma del numero di pezzi persi, l'elenco è già ordinato in modo decrescente di numero di pezzi persi.
D4 - SERVICE LEVEL
- thmonslev, thdayslev con relaviti commenti
Gestire l'inserimento di queste soglie ed anche delle soglie thmonscrap e thmonrip, in una pagina di configurazione associata al plant.
ALTER TABLE ubicaz ADD COLUMN thmonslev DOUBLE PRECISION; ALTER TABLE ubicaz ADD COLUMN thdayslev DOUBLE PRECISION; comment ON COLUMN ubicaz.thmonslev IS 'Soglia mensile Service Level'; comment ON COLUMN ubicaz.thdayslev IS 'Soglia giornaliera Service Level';
Mobile App
Di seguito la pagina di accesso all'APP.
Dopo aver selezionato la location si accede alla pagina di registrazione dell'osservazione.
Aggiungere la scelta del tipo di evento per default "Mobile app observation".
Accesso all'App
Si prevede un nuovo QR-CODE che sarà possibile stampare direttamente dall'applicazione e che contiene il link per l'accesso. Questo QR-CODE potrà essere stampato dalla seguente funzione accessibile per tiposet='S' o tiposet='R'.
L'accesso può essere svolto attraverso una delle seguenti modalità:
- per ogni QR-CODE della location, si aggiunge sulla stampa un piccolo QR-CODE per accedere all'App (contiene il link)
- in varie posizioni nel plant è presente il QR-CODE per l'accesso all'applicazione indipendentemente dal QR-CODE della zona
- scaricare da Google Play store l'apk solo per android ed usare l'apk
- digitare manualmente nel browser il link di accesso
Login all'app
Una volta acceduto all'App essa richiede sempre il login. Attraverso un apposito parametro di accesso l'applicazione può permettere il login come Guest; in questo modo anche utenti esterni e non registrati potranno accedere all'applicazione e registrare osservazioni.
Scelta manuale della location
Condizione 1 - Guest
Il Guest entra in una sessione di scelta che poi lo porterà nella pagina di compilazione esattamente come fa la lettura del qr-code.
La pagina di scelta e' fatta come segue:
- ha una riga di ricerca (lente)
- sotto ha una lista di location
L'applicazione svolge la seguente sequenza di operazioni:
- al primo ingresso le location sono i plant (tiposet='S')
- se clicco su un plant entro nel livello sotto team (tiposet='R')
- se clicco sul team entro nel livello linea (tipset='P')
- se clicco sulla linea entro in compilazione
Condizione 2 - Operatore loggato
Tutto come condizione 1, ma l'operatore loggato entra nella lista dei plant visualizzando solo i plant a lui associati, se in workpla ha piu' di un plant, mentre se ha un solo plant associato allora entra direttamente nei teams. Se non ha alcun plant associato allora parte da tutti i plant (o non vede nulla ?).
3 tipi di Observation
Aggiungere i seguenti campi.
ALTER TABLE project ADD COLUMN safetype VARCHAR(2),ADD COLUMN whathappen VARCHAR(1024),ADD COLUMN potinj VARCHAR(1024), ADD COLUMN gravity VARCHAR(2), ADD COLUMN pertype VARCHAR(1024); comment ON COLUMN project.safetype IS 'relativo a objiter.tipo=''N'', indica: N=near miss,A=unsafe action,C=unsafe condition,E=unsafe equipement'; comment ON COLUMN project.whathappen IS 'relativo a objiter.tipo=''N'', indica: what happen'; comment ON COLUMN project.safetype IS 'relativo a objiter.tipo=''N'', indica: potenziali incidenti'; comment ON COLUMN project.gravity IS 'relativo a objiter.tipo=''N'', indica: R=red,Y=yellow,G=green'; comment ON COLUMN project.pertype IS 'relativo a objiter.tipo=''5S'' oppure ''TPM'', indica: Performance Type';
Aggiungere inoltre la seguente tabella da utilizzare per la pagina di safety.
CREATE TABLE public.prjunsafe ( codprj INTEGER NOT NULL, pos INTEGER NOT NULL, descrizio CHARACTER VARYING(1024) ); COMMENT ON TABLE public.prjunsafe IS 'How can we prevent the occurrence/unsafe situation?'; COMMENT ON COLUMN public.prjunsafe.codprj IS 'codice progetto'; COMMENT ON COLUMN public.prjunsafe.pos IS 'sequenza per un dato progetto'; ALTER TABLE ONLY public.prjunsafe ADD CONSTRAINT ix_prjunsafe_key PRIMARY KEY (codprj, pos); ALTER TABLE ONLY public.prjunsafe ADD CONSTRAINT ix_prjunsafe_codprj FOREIGN KEY (codprj) REFERENCES public.project(codice) ON UPDATE CASCADE ON DELETE CASCADE;
Aggiungere alle anags la tipologia di unsafe
INSERT INTO public.anags VALUES ('it', 'unsafe-type', 'A', 'Unsafe Action', 1, '', ''); INSERT INTO public.anags VALUES ('it', 'unsafe-type', 'C', 'Unsafe Condition', 2, '', ''); INSERT INTO public.anags VALUES ('it', 'unsafe-type', 'E', 'Unsafe Equipment', 3, '', ''); INSERT INTO public.anags VALUES ('it', 'unsafe-type', 'N', 'Near Miss', 4, '', ''); INSERT INTO public.anags VALUES ('en', 'unsafe-type', 'A', 'Unsafe Action', 1, '', ''); INSERT INTO public.anags VALUES ('en', 'unsafe-type', 'C', 'Unsafe Condition', 2, '', ''); INSERT INTO public.anags VALUES ('en', 'unsafe-type', 'E', 'Unsafe Equipment', 3, '', ''); INSERT INTO public.anags VALUES ('en', 'unsafe-type', 'N', 'Near Miss', 4, '', ''); INSERT INTO public.anags VALUES ('de', 'unsafe-type', 'A', 'Unsafe Action', 1, '', ''); INSERT INTO public.anags VALUES ('de', 'unsafe-type', 'C', 'Unsafe Condition', 2, '', ''); INSERT INTO public.anags VALUES ('de', 'unsafe-type', 'E', 'Unsafe Equipment', 3, '', ''); INSERT INTO public.anags VALUES ('de', 'unsafe-type', 'N', 'Near Miss', 4, '', ''); INSERT INTO public.anags VALUES ('pl', 'unsafe-type', 'A', 'Unsafe Action', 1, '', ''); INSERT INTO public.anags VALUES ('pl', 'unsafe-type', 'C', 'Unsafe Condition', 2, '', ''); INSERT INTO public.anags VALUES ('pl', 'unsafe-type', 'E', 'Unsafe Equipment', 3, '', ''); INSERT INTO public.anags VALUES ('pl', 'unsafe-type', 'N', 'Near Miss', 4, '', '');
L'app permette di selezionare una tra le seguenti funzioni:
- Observation: apre la pagina delle osservazioni già realizzata
- Safety: apre la pagina safety vedi sotto
- TPM: apre la pagina TPM vedi sotto
- 5S: apre la pagina 5S vedi sotto
CIC
Safety
S1 - Safety Cross
E' necessario integrare il record senza infortuni e la data da cui comincia il record, a tal fine aggiungiamo la possibilità di poter inserire nell'anagrafica ubicaz i seguenti campi:
ALTER TABLE ubicaz ADD COLUMN hrecnr INTEGER, ADD COLUMN hrecgg CHARACTER VARYING(9); comment ON COLUMN ubicaz.hrecnr IS 'Record in termini di numero di giorni senza infortuni per il Team tipsoet=''R'''; comment ON COLUMN ubicaz.hrecgg IS 'Data di inizio del record senza infortuni';
L'agente restituirà per ogni green-cross due campi aggiuntivi:
- hrecnr: numero di giorni senza infortuni
- hrecgg: data di inizio del record
Questi dati dovranno essere visualizzati a destra come segue.
Un unico BOX riferito all'oggetto (codubi) sul quale stiamo lavorando.
L'AgentDigCICSup ritorna i vlaori necessari, vedi sotto.
E' necessario configurare i dati necessari al calcolo del record infortuni di seguito.
Aggiungere a tale scopo l'icona di accesso alla apposita scheda come segue.
L'ulteriore campo visibile è la data di avvio della location necessario per il calcolo dei record; questo dovrà essere associato all'elemento selezionato e dovrà essere editabile, una volta modificato va su ubicaz.datareg.
S3 - TPM / 5S Assessment (Kami Shabai)
Si tratta di pianificazione kami shabai (modello da lean manufacturing). In pratica si pianificano una serie di attività che hanno certi obiettivi definiti dalla carta delle attività. Le attività vengono assegnate a un team e vengono pianificate nel tempo con una certa frequenza (settimanali, giornaliere, altro…).
Il tipo di objiter dedicato ai kami shabai è K ([K]ami shabai).
Il team viene inserito tra gli owner, il team leader viene inserito come objiter.codoper ed anche nel objteam con tipo='O'; gli altri partecipanti al team vanno inseriti solo in objteam.
A partire da un calendario mensile è possibile vedere giornalmente la pianificazione di queste attività. Un auditor ha il compito di selezionare una cella in cui è presente una attività e visualizzare la T-CARD. La T-CARD è una carta che descrive alcune informazioni dell'attività. L'auditor ha il compito di ispezionare l'area interessata dall'attività e vedere se trova proprietà corrispondenti a quelle previste dalla T-CARD; se c'è corrispondenza allora da un feedback positivo (MEET=1) e la card si colora di verde, altrimenti da un feedback negativo (MEET=0) e la card si colora di rosso. Cliccando sulla cella è possibile visionare tutte le T-CARD colorate che sono già state assegnate a tale area con il rispettivo esito.
Quando l'auditor clicca su una cella, viene automaticamente inserito nel team di approver per l'objiter interessato, se non è già presente; in questo modo l'utente dall'auditor potrà approvare/rigettare la specifica iter.
I tipi di attività che si vedono dal calendario dell'esempio sono:
- QA
- C
- FPS
- Safety
Quando si alloca una nuova card di un certo tipo, si dovrà applicare un contatore di card di quel tipo e incrementarlo. A tale scopo la CARD va creata direttamente tramite AgentDigCICSup; l'agente riceve in ingresso i dati della newobjiter piu' il tipo di card ed avrà il compito di svolgere tutte le operazioni di inizializzazione dell'objiter e del project con l'assegnazione dell'ID card. Di seguito la modalità di comunicazione.
La seguente tabella contiene la lista delle attività con relative frequenze ed inoltre visualizza due T-CARD QA2 una negativa (rossa) e l'altra positiva (verde).
Quindi gli utenti devono innanzitutto compilare la tabella a destra. Tale tabella alimenta il seguente calendario.
Nel calendario si vedono in grigio le celle associate ad una CARD, cliccando si può:
- visionare l'elenco delle card già create
- creare una nuova card con un esito
Come si vede le card gestiscono i seguenti dati descrittivi che vanno inseriti manualmente per la predisposizione della riga:
- Business excellence
- Requisiti
- Chiarimento/Spiegazione
- Prova di conformità
- Frequenza
- Responsabile
- Valutazione
Tutti questi campi andranno inseriti in project.
Per la procedura di gestione dell'informazione e la calendarizzazione sarà svolta come al seguente punto
- Short time TPM5S nel sottoparagrafo degli eventi periodici
Ogni T-CARD corrisponderà ad una specifica ITER che può essere approved (meet=1) oppure rejected (meet=0), nel primo caso l'attività si chiude nel secondo si può creare una nuova card per lo stesso specifico evento.
Per poter creare una nuova T-CARD (iter) per uno specifico evento sarà necessario allocarla con un tm che ricada nel medesimo giorno, ma che sia maggiore della ITER precedente.
In base a quanto descritto aggiungiamo i seguenti campi alla struttura project.
ALTER TABLE project ADD COLUMN buex VARCHAR(1024), ADD COLUMN req VARCHAR(1024), ADD COLUMN spie VARCHAR(1024), ADD COLUMN cotest VARCHAR(1024), ADD COLUMN valdesc VARCHAR(1024), ADD COLUMN tipocar VARCHAR(101), ADD COLUMN idcar INTEGER; comment ON COLUMN project.buex IS 'Business exellence (vedi tabella kami shabai)'; comment ON COLUMN project.req IS 'Requisiti (vedi tabella kami shabai)'; comment ON COLUMN project.spie IS 'Chiarimento/Spiegazione (vedi tabella kami shabai)'; comment ON COLUMN project.cotest IS 'Test di conformità (vedi tabella kami shabai)'; comment ON COLUMN project.valdesc IS 'Valutazione (vedi tabella kami shabai)'; comment ON COLUMN project.tipocar IS 'Tipo carta (vedi tabella kami shabai)'; comment ON COLUMN project.idcar IS 'Numero progressivo della carta (vedi tabella kami shabai)';
Query per aggiungere le anags di tipocard per il Kami Shabai:
DELETE FROM anags WHERE tag='ks-tipocard'; INSERT INTO public.anags VALUES ('it', 'ks-tipocard', 'QA', 'QA', 1, '', ''); INSERT INTO public.anags VALUES ('it', 'ks-tipocard', 'C', 'C', 2, '', ''); INSERT INTO public.anags VALUES ('it', 'ks-tipocard', 'FPS', 'FPS', 3, '', ''); INSERT INTO public.anags VALUES ('it', 'ks-tipocard', 'Safety', 'Safety', 4, '', ''); INSERT INTO public.anags VALUES ('en', 'ks-tipocard', 'QA', 'QA', 1, '', ''); INSERT INTO public.anags VALUES ('en', 'ks-tipocard', 'C', 'C', 2, '', ''); INSERT INTO public.anags VALUES ('en', 'ks-tipocard', 'FPS', 'FPS', 3, '', ''); INSERT INTO public.anags VALUES ('en', 'ks-tipocard', 'Safety', 'Safety', 4, '', ''); INSERT INTO public.anags VALUES ('de', 'ks-tipocard', 'QA', 'QA', 1, '', ''); INSERT INTO public.anags VALUES ('de', 'ks-tipocard', 'C', 'C', 2, '', ''); INSERT INTO public.anags VALUES ('de', 'ks-tipocard', 'FPS', 'FPS', 3, '', ''); INSERT INTO public.anags VALUES ('de', 'ks-tipocard', 'Safety', 'Safety', 4, '', ''); INSERT INTO public.anags VALUES ('pl', 'ks-tipocard', 'QA', 'QA', 1, '', ''); INSERT INTO public.anags VALUES ('pl', 'ks-tipocard', 'C', 'C', 2, '', ''); INSERT INTO public.anags VALUES ('pl', 'ks-tipocard', 'FPS', 'FPS', 3, '', ''); INSERT INTO public.anags VALUES ('pl', 'ks-tipocard', 'Safety', 'Safety', 4, '', '');
S4 - Audit
Meeting Standard
CREATE TABLE public.protocol ( codice INTEGER NOT NULL, codubi CHARACTER VARYING(51), frequency CHARACTER VARYING(51), DAY CHARACTER VARYING(101), TIME CHARACTER VARYING(10), purpose CHARACTER VARYING(3000), actionplan CHARACTER VARYING(3000), leader CHARACTER VARYING(101), timekeeper CHARACTER VARYING(101), partecipants CHARACTER VARYING(3000), warnimage CHARACTER VARYING(101) ); ALTER TABLE public.protocol OWNER TO postgres; COMMENT ON TABLE public.protocol IS 'Tabella dei Meeting Protocols'; COMMENT ON COLUMN public.protocol.codubi IS 'Codice del luogo'; COMMENT ON COLUMN public.protocol.frequency IS 'Frequenza del meeting'; COMMENT ON COLUMN public.protocol.day IS 'Giorni della settimana del meeting'; COMMENT ON COLUMN public.protocol.time IS 'Orario del meeting'; COMMENT ON COLUMN public.protocol.purpose IS 'Scopo del meeting'; COMMENT ON COLUMN public.protocol.actionplan IS 'Actionplan del meeting'; COMMENT ON COLUMN public.protocol.leader IS 'Leader del meeting'; COMMENT ON COLUMN public.protocol.timekeeper IS 'Timekeeper del meeting'; COMMENT ON COLUMN public.protocol.partecipants IS 'Partecipanti al meeting'; COMMENT ON COLUMN public.protocol.warnimage IS 'Immagine warning di anteprima'; ALTER TABLE ONLY public.protocol ADD CONSTRAINT ix_protocol_codice PRIMARY KEY (codice); ALTER TABLE ONLY public.protocol ADD CONSTRAINT ix_protocol_codubi FOREIGN KEY (codubi) REFERENCES public.ubicaz(codice) ON UPDATE CASCADE ON DELETE RESTRICT; CREATE TABLE public.agenda ( codprot INTEGER NOT NULL, pos INTEGER, descrizio CHARACTER VARYING(256), responsible CHARACTER VARYING(101), TIME FLOAT ); ALTER TABLE public.agenda OWNER TO postgres; COMMENT ON TABLE public.agenda IS 'Tabella agenda per i meeting protocols'; COMMENT ON COLUMN public.agenda.codprot IS 'Codice riferimento protocollo'; COMMENT ON COLUMN public.agenda.pos IS 'Ordine degli argomenti in agenda'; COMMENT ON COLUMN public.agenda.descrizio IS 'Descrizione'; COMMENT ON COLUMN public.agenda.responsible IS 'Responsabile - ruolo che ricopre'; COMMENT ON COLUMN public.agenda.time IS 'durata del punto in agenda'; ALTER TABLE ONLY public.agenda ADD CONSTRAINT ix_agenda_codprot FOREIGN KEY (codprot) REFERENCES public.protocol(codice) ON UPDATE CASCADE ON DELETE CASCADE; CREATE TABLE public.protrules ( codprot INTEGER NOT NULL, pos INTEGER, descrizio CHARACTER VARYING(256) ); ALTER TABLE public.protrules OWNER TO postgres; COMMENT ON TABLE public.protrules IS 'Tabella agenda per i meeting protocols'; COMMENT ON COLUMN public.protrules.codprot IS 'Codice riferimento protocollo'; COMMENT ON COLUMN public.protrules.pos IS 'Ordine degli argomenti in agenda'; COMMENT ON COLUMN public.protrules.descrizio IS 'Descrizione'; ALTER TABLE ONLY public.protrules ADD CONSTRAINT ix_protrules_codprot FOREIGN KEY (codprot) REFERENCES public.protocol(codice) ON UPDATE CASCADE ON DELETE CASCADE;
Aggiunta dei campi al meeting protocol
ALTER TABLE protocol ADD COLUMN kpisafety VARCHAR(51); ALTER TABLE protocol ADD COLUMN kpiquality VARCHAR(51); ALTER TABLE protocol ADD COLUMN kpidelivery VARCHAR(51); ALTER TABLE protocol ADD COLUMN kpicost VARCHAR(51); ALTER TABLE protocol ADD COLUMN warnimage VARCHAR(101);
Safety Report
CREATE TABLE public.safetyreport ( codice INTEGER NOT NULL, descrizio CHARACTER VARYING(101), zord INTEGER, tipodato VARCHAR(2) ); ALTER TABLE public.safetyreport OWNER TO postgres; COMMENT ON TABLE public.safetyreport IS 'Tabella tematica dei safety report'; ALTER TABLE ONLY public.safetyreport ADD CONSTRAINT ix_safetyreport_codice PRIMARY KEY (codice); INSERT INTO safetyreport (codice, descrizio, zord) VALUES (1, 'Accident Description', 1); INSERT INTO safetyreport (codice, descrizio, zord) VALUES (2, 'Interim Containment Actions', 2); INSERT INTO safetyreport (codice, descrizio, zord) VALUES (3, 'Root Cause Analysis', 3); INSERT INTO safetyreport (codice, descrizio, zord) VALUES (4, 'Preventive Actions', 4); INSERT INTO safetyreport (codice, descrizio, zord) VALUES (5, 'Verifications of Corrective Actions', 5); INSERT INTO safetyreport (codice, descrizio, zord) VALUES (6, 'Lost Time (days)', 6); INSERT INTO safetyreport (codice, descrizio, zord) VALUES (7, 'Report Closed', 7); CREATE TABLE public.safprj ( codsafety INTEGER, codprj INTEGER, codoper VARCHAR(51), descrizio VARCHAR(512), tmfin FLOAT ); ALTER TABLE public.safprj OWNER TO postgres; COMMENT ON TABLE public.safprj IS 'Associazione i project di tipo safety e i temi del safety report'; ALTER TABLE ONLY public.safprj ADD CONSTRAINT ix_safprj_codsafety FOREIGN KEY (codsafety) REFERENCES public.safetyreport(codice) ON UPDATE CASCADE ON DELETE RESTRICT; ALTER TABLE ONLY public.safprj ADD CONSTRAINT ix_safprj_codprj FOREIGN KEY (codprj) REFERENCES public.project(codice) ON UPDATE CASCADE ON DELETE CASCADE; ALTER TABLE ONLY public.safprj ADD CONSTRAINT ix_safprj_codoper FOREIGN KEY (codoper) REFERENCES public.operato(codice) ON UPDATE CASCADE ON DELETE RESTRICT;
FPS ACHIVEMENT
CREATE TABLE fpsachievement ( codubi CHARACTER VARYING(51), MONTH INTEGER, YEAR INTEGER, actual FLOAT, target FLOAT, forecast FLOAT ); ALTER TABLE ONLY public.fpsachievement ADD CONSTRAINT ix_fpsachievement_pkey PRIMARY KEY (codubi, MONTH, YEAR); ALTER TABLE ONLY public.fpsachievement ADD CONSTRAINT ix_fpsachievement_codubi FOREIGN KEY (codubi) REFERENCES public.ubicaz(codice) ON UPDATE CASCADE ON DELETE CASCADE;
Inserimento manuale dati per le risorse che non sono connesse con sistema OEE Next
Per alcune teamboards è stata data la possibilità di aggiungere manualmente dei KPIs relativi su qualità, costo e delivery. In particolare per "Scraps & Reworks Pareto", "Downtime Pareto" e "Order Achivement Pareto". Questa tabella per gestire gli inserimenti manuali:
CREATE TABLE public.kpispareto ( codubi CHARACTER VARYING(101), causa CHARACTER VARYING(101), tm DOUBLE PRECISION, nr INTEGER, codoper CHARACTER VARYING(101), TYPE CHARACTER VARYING(5), DATA CHARACTER VARYING(9), codice INTEGER NOT NULL ); COMMENT ON COLUMN public.kpispareto.tm IS 'tm di registrazione'; COMMENT ON COLUMN public.kpispareto.type IS 'D = Downtime Pareto, S = Scraps & Rework pareto, O = Order Achivment Pareto'; COMMENT ON COLUMN public.kpispareto.data IS 'Data di registrazione'; ALTER TABLE ONLY public.kpispareto ADD CONSTRAINT ix_kpispareto_pk PRIMARY KEY (codice); ALTER TABLE ONLY public.kpispareto ADD CONSTRAINT ix_kpispareto_codoper FOREIGN KEY (codoper) REFERENCES public.operato(codice) ON UPDATE CASCADE ON DELETE CASCADE; ALTER TABLE ONLY public.kpispareto ADD CONSTRAINT ix_kpispareto_codubi FOREIGN KEY (codubi) REFERENCES public.ubicaz(codice) ON UPDATE CASCADE ON DELETE CASCADE;
Per abilitare quali risorse dovrenno utilizzare la pagina di inserimento manuale è stato messo su wip-settings la seguente chiave:
manualkpis:{ list:[ {k:'150121', v:'Others Fabricated (DAN)'}, {k:'FIMDIP03', v:'TB Fabricated Upstream'}, {k:'FIMDIP04', v:'TB Fabricated Downstream'}, ] }
I codici presenti in lista avranno accesso alla pagina di inserimento manuale dei dati nei pareto. Le altre risorse invece accederanno alla vista di default, con i dati collegati a OEE
Proactive KPIs
AgentGraphSup configurazione
<agent lib="/usr/lib/libdigcic.so.0.0.0" create="agentGraphSup" live="1" name="graph"> <param name="agps" value="prepstat"/> </agent>
Safety Actions
Per gestire alcuni KPIs sulle actions abbiamo dovuto introdurre il concetto di "Safety Action".
Una Safety Action è un action generica che può essere associata a diversi tipi di oggetto (objiter), in particolare a:
- Job Safety Observations → objiter.tipo='H'
- Safety Report → objiter.tipo='A|N|B|F|R'
- Risk Assessmebr → objiter.tipo='U' (nuovo oggetto che può essere gestito in modo simile a un JSO)
Per implementare utilizzando i dati che storicamente sono stati inseriti, vengono trasformate in "safety actions" i seguenti oggetti per tipo:
Job Safety Observation → ogni suggestion di una JSO diventa una safety action. Le suggestion dei JSO sono salvate nella tabella prjunsafe
Safety Report → nel safety report ci sono configurare 2 action (safprj.codsafety = 2 e safprj.codsafey = 4). Ognuna di queste action diventano una safety action.
Struttura di una safety action:
CREATE TABLE public.actionstype ( codice INTEGER NOT NULL, descrizio CHARACTER VARYING(51), tipo CHARACTER VARYING(51), zord INTEGER ); ALTER TABLE public.actionstype OWNER TO postgres; COMMENT ON TABLE public.actionstype IS 'Tabella che contiene la tipologia delle azioni legate al safety (Safety Report, Job Safety Observation, Risk)'; COMMENT ON COLUMN public.actionstype.tipo IS 'Tipologia di tipi di azione. RA -> Risk Assessment, SR -> Safety Report & JSO'; ALTER TABLE ONLY public.actionstype ADD CONSTRAINT ix_actionstype_pk PRIMARY KEY (codice); INSERT INTO actionstype (codice, descrizio, tipo, zord) VALUES (1, 'Azioni di contenimento provvisorie', 'SR', 1); INSERT INTO actionstype (codice, descrizio, tipo, zord) VALUES (2, 'Azioni preventive', 'SR', 2); INSERT INTO actionstype (codice, descrizio, tipo, zord) VALUES (3, 'Building', 'RA', 1); INSERT INTO actionstype (codice, descrizio, tipo, zord) VALUES (4, 'Installation', 'RA', 2); INSERT INTO actionstype (codice, descrizio, tipo, zord) VALUES (5, 'Zoning', 'RA', 3); INSERT INTO actionstype (codice, descrizio, tipo, zord) VALUES (6, 'PPE', 'RA', 4); INSERT INTO actionstype (codice, descrizio, tipo, zord) VALUES (7, 'Tools', 'RA', 5); INSERT INTO actionstype (codice, descrizio, tipo, zord) VALUES (8, 'Another', 'RA', 6); CREATE TABLE public.safetyactions ( codprj INTEGER, descrizio CHARACTER VARYING(1000), tmcre DOUBLE PRECISION, tmtarget DOUBLE PRECISION, tmclosed DOUBLE PRECISION, acttype INTEGER, STATUS CHARACTER VARYING(2), codoper CHARACTER VARYING(51), zord INTEGER ); ALTER TABLE public.safetyactions OWNER TO postgres; COMMENT ON TABLE public.safetyactions IS 'Tabella che contiene tutte le azioni preventive e correttive legate al safety (Safety Report, Job Safety Observation, Risk)'; COMMENT ON COLUMN public.safetyactions.codprj IS 'project.codice'; COMMENT ON COLUMN public.safetyactions.tmcre IS 'tm di creazione dell''azione'; COMMENT ON COLUMN public.safetyactions.tmtarget IS 'tm di prevista chiusura azione'; COMMENT ON COLUMN public.safetyactions.tmclosed IS 'tm chiusura effettiva dell''azione'; COMMENT ON COLUMN public.safetyactions.status IS 'O = Open, C = Close'; COMMENT ON COLUMN public.safetyactions.zord IS 'Posizione'; ALTER TABLE ONLY public.safetyactions ADD CONSTRAINT ix_safetyactions_acttype FOREIGN KEY (acttype) REFERENCES public.actionstype(codice) ON UPDATE CASCADE ON DELETE RESTRICT; ALTER TABLE ONLY public.safetyactions ADD CONSTRAINT ix_safetyactions_codoper FOREIGN KEY (codoper) REFERENCES public.operato(codice) ON UPDATE CASCADE ON DELETE CASCADE; ALTER TABLE ONLY public.safetyactions ADD CONSTRAINT ix_safetyactions_codprj FOREIGN KEY (codprj) REFERENCES public.project(codice) ON UPDATE CASCADE ON DELETE CASCADE;
Query per modificare e trasformare in safety actions le informazioni dei JSO e dei Safety Report esistenti:
INSERT INTO safetyactions SELECT safprj.codprj, safprj.descrizio, objiter.tmcre AS tmcre, tmfin AS tmtarget, tmfeed AS tmclosed, '1' AS acttype, 'C' AS STATUS, safprj.codoper, '1' AS zord FROM safprj JOIN objiter ON safprj.codprj = objiter.codice JOIN iter ON objiter.codice = iter.codobj WHERE objiter.state = 'A' AND safprj.codsafety = 2; INSERT INTO safetyactions SELECT safprj.codprj, safprj.descrizio, objiter.tmcre AS tmcre, tmfin AS tmtarget, NULL AS tmclosed, '1' AS acttype, 'O' AS STATUS, safprj.codoper, '1' AS zord FROM safprj JOIN objiter ON safprj.codprj = objiter.codice JOIN iter ON objiter.codice = iter.codobj WHERE objiter.state <> 'A' AND safprj.codsafety = 2; INSERT INTO safetyactions SELECT safprj.codprj, safprj.descrizio, objiter.tmcre AS tmcre, tmfin AS tmtarget, tmfeed AS tmclosed, '2' AS acttype, 'C' AS STATUS, safprj.codoper, '1' AS zord FROM safprj JOIN objiter ON safprj.codprj = objiter.codice JOIN iter ON objiter.codice = iter.codobj WHERE objiter.state = 'A' AND safprj.codsafety = 4; INSERT INTO safetyactions SELECT safprj.codprj, safprj.descrizio, objiter.tmcre AS tmcre, tmfin AS tmtarget, NULL AS tmclosed, '2' AS acttype, 'O' AS STATUS, safprj.codoper, '1' AS zord FROM safprj JOIN objiter ON safprj.codprj = objiter.codice JOIN iter ON objiter.codice = iter.codobj WHERE objiter.state <> 'A' AND safprj.codsafety = 4; DELETE FROM safprj WHERE codsafety = 2; DELETE FROM safetyreport WHERE codice = 2; DELETE FROM safprj WHERE codsafety = 4; DELETE FROM safetyreport WHERE codice = 4; UPDATE safetyreport SET codice = 2, zord = 2 WHERE codice = 3; UPDATE safetyreport SET codice = 3, zord = 3 WHERE codice = 5; UPDATE safetyreport SET codice = 4, zord = 4 WHERE codice = 6; UPDATE safetyreport SET codice = 5, zord = 5 WHERE codice = 7; INSERT INTO safetyactions SELECT prjunsafe.codprj, prjunsafe.descrizio, objiter.tmcre, NULL AS tmtarget, tmfeed AS tmclosed, NULL AS acttype, 'C' AS STATUS, NULL AS codoper, pos AS zord FROM prjunsafe JOIN objiter ON prjunsafe.codprj = objiter.codice LEFT JOIN iter ON objiter.codice = iter.codobj WHERE objiter.tipo = 'H' AND objiter.state = 'A'; DELETE FROM objiter WHERE codice = 15456; INSERT INTO safetyactions SELECT prjunsafe.codprj, prjunsafe.descrizio, objiter.tmcre, NULL AS tmtarget, NULL AS tmclosed, NULL AS acttype, 'O' AS STATUS, NULL AS codoper, pos AS zord FROM prjunsafe JOIN objiter ON prjunsafe.codprj = objiter.codice LEFT JOIN iter ON objiter.codice = iter.codobj WHERE objiter.tipo = 'H' AND objiter.state <> 'A';
KPI #4 - 5S Score
1 - Plant Level:
Come periodo di riferimento si prende gli ultimi 365 giorni (in 12 mesi). Il plant rate è una media pesata per il numero di persone che lavora ad ogni asset dei vari 5s audit fatti.
2 - Organization Level:
Come periodo di riferimento si prende gli ultimi 365 giorni. Viene mostrato il plant rate medio del periodo selezionato, data una singola organizzazione.
3 - Franke Level:
Come periodo di riferimento si prende gli ultimi 365 giorni. Viene mostrata la media di tutti i plant rate medio per ogni organizzazione.
NB I target devono essere messi a livello di ubicaz e rappresenterà una linea orizzontale sopra il grafico.
Query per estrarre lo score (media voto delle 5 risposte dell'audit) del singolo audit. Ogni riga corrisponde ad un audit con il suo score medio.
Se il codubi dell'audit è di tiposet 'P' allora abbiamo in mancost il numero di operatori che lavorano su quell'asset. Questo mancost ci servirà per fare la media pesata.
WITH RECURSIVE treeubi AS (SELECT u.* FROM ubicaz u WHERE u.codice = 'FKT' UNION ALL SELECT u.* FROM ubicaz u, treeubi WHERE u.codubib = treeubi.codice), sinans AS (SELECT codoper, MAX(codice) AS codice, codclista FROM answer GROUP BY codoper, codclista) SELECT objiter.codice, objiter.tmcre, objiter.tipo, objiter.dayofmonth, objiter.month, objiter.year, project.descrizio, operato.nominati AS creator, treeubi.descrizio AS asset, treeubi.tiposet, treeubi.mancost, project.codubi, AVG(answer.value::NUMERIC) AS score FROM objiter INNER JOIN project ON objiter.codice = project.codice INNER JOIN operato ON objiter.codoper = operato.codice INNER JOIN treeubi ON project.codubi = treeubi.codice JOIN prjtask ON prjtask.codprj = objiter.codice JOIN clista ON clista.codptask = prjtask.codice JOIN sinans ON clista.codice = sinans.codclista JOIN answer ON sinans.codice = answer.codice WHERE objiter.tipo='P' AND objiter.tmcre >= 1672527600 AND objiter.tmcre <= 1704063599 GROUP BY objiter.codice, objiter.tmcre, objiter.tipo, objiter.dayofmonth, objiter.month, objiter.year, project.descrizio, creator, asset, tiposet, mancost, project.codubi ORDER BY tmcre DESC
Dato che in precedenza gli audit venivano fatti a livello di teamboard (tiposet 'R') e questa specifica è cambiata negli ultimi due mesi proprio per gestire il numero di operatori per asset, è possibile che se un audit è stato precedentemente fatto a livello di teamboard non abbia mancost per fare la media pesata. In questo caso potremmo gestire ciò (a tendere non ci saranno più audit a livello di teamboard ma solo a livello di asset) sommando tutti gli operatori di tutti gli asset di ogni teamboard e facendo la media pesata con questo valore.
SELECT t.codice, SUM(a.mancost) FROM ubicaz t JOIN ubicaz a ON t.codice = a.codubib WHERE t.tiposet = 'R' GROUP BY t.codice
QUERY PER I GRAFICI
Questa query prende in ingresso un codubi (codice del plant), un fromtm ed un totm. I tm vengono utilizzati come filtro sul cambo objiter.tmcre, che dovrà essere incluso tra i due tm passati.
Per default i due tm devono essere gli ultimi 12 mesi, escluso il mese corrente. Esempio, sono a gennaio 2024, il fromtm deve essere il 01/01/2023 ed il totm 31/12/2023
WITH RECURSIVE treeubi AS (SELECT u.* FROM ubicaz u WHERE u.codice = 'FKT' UNION ALL SELECT u.* FROM ubicaz u, treeubi WHERE u.codubib = treeubi.codice), sinans AS (SELECT codoper, MAX(codice) AS codice, codclista FROM answer GROUP BY codoper, codclista), scores AS (SELECT objiter.codice, objiter.tmcre, objiter.tipo, objiter.dayofmonth, objiter.month, objiter.year, project.descrizio, operato.nominati AS creator, treeubi.descrizio AS asset, treeubi.tiposet, treeubi.mancost, project.codubi, AVG(answer.value::NUMERIC) AS score FROM objiter INNER JOIN project ON objiter.codice = project.codice INNER JOIN operato ON objiter.codoper = operato.codice INNER JOIN treeubi ON project.codubi = treeubi.codice JOIN prjtask ON prjtask.codprj = objiter.codice JOIN clista ON clista.codptask = prjtask.codice JOIN sinans ON clista.codice = sinans.codclista JOIN answer ON sinans.codice = answer.codice WHERE objiter.tipo='P' AND objiter.tmcre >= 1676502000 AND objiter.tmcre <= 1705391447 AND mancost IS NOT NULL AND mancost > 0 GROUP BY objiter.codice, objiter.tmcre, objiter.tipo, objiter.dayofmonth, objiter.month, objiter.year, project.descrizio, creator, asset, tiposet, mancost, project.codubi ORDER BY tmcre DESC), totoper AS (SELECT SUM(mancost) AS total, MONTH, YEAR FROM scores GROUP BY MONTH, YEAR) SELECT 'FKT' AS resource, scores.year, scores.month AS xasys, SUM((mancost*score))/totoper.total AS v_fivesrate FROM scores JOIN totoper ON scores.year = totoper.year AND scores.month = totoper.month GROUP BY scores.year, scores.month, totoper.total, resource ORDER BY resource, scores.year DESC, scores.month DESC
Questa query, per FKT, ritorna per ogni mese il 5s rating, che è proprio il valore che serve a disegnare il grafico:
La seguente query è sufficiente sia per l'organization che per franke level, basta passare un codubi di organization o il codubi di franke
WITH RECURSIVE treeubi AS ( SELECT ubicaz.codice, ubicaz.descrizio, ubicaz.tiposet, ubicaz.codubib, ARRAY[]::VARCHAR[] || ubicaz.descrizio AS ancestors, ARRAY[]::VARCHAR[] || ubicaz.codice AS ancestorscode, ARRAY[]::VARCHAR[] || ubicaz.tiposet AS ancestorsts, mancost FROM ubicaz WHERE codice = 'franke001' UNION ALL SELECT ubicaz.codice, ubicaz.descrizio, ubicaz.tiposet, ubicaz.codubib, treeubi.ancestors || ubicaz.descrizio, treeubi.ancestorscode || ubicaz.codice, treeubi.ancestorsts || ubicaz.tiposet, ubicaz.mancost FROM ubicaz, treeubi WHERE ubicaz.codubib = treeubi.codice ), sinans AS ( SELECT codoper, MAX(codice) AS codice, codclista FROM answer GROUP BY codoper, codclista ), scores AS ( SELECT ancestors, ancestorscode, objiter.codice, objiter.tmcre, objiter.tipo, objiter.dayofmonth, objiter.month, objiter.year, project.descrizio, operato.nominati AS creator, treeubi.descrizio AS asset, treeubi.tiposet, treeubi.mancost, project.codubi, AVG(answer.value::NUMERIC) AS score FROM objiter INNER JOIN project ON objiter.codice = project.codice INNER JOIN operato ON objiter.codoper = operato.codice INNER JOIN treeubi ON project.codubi = treeubi.codice JOIN prjtask ON prjtask.codprj = objiter.codice JOIN clista ON clista.codptask = prjtask.codice JOIN sinans ON clista.codice = sinans.codclista JOIN answer ON sinans.codice = answer.codice WHERE objiter.tipo='P' AND mancost IS NOT NULL AND mancost > 0 AND objiter.tmcre >= 1676502000 AND objiter.tmcre <= 1705391447 GROUP BY ancestors, ancestorscode, objiter.codice, objiter.tmcre, objiter.tipo, objiter.dayofmonth, objiter.month, objiter.year, project.descrizio, creator, asset, tiposet, mancost, project.codubi ORDER BY tmcre DESC ), totoper AS ( SELECT SUM(mancost) AS total, MONTH, YEAR FROM scores GROUP BY MONTH, YEAR ) SELECT REPLACE(REPLACE(SPLIT_PART(ancestors::text, ',', 2), '{',''), ' ', '') AS resource, REPLACE(SPLIT_PART(ancestorscode::text, ',', 2), '{', '') AS xasys, scores.year, scores.month, SUM((mancost*score))/totoper.total AS v_fivesrate FROM scores JOIN totoper ON scores.year = totoper.year AND scores.month = totoper.month GROUP BY scores.year, scores.month, totoper.total, resource, xasys ORDER BY resource, scores.year DESC, scores.month DESC;
Chiamata Agent KPI #4
PLANT level:
- Nome dell'agente: graph
- ask
- request: fivescore
- p1: rec(codubi,fromtm,totm,tiposet)
- codubi = codice ubicaz
- fromtm = tm di inzio
- totm = tm di fine
- tiposet = tipo settore (S)
- retv: rec(resource,year,xasys,v_fivesrate) ESEMPIO:
- resource = "FKT"
- year = 2023
- xasys = 12
- v_fivesrate = 2.6
ORGANIZATIONAL and FRANKE level:
- Nome dell'agente: graph
- ask
- request: fivescore
- p1: rec(codubi,fromtm,totm,tiposet)
- codubi = codice ubicaz
- fromtm = tm di inzio
- totm = tm di fine
- tiposet = tipo settore (A o W)
- retv: rec(resource,xasys,year,month,v_fivesrate) ESEMPIO:
- resource = "CICBoardPlantFKTSwitzerlandAarburg"
- xasys = "FKT"
- year = 2023
- month = 12
- v_fivesrate = 0.2
KPI #5 - Nr. of deviations/Safety visits
Andrebbe aggiunto al DSFM un nuovo elemento, la gemba walk observaion. È un report che viene fatto dai manager e dai supervisori che vanno in visita nel processo. Dato che di fatto sarebbero identiche alle Job Safety Observations, con Bladimir abbiamo concordato di aggiungere un flag agli oggetti JSO per identificare quelli che sono JSO e quelli che sono Gemba Wolk Observation Report.
Per questo KPI si considereranno quindi tutti i JSO che hanno il flag "Gemba Walk Observation Report", ed in particolare le safety actions relative.
I "nr. of deviations" di un gemba walk sarebbero le azioni legate al gembra walk stesso.
ALTER TABLE project ADD COLUMN sogw INTEGER DEFAULT 0; COMMENT ON COLUMN project.sogw IS '0 -> classico JSO, 1 -> Safety Observation Gemba Walk.';
Nuovo campo sogw nella tabella project, se 1 → Gemba Walk Observation, se 0, classico JSO. Quindi per questo KPI vanno prese in considerazione tutte e sole le action degli objiter di tipo 'H', legate ai project con sogw = 1.
Le safety visits sono dati che a tendere andremo ad imporarci da un file excel che ci metteranno a disposizione ogni mese, e deriva da uniestrazione dal loro cognos ibm. Al momento diamo loro la possibilità di inserire manualmente questi valori. Comunque andranno salvati in una tabella. Le safety visits sono per mese per plant.
CREATE TABLE public.kpiubiext ( codubi CHARACTER VARYING(51) NOT NULL, MONTH INTEGER NOT NULL, YEAR INTEGER NOT NULL, fte INTEGER ); COMMENT ON COLUMN kpiubiext.fte IS 'il numero di executed walks per mese da parte del business'; ALTER TABLE public.kpiubiext OWNER TO postgres; ALTER TABLE ONLY public.kpiubiext ADD CONSTRAINT ix_kpiubiext_pkey PRIMARY KEY (codubi, MONTH, YEAR); ALTER TABLE ONLY public.kpiubiext ADD CONSTRAINT ix_kpiubiext_codubi FOREIGN KEY (codubi) REFERENCES public.ubicaz(codice) ON UPDATE CASCADE ON DELETE CASCADE;
QUERY PER I GRAFICI
WITH RECURSIVE treeubi AS (SELECT u.* FROM ubicaz u WHERE u.codice = 'FKT' UNION ALL SELECT u.* FROM ubicaz u, treeubi WHERE u.codubib = treeubi.codice), kpiext AS (SELECT * FROM kpiubiext WHERE codubi = 'FKT') SELECT 'FKT' AS resource, objiter.month, objiter.year, COUNT(safetyactions.*) AS tasks, kpiext.fte, COUNT(safetyactions.*)::FLOAT/fte AS rate FROM objiter JOIN project ON objiter.codice = project.codice JOIN treeubi ON project.codubi = treeubi.codice JOIN safetyactions ON project.codice = safetyactions.codprj JOIN kpiext ON objiter.month = kpiext.month AND objiter.year = kpiext.year WHERE tipo = 'H' AND project.sogw = 1 AND objiter.tmcre >= 1676502000 AND objiter.tmcre <= 1705391447 GROUP BY resource, objiter.month, objiter.year, fte ORDER BY YEAR DESC, MONTH DESC
Questa query, per FKT, ritorna per ogni mese rate del numero di actions sul numero di safety visits (kpiubiext.fte):
- A livello di Organization sarà la somma di tutte le actions del periodo stabilito sulla somma del numero FTE del periodo stabilito (per ogni plant dell'organization)
WITH RECURSIVE treeubi AS ( SELECT ubicaz.codice, ubicaz.descrizio, ubicaz.tiposet, ubicaz.codubib, ARRAY[]::VARCHAR[] || ubicaz.descrizio AS ancestors, ARRAY[]::VARCHAR[] || ubicaz.codice AS ancestorscode, ARRAY[]::VARCHAR[] || ubicaz.tiposet AS ancestorsts, mancost FROM ubicaz WHERE codice = 'franke001' UNION ALL SELECT ubicaz.codice, ubicaz.descrizio, ubicaz.tiposet, ubicaz.codubib, treeubi.ancestors || ubicaz.descrizio, treeubi.ancestorscode || ubicaz.codice, treeubi.ancestorsts || ubicaz.tiposet, ubicaz.mancost FROM ubicaz, treeubi WHERE ubicaz.codubib = treeubi.codice ), kpiext AS (SELECT kpiubiext.* FROM kpiubiext JOIN treeubi ON kpiubiext.codubi = treeubi.codice), base AS ( SELECT REPLACE(REPLACE(SPLIT_PART(treeubi.ancestors::text, ',', 2), '{',''), '"', '') AS resource, REPLACE(SPLIT_PART(treeubi.ancestorscode::text, ',', 2), '{', '') AS rescode, objiter.month, objiter.year, COUNT(safetyactions.*) AS tasks, kpiext.fte, COUNT(safetyactions.*)::FLOAT/fte AS rate FROM objiter JOIN project ON objiter.codice = project.codice JOIN treeubi ON project.codubi = treeubi.codice JOIN safetyactions ON project.codice = safetyactions.codprj JOIN kpiext ON objiter.month = kpiext.month AND objiter.year = kpiext.year WHERE tipo = 'H' AND project.sogw = 1 AND objiter.tmcre >= 1676502000 AND objiter.tmcre <= 1705391447 AND REPLACE(SPLIT_PART(treeubi.ancestorscode::text, ',', 2), '{', '') = kpiext.codubi GROUP BY resource, rescode, objiter.month, objiter.year, fte ORDER BY YEAR DESC, MONTH DESC) SELECT base.resource, base.rescode AS xasys, SUM(tasks) AS v_task, SUM(fte) AS v_fte, SUM(tasks)::FLOAT/SUM(fte) AS v_rate FROM base GROUP BY resource, xasys
- A livello di Franke sarà la somma di tutte le actions del periodo stabilito sulla somma del numero FTE del periodo stabilito (per ogni organization Franke)
WITH RECURSIVE treeubi AS ( SELECT ubicaz.codice, ubicaz.descrizio, ubicaz.tiposet, ubicaz.codubib, ARRAY[]::VARCHAR[] || ubicaz.descrizio AS ancestors, ARRAY[]::VARCHAR[] || ubicaz.codice AS ancestorscode, ARRAY[]::VARCHAR[] || ubicaz.tiposet AS ancestorsts, mancost FROM ubicaz WHERE codice = 'franke' UNION ALL SELECT ubicaz.codice, ubicaz.descrizio, ubicaz.tiposet, ubicaz.codubib, treeubi.ancestors || ubicaz.descrizio, treeubi.ancestorscode || ubicaz.codice, treeubi.ancestorsts || ubicaz.tiposet, ubicaz.mancost FROM ubicaz, treeubi WHERE ubicaz.codubib = treeubi.codice ), kpiext AS (SELECT kpiubiext.* FROM kpiubiext JOIN treeubi ON kpiubiext.codubi = treeubi.codice), base AS ( SELECT REPLACE(REPLACE(SPLIT_PART(treeubi.ancestors::text, ',', 2), '{',''), '"', '') AS resource, REPLACE(SPLIT_PART(treeubi.ancestorscode::text, ',', 2), '{', '') AS rescode, objiter.month, objiter.year, COUNT(safetyactions.*) AS tasks, kpiext.fte, COUNT(safetyactions.*)::FLOAT/fte AS rate FROM objiter JOIN project ON objiter.codice = project.codice JOIN treeubi ON project.codubi = treeubi.codice JOIN safetyactions ON project.codice = safetyactions.codprj JOIN kpiext ON objiter.month = kpiext.month AND objiter.year = kpiext.year WHERE tipo = 'H' AND project.sogw = 1 AND objiter.tmcre >= 1676502000 AND objiter.tmcre <= 1705391447 AND REPLACE(SPLIT_PART(treeubi.ancestorscode::text, ',', 3), '{', '') = kpiext.codubi GROUP BY resource, rescode, objiter.month, objiter.year, fte ORDER BY YEAR DESC, MONTH DESC) SELECT base.resource, base.rescode AS xasys, SUM(tasks) AS v_sumtask, SUM(fte) AS v_sumfte, SUM(tasks)::FLOAT/SUM(fte) AS v_rate FROM base GROUP BY resource, xasys
Chiamata Agent KPI #5
PLANT level:
- Nome dell'agente: graph
- ask
- request: deviations
- p1: rec(codubi,fromtm,totm,tiposet)
- codubi = codice ubicaz
- fromtm = tm di inzio
- totm = tm di fine
- tiposet = tipo settore (S)
- retv: rec(resource,year,xasys,v_task,v_fte,v_rate) ESEMPIO:
- resource = "FKT"
- year = 2024
- xasys = 1
- v_task = 5
- v_fte = 14
- v_rate = 0.35714285714285715
ORGANIZATIONAL level:
- Nome dell'agente: prepstat
- ask
- request: kpi5.organization
- p1: rec(codubi,fromtm,totm)
- codubi = codice ubicaz
- fromtm = tm di inzio
- totm = tm di fine
- retv: rec(resource,xasys,v_task,v_fte,v_rate) ESEMPIO:
- resource = "CIC Board Plant FBS Germany Bad Säkingen"
- xasys: "FBS"
- v_task = 1
- v_fte = 9
- v_rate = 0.1111111111111111
FRANKE level:
- Nome dell'agente: prepstat
- ask
- request: kpi5.franke
- p1: rec(codubi,fromtm,totm)
- codubi = codice ubicaz
- fromtm = tm di inzio
- fromtm = tm di fine
- retv: rec(resource,xasys,v_sumtask,v_sumfte,v_rate) ESEMPIO:
- resource = "Sinks"
- xasys= "franke001"
- v_sumtask = 134
- v_sumfte = 197
- v_rate = 0.6802030456852792
KPI #6 - Maturity Assessment Score
CREATE TABLE public.malevels ( codice INTEGER NOT NULL, descrizio CHARACTER VARYING(51), score INTEGER, bgcolor CHARACTER VARYING(51), fgcolor CHARACTER VARYING(51) ); ALTER TABLE public.malevels OWNER TO postgres; INSERT INTO public.malevels VALUES (1, 'Pathologic', 1, 'red', '#FFFFFF'); INSERT INTO public.malevels VALUES (2, 'Reactive', 2, 'orange', '#FFFFFF'); INSERT INTO public.malevels VALUES (3, 'Calculative', 3, 'yellow', '#000000'); INSERT INTO public.malevels VALUES (4, 'Proactive', 4, 'blue', '#FFFFFF'); INSERT INTO public.malevels VALUES (5, 'Innovative', 5, 'green', '#FFFFFF'); ALTER TABLE ONLY public.malevels ADD CONSTRAINT ix_malevels_pk PRIMARY KEY (codice); CREATE TABLE public.matopics ( codice INTEGER NOT NULL, descrizio CHARACTER VARYING(51), zord INTEGER ); ALTER TABLE public.matopics OWNER TO postgres; INSERT INTO public.matopics VALUES (1, 'Safety Culture', 1); INSERT INTO public.matopics VALUES (2, 'Governance, communication and training', 2); INSERT INTO public.matopics VALUES (3, 'Risk management', 3); INSERT INTO public.matopics VALUES (4, 'Task level instruction', 4); INSERT INTO public.matopics VALUES (5, 'Infrastructure', 5); INSERT INTO public.matopics VALUES (6, 'Driver for safety', 6); INSERT INTO public.matopics VALUES (7, 'Bradley curve', 7); INSERT INTO public.matopics VALUES (8, 'Safety Ambition', 8); ALTER TABLE ONLY public.matopics ADD CONSTRAINT ix_matopics_pk PRIMARY KEY (codice); CREATE TABLE public.mamatrix ( codice INTEGER NOT NULL, descrizio CHARACTER VARYING(1001), codlevel INTEGER, codtopic INTEGER ); ALTER TABLE public.mamatrix OWNER TO postgres; COMMENT ON COLUMN public.mamatrix.codlevel IS 'Riferimento a malevels.codice'; COMMENT ON COLUMN public.mamatrix.codtopic IS 'Riferimento a matopics.codice'; INSERT INTO public.mamatrix VALUES (1, 'Re-active safety culture, shortcomings not always addressed', 1, 1); INSERT INTO public.mamatrix VALUES (2, 'Re-active safety culture, shortcomings trigger action', 2, 1); INSERT INTO public.mamatrix VALUES (3, 'Re-active safety culture with some pro-active elements in place', 3, 1); INSERT INTO public.mamatrix VALUES (4, 'Pro-active safety culture at all levels. Elements of autonomous teams in place', 4, 1); INSERT INTO public.mamatrix VALUES (5, 'Fully effective pro-active safety culture at all levels of the organisation', 5, 1); INSERT INTO public.mamatrix VALUES (6, 'Governance, communication & training on an ad hoc basis', 1, 2); INSERT INTO public.mamatrix VALUES (7, 'Governance, communication & training processes initiated', 2, 2); INSERT INTO public.mamatrix VALUES (8, 'Governance, communication & training processes in place, training is being applied', 3, 2); INSERT INTO public.mamatrix VALUES (9, 'PDCA applied on governance, communication & training', 4, 2); INSERT INTO public.mamatrix VALUES (10, 'GOvernance, communication & training fully effective', 5, 2); INSERT INTO public.mamatrix VALUES (11, 'Ad hoc risk management approach, lack of structure & processes', 1, 3); INSERT INTO public.mamatrix VALUES (12, 'Safety standards partially defined and risk assessmentprocess initiated', 2, 3); INSERT INTO public.mamatrix VALUES (13, 'Safety Standards defined & documented, risk assessment process in place', 3, 3); INSERT INTO public.mamatrix VALUES (14, 'Risk management audit & optimization process initiated (including Moc)', 4, 3); INSERT INTO public.mamatrix VALUES (15, 'Risk management audit & optimization process in place and effective (including Moc)', 5, 3); INSERT INTO public.mamatrix VALUES (16, 'Task level instructions (with safety being integrated) are hardly available', 1, 4); INSERT INTO public.mamatrix VALUES (17, 'Task level instructions available for most standard tasks, permit system initiated', 2, 4); INSERT INTO public.mamatrix VALUES (18, 'Task level instructions available for most standard tasks, permit system in place', 3, 4); INSERT INTO public.mamatrix VALUES (19, 'Instructions available for all tasks, permits system fully implemented. High degree of compliance', 4, 4); INSERT INTO public.mamatrix VALUES (20, 'Instructions issued for every task done. Very high level of compliance', 5, 4); INSERT INTO public.mamatrix VALUES (21, 'Infrastructure meets legal and industry standards partially (<90%)', 1, 5); INSERT INTO public.mamatrix VALUES (22, 'Infrastructure meets legal and industry standards partially (>90%)', 2, 5); INSERT INTO public.mamatrix VALUES (23, 'Infrastructure meets legal and industry standards', 3, 5); INSERT INTO public.mamatrix VALUES (24, 'Elimination of risks is partially done during the design phase', 4, 5); INSERT INTO public.mamatrix VALUES (25, 'Elimination of risks is maximised during the design phase', 5, 5); INSERT INTO public.mamatrix VALUES (26, 'Driver for safety is the Health & Safety team', 1, 6); INSERT INTO public.mamatrix VALUES (27, 'Safety is driven by management, still dependence on the H&S team', 2, 6); INSERT INTO public.mamatrix VALUES (28, 'Safety is driven by management', 3, 6); INSERT INTO public.mamatrix VALUES (29, 'Safety is driven by management and supervision', 4, 6); INSERT INTO public.mamatrix VALUES (30, 'Safety is driven by management and supervision and the operational teams', 5, 6); INSERT INTO public.mamatrix VALUES (31, 'Bradley curve status: Natural instinct', 1, 7); INSERT INTO public.mamatrix VALUES (32, 'Dependent, legal compliance', 2, 7); INSERT INTO public.mamatrix VALUES (33, 'Dependent, Corporate Ambition', 3, 7); INSERT INTO public.mamatrix VALUES (34, 'Independent, Corporate Ambition', 4, 7); INSERT INTO public.mamatrix VALUES (35, 'Interdependent, Corporate Ambition', 5, 7); INSERT INTO public.mamatrix VALUES (36, 'No formal safety ambition', 1, 8); INSERT INTO public.mamatrix VALUES (37, 'Legal compliance as a main driver', 2, 8); INSERT INTO public.mamatrix VALUES (38, 'Comporate ambition (Zero Harm) as a main driver', 3, 8); INSERT INTO public.mamatrix VALUES (39, 'Corporate ambition partially implemented', 4, 8); INSERT INTO public.mamatrix VALUES (40, 'Corporate ambition implemented', 5, 8); ALTER TABLE ONLY public.mamatrix ADD CONSTRAINT ix_mamatrix_pk PRIMARY KEY (codice); ALTER TABLE ONLY public.mamatrix ADD CONSTRAINT ix_mamatrix_codlevel FOREIGN KEY (codlevel) REFERENCES public.malevels(codice) ON UPDATE CASCADE ON DELETE RESTRICT; ALTER TABLE ONLY public.mamatrix ADD CONSTRAINT ix_mamatrix_codtopic FOREIGN KEY (codtopic) REFERENCES public.matopics(codice) ON UPDATE CASCADE ON DELETE RESTRICT; CREATE TABLE public.maplantaudit ( codice INTEGER NOT NULL, codubi CHARACTER VARYING(51) NOT NULL, tm DOUBLE PRECISION NOT NULL, DATA CHARACTER VARYING(51), codoper CHARACTER VARYING(51) ); ALTER TABLE public.maplantaudit OWNER TO postgres; ALTER TABLE ONLY public.maplantaudit ADD CONSTRAINT ix_maplantaudit_pk PRIMARY KEY (codice); ALTER TABLE ONLY public.maplantaudit ADD CONSTRAINT ix_maplantaudit_codoper FOREIGN KEY (codoper) REFERENCES public.operato(codice) ON UPDATE CASCADE ON DELETE RESTRICT; ALTER TABLE ONLY public.maplantaudit ADD CONSTRAINT ix_maplantaudit_codubi FOREIGN KEY (codubi) REFERENCES public.ubicaz(codice) ON UPDATE CASCADE ON DELETE CASCADE; CREATE TABLE public.maplantscore ( codaudit INTEGER NOT NULL, score DOUBLE PRECISION, codtopic INTEGER NOT NULL ); ALTER TABLE public.maplantscore OWNER TO postgres; COMMENT ON COLUMN public.maplantscore.codaudit IS 'Riferimento a maplantaudit.codice'; COMMENT ON COLUMN public.maplantscore.score IS 'Voto che viene dato nel singolo audit, da 1.0 a 5.0'; ALTER TABLE ONLY public.maplantscore ADD CONSTRAINT ix_maplantscore_codtopic FOREIGN KEY (codtopic) REFERENCES public.matopics(codice) ON UPDATE CASCADE ON DELETE CASCADE; ALTER TABLE ONLY public.maplantscore ADD CONSTRAINT ix_maplantscore_codaudit FOREIGN KEY (codaudit) REFERENCES public.maplantaudit(codice) ON UPDATE CASCADE ON DELETE CASCADE;
Ogni plant deve poter impostare il suo target per il maturity assessment. Aggiunta di un campo in ubicaz che gestisce questo target:
ALTER TABLE ubicaz ADD COLUMN maturitytarget DOUBLE PRECISION;
KPI
NB: Livello stabilimento ⇒ ubicaz.tiposet = 'S'. Livello di organizzazione ⇒ ubicaz.tiposet = 'A'. Franke è suddivisa in 5 organizzazioni: Sinks, Hoodss, Food Service, Supply Chain, Coffee System.
Quando si parla a livello di plant si intende la singola ubicaz, quindi il codice di un plant
Quando si parla a livello di organizzazione, si intende tutte le ubicaz figlie di una certa organizzazione. Esempio → organizzazione sinks, tutte le ubicaz di sinks
Quando si parla a livello di franke, si intende tutte le ubicaz di tipo 'A', ovvero tutte le organizzazioni.
Per il grafico si vuole utilizzare il radarchart:
QUERY PER I GRAFICI
- Livello di stabilimento:
Si prende l'ultimo audit inserito:
WITH audit AS (SELECT * FROM maplantaudit WHERE codubi = 'FKT' AND tm>=1674169200 AND tm <= 1705311642 ORDER BY tm DESC LIMIT 1) SELECT ubicaz.maturitytarget AS v_target, matopics.codice AS codtopic, ubicaz.codice, ubicaz.descrizio, ubicaz.maturitytarget, matopics.descrizio AS xasys, maplantscore.score AS v_score, tm, codaudit FROM audit JOIN maplantscore ON audit.codice = maplantscore.codaudit JOIN matopics ON maplantscore.codtopic = matopics.codice JOIN ubicaz ON audit.codubi = ubicaz.codice ORDER BY matopics.zord
- Organizational & Franke Level
In questo caso i radarcharts saranno 2, uno con la media voti per location e l'altro con la media voti per topic. Di seguito le due query:
LOCATION:
WITH RECURSIVE treeubi AS ( SELECT ubicaz.codice, ubicaz.descrizio, ubicaz.maturitytarget, ubicaz.tiposet, ubicaz.codubib, ARRAY[]::VARCHAR[] || ubicaz.descrizio AS ancestors, ARRAY[]::VARCHAR[] || ubicaz.codice AS ancestorscode, ARRAY[]::VARCHAR[] || ubicaz.tiposet AS ancestorsts, mancost FROM ubicaz WHERE codice = 'franke001' UNION ALL SELECT ubicaz.codice, ubicaz.descrizio, ubicaz.maturitytarget, ubicaz.tiposet, ubicaz.codubib, treeubi.ancestors || ubicaz.descrizio, treeubi.ancestorscode || ubicaz.codice, treeubi.ancestorsts || ubicaz.tiposet, ubicaz.mancost FROM ubicaz, treeubi WHERE ubicaz.codubib = treeubi.codice ), lastaudit AS (SELECT MAX(tm) AS tm, codubi FROM maplantaudit JOIN treeubi ON maplantaudit.codubi = treeubi.codice WHERE tm>= 1674169200 AND tm <= 1705311642 GROUP BY codubi), audit AS (SELECT maplantaudit.* FROM maplantaudit JOIN lastaudit ON maplantaudit.tm = lastaudit.tm AND maplantaudit.codubi = lastaudit.codubi) SELECT REPLACE(REPLACE(REPLACE(SPLIT_PART(treeubi.ancestors::text, ',', 2), '{',''), '}', ''), '"', '') AS resource, REPLACE(REPLACE(SPLIT_PART(treeubi.ancestorscode::text, ',', 2), '{', ''), '}', '') AS xasys, treeubi.maturitytarget AS v_target, AVG(maplantscore.score) AS v_score FROM audit JOIN maplantscore ON audit.codice = maplantscore.codaudit JOIN matopics ON maplantscore.codtopic = matopics.codice JOIN treeubi ON audit.codubi = treeubi.codice GROUP BY resource, xasys, maturitytarget
TOPIC:
WITH RECURSIVE treeubi AS ( SELECT ubicaz.codice, ubicaz.descrizio, ubicaz.maturitytarget, ubicaz.tiposet, ubicaz.codubib, ARRAY[]::VARCHAR[] || ubicaz.descrizio AS ancestors, ARRAY[]::VARCHAR[] || ubicaz.codice AS ancestorscode, ARRAY[]::VARCHAR[] || ubicaz.tiposet AS ancestorsts, mancost FROM ubicaz WHERE codice = 'franke001' UNION ALL SELECT ubicaz.codice, ubicaz.descrizio, ubicaz.maturitytarget, ubicaz.tiposet, ubicaz.codubib, treeubi.ancestors || ubicaz.descrizio, treeubi.ancestorscode || ubicaz.codice, treeubi.ancestorsts || ubicaz.tiposet, ubicaz.mancost FROM ubicaz, treeubi WHERE ubicaz.codubib = treeubi.codice ), lastaudit AS (SELECT MAX(tm) AS tm, codubi FROM maplantaudit JOIN treeubi ON maplantaudit.codubi = treeubi.codice WHERE tm>= 1674169200 AND tm <= 1705311642 GROUP BY codubi), audit AS (SELECT maplantaudit.* FROM maplantaudit JOIN lastaudit ON maplantaudit.tm = lastaudit.tm AND maplantaudit.codubi = lastaudit.codubi) SELECT matopics.codice AS codtopic, matopics.descrizio AS xasys, treeubi.maturitytarget AS v_target, AVG(maplantscore.score) AS v_score FROM audit JOIN maplantscore ON audit.codice = maplantscore.codaudit JOIN matopics ON maplantscore.codtopic = matopics.codice JOIN treeubi ON audit.codubi = treeubi.codice GROUP BY matopics.codice, matopics.descrizio, maturitytarget
La media dei punteggi dell'ultimo audit per ogni ubicaz dell'organizzazione (nel caso di franke, per ogni orgranizzazione di franke)
Chiamata Agent KPI #6
PLANT level:
- Nome dell'agente: prepstat
- ask
- request: kpi6.plant
- p1: rec(codubi,fromtm,totm)
- codubi = codice ubicaz
- fromtm = tm di inzio
- totm = tm di fine
- retv: rec(v_target,codtopic,codice,descrizio,maturitytarget,xasys,v_score,tm,codaudit) ESEMPIO:
- v_target = 3
- codtopic = 1
- codice = "FKT"
- descrizio = "CIC Board Plant FKT Switzerland Aarburg"
- maturitytarget = 3
- xasys = "Safety Culture"
- v_score = 2.8
- tm = 1705327488
- codaudit = 12
ORGANIZATIONAL and FRANKE level:
- Nome dell'agente: prepstat
- ask
- request: kpi6
- p1: rec(_subkey,codubi,fromtm,totm)
- _subkey = subkey delle query da eseguire divise da virgola (location,topic)
- codubi = codice ubicaz
- fromtm = tm di inzio
- totm = tm di fine
- retv: i valori di "kpi6.location" e "kpi6.topic" ritorneranno come stringhe!
[ { "kpi6.location":[ { "resource":"CIC Plant FIM IND Aurangabad", "xasys":"FIM", "v_target":3.0, "v_score":2.3999999999999999 }, ... ], "kpi6.topic":[ { "codtopic":2, "xasys":"Governance, communication and training", "v_target":3.0, "v_score":2.3999999999999999 }, ... ] } ]
KPI #7 - Nr° Actions closed/open
Monitoraggio del rate di chiusura delle azioni che provengono dalle JSO, Safety Reports e Risk Assessment.
Esempio di due stack diversi sullo stesso chart
QUERY PER I GRAFICI
WITH RECURSIVE treeubi AS (SELECT u.* FROM ubicaz u WHERE u.codice = 'FKT' UNION ALL SELECT u.* FROM ubicaz u, treeubi WHERE u.codubib = treeubi.codice), allacts AS (SELECT EXTRACT(MONTH FROM TIMESTAMP WITH TIME ZONE 'epoch' + tmcre * INTERVAL '1 second') AS MONTH, EXTRACT(YEAR FROM TIMESTAMP WITH TIME ZONE 'epoch' + tmcre * INTERVAL '1 second') AS YEAR, COUNT(safetyactions.*) AS total FROM project JOIN treeubi ON project.codubi = treeubi.codice JOIN safetyactions ON project.codice = safetyactions.codprj WHERE safetyactions.tmcre >= 1676502000 AND safetyactions.tmcre <= 1705391447 GROUP BY MONTH, YEAR), closedacts AS (SELECT EXTRACT(MONTH FROM TIMESTAMP WITH TIME ZONE 'epoch' + tmcre * INTERVAL '1 second') AS MONTH, EXTRACT(YEAR FROM TIMESTAMP WITH TIME ZONE 'epoch' + tmcre * INTERVAL '1 second') AS YEAR, COUNT(safetyactions.*) AS numclosed FROM project JOIN treeubi ON project.codubi = treeubi.codice JOIN safetyactions ON project.codice = safetyactions.codprj WHERE safetyactions.tmcre >= 1676502000 AND safetyactions.tmcre <= 1705391447 AND safetyactions.status = 'C' AND (safetyactions.tmclosed-safetyactions.tmcre)/86400 < 90 GROUP BY MONTH, YEAR), openacts AS (SELECT EXTRACT(MONTH FROM TIMESTAMP WITH TIME ZONE 'epoch' + tmcre * INTERVAL '1 second') AS MONTH, EXTRACT(YEAR FROM TIMESTAMP WITH TIME ZONE 'epoch' + tmcre * INTERVAL '1 second') AS YEAR, COUNT(safetyactions.*) AS numopen FROM project JOIN treeubi ON project.codubi = treeubi.codice JOIN safetyactions ON project.codice = safetyactions.codprj WHERE safetyactions.tmcre >= 1676502000 AND safetyactions.tmcre <= 1705391447 AND safetyactions.status = 'O' AND (tm()-safetyactions.tmcre)/86400 > 90 GROUP BY MONTH, YEAR) SELECT DISTINCT 'FKT' AS resource, allacts.month AS xasys, allacts.year, total AS v_total, numclosed AS v_numclosed, numopen AS v_numopen FROM allacts LEFT JOIN closedacts ON allacts.month = closedacts.month AND allacts.year = closedacts.year LEFT JOIN openacts ON allacts.month = openacts.month AND allacts.year = openacts.year ORDER BY YEAR DESC, xasys DESC
Organization Level:
WITH RECURSIVE treeubi AS ( SELECT ubicaz.codice, ubicaz.descrizio, ubicaz.tiposet, ubicaz.codubib, ARRAY[]::VARCHAR[] || ubicaz.descrizio AS ancestors, ARRAY[]::VARCHAR[] || ubicaz.codice AS ancestorscode, ARRAY[]::VARCHAR[] || ubicaz.tiposet AS ancestorsts, mancost FROM ubicaz WHERE codice = 'franke001' UNION ALL SELECT ubicaz.codice, ubicaz.descrizio, ubicaz.tiposet, ubicaz.codubib, treeubi.ancestors || ubicaz.descrizio, treeubi.ancestorscode || ubicaz.codice, treeubi.ancestorsts || ubicaz.tiposet, ubicaz.mancost FROM ubicaz, treeubi WHERE ubicaz.codubib = treeubi.codice ), allacts AS (SELECT REPLACE(REPLACE(REPLACE(SPLIT_PART(ancestors::text, ',', 2), '{',''), '}', ''), '"', '') AS resource, REPLACE(REPLACE(SPLIT_PART(ancestorscode::text, ',', 2), '{', ''), '}', '') AS rescode, COUNT(safetyactions.*) AS total FROM project JOIN treeubi ON project.codubi = treeubi.codice JOIN safetyactions ON project.codice = safetyactions.codprj WHERE safetyactions.tmcre >= 1676502000 AND safetyactions.tmcre <= 1705391447 GROUP BY resource, rescode), closedacts AS (SELECT REPLACE(REPLACE(REPLACE(SPLIT_PART(ancestors::text, ',', 2), '{',''), '}', ''), '"', '') AS resource, REPLACE(REPLACE(SPLIT_PART(ancestorscode::text, ',', 2), '{', ''), '}', '') AS rescode, COUNT(safetyactions.*) AS numclosed FROM project JOIN treeubi ON project.codubi = treeubi.codice JOIN safetyactions ON project.codice = safetyactions.codprj WHERE safetyactions.tmcre >= 1676502000 AND safetyactions.tmcre <= 1705391447 AND safetyactions.status = 'C' AND (safetyactions.tmclosed-safetyactions.tmcre)/86400 < 90 GROUP BY resource, rescode), openacts AS (SELECT REPLACE(REPLACE(REPLACE(SPLIT_PART(ancestors::text, ',', 2), '{',''), '}', ''), '"', '') AS resource, REPLACE(REPLACE(SPLIT_PART(ancestorscode::text, ',', 2), '{', ''), '}', '') AS rescode, COUNT(safetyactions.*) AS numopen FROM project JOIN treeubi ON project.codubi = treeubi.codice JOIN safetyactions ON project.codice = safetyactions.codprj WHERE safetyactions.tmcre >= 1676502000 AND safetyactions.tmcre <= 1705391447 AND safetyactions.status = 'O' AND (tm()-safetyactions.tmcre)/86400 > 90 GROUP BY resource, rescode) SELECT allacts.resource, allacts.rescode AS xasys, total AS v_total, numclosed AS v_numclosed, numopen AS v_numopen FROM allacts LEFT JOIN closedacts ON allacts.rescode = closedacts.rescode LEFT JOIN openacts ON allacts.rescode = openacts.rescode ORDER BY resource
Franke Level:
WITH RECURSIVE treeubi AS ( SELECT ubicaz.codice, ubicaz.descrizio, ubicaz.tiposet, ubicaz.codubib, ARRAY[]::VARCHAR[] || ubicaz.descrizio AS ancestors, ARRAY[]::VARCHAR[] || ubicaz.codice AS ancestorscode, ARRAY[]::VARCHAR[] || ubicaz.tiposet AS ancestorsts, mancost FROM ubicaz WHERE codice = 'franke' UNION ALL SELECT ubicaz.codice, ubicaz.descrizio, ubicaz.tiposet, ubicaz.codubib, treeubi.ancestors || ubicaz.descrizio, treeubi.ancestorscode || ubicaz.codice, treeubi.ancestorsts || ubicaz.tiposet, ubicaz.mancost FROM ubicaz, treeubi WHERE ubicaz.codubib = treeubi.codice ), allacts AS (SELECT REPLACE(REPLACE(REPLACE(SPLIT_PART(ancestors::text, ',', 2), '{',''), '}', ''), '"', '') AS resource, REPLACE(REPLACE(SPLIT_PART(ancestorscode::text, ',', 2), '{', ''), '}', '') AS rescode, COUNT(safetyactions.*) AS total FROM project JOIN treeubi ON project.codubi = treeubi.codice JOIN safetyactions ON project.codice = safetyactions.codprj WHERE safetyactions.tmcre >= 1676502000 AND safetyactions.tmcre <= 1705391447 GROUP BY resource, rescode), closedacts AS (SELECT REPLACE(REPLACE(REPLACE(SPLIT_PART(ancestors::text, ',', 2), '{',''), '}', ''), '"', '') AS resource, REPLACE(REPLACE(SPLIT_PART(ancestorscode::text, ',', 2), '{', ''), '}', '') AS rescode, COUNT(safetyactions.*) AS numclosed FROM project JOIN treeubi ON project.codubi = treeubi.codice JOIN safetyactions ON project.codice = safetyactions.codprj WHERE safetyactions.tmcre >= 1676502000 AND safetyactions.tmcre <= 1705391447 AND safetyactions.status = 'C' AND (safetyactions.tmclosed-safetyactions.tmcre)/86400 < 90 GROUP BY resource, rescode), openacts AS (SELECT REPLACE(REPLACE(REPLACE(SPLIT_PART(ancestors::text, ',', 2), '{',''), '}', ''), '"', '') AS resource, REPLACE(REPLACE(SPLIT_PART(ancestorscode::text, ',', 2), '{', ''), '}', '') AS rescode, COUNT(safetyactions.*) AS numopen FROM project JOIN treeubi ON project.codubi = treeubi.codice JOIN safetyactions ON project.codice = safetyactions.codprj WHERE safetyactions.tmcre >= 1676502000 AND safetyactions.tmcre <= 1705391447 AND safetyactions.status = 'O' AND (tm()-safetyactions.tmcre)/86400 > 90 GROUP BY resource, rescode) SELECT allacts.resource AS xasys, allacts.rescode, total AS v_total, numclosed AS v_numclosed, numopen AS v_numopen FROM allacts LEFT JOIN closedacts ON allacts.rescode = closedacts.rescode LEFT JOIN openacts ON allacts.rescode = openacts.rescode ORDER BY xasys
Chiamata Agent KPI #7
PLANT level:
- Nome dell'agente: graph
- ask
- request: maturity
- p1: rec(codubi,fromtm,totm,tiposet)
- codubi = codice ubicaz
- fromtm = tm di inzio
- totm = tm di fine
- tiposet = tipologia settore (S)
- retv: rec(resource,xasys,year,v_total,v_numclosed,v_numopen) ESEMPIO:
- resource = "FKT"
- xasys = 1
- year = 2024
- v_total = 9
- v_numclosed = 0
- v_numopen = 0
ORGANIZATIONAL level:
- Nome dell'agente: prepstat
- ask
- request: kpi7.organization
- p1: rec(codubi,fromtm,totm)
- codubi = codice ubicaz
- fromtm = tm di inzio
- totm = tm di fine
- retv: rec(resource,xasys,v_total,v_numclosed,v_numopen) ESEMPIO:
- resource = "CIC Board Plant FBS Germany Bad Säkingen"
- xasys = ""FBS""
- v_total = 1
- v_numclosed = "" (se NULL prepstat ritorna "")
- v_numopen = 1
FRANKE level:
- Nome dell'agente: prepstat
- ask
- request: kpi7.franke
- p1: rec(codubi,fromtm,totm)
- codubi = codice ubicaz
- fromtm = tm di inzio
- totm = tm di fine
- retv: rec(resource,xasys,v_total,v_numclosed,v_numopen) ESEMPIO:
- xasys = "Food Services"
- rescode = "franke005"
- v_total = 936
- v_numclosed = 369
- v_numopen = 508
RIKS ASSESSMENT
Utilizzo di un nuovo objiter, di tipo 'U'.
Un Risk Assessment è simile, a livello di struttura, ad un JSO, per cui si andranno a modificare le pagine di gestione del JSO per poter gestire anche questo nuovo tipo di oggetto.
Per il risk assessment abbiamo bisogno di alcune tabelle anagrafiche.
CREATE TABLE public.rafrequence ( codice CHARACTER VARYING(11) NOT NULL, descrizio CHARACTER VARYING(51), severity INTEGER ); ALTER TABLE public.rafrequence OWNER TO postgres; COMMENT ON TABLE public.rafrequence IS 'Tabella delle frequenze ammesse per il risk assessment'; INSERT INTO public.rafrequence VALUES ('C', 'Continua', 1); INSERT INTO public.rafrequence VALUES ('D', 'Giornaliera', 2); INSERT INTO public.rafrequence VALUES ('W', 'Settimanale', 3); INSERT INTO public.rafrequence VALUES ('M', 'Mensile', 4); INSERT INTO public.rafrequence VALUES ('Y', 'Annuale', 5); ALTER TABLE ONLY public.rafrequence ADD CONSTRAINT ix_rafrequence_pk PRIMARY KEY (codice); -- Per gestire i due nuovi campi hazard description e hazard control ALTER TABLE project ADD COLUMN hazard VARCHAR(501); ALTER TABLE project ADD COLUMN hazardctrl VARCHAR(501); ALTER TABLE project ADD COLUMN rafreq VARCHAR(11); ALTER TABLE project ADD COLUMN crlsev INTEGER; ALTER TABLE project ADD COLUMN crlprob INTEGER; ALTER TABLE project ADD COLUMN frlsev INTEGER; ALTER TABLE project ADD COLUMN frlprob INTEGER; --Severity CREATE TABLE public.raseverity ( codice INTEGER NOT NULL, descrizio CHARACTER VARYING(51), rating INTEGER ); ALTER TABLE public.raseverity OWNER TO postgres; COMMENT ON TABLE public.raseverity IS 'Tabella delle severità per il risk management'; INSERT INTO public.raseverity VALUES (1, 'Fatale o Fatale Multiplo', 16); INSERT INTO public.raseverity VALUES (2, 'Disabilità Permanente', 8); INSERT INTO public.raseverity VALUES (3, 'Tempo Perso', 4); INSERT INTO public.raseverity VALUES (4, 'Cure Mediche', 2); INSERT INTO public.raseverity VALUES (5, 'Primo Soccorso', 1); ALTER TABLE ONLY public.raseverity ADD CONSTRAINT ix_raseverity_pk PRIMARY KEY (codice); --Probability CREATE TABLE public.raprobability ( codice INTEGER NOT NULL, descrizio CHARACTER VARYING(51), rating INTEGER ); ALTER TABLE public.raprobability OWNER TO postgres; COMMENT ON TABLE public.raprobability IS 'Tabella delle probabilità previste nel Rik Assessment'; INSERT INTO public.raprobability VALUES (1, 'Impossibile', 1); INSERT INTO public.raprobability VALUES (2, 'Molto Improbabile', 2); INSERT INTO public.raprobability VALUES (3, 'Improbabile', 4); INSERT INTO public.raprobability VALUES (4, 'Possibile', 8); INSERT INTO public.raprobability VALUES (5, 'Probabile', 30); INSERT INTO public.raprobability VALUES (6, 'Molto Probabile', 60); ALTER TABLE ONLY public.raprobability ADD CONSTRAINT ix_raprobability_pk PRIMARY KEY (codice);
COGNOS KPI
Creato un nuovo ruolo all'interno del digcic.
Utente: cognos_user
Password: W4rJA5xmC92yZ$RGKb#iKA
Questo utente ha accesso ad una sola tabella del database, la cognoskpi (al momento, 06-03-2024, la struttura è temporanea).
Una volta al mese cognos si connetterà a questa tabella per inserire i dati dei KPI.
Email Notification System
Si richiede di sviluppare un sistema di notifica tramite email quando:
1) Viene assegnato/riassegnato un responsabile ad una safety action
2) Viene assegnato/riassegnato un problem solver ad un action plan
Safety Action
Una safety action è un'azione solitamente collegata ai Job Safety Observation e alle Vulnerability Management.
Ogni azione ha un responsabile che si dovrà occupare di eseguirla. Il responsabile viene identificato nel campo safetyactions.codoper
Action Plan
Esistono 4 tipologie di actionplan all'interno del DSFM. Quality, Delivery, Cost e Maintenance.
Gli action plan sono objiter di tipo Q (quality), O (cost), W (delivery), I (maintenance).
L'utente a cui è assegnato un actionplan si trova nel campo codoperres della tabella project
Il sistema di notifica dovrà essere configurabile ed in particolare:
- potrà essere abilitato per alcuni plant (ubicaz.tiposet = 'S').
- potrà essere abilitato per le safety action
- potrà essere abilitato per ogni singolo action plan
Ogni action plan ed ogni safety action saranno collegati ad una ubicaz (che potrà essere di tiposet S, R o P).
Se gerarchicamente l'ubicaz associata ad una safety action o ad un action plan appartiene ai plant abilitati e se l'oggetto stesso (safety action o lo specifico action plan) è abilitato all'invio della notifica, sarà possibile l'invio delle email verso il responsabile definito.
Quando inviare l'email?
Al salvataggio (inserimento o update) di un action plan o di una safety action vanno verificate le seguenti condizioni:
- gerarchicamente l'ubicaz associata ad una safety action o ad un action plan appartiene ai plant abilitati
WITH RECURSIVE treeubi AS ( SELECT u.* FROM ubicaz u WHERE u.codice = project.codubi UNION ALL SELECT u.* FROM ubicaz u, treeubi WHERE u.codice = treeubi.codubib ) SELECT DISTINCT treeubi.* FROM treeubi WHERE tiposet = 'S'
- l'oggetto stesso (safety action o lo specifico action plan) è abilitato
- il responsabile dell'azione è definito
Se tutte queste condizioni sono vere, l'email dovrà essere inviata al responsabile.
Quando viene assegnato un nuovo responsabile (e rimangono valide le condizioni predecenti), il vecchio responsabile dovrà essere notificato del cambio owner ed il nuovo responsabile dovrà essere notificato dell'avvenuta assegnazione di una SA o di un AP
Creazioni tabelle dei setting
CREATE TABLE public.emailsetting ( codubi CHARACTER VARYING(51) NOT NULL, TYPE CHARACTER VARYING(2) NOT NULL, tmreminder INTEGER DEFAULT 0, deflang VARCHAR(8) ); ALTER TABLE public.emailsetting OWNER TO postgres; COMMENT ON TABLE public.emailsetting IS 'Tabella che configura il sistema di notifica email. Gli stabilimenti presenti in questa tabella (codubi) potranno ricevere notifiche per gli oggetti definiti dal campo type. '; COMMENT ON COLUMN public.emailsetting.type IS 'Q: Action Plan Quality, O: Action Plan Cost, W: Action Plan Delivery, I: Action Plan Maintenance, S: Safety Actions'; COMMENT ON COLUMN public.emailsetting.tmreminder IS 'il tm in secondi per cui deve essere inviata un''email di reminder. Se 0 il reminder non è attivo'; ALTER TABLE ONLY public.emailsetting ADD CONSTRAINT ix_emailsetting_pk PRIMARY KEY (codubi, TYPE); ALTER TABLE ONLY public.emailsetting ADD CONSTRAINT ix_emailsetting_codubi FOREIGN KEY (codubi) REFERENCES public.ubicaz(codice) ON UPDATE CASCADE ON DELETE CASCADE NOT VALID; CREATE TABLE public.emailope ( codice DOUBLE PRECISION NOT NULL, TYPE CHARACTER VARYING(2) NOT NULL, codoper CHARACTER VARYING(51), tm DOUBLE PRECISION, tmlast DOUBLE PRECISION ); ALTER TABLE public.emailope OWNER TO postgres; COMMENT ON TABLE public.emailope IS 'In questa tabella vengono salvati gli invii email effettuati'; COMMENT ON COLUMN public.emailope.codice IS 'questo codice fa riferimento a objiter.codice se type è Q,O,W,I. Altrimenti farà riferimento al campo safetyactions.codice se di tipo S'; COMMENT ON COLUMN public.emailope.type IS 'Valori ammessi: Q: Quality Action Plan, O: Cost Action Plan, W: Delivery Action Plan, I: Maintenance Action Plan, M: Safety Action'; COMMENT ON COLUMN public.emailope.codoper IS 'l''utente che dovrà ricevere l''email'; COMMENT ON COLUMN public.emailope.tm IS 'il tm di primo invio email'; COMMENT ON COLUMN public.emailope.tmlast IS 'il tm dell''ultimo invio fatto'; ALTER TABLE ONLY public.emailope ADD CONSTRAINT ix_emailope_pk PRIMARY KEY (codice, TYPE); ALTER TABLE ONLY public.emailope ADD CONSTRAINT ix_emailope_codoper FOREIGN KEY (codoper) REFERENCES public.operato(codice) ON UPDATE CASCADE ON DELETE RESTRICT NOT VALID;
Creazione di un campo codice univoco per la tabella safetyactions
Creare un campo codice per la tabella safetyactions e valorizzarlo con un id incrementale:
ALTER TABLE safetyactions ADD COLUMN codice FLOAT; WITH numerati AS ( SELECT ctid, ROW_NUMBER() OVER () AS nuovo_codice FROM safetyactions ) UPDATE safetyactions SET codice = numerati.nuovo_codice FROM numerati WHERE safetyactions.ctid = numerati.ctid;
Ricordarsi di fare la addrecnume!!
CREATE TABLE public.operacom ( codice INTEGER NOT NULL, KEY CHARACTER VARYING(51), tipo CHARACTER VARYING(2), descrizio CHARACTER VARYING(101) ); ALTER TABLE public.operacom OWNER TO postgres; COMMENT ON TABLE public.operacom IS 'Tabella che contiene l''entry point per ogni messaggio utente (testo o markdown). Messaggi che poi possono essere utilizzati per invio email o altro.'; COMMENT ON COLUMN public.operacom.key IS 'chiave aggiuntiva di testo per utilizzo delle chiamate agente'; COMMENT ON COLUMN public.operacom.tipo IS 'T=testo, M=markdown'; COMMENT ON COLUMN public.operacom.descrizio IS 'Descrizione della key (opzionale)'; INSERT INTO public.operacom (codice, KEY, tipo, descrizio) VALUES (1, 'assign', 'T', 'Assegnazione Safety'); INSERT INTO public.operacom (codice, KEY, tipo, descrizio) VALUES (2, 'unassign', 'T', 'Disassegnazione operatore'); INSERT INTO public.operacom (codice, KEY, tipo, descrizio) VALUES (3, 'reminder', 'T', 'Reminder di un''azione in carico'); ALTER TABLE ONLY public.operacom ADD CONSTRAINT ix_operacom_codice PRIMARY KEY (codice); ALTER TABLE ONLY public.operacom ADD CONSTRAINT ix_operacom_key UNIQUE (KEY); CREATE TABLE public.operalang ( codice CHARACTER VARYING(51) NOT NULL, descrizio CHARACTER VARYING(256) ); ALTER TABLE public.operalang OWNER TO postgres; COMMENT ON TABLE public.operalang IS 'Definizione delle lingue supportate dal sistema di comunicazione con utenti (operacom)'; INSERT INTO public.operalang (codice, descrizio) VALUES ('en', 'English'); INSERT INTO public.operalang (codice, descrizio) VALUES ('cs', 'Slovacco'); INSERT INTO public.operalang (codice, descrizio) VALUES ('cz', 'Slovacco'); INSERT INTO public.operalang (codice, descrizio) VALUES ('de', 'Tedesco'); INSERT INTO public.operalang (codice, descrizio) VALUES ('es', 'Spagnolo'); INSERT INTO public.operalang (codice, descrizio) VALUES ('fr', 'Francese'); INSERT INTO public.operalang (codice, descrizio) VALUES ('it', 'Italia'); INSERT INTO public.operalang (codice, descrizio) VALUES ('pl', 'Portogallo'); INSERT INTO public.operalang (codice, descrizio) VALUES ('ro', 'Romania'); INSERT INTO public.operalang (codice, descrizio) VALUES ('ru', 'Russia'); INSERT INTO public.operalang (codice, descrizio) VALUES ('tr', 'Turchia'); INSERT INTO public.operalang (codice, descrizio) VALUES ('zh-cn', 'Cina'); ALTER TABLE ONLY public.operalang ADD CONSTRAINT ix_operalang_codice PRIMARY KEY (codice); CREATE TABLE public.operamsg ( codcom INTEGER NOT NULL, codlang CHARACTER VARYING(51) NOT NULL, subject CHARACTER VARYING(512), msg text, attachments text ); ALTER TABLE public.operamsg OWNER TO postgres; COMMENT ON TABLE public.operamsg IS 'La tabella contiene la lista dei messaggi definiti nella comunicazione con utenti (operacom) e associati alla relativa lingua. Il tipo di messaggio e'' specificato in operacom.tipo (T=text, M=markdown)'; COMMENT ON COLUMN public.operamsg.codcom IS 'Codice comunicazione (operacom)'; COMMENT ON COLUMN public.operamsg.codlang IS 'Codice lingua (operalang)'; COMMENT ON COLUMN public.operamsg.subject IS 'Oggetto del messaggio (per messaggi di posta elettronica)'; COMMENT ON COLUMN public.operamsg.msg IS 'Messaggio nel formato previsto (testo o markdown)'; COMMENT ON COLUMN public.operamsg.attachments IS 'Percorso dei file da allegare divisi da virgola (in caso di posta elettronica)'; INSERT INTO public.operamsg VALUES (1, 'en', 'New Safety Action', '<div>Hello <b>$nominati</b>, <br /> a new Safety Action (id: $codice) has been assign to you! <br /> You can view it by accessing this link:<br /> <a href="https://dsfm.franke.world/isw/webapp/franke/digcic/main/index?msal=1&mslogin=1#navigateto/codprj:$codprj">https://dsfm.franke.world/isw/webapp/franke/digcic/main/index?msal=1&mslogin=1#navigateto/codprj:$codprj</a> <br /><br /> <u>Please don''t reply to this email!</u> <br /> Best Regards </div>', NULL); INSERT INTO public.operamsg VALUES (2, 'en', 'Unassign Safety Action', '<div>Hello <b>$nominati</b>, <br /> you are no longer in charge of the Safety Action (ID: $codice). It has been reassigned. <br /><br /> <u>Please don''t reply to this email!</u> <br /> Best Regards </div>', NULL); INSERT INTO public.operamsg VALUES (3, 'en', 'Reminder Safety Action', '<div>Hello <b>$nominati</b>, <br /> the safety action (id:$codice) is still open. Please, check it again!<br /> <a href="https://dsfm.franke.world/isw/webapp/franke/digcic/main/index?msal=1&mslogin=1#navigateto/codprj:$codprj">https://dsfm.franke.world/isw/webapp/franke/digcic/main/index?msal=1&mslogin=1#navigateto/codprj:$codprj</a> <br /><br /> <u>Please don''t reply to this email!</u> <br /> Best Regards </div>', NULL); INSERT INTO public.operamsg VALUES (1, 'cs', 'Nová bezpečnostní akce', '<div>Ahoj <b>$nominati</b>,<br />byla ti přidělena nová bezpečnostní akce (ID: $codice)!<br />Můžeš ji zobrazit kliknutím na tento odkaz:<br /><a href="https://dsfm.franke.world/isw/webapp/franke/digcic/main/index?msal=1&mslogin=1#navigateto/codprj:$codprj">Otevřít bezpečnostní akci</a><br /><br /><u>Na tento e-mail neodpovídej!</u><br />S pozdravem</div>', NULL); INSERT INTO public.operamsg VALUES (1, 'de', 'Neue Sicherheitsmaßnahme', '<div>Hallo <b>$nominati</b>,<br />dir wurde eine neue Sicherheitsmaßnahme (ID: $codice) zugewiesen!<br />Du kannst sie über diesen Link einsehen:<br /><a href="https://dsfm.franke.world/isw/webapp/franke/digcic/main/index?msal=1&mslogin=1#navigateto/codprj:$codprj">Sicherheitsmaßnahme anzeigen</a><br /><br /><u>Bitte antworte nicht auf diese E-Mail!</u><br />Mit freundlichen Grüßen</div>', NULL); INSERT INTO public.operamsg VALUES (1, 'es', 'Nueva Acción de Seguridad', '<div>Hola <b>$nominati</b>,<br />se te ha asignado una nueva Acción de Seguridad (ID: $codice)!<br />Puedes verla accediendo a este enlace:<br /><a href="https://dsfm.franke.world/isw/webapp/franke/digcic/main/index?msal=1&mslogin=1#navigateto/codprj:$codprj">Ver Acción de Seguridad</a><br /><br /><u>¡Por favor, no respondas a este correo electrónico!</u><br />Saludos cordiales</div>', NULL); INSERT INTO public.operamsg VALUES (1, 'fr', 'Nouvelle Action de Sécurité', '<div>Bonjour <b>$nominati</b>,<br />une nouvelle Action de Sécurité (ID: $codice) vous a été assignée!<br />Vous pouvez la consulter en accédant à ce lien:<br /><a href="https://dsfm.franke.world/isw/webapp/franke/digcic/main/index?msal=1&mslogin=1#navigateto/codprj:$codprj">Voir l''Action de Sécurité</a><br /><br /><u>Veuillez ne pas répondre à cet e-mail!</u><br />Cordialement</div>', NULL); INSERT INTO public.operamsg VALUES (1, 'it', 'Nuova Azione di Sicurezza', '<div>Ciao <b>$nominati</b>,<br />ti è stata assegnata una nuova Azione di Sicurezza (ID: $codice)!<br />Puoi visualizzarla accedendo a questo link:<br /><a href="https://dsfm.franke.world/isw/webapp/franke/digcic/main/index?msal=1&mslogin=1#navigateto/codprj:$codprj">Visualizza Azione di Sicurezza</a><br /><br /><u>Per favore, non rispondere a questa email!</u><br />Cordiali saluti</div>', NULL); INSERT INTO public.operamsg VALUES (1, 'pl', 'Nowe Działanie Bezpieczeństwa', '<div>Cześć <b>$nominati</b>,<br />przypisano Ci nowe Działanie Bezpieczeństwa (ID: $codice)!<br />Możesz je zobaczyć, klikając ten link:<br /><a href="https://dsfm.franke.world/isw/webapp/franke/digcic/main/index?msal=1&mslogin=1#navigateto/codprj:$codprj">Zobacz Działanie Bezpieczeństwa</a><br /><br /><u>Proszę, nie odpowiadaj na tego e-maila!</u><br />Pozdrawiam</div>', NULL); INSERT INTO public.operamsg VALUES (1, 'ro', 'Acțiune de Securitate Nouă', '<div>Bună <b>$nominati</b>,<br />ți-a fost atribuită o nouă Acțiune de Securitate (ID: $codice)!<br />O poți vizualiza accesând acest link:<br /><a href="https://dsfm.franke.world/isw/webapp/franke/digcic/main/index?msal=1&mslogin=1#navigateto/codprj:$codprj">Vizualizează Acțiunea de Securitate</a><br /><br /><u>Te rugăm să nu răspunzi la acest e-mail!</u><br />Cu stimă</div>', NULL); INSERT INTO public.operamsg VALUES (1, 'ru', 'Новое Мероприятие по Безопасности', '<div>Здравствуйте <b>$nominati</b>,<br />вам назначено новое Мероприятие по Безопасности (ID: $codice)!<br />Вы можете просмотреть его по этой ссылке:<br /><a href="https://dsfm.franke.world/isw/webapp/franke/digcic/main/index?msal=1&mslogin=1#navigateto/codprj:$codprj">Просмотреть Мероприятие по Безопасности</a><br /><br /><u>Пожалуйста, не отвечайте на это письмо!</u><br />С уважением</div>', NULL); INSERT INTO public.operamsg VALUES (1, 'tr', 'Yeni Güvenlik Eylemi', '<div>Merhaba <b>$nominati</b>,<br />size yeni bir Güvenlik Eylemi (ID: $codice) atandı!<br />Bu bağlantıya tıklayarak görüntüleyebilirsiniz:<br /><a href="https://dsfm.franke.world/isw/webapp/franke/digcic/main/index?msal=1&mslogin=1#navigateto/codprj:$codprj">Güvenlik Eylemini Görüntüle</a><br /><br /><u>Lütfen bu e-postaya cevap vermeyin!</u><br />Saygılarımızla</div>', NULL); INSERT INTO public.operamsg VALUES (1, 'zh-cn', '新的安全行动', '<div>你好 <b>$nominati</b>,<br />你被分配了一个新的安全行动(ID: $codice)!<br />你可以通过以下链接查看:<br /><a href="https://dsfm.franke.world/isw/webapp/franke/digcic/main/index?msal=1&mslogin=1#navigateto/codprj:$codprj">查看安全行动</a><br /><br /><u>请不要回复此电子邮件!</u><br />此致敬礼</div>', NULL); INSERT INTO public.operamsg VALUES (2, 'cs', 'Odebrání bezpečnostní akce', '<div>Ahoj <b>$nominati</b>,<br />již nejsi odpovědný za bezpečnostní akci (ID: $codice). Byla přidělena někomu jinému.<br /><br /><u>Na tento e-mail neodpovídej!</u><br />S pozdravem</div>', NULL); INSERT INTO public.operamsg VALUES (2, 'de', 'Sicherheitsmaßnahme Entzogen', '<div>Hallo <b>$nominati</b>,<br />du bist nicht mehr für die Sicherheitsmaßnahme (ID: $codice) verantwortlich. Sie wurde neu zugewiesen.<br /><br /><u>Bitte antworte nicht auf diese E-Mail!</u><br />Mit freundlichen Grüßen</div>', NULL); INSERT INTO public.operamsg VALUES (2, 'es', 'Acción de Seguridad Desasignada', '<div>Hola <b>$nominati</b>,<br />ya no estás a cargo de la Acción de Seguridad (ID: $codice). Ha sido reasignada.<br /><br /><u>¡Por favor, no respondas a este correo electrónico!</u><br />Saludos cordiales</div>', NULL); INSERT INTO public.operamsg VALUES (2, 'fr', 'Action de Sécurité Révoquée', '<div>Bonjour <b>$nominati</b>,<br />vous n''êtes plus en charge de l''Action de Sécurité (ID: $codice). Elle a été réassignée.<br /><br /><u>Veuillez ne pas répondre à cet e-mail!</u><br />Cordialement</div>', NULL); INSERT INTO public.operamsg VALUES (2, 'it', 'Azione di Sicurezza Revocata', '<div>Ciao <b>$nominati</b>,<br />non sei più responsabile dell''Azione di Sicurezza (ID: $codice). È stata riassegnata.<br /><br /><u>Per favore, non rispondere a questa email!</u><br />Cordiali saluti</div>', NULL); INSERT INTO public.operamsg VALUES (2, 'pl', 'Usunięcie Działania Bezpieczeństwa', '<div>Cześć <b>$nominati</b>,<br />nie jesteś już odpowiedzialny za Działanie Bezpieczeństwa (ID: $codice). Zostało ono przypisane komuś innemu.<br /><br /><u>Proszę, nie odpowiadaj na tego e-maila!</u><br />Pozdrawiam</div>', NULL); INSERT INTO public.operamsg VALUES (2, 'ro', 'Revocare Acțiune de Securitate', '<div>Bună <b>$nominati</b>,<br />nu mai ești responsabil pentru Acțiunea de Securitate (ID: $codice). A fost reasignată.<br /><br /><u>Te rugăm să nu răspunzi la acest e-mail!</u><br />Cu stimă</div>', NULL); INSERT INTO public.operamsg VALUES (2, 'ru', 'Отмена Назначения Меры Безопасности', '<div>Здравствуйте <b>$nominati</b>,<br />вы больше не отвечаете за Меру Безопасности (ID: $codice). Она была переназначена.<br /><br /><u>Пожалуйста, не отвечайте на это письмо!</u><br />С уважением</div>', NULL); INSERT INTO public.operamsg VALUES (2, 'tr', 'Güvenlik Eylemi Ataması Kaldırıldı', '<div>Merhaba <b>$nominati</b>,<br />Güvenlik Eylemi (ID: $codice) artık sizin sorumluluğunuzda değil. Başka birine atandı.<br /><br /><u>Lütfen bu e-postaya cevap vermeyin!</u><br />Saygılarımızla</div>', NULL); INSERT INTO public.operamsg VALUES (2, 'zh-cn', '安全行动取消分配', '<div>你好 <b>$nominati</b>,<br />你不再负责安全行动(ID: $codice)。它已被重新分配。<br /><br /><u>请不要回复此电子邮件!</u><br />此致敬礼</div>', NULL); INSERT INTO public.operamsg VALUES (3, 'cs', 'Připomenutí bezpečnostní akce', '<div>Ahoj <b>$nominati</b>,<br />bezpečnostní akce (ID: $codice) je stále otevřená. Zkontroluj ji prosím znovu!<br /><a href="https://dsfm.franke.world/isw/webapp/franke/digcic/main/index?msal=1&mslogin=1#navigateto/codprj:$codprj">Otevřít odkaz</a><br /><br /><u>Na tento e-mail neodpovídej!</u><br />S pozdravem</div>', NULL); INSERT INTO public.operamsg VALUES (3, 'de', 'Erinnerung Sicherheitsmaßnahme', '<div>Hallo <b>$nominati</b>,<br />die Sicherheitsmaßnahme (ID: $codice) ist noch offen. Bitte überprüfe sie erneut!<br /><a href="https://dsfm.franke.world/isw/webapp/franke/digcic/main/index?msal=1&mslogin=1#navigateto/codprj:$codprj">Link öffnen</a><br /><br /><u>Bitte antworte nicht auf diese E-Mail!</u><br />Mit freundlichen Grüßen</div>', NULL); INSERT INTO public.operamsg VALUES (3, 'es', 'Recordatorio Acción de Seguridad', '<div>Hola <b>$nominati</b>,<br />la acción de seguridad (ID: $codice) sigue abierta. ¡Por favor, revísala de nuevo!<br /><a href="https://dsfm.franke.world/isw/webapp/franke/digcic/main/index?msal=1&mslogin=1#navigateto/codprj:$codprj">Abrir enlace</a><br /><br /><u>¡Por favor, no respondas a este correo electrónico!</u><br />Saludos</div>', NULL); INSERT INTO public.operamsg VALUES (3, 'fr', 'Rappel Action de Sécurité', '<div>Bonjour <b>$nominati</b>,<br />l''action de sécurité (ID: $codice) est toujours ouverte. Merci de la vérifier à nouveau !<br /><a href="https://dsfm.franke.world/isw/webapp/franke/digcic/main/index?msal=1&mslogin=1#navigateto/codprj:$codprj">Ouvrir le lien</a><br /><br /><u>Veuillez ne pas répondre à cet e-mail !</u><br />Cordialement</div>', NULL); INSERT INTO public.operamsg VALUES (3, 'it', 'Promemoria Azione di Sicurezza', '<div>Ciao <b>$nominati</b>,<br />l''azione di sicurezza (ID: $codice) è ancora aperta. Per favore, ricontrollala!<br /><a href="https://dsfm.franke.world/isw/webapp/franke/digcic/main/index?msal=1&mslogin=1#navigateto/codprj:$codprj">Apri il link</a><br /><br /><u>Per favore, non rispondere a questa email!</u><br />Cordiali saluti</div>', NULL); INSERT INTO public.operamsg VALUES (3, 'pl', 'Przypomnienie o Działaniu Bezpieczeństwa', '<div>Cześć <b>$nominati</b>,<br />działanie bezpieczeństwa (ID: $codice) jest nadal otwarte. Proszę, sprawdź je ponownie!<br /><a href="https://dsfm.franke.world/isw/webapp/franke/digcic/main/index?msal=1&mslogin=1#navigateto/codprj:$codprj">Otwórz link</a><br /><br /><u>Proszę, nie odpowiadaj na tego maila!</u><br />Pozdrawiam</div>', NULL); INSERT INTO public.operamsg VALUES (3, 'ro', 'Memento Acțiune de Securitate', '<div>Bună <b>$nominati</b>,<br />acțiunea de securitate (ID: $codice) este încă deschisă. Te rugăm să o verifici din nou!<br /><a href="https://dsfm.franke.world/isw/webapp/franke/digcic/main/index?msal=1&mslogin=1#navigateto/codprj:$codprj">Deschide linkul</a><br /><br /><u>Te rugăm să nu răspunzi la acest e-mail!</u><br />Cu stimă</div>', NULL); INSERT INTO public.operamsg VALUES (3, 'ru', 'Напоминание о Мере Безопасности', '<div>Здравствуйте <b>$nominati</b>,<br />мера безопасности (ID: $codice) всё ещё открыта. Пожалуйста, проверьте её снова!<br /><a href="https://dsfm.franke.world/isw/webapp/franke/digcic/main/index?msal=1&mslogin=1#navigateto/codprj:$codprj">Открыть ссылку</a><br /><br /><u>Пожалуйста, не отвечайте на это письмо!</u><br />С уважением</div>', NULL); INSERT INTO public.operamsg VALUES (3, 'tr', 'Güvenlik Eylemi Hatırlatması', '<div>Merhaba <b>$nominati</b>,<br />güvenlik eylemi (ID: $codice) hâlâ açık. Lütfen tekrar kontrol et!<br /><a href="https://dsfm.franke.world/isw/webapp/franke/digcic/main/index?msal=1&mslogin=1#navigateto/codprj:$codprj">Bağlantıyı aç</a><br /><br /><u>Lütfen bu e-postaya cevap vermeyin!</u><br />Saygılarımızla</div>', NULL); INSERT INTO public.operamsg VALUES (3, 'zh-cn', '安全行动提醒', '<div>你好 <b>$nominati</b>,<br />安全行动(ID: $codice)仍然未完成。请再次检查!<br /><a href="https://dsfm.franke.world/isw/webapp/franke/digcic/main/index?msal=1&mslogin=1#navigateto/codprj:$codprj">打开链接</a><br /><br /><u>请不要回复此电子邮件!</u><br />此致敬礼</div>', NULL); ALTER TABLE ONLY public.operamsg ADD CONSTRAINT ix_operamsg_key PRIMARY KEY (codcom, codlang); ALTER TABLE ONLY public.operamsg ADD CONSTRAINT ix_operamsg_codcom FOREIGN KEY (codcom) REFERENCES public.operacom(codice) ON UPDATE CASCADE ON DELETE CASCADE; ALTER TABLE ONLY public.operamsg ADD CONSTRAINT ix_operamsg_codlang FOREIGN KEY (codlang) REFERENCES public.operalang(codice) ON UPDATE CASCADE ON DELETE RESTRICT;
Parametri XML
<agent lib="/usr/lib/libiadata.so.0.0.0" CREATE="agentData" live="1" name="prepdig"> <param name="agdb" VALUE="tpevodb" /> <param name="path" VALUE="/code/cpp/sql/digcic" /> </agent> <agent lib="/usr/lib/libcomhand.so.0.0.0" CREATE="agentOperaCom" live="1" name="operacom"> <param name="agdb" VALUE="tpevodb"/> <param name="agch" VALUE="smtp"/> <param name="prefix" VALUE="$" /> <param name="suffix" VALUE="$" /> </agent> <agent lib="/usr/lib/libcomhand.so.0.0.0" CREATE="agentSmtp" live="1" name="smtp"> <param name="server" VALUE="smtp://smtp-eu.franke.world:587"/> <param name="usr" VALUE="Franke-DSFM.CH@franke.com"/> <param name="pw" VALUE="gWvx?GRaqsEutjDaxGcC"/> <param name="insecure" VALUE="1"/> <!-- <param name="cacert" value="/nextdata/code/cfg/certs/franke/dsfm/dsfm.franke.world.ca-bundle"/> --> <param name="sendmail" VALUE="Franke-DSFM.CH@franke.com"/> <param name="sendname" VALUE="DSFM"/> <param name="timeoutconn" VALUE="10"/> <param name="timeoutsend" VALUE="60"/> </agent> <agent lib="/usr/lib/libdigcic.so.0.0.0" CREATE="agentActionNotify" live="1" name="actmail"> <param name="agdb" VALUE="tpevodb" /> <param name="agcom" VALUE="operacom" /> <param name="keynew" VALUE="assign" /> <param name="keydel" VALUE="unassign" /> <param name="keyrem" VALUE="reminder" /> <!-- Ogni tipologia ha un suo messaggio configurato che si identifica con "$TIPO"|"$TIPO_chiamata" ($TIPO_chiamata è la chiave di operacom.key) --> <param name="confkeynew" VALUE="S|S_assign,Q|Q_assign" /> <param name="confkeydel" VALUE="S|S_unassign" /> <param name="confkeyrem" VALUE="S|S_reminder" /> <param name="tm" VALUE="300000" /> <param name="agps" VALUE="prepdig" /> </agent>
Richiesta invio email all'owner dell'oggetto
Ci è stato richiesto di poter ricevere un'email anche da parte dell'owner di un oggetto. Per fare questo è necessario apporre le seguenti modifiche alla tabella emailsetting, per gestire gli utenti che devono ricevere l'email, che ora possono essere due (owner e responsabile):
ALTER TABLE emailsetting ADD COLUMN codoperfield VARCHAR(51); ALTER TABLE emailsetting ADD COLUMN msgkey VARCHAR(4); UPDATE emailsetting SET codoperfield = 'codoperres', msgkey = TYPE; ALTER TABLE emailsetting DROP CONSTRAINT ix_emailsetting_pk; -- alter table emailsetting add constraint ix_emailsetting_pk PRIMARY KEY (codubi,type,codoperfield); ALTER TABLE emailsetting ADD CONSTRAINT ix_emailsetting_pk PRIMARY KEY (codubi,msgkey);
Aggiunta una tabella per gestire le richieste ed i messaggi. Sono state tolte le chiavi dei messaggi dall'xml e sono state gestite nella tabella actionkeys
CREATE TABLE public.actionkeys ( TYPE CHARACTER VARYING(4) NOT NULL, operation CHARACTER VARYING(250) NOT NULL, comkey CHARACTER VARYING(51) ); ALTER TABLE public.actionkeys OWNER TO postgres; COMMENT ON TABLE public.actionkeys IS 'Tabella per la gestione delle azioni di mail'; COMMENT ON COLUMN public.actionkeys.type IS 'Tipologia di action'; COMMENT ON COLUMN public.actionkeys.operation IS 'Operazione della mail (unassign, assign, reminder)'; COMMENT ON COLUMN public.actionkeys.comkey IS 'Campo operacom.key per selezione del messaggio da inviare'; INSERT INTO public.actionkeys VALUES ('Q', 'assign', 'Q_assign'); INSERT INTO public.actionkeys VALUES ('V', 'assign', 'V_assign'); INSERT INTO public.actionkeys VALUES ('H', 'assign', 'H_assign'); INSERT INTO public.actionkeys VALUES ('M', 'assign', 'M_assign'); INSERT INTO public.actionkeys VALUES ('S', 'assign', 'S_assign'); INSERT INTO public.actionkeys VALUES ('W', 'assign', 'W_assign'); INSERT INTO public.actionkeys VALUES ('O', 'assign', 'O_assign'); INSERT INTO public.actionkeys VALUES ('I', 'assign', 'I_assign'); INSERT INTO public.actionkeys VALUES ('Z', 'assign', 'Z_assign'); INSERT INTO public.actionkeys VALUES ('J', 'assign', 'J_assign'); INSERT INTO public.actionkeys VALUES ('Q', 'unassign', 'Q_unassign'); INSERT INTO public.actionkeys VALUES ('V', 'unassign', 'V_unassign'); INSERT INTO public.actionkeys VALUES ('H', 'unassign', 'H_unassign'); INSERT INTO public.actionkeys VALUES ('M', 'unassign', 'M_unassign'); INSERT INTO public.actionkeys VALUES ('S', 'unassign', 'S_unassign'); INSERT INTO public.actionkeys VALUES ('W', 'unassign', 'W_unassign'); INSERT INTO public.actionkeys VALUES ('O', 'unassign', 'O_unassign'); INSERT INTO public.actionkeys VALUES ('I', 'unassign', 'I_unassign'); INSERT INTO public.actionkeys VALUES ('Z', 'unassign', 'Z_unassign'); INSERT INTO public.actionkeys VALUES ('J', 'unassign', 'J_unassign'); INSERT INTO public.actionkeys VALUES ('Q', 'reminder', 'Q_reminder'); INSERT INTO public.actionkeys VALUES ('V', 'reminder', 'V_reminder'); INSERT INTO public.actionkeys VALUES ('H', 'reminder', 'H_reminder'); INSERT INTO public.actionkeys VALUES ('M', 'reminder', 'M_reminder'); INSERT INTO public.actionkeys VALUES ('S', 'reminder', 'S_reminder'); INSERT INTO public.actionkeys VALUES ('W', 'reminder', 'W_reminder'); INSERT INTO public.actionkeys VALUES ('O', 'reminder', 'O_reminder'); INSERT INTO public.actionkeys VALUES ('I', 'reminder', 'I_reminder'); INSERT INTO public.actionkeys VALUES ('Z', 'reminder', 'Z_reminder'); INSERT INTO public.actionkeys VALUES ('J', 'reminder', 'J_reminder'); INSERT INTO public.actionkeys VALUES ('JO', 'assign', 'JO_assign'); INSERT INTO public.actionkeys VALUES ('JO', 'reminder', 'JO_reminder'); INSERT INTO public.actionkeys VALUES ('JO', 'unassign', 'JO_unassign'); INSERT INTO public.actionkeys VALUES ('SO', 'assign', 'SO_assign'); INSERT INTO public.actionkeys VALUES ('SO', 'reminder', 'SO_reminder'); INSERT INTO public.actionkeys VALUES ('SO', 'unassign', 'SO_unassign'); INSERT INTO public.actionkeys VALUES ('ZB', 'assign', 'ZB_assign'); INSERT INTO public.actionkeys VALUES ('ZB', 'reminder', 'ZB_reminder'); INSERT INTO public.actionkeys VALUES ('ZB', 'unassign', 'ZB_unassign'); ALTER TABLE ONLY public.actionkeys ADD CONSTRAINT actionkeys_pkey PRIMARY KEY (TYPE, operation);


































