CREATE INDEX ITBPROGRAMACAO_30
ON TBPROGRAMACAO COMPUTED BY (
	iif(TIPO = 'A' and STATUS IN ('0','1'),1,
	iif(TIPO = 'A' and STATUS IN ('2','3'),2,
	iif(TIPO = 'A' and STATUS = '2',3,
	iif(TIPO = 'A' and STATUS < 2,4,0))))
);

ALTER TABLE TBPROGRAMACAO
    ADD SITUACAO COMPUTED BY (iif(TIPO = 'A' and STATUS IN ('0','1'),1,
iif(TIPO = 'A' and STATUS IN ('2','3'),2,
iif(TIPO = 'A' and STATUS = '2',3,
iif(TIPO = 'A' and STATUS < 2,4,0)))));

CREATE DESCENDING INDEX ITBCALENDARIO_UP_ESTACAO_01
ON TBCALENDARIO_UP_ESTACAO (UP_ID,ESTACAO,DATA);

SET TERM ^ ;

CREATE OR ALTER procedure SPU_REPROGRAMACAO_BOJO (
    ESTABELECIMENTO_1 integer,
    TIPO_1 char(1),
    GP_1 integer,
    UP_1 integer,
    ESTACAO_1 integer,
    DATAHORA timestamp = null,
    ORDEM_DATA_REMESSA integer = 0)
