
-- Storeprocedure {plpgsql_call_handler()} Versao {002} Esquema {padrao} Descricao {FUNCAO TRATADORA DE CHAMADAS}
-- ------------------------------------------------------------

CREATE OR REPLACE FUNCTION padrao.plpgsql_call_handler() RETURNS language_handler
    AS '$libdir/plpgsql'
LANGUAGE C;

-- -------------------------------------------------------------------------
-- Tabela {auditoria} Versao {011}  Esquema {padrao} Descricao {Dados auditados versao 2}
-- ------------------------------------------------------------------------

CREATE TABLE padrao.auditoria(
  pkyaud SERIAL NOT NULL,          
  dthaud timestamp with time zone, 
  usuaud character varying(30),    
  hosaud character varying(30),    
  banaud character varying(30),    
  scmaud text[],                   
  tabaud character varying(60),    
  camaud text,                     
  npkaud character varying(60)[],  
  vpkaud character varying(60)[],  
  nukaud character varying(60)[],  
  vukaud character varying(60)[],  
  tacaud character(6),             
  maqaud character varying(40),    
  vanaud text,                     
  vnoaud text,                     
  queaud text,                     
  data_hora_sync TIMESTAMP NULL,
  CONSTRAINT auditoria_pkey PRIMARY KEY (pkyaud),
  CONSTRAINT auditoria_check_pk CHECK (array_length(npkaud, 1) = array_length(vpkaud, 1)),
  CONSTRAINT auditoria_check_uk CHECK (array_length(nukaud, 1) = array_length(vukaud, 1))
);

-- Storeprocedure {assert(BOOLEAN, CHARACTER VARYING)} Versao {011} Esquema {padrao} Descricao {fazer o assert (checagem)}
-- ------------------------------------------------------------

CREATE OR REPLACE FUNCTION padrao.assert(BOOLEAN, CHARACTER VARYING)
  RETURNS void AS
$BODY$

BEGIN
 IF NOT $1 OR $1 IS NULL THEN
   IF $2 IS NOT NULL THEN
     RAISE EXCEPTION 'Assert failure: %', $2;
   END IF;
   --RAISE NOTICE 'Assert. Message is null';
 END IF;
END;
$BODY$
 LANGUAGE 'plpgsql' VOLATILE;

-- Storeprocedure {log_to_auditoria()} Versao {025} Esquema {padrao} Descricao {log_to_auditoria}
-- ------------------------------------------------------------

CREATE OR REPLACE FUNCTION padrao.log_to_auditoria() 
	RETURNS TRIGGER AS
$BODY$

