CREATE GENERATOR GTBPROGRAMACAO_REGISTRO_OP;

CREATE TABLE TBPROGRAMACAO_REGISTRO_OP (
    ID                INTEGER NOT NULL,
    PROGRAMACAO_ID    INTEGER NOT NULL,
    DATAHORA          TIMESTAMP DEFAULT 'NOW',
    STATUS            CHAR(1) DEFAULT '0',
    OPERADOR_ID       INTEGER DEFAULT 0,
    JUSTIFICATIVA_ID  INTEGER DEFAULT 0,
    REQUISICAO_ID     INTEGER DEFAULT 0,
    ESTACAO_ID        INTEGER DEFAULT 0
);

CREATE OR ALTER trigger ttbprogramacao_registro_op_bi0 for tbprogramacao_registro_op
active before insert position 0
as
begin
  if (new.id is null) then
      new.id = gen_id(Gtbprogramacao_registro_op,1);
end;

CREATE INDEX ITBPROGRAMACAO_REGISTRO_OP_01 ON TBPROGRAMACAO_REGISTRO_OP (PROGRAMACAO_ID);
CREATE INDEX ITBPROGRAMACAO_REGISTRO_OP_02 ON TBPROGRAMACAO_REGISTRO_OP (STATUS);
CREATE INDEX ITBPROGRAMACAO_REGISTRO_OP_03 ON TBPROGRAMACAO_REGISTRO_OP (DATAHORA);
CREATE INDEX ITBPROGRAMACAO_REGISTRO_OP_04 ON TBPROGRAMACAO_REGISTRO_OP (OPERADOR_ID);
CREATE INDEX ITBPROGRAMACAO_REGISTRO_OP_05 ON TBPROGRAMACAO_REGISTRO_OP (REQUISICAO_ID);
CREATE INDEX ITBPROGRAMACAO_REGISTRO_OP_06 ON TBPROGRAMACAO_REGISTRO_OP (DATAHORA);
CREATE INDEX ITBPROGRAMACAO_REGISTRO_OP_07 ON TBPROGRAMACAO_REGISTRO_OP (JUSTIFICATIVA_ID);
CREATE INDEX ITBPROGRAMACAO_REGISTRO_OP_08 ON TBPROGRAMACAO_REGISTRO_OP (ESTACAO_ID);
CREATE DESCENDING INDEX ITBPROGRAMACAO_REGISTRO_OP_09 ON TBPROGRAMACAO_REGISTRO_OP (STATUS);
CREATE INDEX ITBPROGRAMACAO_REGISTRO_OP_10 ON TBPROGRAMACAO_REGISTRO_OP (PROGRAMACAO_ID, STATUS);
CREATE DESCENDING INDEX ITBPROGRAMACAO_REGISTRO_OP_11 ON TBPROGRAMACAO_REGISTRO_OP (PROGRAMACAO_ID, STATUS);
CREATE DESCENDING INDEX ITBPROGRAMACAO_REGISTRO_OP_12 ON TBPROGRAMACAO_REGISTRO_OP (PROGRAMACAO_ID, DATAHORA);
CREATE DESCENDING INDEX ITBPROGRAMACAO_REGISTRO_OP_13 ON TBPROGRAMACAO_REGISTRO_OP (DATAHORA);

CREATE OR ALTER procedure spc_processar_tempo_op (
    i_programacao_id integer)
returns (
    o_tempo_fracao_minuto numeric(18,4),
    obs varchar(200))
as
declare variable historico_id integer;
declare variable historico_datahora timestamp;
declare variable historico_status char(1);
declare variable status_anterior char(1);
declare variable datahora_anterior timestamp;
declare variable programacao_id integer;
declare variable tempo_fracao_dia numeric(18,4);
declare variable justificativa_id integer;
begin
        :PROGRAMACAO_ID = I_PROGRAMACAO_ID;
        /* INICIALIZA O CONTADOR DE TEMPO TOTAL */
        TEMPO_FRACAO_DIA = 0;
    
        /* INICIO DO LACO QUE CONSULTA OS HISTORICOS DA PROGRAMACAO */
        FOR
            SELECT
                R.ID,
                R.DATAHORA,
                R.STATUS,
                r.justificativa_id
             FROM TBPROGRAMACAO_REGISTRO_OP R
            WHERE R.PROGRAMACAO_ID = :PROGRAMACAO_ID
            ORDER BY DATAHORA
        INTO
            :HISTORICO_ID,
            :HISTORICO_DATAHORA, 
            :HISTORICO_STATUS,
            :JUSTIFICATIVA_ID
        DO
        BEGIN
            
            /* VERIFICA SE EH TEMPO PRODUTIVO */
            /* 0 - INICIADO/REINICIADO; 1 - PARADO; 2 - FINALIZADO */
            IF ( (STATUS_ANTERIOR = '0' AND HISTORICO_STATUS = '1') OR (STATUS_ANTERIOR = '0' AND HISTORICO_STATUS = '2') ) THEN
            BEGIN
                /* CALCULA O TEMPO PRODUTIVO E CONVERTE PARA FRACAO DE MINUTO */
                TEMPO_FRACAO_DIA      = (TEMPO_FRACAO_DIA + HISTORICO_DATAHORA - DATAHORA_ANTERIOR);
                O_TEMPO_FRACAO_MINUTO = TEMPO_FRACAO_DIA*24*60;
            END
    
            /* GUARDA A DATAHORA E O STATUS ATUAL, PARA SER UTILIZADO NO PROXIMO REGISTRO */
            DATAHORA_ANTERIOR = :HISTORICO_DATAHORA;
            STATUS_ANTERIOR   = :HISTORICO_STATUS;

            if(JUSTIFICATIVA_ID > 0)then
            begin
               OBS = coalesce((select first 1 j.descricao from tbjustificativa j where j.id = :JUSTIFICATIVA_ID),'');
            end else
            begin
               OBS = '';
            end

        END

        SUSPEND;