as
declare variable TEMPO numeric(15,4);
declare variable TABELA_ID integer;
declare variable PROGRAMACAO_ID integer;
declare variable TEMPO_PROGRAMACAO numeric(15,4);
declare variable DATAHORA_PARTIDA timestamp;
declare variable DATAHORA_REMESSA timestamp;
declare variable DATA_PARTIDA date;
declare variable TURNO_HORA time;
declare variable PROGRAMACAO_ID_2 integer;
declare variable DATAHORA_INICIO_2 timestamp;
declare variable DATAHORA_FIM_2 timestamp;
declare variable DATA_2 date;
declare variable MINUTO_INICIO_2 numeric(15,4);
declare variable MINUTO_FIM_2 numeric(15,4);
declare variable TEMPO_2 numeric(15,4);
BEGIN

      --Status
      --0 - Parado
      --1 - Iniciado, mas parado
      --2 - Em andamento
      --3 - Finalizado
      --4 - Encerrado

    EXECUTE PROCEDURE SPU_PROGRAMACAO_TEMPO(:ESTABELECIMENTO_1,:GP_1,:UP_1,:ESTACAO_1);


    /* VERIFICA SE FOI PASSADA ALGUMA DATA NO PARAMENTRO */
    IF ( DATAHORA IS NOT NULL ) THEN
    BEGIN
        DATAHORA_PARTIDA = DATAHORA;
    END
    ELSE
    BEGIN
    
        /* CAPTURA A PRIMEIRA DATA/HORA DISPONIVEL DA ESTACAO (SE ESTIVER EM PRODUCAO) */
        SELECT
            DATAHORA_PARTIDA,
            CAST(DATAHORA_PARTIDA AS DATE) DATA_PARTIDA
        FROM (
            SELECT
                (SELECT FIRST 1 DATEADD(1 MINUTE TO P.DATAHORA_FIM)
                      FROM TBPROGRAMACAO P
                     WHERE P.ESTABELECIMENTO_ID = :ESTABELECIMENTO_1
                       --AND P.TIPO = 'A'
                       --AND P.STATUS = 2
                       AND P.SITUACAO = 3
                       AND P.GP_ID = :GP_1
                       AND P.UP_ID = :UP_1
                       AND P.ESTACAO = :ESTACAO_1
                     ORDER BY DATAHORA_FIM DESC) DATAHORA_PARTIDA
            FROM
            RDB$DATABASE )
         INTO
            :DATAHORA_PARTIDA,
            :DATA_PARTIDA;

        /* SE ESTACAO ESTIVER EM PRODUCAO, PEGARA A PRIMEIRA HORA DISPONIVEL APOS O TALAO EM PRODUCAO, SENAO PEGARA A DATAHORA CORRENTE */
        DATAHORA_PARTIDA = COALESCE(:DATAHORA_PARTIDA,CURRENT_TIMESTAMP);
    END

    DATAHORA_PARTIDA = COALESCE(:DATAHORA_PARTIDA,CURRENT_TIMESTAMP);

    FOR
        SELECT
            ID,
            TEMPO,
            TABELA_ID,
            DATAHORA_REMESSA
        FROM (
            SELECT A.ID, TEMPO, A.TABELA_ID, CAST(A.DATA AS TIMESTAMP) DATAHORA_REMESSA, A.DATAHORA_INICIO, A.DATA
              FROM TBPROGRAMACAO A
             WHERE A.ESTABELECIMENTO_ID = :ESTABELECIMENTO_1
               --AND A.TIPO    = :TIPO_1
               --AND A.STATUS  < 2
               AND A.SITUACAO = 1
               AND A.GP_ID   = :GP_1
               AND A.UP_ID   = :UP_1
               AND A.ESTACAO = :ESTACAO_1

               AND NOT (A.STATUS = 1 AND A.STATUS_REQUISICAO = 1)
               --AND A.QUANTIDADE > 0
               --AND A.datahora_inicio < dateadd(hour, 168 ,current_timestamp)
        ) Z
        ORDER BY IIF(:ORDEM_DATA_REMESSA = 1,DATA,NULL), DATAHORA_INICIO
        --ORDER BY DATA,DATAHORA_INICIO
        --alterado para taloes de datas diferentes se misturarem
    
    INTO
        :PROGRAMACAO_ID,
        :TEMPO,
        :TABELA_ID,
        :DATAHORA_REMESSA
    DO
    BEGIN
    
        IF ( :DATAHORA_REMESSA > :DATAHORA_PARTIDA  ) THEN
        BEGIN
            DATAHORA_PARTIDA = :DATAHORA_REMESSA;
        END

        IF(DATAHORA_PARTIDA < current_timestamp)THEN
        BEGIN
            DATAHORA_PARTIDA = dateadd(minute,1,current_timestamp);
        END

        DATA_PARTIDA =
        IIF(
            CAST((DATAHORA_PARTIDA/* - (1.00000/24/60)*/) AS TIME) < (SELECT FIRST 1 T.HORA_INICIO FROM TBTURNO_PRODUCAO T WHERE T.CODIGO = 1 AND T.DIA_SEMANA = EXTRACT(WEEKDAY FROM CAST(:DATAHORA_PARTIDA AS DATE))),
            (SELECT FIRST 1 C.DATA
               FROM TBCALENDARIO_UP_ESTACAO C
              WHERE C.UP_ID = :UP_1
                AND C.ESTACAO = :ESTACAO_1
                AND C.MINUTOS > 0
                AND C.DATA < CAST(:DATAHORA_PARTIDA AS DATE)
              ORDER BY C.DATA DESC),
            (SELECT FIRST 1 C.DATA
               FROM TBCALENDARIO_UP_ESTACAO C
              WHERE C.UP_ID = :UP_1
                AND C.ESTACAO = :ESTACAO_1
                AND C.MINUTOS > 0
                AND C.DATA >= CAST(:DATAHORA_PARTIDA AS DATE)
              ORDER BY C.DATA)
        );

        /*
        UPDATE TBPROGRAMACAO P
           SET P.DATA = :DATA_PARTIDA
         WHERE P.ID   = :PROGRAMACAO_ID;
        */

        DATAHORA_PARTIDA = (
        SELECT DATAHORA_FIM
          FROM SPU_PROGRAMACAO_BOJO (
               :ESTABELECIMENTO_1,
               :TIPO_1,
               :PROGRAMACAO_ID,
               :DATAHORA_PARTIDA,
               :GP_1,
               :UP_1,
               :TEMPO,
               :ESTACAO_1
            )
        );

    END