DECLARE
    _DTHAUD     timestamp;     -- data hora da acao
    _USUAUD     name;          -- usuario da acao
    _HOSAUD     inet;          -- Host onde se encontra o banco de dados 
    _BANAUD     name;          -- banco de dados onde ocorreu a acao
    _SCHAUD     VARCHAR[];     -- schema onde ocorreu a acao
    _TABAUD     name;          -- tabela onde ocorreu a acao
    _CAMAUD     text;          -- campos da tabela 
    _TACAUD     text;          -- Tipo da acao ocorrida na tabela (insert, update ou delete)
    _MAQAUD     inet;          -- ip da m�quina que fez a acao
    _VNOAUD     text;          -- valor novo do campo afetado 
    _VANAUD     text;          -- valor antigo do campo afetado
    _QUEAUD     text;          -- query executada durante a acao     

      --pega os nomes das chaves primarias e coloca dentro de um array.
     _PK_NAMES CONSTANT VARCHAR[] := ARRAY(SELECT a.attname AS pk_name FROM pg_class c, pg_attribute a,                                                                                                pg_index i
     WHERE c.oid = i.indrelid
     AND a.attrelid = i.indexrelid
     AND a.attisdropped = FALSE
     AND a.attnum > 0
     AND i.indisprimary = TRUE
     AND c.oid = TG_RELID); 

     --pega o nome dos campos da tabela e coloca dentro de um array
    _FIELD_NAMES CONSTANT VARCHAR[] := ARRAY(SELECT a.attname AS pk_name FROM pg_class c, pg_attribute a
     WHERE c.oid = a.attrelid
     AND a.attisdropped = FALSE
     AND a.attnum > 0
     AND c.oid = TG_RELID ); 

    _PK_VALUES VARCHAR[]; 
    
    --pega os nomes das chaves unicas e coloca dentro de um array.
     _UK_NAMES CONSTANT VARCHAR[] := ARRAY(SELECT a.attname AS pk_name FROM pg_class c, pg_attribute a,                                                                                                pg_index i
     WHERE c.oid = i.indrelid
     AND a.attrelid = i.indexrelid
     AND a.attisdropped = FALSE
     AND a.attnum > 0
     AND i.indisprimary = FALSE
     AND i.indisunique = TRUE
     AND c.oid = TG_RELID); 


    _UK_VALUES VARCHAR[]; 

    BEGIN  

    --utiliza a fun��o assert para checar que a trigger ser� executada apenas ap�s as a��es
    PERFORM padrao.assert(TG_WHEN = 'AFTER', 'Wrong execution of fnc_audit(): should only be executed AFTER an event!');
    --utiliza a fun��o assert para checar que a trigger ser� executada por cada linha
    PERFORM padrao.assert(TG_LEVEL = 'ROW', 'Wrong execution of fnc_audit(): should only be executed FOR EACH ROW!');
    --utiliza a fun��o assert para checar que o nome da tabela n�o est� nulo
    PERFORM padrao.assert(TG_TABLE_NAME IS NOT NULL, 'TG_TABLE_NAME IS NULL');
    --utiliza a fun��o assert para chegar se a tabela possui chaves prim�rias. N�o pode ser nulo.
    PERFORM padrao.assert(_PK_NAMES IS NOT NULL AND array_length(_PK_NAMES, 1) IS NOT NULL, 'Table ' || TG_TABLE_NAME || ' can not be logged: it has no PK!');
    --utiliza a fun��o assert para chegar se a tabela possui chaves prim�rias. N�o pode ser nulo.
    --PERFORM padrao.assert(_UK_NAMES IS NOT NULL AND array_length(_UK_NAMES, 1) IS NOT NULL, 'Table ' || TG_TABLE_NAME || ' can not be logged: it has no UNIQUE!');


    --Se por acidente a trigger for atribuida a pr�pria tabela de auditoria finaliza sem fazer nada.
    IF TG_TABLE_NAME = 'auditoria' THEN
    RETURN NULL;
    END IF; 

    _DTHAUD := current_timestamp;  --pega a data/hora atual
    _MAQAUD := inet_client_addr(); --pega o ip da m�quina que praticou a acao
    _USUAUD := current_user;       --pega o usu�rio que praticou a acao
    _HOSAUD := inet_server_addr(); --pega o ip do servidor onde est� o banco de dados
    _BANAUD := current_database(); --pega o nome do banco de dados
    ---_SCHAUD := ARRAY(SELECT schemaname AS esquema FROM pg_catalog.pg_tables WHERE tablename =   TG_TABLE_NAME AND schemaname NOT IN ('pg_catalog', 'information_schema', 'pg_toast') ORDER BY schemaname); --pega o nome do schema onde a tabela que est� sendo auditada est�
    _SCHAUD := current_schemas(false); --pega o nome do schema onde a tabela que est� sendo auditada est�
    _TABAUD := TG_TABLE_NAME; --pega o nome da tabela
    _CAMAUD := (SELECT string_agg(column_name,',') FROM information_schema.columns WHERE table_name = TG_RELNAME); --pega o nome dos campos da tabela
    _TACAUD := TG_OP; --pega a acao executada (INSERT, UPDATE ou DELETE)
    _QUEAUD := (SELECT current_query()); --pega a query executada    
 --pega os valores das chaves prim�rias
	FOR i IN 1 .. array_length(_PK_NAMES, 1)
	LOOP
	 DECLARE
	  tmp text;
	  tmp_record record;
	 BEGIN
	  CASE TG_OP
	  WHEN 'UPDATE', 'INSERT' THEN tmp_record = NEW;
	  WHEN 'DELETE' THEN tmp_record = OLD;
	  END CASE; 
	
	  EXECUTE 'SELECT $1.' || quote_ident(_PK_NAMES[i]) INTO STRICT tmp USING tmp_record;
	  _PK_VALUES[i] := tmp;
	 END;
	END LOOP;   

	--pega os valores das chaves unica
	IF _UK_NAMES IS NOT NULL AND array_length(_UK_NAMES, 1) IS NOT NULL THEN
		FOR i IN 1 .. array_length(_UK_NAMES, 1)
		LOOP
		 DECLARE
		  tmp text;
		  tmp_record record;
		 BEGIN
		  CASE TG_OP
		  WHEN 'UPDATE', 'INSERT' THEN tmp_record = NEW;
		  WHEN 'DELETE' THEN tmp_record = OLD;
		  END CASE; 
		
		  EXECUTE 'SELECT $1.' || quote_ident(_UK_NAMES[i]) INTO STRICT tmp USING tmp_record;
		  _UK_VALUES[i] := tmp;
		 END;
		END LOOP; 
	 END IF;  

 --utiliza a fun��o assert para checar se os valores das chaves prim�rias n�o s�o nulos. 
 PERFORM padrao.assert(_PK_VALUES IS NOT NULL AND array_length(_PK_VALUES, 1) IS NOT NULL, '_PK_VALUES IS NULL');

 --utiliza a fun��o assert para checar se est� correta a mesma quantidade de nomes e valores de chaves prim�rias. 
 PERFORM padrao.assert(array_length(_PK_VALUES, 1) = array_length(_PK_NAMES, 1), '_PK_VALUES
  count not equal to _PK_NAMES count in table ' || TG_TABLE_NAME); 


  --insere os dados coletados de acordo com a acao executada
    IF (TG_OP = 'INSERT') THEN 
          INSERT INTO padrao.auditoria(dthaud, usuaud, hosaud, banaud, scmaud, tabaud, camaud, npkaud, vpkaud, nukaud, vukaud,tacaud, maqaud, vanaud, vnoaud, queaud, data_hora_sync)
               VALUES (_DTHAUD, _USUAUD, _HOSAUD::text, _BANAUD::text, _SCHAUD, _TABAUD, _CAMAUD,_PK_NAMES, _PK_VALUES,_UK_NAMES, _UK_VALUES, _TACAUD, _MAQAUD, NULL, NEW, _QUEAUD, CAST('01/01/1969' AS DATE) + INTERVAL '0 DAYS');
          RETURN NEW;
     ELSIF (TG_OP = 'UPDATE') THEN
         INSERT INTO padrao.auditoria(dthaud, usuaud, hosaud, banaud, scmaud, tabaud, camaud, npkaud, vpkaud, nukaud, vukaud,tacaud, maqaud, vanaud, vnoaud, queaud, data_hora_sync)
               VALUES (_DTHAUD, _USUAUD, _HOSAUD::text, _BANAUD::text, _SCHAUD, _TABAUD, _CAMAUD, _PK_NAMES, _PK_VALUES, _UK_NAMES, _UK_VALUES, _TACAUD, _MAQAUD, OLD, NEW, _QUEAUD, CAST('01/01/1969' AS DATE) + INTERVAL '0 DAYS');
          RETURN NEW;
     ELSIF (TG_OP = 'DELETE') THEN 
          INSERT INTO padrao.auditoria(dthaud, usuaud, hosaud, banaud, scmaud, tabaud, camaud, npkaud, vpkaud, nukaud, vukaud,tacaud, maqaud, vanaud, vnoaud, queaud, data_hora_sync)
               VALUES (_DTHAUD, _USUAUD, _HOSAUD::text, _BANAUD::text, _SCHAUD, _TABAUD, _CAMAUD,_PK_NAMES, _PK_VALUES,_UK_NAMES, _UK_VALUES, _TACAUD, _MAQAUD, OLD, NULL, _QUEAUD, CAST('01/01/1969' AS DATE) + INTERVAL '0 DAYS');
          RETURN OLD;
        END IF;
        RETURN NULL; -- o resultado � ignorado uma vez que este � um gatilho AFTER
    END; 

$BODY$
LANGUAGE 'plpgsql' VOLATILE STRICT;

-- Gatilho {log_to_auditoria_cad_cadastro()} Versao {009} Esquema {empresa} Descricao {Grava integracao auditoria }
-- ------------------------------------------------------------

CREATE TRIGGER log_to_auditoria_cad_cadastro AFTER INSERT OR UPDATE OR DELETE  ON cad_cadastro
  FOR EACH ROW EXECUTE PROCEDURE padrao.log_to_auditoria();
  
-- Gatilho {log_to_auditoria_cad_cadastro_vendedor()} Versao {009} Esquema {empresa} Descricao {Grava integracao auditoria }
-- ------------------------------------------------------------

CREATE TRIGGER log_to_auditoria_cad_cadastro_vendedor AFTER INSERT OR UPDATE OR DELETE  ON cad_cadastro_vendedor
  FOR EACH ROW EXECUTE PROCEDURE padrao.log_to_auditoria();
  
-- Gatilho {log_to_auditoria_cad_cadastro_anexos()} Versao {009} Esquema {empresa} Descricao {Grava integracao auditoria }
-- ------------------------------------------------------------

CREATE TRIGGER log_to_auditoria_cad_cadastro_anexos AFTER INSERT OR UPDATE OR DELETE  ON cad_cadastro_anexos
  FOR EACH ROW EXECUTE PROCEDURE padrao.log_to_auditoria();
  
    
-- Gatilho {log_to_auditoria_fat_docto_c()} Versao {009} Esquema {empresa} Descricao {Grava integracao auditoria }
-- ------------------------------------------------------------

CREATE TRIGGER log_to_auditoria_fat_docto_c AFTER INSERT OR UPDATE OR DELETE  ON fat_docto_c
  FOR EACH ROW EXECUTE PROCEDURE padrao.log_to_auditoria();

-- Gatilho {log_to_auditoria_fat_parameters()} Versao {001} Esquema {empresa} Descricao {Grava integracao auditoria }
-- ------------------------------------------------------------

CREATE TRIGGER log_to_auditoria_fat_parameters AFTER INSERT OR UPDATE OR DELETE  ON fat_parameters
  FOR EACH ROW EXECUTE PROCEDURE padrao.log_to_auditoria();

    
-- Gatilho {log_to_auditoria_fat_docto_o()} Versao {009} Esquema {empresa} Descricao {Grava integracao auditoria }
-- ------------------------------------------------------------

CREATE TRIGGER log_to_auditoria_fat_docto_o AFTER INSERT OR UPDATE OR DELETE  ON fat_docto_o
  FOR EACH ROW EXECUTE PROCEDURE padrao.log_to_auditoria();
  
    
-- Gatilho {log_to_auditoria_fat_docto_i()} Versao {009} Esquema {empresa} Descricao {Grava integracao auditoria }
-- ------------------------------------------------------------

CREATE TRIGGER log_to_auditoria_fat_docto_i AFTER INSERT OR UPDATE OR DELETE  ON fat_docto_i
  FOR EACH ROW EXECUTE PROCEDURE padrao.log_to_auditoria();
  
    
-- Gatilho {log_to_auditoria_fat_docto_pc()} Versao {009} Esquema {empresa} Descricao {Grava integracao auditoria }
-- ------------------------------------------------------------

CREATE TRIGGER log_to_auditoria_fat_docto_pc AFTER INSERT OR UPDATE OR DELETE  ON fat_docto_pc
  FOR EACH ROW EXECUTE PROCEDURE padrao.log_to_auditoria();
  
-- Gatilho {log_to_auditoria_fat_docto_pi()} Versao {009} Esquema {empresa} Descricao {Grava integracao auditoria }
-- ------------------------------------------------------------

CREATE TRIGGER log_to_auditoria_fat_docto_pi AFTER INSERT OR UPDATE OR DELETE  ON fat_docto_pi
  FOR EACH ROW EXECUTE PROCEDURE padrao.log_to_auditoria();
  
-- Gatilho {log_to_auditoria_fat_docto_pa()} Versao {009} Esquema {empresa} Descricao {Grava integracao auditoria }
-- ------------------------------------------------------------

CREATE TRIGGER log_to_auditoria_fat_docto_pa AFTER INSERT OR UPDATE OR DELETE  ON fat_docto_pa
  FOR EACH ROW EXECUTE PROCEDURE padrao.log_to_auditoria();
  
    
-- Gatilho {log_to_auditoria_cad_atendiemnto()} Versao {009} Esquema {empresa} Descricao {Grava integracao auditoria }
-- ------------------------------------------------------------

CREATE TRIGGER log_to_auditoria_cad_atendiemnto AFTER INSERT OR UPDATE OR DELETE  ON cad_atendimento
  FOR EACH ROW EXECUTE PROCEDURE padrao.log_to_auditoria();
  
-- Gatilho {log_to_auditoria_cad_sugestao()} Versao {009} Esquema {empresa} Descricao {Grava integracao auditoria }
-- ------------------------------------------------------------

CREATE TRIGGER log_to_auditoria_cad_sugestao AFTER INSERT OR UPDATE OR DELETE  ON cad_sugestoes
  FOR EACH ROW EXECUTE PROCEDURE padrao.log_to_auditoria();
  
-- Gatilho {log_to_auditoria_fat_produto()} Versao {009} Esquema {empresa} Descricao {Grava integracao auditoria }
-- ------------------------------------------------------------

CREATE TRIGGER log_to_auditoria_fat_produto AFTER INSERT OR UPDATE OR DELETE  ON fat_produto
  FOR EACH ROW EXECUTE PROCEDURE padrao.log_to_auditoria();
  
-- Gatilho {log_to_auditoria_fat_produto_preco()} Versao {009} Esquema {empresa} Descricao {Grava integracao auditoria }
-- ------------------------------------------------------------

CREATE TRIGGER log_to_auditoria_fat_produto_preco AFTER INSERT OR UPDATE OR DELETE  ON fat_produto_preco
  FOR EACH ROW EXECUTE PROCEDURE padrao.log_to_auditoria();
  
-- Gatilho {log_to_auditoria_financ_cc()} Versao {009} Esquema {empresa} Descricao {Grava integracao auditoria }
-- ------------------------------------------------------------

CREATE TRIGGER log_to_auditoria_financ_cc AFTER INSERT OR UPDATE OR DELETE  ON financ_cc
  FOR EACH ROW EXECUTE PROCEDURE padrao.log_to_auditoria();
  
-- Gatilho {log_to_auditoria_financ_cc_movto()} Versao {009} Esquema {empresa} Descricao {Grava integracao auditoria }
-- ------------------------------------------------------------

CREATE TRIGGER log_to_auditoria_financ_cc_movto AFTER INSERT OR UPDATE OR DELETE  ON financ_cc_movto
  FOR EACH ROW EXECUTE PROCEDURE padrao.log_to_auditoria();
  
-- Gatilho {log_to_auditoria_financ_cc_movcl()} Versao {009} Esquema {empresa} Descricao {Grava integracao auditoria }
-- ------------------------------------------------------------

CREATE TRIGGER log_to_auditoria_financ_cc_movcl AFTER INSERT OR UPDATE OR DELETE  ON financ_cc_movcl
  FOR EACH ROW EXECUTE PROCEDURE padrao.log_to_auditoria();
  
-- Gatilho {log_to_auditoria_financ_cc_movto_transf()} Versao {009} Esquema {empresa} Descricao {Grava integracao auditoria }
-- ------------------------------------------------------------

CREATE TRIGGER log_to_auditoria_financ_cc_movto_transf AFTER INSERT OR UPDATE OR DELETE  ON financ_cc_movto_transf
  FOR EACH ROW EXECUTE PROCEDURE padrao.log_to_auditoria();
  
-- Gatilho {log_to_auditoria_financ_rp()} Versao {009} Esquema {empresa} Descricao {Grava integracao auditoria }
-- ------------------------------------------------------------

CREATE TRIGGER log_to_auditoria_financ_rp AFTER INSERT OR UPDATE OR DELETE  ON financ_rp
  FOR EACH ROW EXECUTE PROCEDURE padrao.log_to_auditoria();
  
-- Gatilho {log_to_auditoria_financ_rp_baixas()} Versao {009} Esquema {empresa} Descricao {Grava integracao auditoria }
-- ------------------------------------------------------------

CREATE TRIGGER log_to_auditoria_financ_rp_baixas AFTER INSERT OR UPDATE OR DELETE  ON financ_rp_baixas
  FOR EACH ROW EXECUTE PROCEDURE padrao.log_to_auditoria();
  
-- Gatilho {log_to_auditoria_financ_rp_chpd()} Versao {009} Esquema {empresa} Descricao {Grava integracao auditoria }
-- ------------------------------------------------------------

CREATE TRIGGER log_to_auditoria_financ_rp_chpd AFTER INSERT OR UPDATE OR DELETE  ON financ_rp_chpd
  FOR EACH ROW EXECUTE PROCEDURE padrao.log_to_auditoria();
  
-- Gatilho {log_to_auditoria_financ_rp_cl()} Versao {009} Esquema {empresa} Descricao {Grava integracao auditoria }
-- ------------------------------------------------------------

CREATE TRIGGER log_to_auditoria_financ_rp_cl AFTER INSERT OR UPDATE OR DELETE  ON financ_rp_cl
  FOR EACH ROW EXECUTE PROCEDURE padrao.log_to_auditoria();
  
-- Gatilho {log_to_auditoria_financ_rp_lctobaixa()} Versao {009} Esquema {empresa} Descricao {Grava integracao auditoria }
-- ------------------------------------------------------------

CREATE TRIGGER log_to_auditoria_financ_rp_lctobaixa AFTER INSERT OR UPDATE OR DELETE  ON financ_rp_lctobaixa
  FOR EACH ROW EXECUTE PROCEDURE padrao.log_to_auditoria();
  
-- Gatilho {log_to_auditoria_cad_veiculo()} Versao {009} Esquema {empresa} Descricao {Grava integracao auditoria }
-- ------------------------------------------------------------

CREATE TRIGGER log_to_auditoria_cad_veiculo AFTER INSERT OR UPDATE OR DELETE  ON cad_veiculo
  FOR EACH ROW EXECUTE PROCEDURE padrao.log_to_auditoria();
  
    