end;

ALTER TABLE TBPROGRAMACAO
    ADD TEMPO_OPERACIONAL_REAL NUMERIC(15,4);

COMMENT ON COLUMN TBPROGRAMACAO.OLD_TEMPO_REALIZADO IS
'tempo realizado do talao, em taloes agrupados é o tempo realizado completo';

COMMENT ON COLUMN TBPROGRAMACAO.TEMPO_OPERACIONAL_REAL IS
'tempo operacional realizado';

CREATE OR ALTER trigger ttbprogramacao_registro_a0i for tbprogramacao_registro
inactive after insert position 5
AS
DECLARE VARIABLE FERRAMENTA_ID INTEGER;
begin

    IF ( NEW.STATUS IN ('1','2') ) THEN
    BEGIN

        SELECT
            FIRST 1
            COALESCE(P.FERRAMENTA_ID,0)
        FROM
            TBPROGRAMACAO P
        WHERE
            P.ID = NEW.PROGRAMACAO_ID
        INTO
            FERRAMENTA_ID;


        IF ( FERRAMENTA_ID = 0 ) THEN
        BEGIN                       
            UPDATE TBPROGRAMACAO P
               SET P.TEMPO_REALIZADO = (SELECT FIRST 1 O_TEMPO_FRACAO_MINUTO FROM SPC_PROCESSAR_TEMPO_REALIZADO(NEW.PROGRAMACAO_ID)),
               P.TEMPO_OPERACIONAL_REAL = (SELECT FIRST 1 O_TEMPO_FRACAO_MINUTO FROM spc_processar_tempo_op(NEW.PROGRAMACAO_ID))
             WHERE P.ID = NEW.PROGRAMACAO_ID;
        END

        IF ( FERRAMENTA_ID > 0 ) THEN
        BEGIN
            UPDATE TBPROGRAMACAO P
               SET P.TEMPO_REALIZADO = (SELECT FIRST 1 O_TEMPO_FRACAO_MINUTO FROM spc_programacao_tempo_realizado(NEW.PROGRAMACAO_ID,COALESCE(NEW.REQUISICAO_ID,0)))
             WHERE P.ID = NEW.PROGRAMACAO_ID
               AND COALESCE(P.REQUISICAO_ID,0) = COALESCE(NEW.REQUISICAO_ID,0);
        END
    END
end;

CREATE OR ALTER trigger ttbprogramacao_b4u for tbprogramacao
active before update position 4
AS
DECLARE VARIABLE CONTADOR BIGINT;
BEGIN

    IF ( OLD.STATUS = '2' AND NEW.STATUS IN ('3','1') ) THEN
    BEGIN
        IF ( COALESCE(NEW.FERRAMENTA_ID,0) = 0 ) THEN
        BEGIN                       
            NEW.TEMPO_REALIZADO = (SELECT FIRST 1 O_TEMPO_FRACAO_MINUTO FROM SPC_PROCESSAR_TEMPO_REALIZADO(NEW.ID));
            NEW.TEMPO_OPERACIONAL_REAL = (SELECT FIRST 1 O_TEMPO_FRACAO_MINUTO FROM spc_processar_tempo_op(NEW.ID));
        END

        IF ( COALESCE(NEW.FERRAMENTA_ID,0) > 0 ) THEN
        BEGIN
            NEW.TEMPO_REALIZADO = (SELECT FIRST 1 O_TEMPO_FRACAO_MINUTO FROM spc_programacao_tempo_realizado(NEW.ID,NEW.REQUISICAO_ID));
        END
    END