--    FOR
--        SELECT P.ID,
--               P.DATAHORA_INICIO,
--               P.DATAHORA_FIM, 
--               P.TEMPO,
--               P.DATA
--          FROM TBPROGRAMACAO P
--         WHERE P.ESTABELECIMENTO_ID = :ESTABELECIMENTO_1
--           AND P.TIPO               = :TIPO_1
--           AND P.GP_ID              = :GP_1
--           AND P.UP_ID              = :UP_1
--           AND P.ESTACAO            = :ESTACAO_1
--           AND P.STATUS IN ('0','1')
--           AND NOT (P.STATUS = 1 AND P.STATUS_REQUISICAO = 1)
--         ORDER BY DATAHORA_INICIO
--    INTO
--        :PROGRAMACAO_ID_2,
--        :DATAHORA_INICIO_2,
--        :DATAHORA_FIM_2,
--        :TEMPO_2,
--        :DATA_2
--    DO
--    BEGIN
--
--        MINUTO_INICIO_2 = ((:TURNO_HORA - CAST('00:00:00' AS TIME))/60) +
--        (SELECT COUNT(*)
--           FROM SPC_CALENDARIO_ESTACAO(
--                :UP_1,
--                :ESTACAO_1,
--                CAST(:DATA_2 || ' 00:00'/* || :TURNO_HORA*/ AS TIMESTAMP),
--                :DATAHORA_INICIO_2)
--          WHERE PRODUTIVO = '1');
--
--        UPDATE TBPROGRAMACAO P
--           SET P.MINUTO_INICIO = :MINUTO_INICIO_2,
--               P.MINUTO_FIM    = :MINUTO_INICIO_2 + :TEMPO_2 - 1
--         WHERE P.ID            = :PROGRAMACAO_ID_2;
--
--    END

END
^

SET TERM ; ^

SET TERM ^ ;

CREATE OR ALTER procedure SPC_PROGRAMACAO_TEMPO_ANALISE (
    ESTABELECIMENTO_ID integer,
    GP_ID integer,
    UP_ID integer,
    ESTACAO integer)
returns (
    PROGRAMACAO_ID integer,
    PRODUTO_ID integer,
    TAMANHO integer,
    MODELO_ID integer,
    COR_ID integer,
    FERRAMENTA_ID integer,
    TEMPO numeric(15,4),
    TMP_OPERACIONAL numeric(15,2),
    STP_FERRAMENTA numeric(15,4),
    STP_FERRAMENTA_AQUECIMENTO numeric(15,4),
    STP_COR numeric(15,4),
    STP_COR_APROVACAO numeric(15,4))
as
declare variable OLD_FERRAMENTA_ID integer;
declare variable OLD_COR_ID integer;
declare variable OLD_FAMILIA_ID integer;
declare variable ESTACAO_SETUP char(1);
declare variable COR_SIMILAR integer;
declare variable TALAO_ID integer;
declare variable PRODUTO_ID1 integer;
declare variable COR_ID1 integer;
declare variable FAMILIA_ID integer;
declare variable DATAHORA_INICIO timestamp;
declare variable DATAHORA_FIM timestamp;
declare variable QUANTIDADE numeric(15,4);
declare variable DATA date;
declare variable STATUS char(1);
declare variable DATAHORA_FINALIZADO timestamp;
declare variable COR_SETUP numeric(15,4);
declare variable COR_SETUP_APROVACAO numeric(15,4);
declare variable FERRAMENTA_SETUP numeric(15,4);
declare variable FERRAMENTA_SETUP_AQUECIMENTO numeric(15,4);
declare variable STATUS_REQUISICAO integer;
declare variable NIVEL_ANTERIOR integer;
declare variable NIVEL_PROXIMO integer;
BEGIN

    SELECT SU.HABILITA_SETUP_AQUECIMENTO
      FROM TBSUB_UP SU
     WHERE SU.UP_ID = :UP_ID
       AND SU.ID    = :ESTACAO
      INTO ESTACAO_SETUP;

    OLD_FERRAMENTA_ID = 0;
    OLD_COR_ID        = 0;
    OLD_FAMILIA_ID    = 0;

    /* CONSULTA TALOES DA PROGRAMACAO (O ULTIMO FINALIZADO E TODOS EM ABERTO) */
    /* A CONSULTA DO ULTIMO TALAO PRODUDIZDO SERA POR CONTA DA NECESSIDADE DE VERIFICAR O REGISTRO ANTERIOR COM O PROXIMO */
    FOR
        SELECT
            X.ID,
            X.TALAO_ID,
            X.PRODUTO_ID,
            PD.COR_CODIGO COR_ID,
            PD.FAMILIA_CODIGO FAMILIA_ID,
            X.FERRAMENTA_ID,
            X.DATAHORA_INICIO,
            X.DATAHORA_FIM,
            X.QUANTIDADE,
            X.DATA,
            X.STATUS,
            X.STATUS_REQUISICAO,
            X.DATAHORA_FINALIZADO,
            C.TEMPO_SETUP COR_SETUP,
            C.TEMPO_SETUP_APROVACAO COR_SETUP_APROVACAO,
            F.TEMPO_SETUP FERRAMENTA_SETUP,
            F.TEMPO_SETUP_AQUECIMENTO FERRAMENTA_SETUP_AQUECIMENTO
        FROM (
            SELECT
                ID,
                TALAO_ID,
                PRODUTO_ID,
                FERRAMENTA_ID,
                DATAHORA_INICIO,
                DATAHORA_FIM,
                QUANTIDADE,
                TEMPO,
                DATA,
                STATUS,
                DATAHORA_FINALIZADO,
                0 STATUS_REQUISICAO
              FROM (
                SELECT FIRST 1
                       P.ID,
                       P.TABELA_ID TALAO_ID,
                       P.PRODUTO_ID,
                       P.FERRAMENTA_ID,
                       P.DATAHORA_INICIO,
                       P.DATAHORA_FIM, 
                       P.QUANTIDADE,
                       P.TEMPO,
                       P.DATA,
                       P.STATUS,
                       R.DATAHORA DATAHORA_FINALIZADO
                  FROM TBPROGRAMACAO P,
                       TBPROGRAMACAO_REGISTRO R
                 WHERE R.PROGRAMACAO_ID     = P.ID

                   AND R.STATUS             <> 1
                   AND P.situacao = 2
                   --AND P.TIPO               = 'A'
                   --AND P.status             IN (2,3)

                   --AND IIF(P.STATUS = 3, R.DATAHORA >= DATEADD(-90 MINUTE TO CURRENT_TIMESTAMP), TRUE)
                   --removido a pedido do haroldo no dia 16/08/2021 (facilitar o entendimento de tempo de setup)


                   AND P.ESTABELECIMENTO_ID = :ESTABELECIMENTO_ID
                   AND P.GP_ID              = :GP_ID
                   AND P.UP_ID              = :UP_ID
                   AND P.ESTACAO            = :ESTACAO
                 ORDER BY DATAHORA_FINALIZADO DESC
                ) A

            UNION
    
            SELECT P.ID,  
                   P.TABELA_ID TALAO_ID,
                   P.PRODUTO_ID,
                   P.FERRAMENTA_ID,
                   P.DATAHORA_INICIO,
                   P.DATAHORA_FIM, 
                   IIF( STATUS_REQUISICAO = 1,
                    COALESCE(
                       (SELECT SUM(J.QUANTIDADE - V.SOBRAS) QUANTIDADE_REQUISICAO
                          FROM TBREQUISICAO J,
                               TBREMESSA_ITEM_PROCESSADO V
                         WHERE V.REMESSA    = J.REMESSA_GERADA
                           AND V.CONTROLE   = J.TALAO
                           AND J.GP_ID      = P.GP_ID
                           AND J.REMESSA    = P.REMESSA_ID
                           AND J.PRODUTO_ID = P.PRODUTO_ID
                           AND J.TAMANHO    = P.TAMANHO),0),
                    P.QUANTIDADE) QUANTIDADE,
                   P.TEMPO,
                   P.DATA,
                   P.STATUS,
                   CAST('01.01.9999 00:00:00' AS TIMESTAMP),
                   P.STATUS_REQUISICAO
              FROM TBPROGRAMACAO P
             WHERE P.ESTABELECIMENTO_ID = :ESTABELECIMENTO_ID

               AND P.GP_ID              = :GP_ID
               AND P.UP_ID              = :UP_ID
               AND P.ESTACAO            = :ESTACAO
               --AND P.TIPO               = 'A'
               --AND P.STATUS            IN ('0','1')
               AND P.situacao = 1
               AND NOT (P.STATUS = 1 AND P.STATUS_REQUISICAO = 1)
        ) X,
        TBPRODUTO PD,
        TBCOR C,
        TBFERRAMENTARIA F

       WHERE PD.CODIGO = X.PRODUTO_ID
         AND C.CODIGO  = PD.COR_CODIGO
         AND F.ID      = X.FERRAMENTA_ID
       ORDER BY DATAHORA_FINALIZADO, DATAHORA_INICIO
    INTO
        :PROGRAMACAO_ID,
        :TALAO_ID,
        :PRODUTO_ID,
        :COR_ID,
        :FAMILIA_ID,
        :FERRAMENTA_ID,
        :DATAHORA_INICIO,
        :DATAHORA_FIM,
        :QUANTIDADE,
        :DATA,
        :STATUS,
        :STATUS_REQUISICAO,
        :DATAHORA_FINALIZADO,
        :COR_SETUP,
        :COR_SETUP_APROVACAO,
        :FERRAMENTA_SETUP,
        :FERRAMENTA_SETUP_AQUECIMENTO
    DO
    BEGIN
        /* VERIFICA SE O TALOES ESTA EM ABERTO/PARADO */
        IF ( STATUS IN ('0','1') ) THEN
        BEGIN

            /* ZERA TODOS OS TEMPO, POIS POR PADRAO NA HAVERA SETUPS */
            TEMPO                      = 0;
            TMP_OPERACIONAL            = 0;
            STP_FERRAMENTA             = 0;
            STP_FERRAMENTA_AQUECIMENTO = 0;
            STP_COR                    = 0;
            STP_COR_APROVACAO          = 0;
              
            /* VERIFICA SE HAVERA SETUP DE FERRAMENTA */
            IF ( FERRAMENTA_ID <> OLD_FERRAMENTA_ID ) THEN
            BEGIN
                --EXCEPTION "..." FERRAMENTA_ID || ' ' || OLD_FERRAMENTA_ID;
                /* APLICA O TEMPO DE SETUP DE FERRAMENTA */
                STP_FERRAMENTA = FERRAMENTA_SETUP;

                /* VERIFICA SE A ESTACAO HABILITA SETUP DE AQUECIMENTO */
                IF ( ESTACAO_SETUP = '1' ) THEN
                BEGIN
                    /* APLICA O TEMPO DE AQUECIMENTO DA FERRAMENTA */
                    STP_FERRAMENTA_AQUECIMENTO = FERRAMENTA_SETUP_AQUECIMENTO;
                END
            END

            /* VERIFICA SE NAO HAVERA SETUP DE FERRAMENTA E EXISTE ALGUM ITEM ANTERIOR */
            /* OBS.: O SETUP DE LIMPEZA DE MATRIZ, SO OCORRE QUANDO NAO HA TROCA DE FERRAMENTA */
            IF ( STP_FERRAMENTA = 0 AND OLD_COR_ID > 0 AND OLD_COR_ID <> COR_ID ) THEN
            BEGIN

                /* APLICA O TEMPO DE LIMPEZA DE FERRAMENTA */
                STP_COR = COR_SETUP;

                /* CONSULTA AS CORES SIMILARES */
                FOR
                    /*SELECT FIRST 1 S.ID
                      FROM TBCOR_SIMILAR S
                     WHERE S.FAMILIA_ID = :OLD_FAMILIA_ID
                       AND S.COR_ID_1   = :OLD_COR_ID
                       AND S.COR_ID_2   = :COR_ID */

                       SELECT FIRST 1
                            c1.nivel_contaminacao,
                            c2.nivel_contaminacao
                          FROM TBCOR c1, tbcor c2
                         WHERE c1.codigo   = :OLD_COR_ID
                           AND c2.codigo   = :COR_ID

                INTO
                    --:COR_SIMILAR
                    :NIVEL_ANTERIOR,
                    :NIVEL_PROXIMO
                DO
                BEGIN
                    /* LIMPA O TEMPO DE SETUP DE COR (LIMPEZA) SE A COR ANTERIOR FOR SIMILIAR A ATUAL */
                    --STP_COR = 0;

                    if(NIVEL_ANTERIOR = NIVEL_PROXIMO and (NIVEL_PROXIMO = 0 or NIVEL_PROXIMO = 100))then
                    begin
                        STP_COR = 0;
                    end

                    if(NIVEL_PROXIMO > NIVEL_ANTERIOR)then
                    begin
                        STP_COR = 0;
                    end

                END
            END

            /* VERIFICA SE HAVERA TROCA DE COR */
            IF ( COR_ID <> OLD_COR_ID OR FERRAMENTA_ID <> OLD_FERRAMENTA_ID  ) THEN
            BEGIN
                /* APLICA O TEMPO DE APROVACAO */
                STP_COR_APROVACAO = COR_SETUP_APROVACAO;
            END



            TMP_OPERACIONAL = COALESCE((
                   SELECT
--                        QTD_TALAO,
--                        REQ,
--                        APROV,
--                        EXTRA,
--                        TEMPO,
                        (IIF(REQ = 0,(QTD_TALAO + EXTRA - APROV),QTD_TALAO + PLACAS) * TEMPO)
                    FROM (
                        SELECT
                           COALESCE(T1.QUANTIDADE,0) QTD_TALAO, -- TOTAL DO TALAO
                           COALESCE(T1.REQUISICAO_ID,0) REQ,

                           COALESCE((
                            SELECT SUM(S.QUANTIDADE - S.SALDO)
                              FROM TBREQUISICAO_SOBRA S
                             WHERE S.REMESSA = RT.REMESSA_ID
                               AND S.TALAO = RT.REMESSA_TALAO_ID
                               AND S.REQUISICAO_ID = 0), 0.0000) APROV, -- SUBTRACAO DAS SOBRAS APROVEITADAS

                            IIF(t1.requisicao_id > 0,
                                COALESCE((
                                SELECT SUM(iif(g.status = 3, g.quantidade - g.saldo, g.quantidade))
                                  FROM TBREQUISICAO_PLACA g
                                 WHERE g.requisicao_id = t1.requisicao_id), 0.0000),0) PLACAS, -- SOMA PLACAS APROVEITADAS
    
                            COALESCE((SELECT FIRST 1 QUANTIDADE FROM VWREMESSA_TALAO TE WHERE TE.ID = RT.TALAO_EXTRA),0) EXTRA, -- INCLUSAO DO TALAO EXTRA
                            COALESCE((SELECT FIRST 1 TEMPO FROM SPC_PROGRAMACAO_TEMPO_BOJO(P1.MODELO_CODIGO, T1.TAMANHO, P1.COR_CODIGO, 1)),0) tempo -- TEMPO POR UNIDADEDIGO, 1)),0)
                       FROM TBPRODUTO P1,
                            TBPROGRAMACAO T1,
                            VWREMESSA_TALAO RT
                      WHERE P1.CODIGO    = :PRODUTO_ID
                        AND T1.tabela_id = :TALAO_ID
                        AND T1.tipo      = 'A'
                        AND RT.ID       = T1.TABELA_ID
                        ) X),0);

            --TMP_OPERACIONAL = (0.421 * QUANTIDADE);

            TEMPO = STP_FERRAMENTA + STP_FERRAMENTA_AQUECIMENTO + STP_COR + STP_COR_APROVACAO + TMP_OPERACIONAL;

            TEMPO = IIF(TRUNC(:TEMPO) = :TEMPO, TRUNC(:TEMPO), TRUNC(:TEMPO) + 1);

            IF ( TMP_OPERACIONAL = 0 ) THEN
            BEGIN
                TEMPO                       = 0;
                STP_FERRAMENTA              = 0;
                STP_FERRAMENTA_AQUECIMENTO  = 0;
                STP_COR                     = 0;
                STP_COR_APROVACAO           = 0;
                FERRAMENTA_ID               = 1; -- IDENTIFICACAO DE FERRAMENTA INEXISTENTE
            END
            
            SUSPEND;
        END

        --SUSPEND;

        /* -- INICIO ------ BLOCO QUE ALIMENTA OS VALORES ANTERIORES ---------- */
        OLD_FERRAMENTA_ID = FERRAMENTA_ID;
        OLD_COR_ID        = COR_ID;
        OLD_FAMILIA_ID    = FAMILIA_ID;
        /* --  FIM   ------ BLOCO QUE ALIMENTA OS VALORES ANTERIORES ---------- */
    END

END
^

SET TERM ; ^