END;

CREATE OR ALTER procedure spu_tempo_programacao_vinc (
    i_programacao_id integer)
as
declare variable contador bigint;
declare variable programacao_id integer;
declare variable remessa_id integer;
declare variable remessa_talao_id integer;
declare variable id integer;
declare variable vinculo_id integer;
declare variable tempo numeric(18,8);
declare variable tempo_previsto numeric(18,8);
declare variable quantidade numeric(18,8);
declare variable tempo_realizado numeric(18,8);
declare variable qtd_total numeric(18,8);
declare variable web char(1);
declare variable linha integer;
declare variable linhas integer;
declare variable tempo_operacional_real numeric(15,4);
declare variable operacional numeric(15,4);
declare variable operacional_realizado numeric(15,4);
begin

    select first 1
        r.tempo_realizado,
        r.tempo_operacional_real
    from tbprogramacao r where r.id = :I_PROGRAMACAO_ID
    into tempo, operacional;

    tempo = coalesce(tempo,0);
    operacional = coalesce(operacional,0);

    --se talao esta vinculado a outros taloes ATUALIZA OS SITUACAO
    for
        select distinct
            quantidade,
            VINCULO_ID,
            PROGRAMACAO_ID,
            REMESSA_ID,
            REMESSA_TALAO_ID,
            ID,
            tempo_realizado,
            tempo_operacional_real,
            row_number() over() as LINHA,
            sum(1) over() LINHAS,
            sum(quantidade) over() QTD_TOTAL
        from(
            SELECT
                r.quantidade,
                v2.vinculo_id,
                r.id as PROGRAMACAO_ID,
                v2.REMESSA_ID,
                v2.TALAO_ID as REMESSA_TALAO_ID,
                t.id as ID,
                r.tempo,
                r.tempo_realizado,
                r.tempo_operacional_real
            from TBTALAO_VINCULO v1, TBTALAO_VINCULO v2, vwremessa_talao t, vwremessa_talao t2, tbprogramacao r, tbprogramacao r2
            where v1.remessa_id = t2.remessa_id
            and v1.talao_id = t2.remessa_talao_id
            and v2.vinculo_id = v1.vinculo_id
            and t.remessa_id = v2.remessa_id
            and t.remessa_talao_id = v2.talao_id
            and r.tabela_id = t.id
            and r2.id = :I_PROGRAMACAO_ID
            and t2.id = r2.tabela_id
            and r2.tipo = 'A'
            and r.tipo = 'A'
        )
    into    
        :quantidade,
        :VINCULO_ID,
        :PROGRAMACAO_ID,
        :REMESSA_ID,
        :REMESSA_TALAO_ID,
        :ID,
        :tempo_previsto,
        :tempo_operacional_real,
        :LINHA,
        :LINHAS,
        :QTD_TOTAL
    do begin

        tempo_realizado       = fn_calc_precision(tempo, fn_calc_precision(quantidade, QTD_TOTAL,'/') ,'*');
        OPERACIONAL_REALIZADO = fn_calc_precision(operacional, fn_calc_precision(quantidade, QTD_TOTAL,'/') ,'*');

        update TBPROGRAMACAO h set h.tempo_realizado = :tempo_realizado,h.tempo_operacional_real = :OPERACIONAL_REALIZADO, h.OLD_TEMPO_REALIZADO = :tempo where h.id = :PROGRAMACAO_ID;

    end

end;

CREATE OR ALTER trigger ttbprogramacao_registro_b10i for tbprogramacao_registro
active before insert position 10
AS
declare variable status_op integer;
declare variable gravar integer;
declare variable status_gravar integer;
begin

    status_op = coalesce((
        SELECT first 1
            R.STATUS
         FROM TBPROGRAMACAO_REGISTRO_OP R
        WHERE R.PROGRAMACAO_ID = new.programacao_id
        ORDER BY DATAHORA desc),-1);


    if(status_op = 0)then
    begin
        gravar = 0;

        if(new.status = 0)then
        begin
            status_gravar = 1;
            gravar = 1;
        end
    
        if(new.status = 1)then
        begin
            status_gravar = 1;
            gravar = 1;
        end
    
        if(new.status = 2)then
        begin
            status_gravar = 2;
            gravar = 1;
        end
    
        if(gravar = 1)then
        begin
            INSERT INTO TBPROGRAMACAO_REGISTRO_OP (
                PROGRAMACAO_ID,
                STATUS,
                OPERADOR_ID,
                JUSTIFICATIVA_ID
            ) VALUES (
               new.PROGRAMACAO_ID,
               :status_gravar,
               new.operador_id,
               0
            );
        end
    end

end;

