CREATE OR REPLACE
PROCEDURE PREVISAO_CONSUMO_ANALITICA_COC(
    P_CDFILIAL      IN VARCHAR2,
    P_CDCIA         IN VARCHAR2,
    P_DATAINI       IN DATE,
    P_DATAFIN       IN DATE,
    P_TIPOPAX       IN VARCHAR2,
    P_REFERENCIA    IN FLOAT,
    P_CDPRODINI     IN VARCHAR2,
    P_CDPRODFIN     IN VARCHAR2,
    P_TCDPRODUTO    IN VARCHAR2,
    P_CDOPERADOR    IN VARCHAR2
)
AS
   V_FILICIA_CORRENTE   VARCHAR2(8);
   V_DATA_CORRENTE      VARCHAR2(16);
   V_VOOTRECHO_CORRENTE VARCHAR2(29);
   V_QTTOTPAX           FLOAT;
   V_REFPAX             FLOAT; /*referencia do calculo de passageiros do voo*/
   V_QTSERVICO          FLOAT;
   V_REFSERV            FLOAT; /*referencia do calculo da quantidade do servico*/
   V_MANUAL             VARCHAR2(4);
   V_NOVO_CODIGO        VARCHAR2(20); /*Utilizado para a novo codigo*/
   V_EXISTE_RECEITA     INTEGER;
   V_CDESPEPROD         VARCHAR2(10);
   V_CDTIPOCOMP         VARCHAR2(3);
   V_QTPADESPEPRO       FLOAT;
BEGIN
   /*-------------------------------------------------------------------------------*/
   /* Apaga previsao de consumo cadastrada anteriormente, mantendo-se as aprovadas  */
   /*-------------------------------------------------------------------------------*/
   DELETE FROM PREVISAOCONSUMOCOC P
   WHERE CDFILIAL = P_CDFILIAL
     AND ((P_CDCIA = 'T') OR (INSTR(P_CDCIA, CDCIA) > 0))
     AND DTPRODUCAO BETWEEN P_DATAINI AND P_DATAFIN
     
     AND ((P_TCDPRODUTO = 'T') OR 
           EXISTS (SELECT 1
                    FROM PRODUTO PT
                   WHERE PT.CDPRODUTO = P.CDPRODUTO
                     AND PT.CDARVPROD BETWEEN P_CDPRODINI AND P_CDPRODFIN))
     AND NOT EXISTS (SELECT 1 
                       FROM PREVCONSCOC
                      WHERE CDFILIAL = P.CDFILIAL
                        AND CDCIA = P.CDCIA
                        AND DTPREVCONS = P.DTPRODUCAO
                        AND CDPRODUTO = P.CDPRODUTO
                        AND IDPREVCONSCOC = 'A');
                        
   DELETE FROM PREVCONSCOC P
   WHERE CDFILIAL = P_CDFILIAL
     AND ((P_CDCIA = 'T') OR (INSTR(P_CDCIA, CDCIA) > 0))
     AND DTPREVCONS BETWEEN P_DATAINI AND P_DATAFIN
     AND ((P_TCDPRODUTO = 'T') OR 
           EXISTS (SELECT 1
                    FROM PRODUTO PT
                   WHERE PT.CDPRODUTO = P.CDPRODUTO
                     AND PT.CDARVPROD BETWEEN P_CDPRODINI AND P_CDPRODFIN))
     AND (IDPREVCONSCOC <> 'A' OR IDPREVCONSCOC IS NULL);
   
   /* Percorre CADA cia, voo e servico no periodo informado */
   FOR C_SERV
   IN
   (
   /* Dados segundo configuracao E DESCONSIDERANDO os que existem em programacoes existentes */
   SELECT C.CDFILIAL, C.CDCIA, C.NRVOO, C.CDTRECHO, C.CDCLASSE,D.DTDATA AS DTPRODUCAO, D.DTDATA + NVL(C.QTDIASPROD, 0) AS DTVOO,
          C.QTPAX, C.QTPAXSBY,
          P.CDSERVICO, P.QTSERV, P.VRLOADSE, P.NRPROPAX, P.IDPROPSERV, P.CDCICLO,
          CASE WHEN NVL(C.VRPEROCUPACAO, 0) = 0 THEN NVL(CF.VRPERCONVOO, 0) ELSE C.VRPEROCUPACAO END AS VRPEROCUPACAO,
          'C' AS TIPO, NULL AS QTTOTPAX, NULL AS QTTOTSERV
     FROM CONFIG_PAX_VOO C
          LEFT JOIN CIAFILI CF ON CF.CDFILIAL = C.CDFILIAL AND 
                                  CF.CDCIA = C.CDCIA
          LEFT JOIN PAD_VOOPREFEQUI P ON P.CDFILIAL = C.CDFILIAL AND
                                          P.CDCIA = C.CDCIA AND
                                          P.NRVOO = C.NRVOO AND
                                          P.CDTRECHO = C.CDTRECHO AND
                                          P.CDCLASSE = C.CDCLASSE
          CROSS JOIN DATA D
    WHERE C.CDFILIAL = P_CDFILIAL
      AND D.DTDATA BETWEEN P_DATAINI AND P_DATAFIN
      AND ((P_CDCIA = 'T') OR (INSTR(P_CDCIA, C.CDCIA) > 0))
      AND C.IDSITVOO = '1' /*Voo ativo*/
      AND (
            C.IDTIPVOO = '1' OR /*Voo regular*/
           (C.IDTIPVOO = '2' AND D.DTDATA + NVL(C.QTDIASPROD, 0) BETWEEN C.DTINIVIGVOO AND C.DTFIMVIGVOO) /*Voo extra*/
          )
      AND C.IDSITVOOTRE = '1'
      AND CASE TO_CHAR(D.DTDATA + NVL(C.QTDIASPROD, 0), 'D') /*Voo habilitado para o dia da semana*/
             WHEN '1' THEN C.IDVOODOM 
             WHEN '2' THEN C.IDVOOSEG
             WHEN '3' THEN C.IDVOOTER
             WHEN '4' THEN C.IDVOOQUA
             WHEN '5' THEN C.IDVOOQUI
             WHEN '6' THEN C.IDVOOSEX
             WHEN '7' THEN C.IDVOOSAB
           END = '1'
      AND P.CDCICLO = CICLO_VIGENTE_COC(C.CDFILIAL, C.CDCIA, C.NRVOO, C.CDTRECHO,
                                        D.DTDATA + NVL(C.QTDIASPROD, 0), P.CDSERVICO, P.CDCLASSE, P.CDCICLO)
      /*Nao pode haver programacao gerada para o dado. Se houver, o dado sera buscado na segunda metade da UNION*/                                  
      AND NOT EXISTS
      (
         SELECT 1
           FROM VOOSPROGSERV V
                INNER JOIN PROGSERVICO PG ON PG.CDFILIAL = V.CDFILIAL AND
                                             PG.NRPROGSERV = V.NRPROGSERV AND
                                             PG.CDCIA = V.CDCIA                                             
                INNER JOIN CLASVOOPROGSERV VC ON VC.CDFILIAL = V.CDFILIAL AND
                                                  VC.NRPROGSERV = V.NRPROGSERV AND
                                                  VC.CDCIA = V.CDCIA AND
                                                  VC.NRVOO = V.NRVOO AND
                                                  VC.CDTRECHO = V.CDTRECHO AND
                                                  VC.DTDECOLVOO = V.DTDECOLVOO
                INNER JOIN SERVCLASSEPROG S ON S.CDFILIAL = V.CDFILIAL AND
                                               S.NRPROGSERV = V.NRPROGSERV AND
                                               S.CDCIA = V.CDCIA AND
                                               S.NRVOO = V.NRVOO AND
                                               S.CDTRECHO = V.CDTRECHO AND
                                               S.DTDECOLVOO = V.DTDECOLVOO AND
                                               S.CDCLASSE = VC.CDCLASSE
          WHERE V.CDFILIAL = C.CDFILIAL
            AND V.CDCIA = C.CDCIA
            AND V.NRVOO = C.NRVOO
            AND V.CDTRECHO = C.CDTRECHO
            AND VC.CDCLASSE = C.CDCLASSE
            AND V.DTPRODUCAO = D.DTDATA
            AND S.CDSERVICO = P.CDSERVICO
            AND PG.IDSITPROGSERV <> 'C'
      )
   
   UNION ALL
   
   /* Dados segundo programacoes existentes no filtro informado*/
   
   SELECT V.CDFILIAL, V.CDCIA, V.NRVOO, V.CDTRECHO, VC.CDCLASSE, V.DTPRODUCAO, MAX(V.DTDECOLVOO) AS DTVOO, 
       NULL AS QTPAX, NULL AS QTPAXSBY,
       S.CDSERVICO, NULL AS QTSERV, NULL AS VRLOADSE, NULL AS NRPROPAX, NULL AS IDPROPSERV, MAX(S.CDCICLO) AS CDCICLO,
       NULL AS VRPEROCUPACAO,
       'P' AS TIPO, SUM(VC.QTTOTPAXCVS) AS QTTOTPAX, SUM(S.QTTORPRODSERV) AS QTPAXSBY
     FROM VOOSPROGSERV V
                INNER JOIN PROGSERVICO PG ON PG.CDFILIAL = V.CDFILIAL AND
                                             PG.NRPROGSERV = V.NRPROGSERV AND
                                             PG.CDCIA = V.CDCIA                                             
          INNER JOIN CLASVOOPROGSERV VC ON VC.CDFILIAL = V.CDFILIAL AND
                                            VC.NRPROGSERV = V.NRPROGSERV AND
                                            VC.CDCIA = V.CDCIA AND
                                            VC.NRVOO = V.NRVOO AND
                                            VC.CDTRECHO = V.CDTRECHO AND
                                            VC.DTDECOLVOO = V.DTDECOLVOO
          INNER JOIN SERVCLASSEPROG S ON S.CDFILIAL = V.CDFILIAL AND
                                         S.NRPROGSERV = V.NRPROGSERV AND
                                         S.CDCIA = V.CDCIA AND
                                         S.NRVOO = V.NRVOO AND
                                         S.CDTRECHO = V.CDTRECHO AND
                                         S.DTDECOLVOO = V.DTDECOLVOO AND
                                         S.CDCLASSE = VC.CDCLASSE
    WHERE V.CDFILIAL = P_CDFILIAL
      AND V.DTPRODUCAO BETWEEN P_DATAINI AND P_DATAFIN
      AND ((P_CDCIA = 'T') OR (INSTR(P_CDCIA, V.CDCIA) > 0))
      AND PG.IDSITPROGSERV <> 'C'
    GROUP BY V.CDFILIAL, V.CDCIA, V.NRVOO, V.CDTRECHO, VC.CDCLASSE, V.DTPRODUCAO, S.CDSERVICO
    ORDER BY CDFILIAL, CDCIA, DTPRODUCAO, NRVOO, CDTRECHO
   )
   LOOP      
      /*indicando filial + companhia em curso
        calculando informacoes que sao unicas por filial + companhia
      */
      IF V_FILICIA_CORRENTE IS NULL OR (V_FILICIA_CORRENTE <> C_SERV.CDFILIAL || C_SERV.CDCIA) THEN
         V_FILICIA_CORRENTE := C_SERV.CDFILIAL || C_SERV.CDCIA;
      END IF;
      
      /*indicando data em curso
        calculando informacoes que sao unicas por data
      */      
      IF V_DATA_CORRENTE IS NULL OR 
         (V_DATA_CORRENTE <> V_FILICIA_CORRENTE || TO_CHAR(C_SERV.DTPRODUCAO, 'YYYYMMDD') ) THEN
         V_DATA_CORRENTE := V_FILICIA_CORRENTE || TO_CHAR(C_SERV.DTPRODUCAO, 'YYYYMMDD');
         
         /* Obtem manual vigente na data */         
         BEGIN
            SELECT MAX(CDMANCIA)
              INTO V_MANUAL
              FROM MANUALCIA 
             WHERE CDCIA = C_SERV.CDCIA
               AND CDFILIAL = C_SERV.CDFILIAL
               AND IDTPMANUAL = 'M'
               AND DTINIVGMA = (SELECT MAX(DTINIVGMA)
                                  FROM MANUALCIA
                                 WHERE CDCIA = C_SERV.CDCIA AND
                                       CDFILIAL = C_SERV.CDFILIAL AND
                                       DTINIVGMA <= C_SERV.DTPRODUCAO);
         EXCEPTION
            WHEN NO_DATA_FOUND THEN
               V_MANUAL := NULL;
         END;         
      END IF;
      
      /*indicando nrvoo + trecho + classe em curso
        calculando informacoes que sao unicas por voo + trecho + classe
      */
      IF V_VOOTRECHO_CORRENTE IS NULL OR 
         (V_VOOTRECHO_CORRENTE <> V_DATA_CORRENTE || C_SERV.NRVOO || C_SERV.CDTRECHO || C_SERV.CDCLASSE ) THEN   
         
         V_VOOTRECHO_CORRENTE := V_DATA_CORRENTE || C_SERV.NRVOO || C_SERV.CDTRECHO || C_SERV.CDCLASSE;
         
         IF C_SERV.TIPO = 'C' THEN 
            /*Registra a referencia do calculo quando for Percentual de Ocupacao ou Media*/
            IF P_TIPOPAX IN ('PER', 'MED') THEN
               
               IF P_TIPOPAX = 'PER' THEN
                  V_REFPAX := CASE WHEN NVL(P_REFERENCIA, 0) = 0 THEN C_SERV.VRPEROCUPACAO ELSE P_REFERENCIA END;
               END IF;
               
               IF P_TIPOPAX = 'MED' THEN
                  V_REFPAX := NVL(TRUNC(P_REFERENCIA), 1);
               END IF;
               
            END IF;            
            
            V_QTTOTPAX := TOTAL_PAX_COC(C_SERV.CDFILIAL, C_SERV.CDCIA, C_SERV.NRVOO, 
                                        C_SERV.CDTRECHO, C_SERV.DTPRODUCAO, C_SERV.CDCLASSE,
                                        C_SERV.QTPAX, C_SERV.QTPAXSBY, P_TIPOPAX,
                                        V_REFPAX);
         
         ELSE
         
            V_QTTOTPAX := C_SERV.QTTOTPAX;
            
         END IF;
      END IF;
      
      /*Quantidade do servico*/
      
      IF C_SERV.TIPO = 'C' THEN
         /*Referencia de calculo para o valor do servico quando proporcao e 
           Proporcional fixa (2)
           Loading (4)
           Quantidade Fixa (5)
         */
         IF C_SERV.IDPROPSERV IN ('2', '4', '5') THEN
            V_REFSERV := CASE C_SERV.IDPROPSERV
                            WHEN '2' THEN NVL(C_SERV.NRPROPAX, 0)
                            WHEN '4' THEN NVL(C_SERV.VRLOADSE, 0)
                            WHEN '5' THEN NVL(C_SERV.QTSERV, 0)
                            ELSE 0
                         END;
         END IF;
         
         V_QTSERVICO := QTDE_SERVICO_COC(C_SERV.CDFILIAL, C_SERV.CDCIA, C_SERV.NRVOO, C_SERV.CDTRECHO,
                                         C_SERV.CDSERVICO, V_QTTOTPAX, C_SERV.IDPROPSERV, V_REFSERV);
      ELSE
      
         V_QTSERVICO := C_SERV.QTTOTSERV;
      
      END IF;
      /*Busca os produtos/receitas do servico, no manual vigente, 
        e grava-os na tabela, com um indicador se produto ou receita 
        A quantidade ja e ajustada com o loading e sobre o valor do servico
      */
      IF V_MANUAL IS NOT NULL AND V_QTSERVICO > 0 THEN
         INSERT INTO PREVISAOCONSUMOCOC
         (CDFILIAL, CDCIA, NRVOO,
          CDTRECHO, CDSERVICO, CDCLASSE, CDCICLO,
          CDMANUAL, CDSUBGRU, CDRECEITA, DTPRODUCAO,
          CDPRODUTO, QUANTIDADE, IDTIPOPROD,
          IDTIPOPAX, QTREFPAX, QTTOTPAX,
          IDPROPSERV, QTREFSERV, QTSERVICO, DTVOO)
          /* Produtos */
         SELECT C_SERV.CDFILIAL, C_SERV.CDCIA, C_SERV.NRVOO,
                C_SERV.CDTRECHO, C_SERV.CDSERVICO, C_SERV.CDCLASSE, C_SERV.CDCICLO, 
                V_MANUAL, S.CDSUBGRU, NULL, C_SERV.DTPRODUCAO,
                P.CDPRODUTO, NVL(P.QTPRODSUMA, 0.00) * NVL(P.VRLOADPSUMA,0.00)/100 * V_QTSERVICO, 'P',
                P_TIPOPAX, V_REFPAX, V_QTTOTPAX,
                C_SERV.IDPROPSERV, V_REFSERV, V_QTSERVICO, C_SERV.DTVOO
           FROM SUBGRUSEMA S            
                INNER JOIN PRODSUBSEMA P ON P.CDFILIAL = S.CDFILIAL AND
                                            P.CDCIA = S.CDCIA AND
                                            P.CDMANCIA = S.CDMANCIA AND
                                            P.CDSERVICO = S.CDSERVICO AND
                                            P.CDCLASSE = S.CDCLASSE AND
                                            P.CDCICLO = S.CDCICLO AND
                                            P.CDSUBGRU = S.CDSUBGRU
                INNER JOIN PRODUTO PT ON PT.CDPRODUTO = P.CDPRODUTO
         WHERE S.CDFILIAL = C_SERV.CDFILIAL
           AND S.CDCIA = C_SERV.CDCIA
           AND S.CDMANCIA = V_MANUAL
           AND S.CDSERVICO = C_SERV.CDSERVICO       
           AND S.CDCLASSE = C_SERV.CDCLASSE
           AND S.CDCICLO = C_SERV.CDCICLO
           AND ((P_TCDPRODUTO = 'T') OR (PT.CDARVPROD BETWEEN P_CDPRODINI AND P_CDPRODFIN))
           AND NOT EXISTS (SELECT 1 
                             FROM PREVCONSCOC
                            WHERE CDFILIAL = C_SERV.CDFILIAL
                              AND CDCIA = C_SERV.CDCIA
                              AND DTPREVCONS = C_SERV.DTPRODUCAO
                              AND CDPRODUTO = P.CDPRODUTO
                              AND IDPREVCONSCOC = 'A')

         UNION ALL
           /* Receitas */
         SELECT C_SERV.CDFILIAL, C_SERV.CDCIA, C_SERV.NRVOO,
                C_SERV.CDTRECHO, C_SERV.CDSERVICO, C_SERV.CDCLASSE, C_SERV.CDCICLO, 
                V_MANUAL, S.CDSUBGRU, R.CDRECEITA, C_SERV.DTPRODUCAO,
                R.CDRECEITA, NVL(R.QTRECSUMA, 0.00) * NVL(R.VRLOADRSUMA, 0.00)/100 * V_QTSERVICO, 'R',
                P_TIPOPAX, V_REFPAX, V_QTTOTPAX,
                C_SERV.IDPROPSERV, V_REFSERV, V_QTSERVICO, C_SERV.DTVOO
           FROM SUBGRUSEMA S
                INNER JOIN RECSUBSEMA R ON R.CDFILIAL = S.CDFILIAL AND
                                           R.CDCIA = S.CDCIA AND
                                           R.CDMANCIA = S.CDMANCIA AND
                                           R.CDSERVICO = S.CDSERVICO AND
                                           R.CDCLASSE = S.CDCLASSE AND
                                           R.CDCICLO = S.CDCICLO AND
                                           R.CDSUBGRU = S.CDSUBGRU                                 
                
          WHERE S.CDFILIAL = C_SERV.CDFILIAL
           AND S.CDCIA = C_SERV.CDCIA
           AND S.CDMANCIA = V_MANUAL
           AND S.CDSERVICO = C_SERV.CDSERVICO       
           AND S.CDCLASSE = C_SERV.CDCLASSE
           AND S.CDCICLO = C_SERV.CDCICLO;
      END IF;
      
   END LOOP;
   /*-----------------------------------------------------*/
   /* Substitui todas as receitas da previsao por sua composicao, 
      ate que nao haja mais receitas na tabela de previsao. 
      Obs: Receitas podem ter subreceitas em sua composicao */
   /*-----------------------------------------------------*/
   LOOP      
      /* Verifica se existem receitas na tabela de previsao  */
      BEGIN
         SELECT MAX(1)
           INTO V_EXISTE_RECEITA
           FROM PREVISAOCONSUMOCOC
          WHERE CDFILIAL = P_CDFILIAL
            AND ((P_CDCIA = 'T') OR (INSTR(P_CDCIA, CDCIA) > 0))
            AND DTPRODUCAO BETWEEN P_DATAINI AND P_DATAFIN            
            AND IDTIPOPROD = 'R';
      EXCEPTION
         WHEN NO_DATA_FOUND THEN
            V_EXISTE_RECEITA := NULL;
      END;
      
      /* Se nao existir mais receitas, sai do loop */
      EXIT WHEN V_EXISTE_RECEITA IS NULL;
      /*-----------------------------------------------------*/
      /*Percorre cada uma das receitas existentes na previsao*/      
      /*-----------------------------------------------------*/
      FOR C_REC IN
      (
         SELECT CDFILIAL, CDCIA, NRVOO,
                CDTRECHO, CDSERVICO, CDCLASSE, CDCICLO,
                CDMANUAL, CDSUBGRU, CDRECEITA,
                DTPRODUCAO, CDPRODUTO, QUANTIDADE,
                IDTIPOPAX, QTREFPAX, QTTOTPAX,
                IDPROPSERV, QTREFSERV, QTSERVICO, DTVOO
           FROM PREVISAOCONSUMOCOC
          WHERE CDFILIAL = P_CDFILIAL
            AND ((P_CDCIA = 'T') OR (INSTR(P_CDCIA, CDCIA) > 0))
            AND DTPRODUCAO BETWEEN P_DATAINI AND P_DATAFIN            
            AND IDTIPOPROD = 'R'
      ) LOOP      
            /* Busca a Especificacao tecnica da receita vigente na data da producao,
               se houver mais de uma, pega a de maior codigo*/
            BEGIN
               SELECT MAX(CDESPEPROD), MAX(QTPADESPEPRO)
               INTO V_CDESPEPROD, V_QTPADESPEPRO
                FROM ESPEPROD
                WHERE
                  CDPRODUTO = C_REC.CDPRODUTO AND
                  DTVALESPEPRO = (SELECT MAX(DTVALESPEPRO) 
                                    FROM ESPEPROD 
                                   WHERE CDPRODUTO = C_REC.CDPRODUTO
                                     AND DTVALESPEPRO <= C_REC.DTPRODUCAO);
            EXCEPTION
                WHEN NO_DATA_FOUND THEN
                  V_CDESPEPROD := NULL;
                  V_QTPADESPEPRO := NULL;
            END;
            
            /* Busca o tipo de composicao. Primeiro verifica se existe um padrao de O.P. indicado e o utiliza.
               Se nao houver um padrao, obtem o tipo de composicao de menor codigo (o primeiro da lista da receita)*/
            BEGIN
                  SELECT MAX(CDTIPOCOMP)
                    INTO V_CDTIPOCOMP
                  FROM
                  (
                     SELECT MAX(CDTIPOCOMP) CDTIPOCOMP
                       FROM TCOMPPRO 
                      WHERE CDPRODUTO = C_REC.CDPRODUTO
                        AND CDESPEPROD = V_CDESPEPROD
                        AND IDTCOMPPROC = 'S'
                      UNION ALL
                     SELECT MIN(CDTIPOCOMP) CDTIPOCOMP
                       FROM TCOMPPRO
                      WHERE CDPRODUTO = C_REC.CDPRODUTO
                        AND CDESPEPROD = V_CDESPEPROD
                        AND NOT EXISTS
                        (
                        SELECT 1
                          FROM TCOMPPRO 
                         WHERE CDPRODUTO = C_REC.CDPRODUTO
                           AND CDESPEPROD = V_CDESPEPROD
                           AND IDTCOMPPROC = 'S'
                        )
                  );
                           
            EXCEPTION
               WHEN NO_DATA_FOUND THEN
                  V_CDTIPOCOMP := NULL;
            END;
            
            /* Insere na tabela da previsao os produtos e sub-receitas da composicao*/            
            FOR C_PROD_REC IN
            (
              /* Produtos */
            SELECT C_REC.CDFILIAL, C_REC.CDCIA, C_REC.NRVOO,
                   C_REC.CDTRECHO, C_REC.CDSERVICO, C_REC.CDCLASSE, C_REC.CDCICLO,
                   C_REC.CDMANUAL, C_REC.CDSUBGRU, C_REC.CDRECEITA,
                   C_REC.DTPRODUCAO, C.CDPRODINSUMO, 
                   CASE WHEN NVL(V_QTPADESPEPRO, 0) = 0 THEN C.QTINSUMO
                        ELSE C.QTINSUMO/V_QTPADESPEPRO
                   END AS QUANTIDADE,
                   'P' AS IDTIPOPROD
              FROM COMPPROD C
                   INNER JOIN PRODUTO P ON P.CDPRODUTO = C.CDPRODINSUMO
             WHERE P.IDPRODCOMISS IS NULL
               AND C.CDPRODUTO = C_REC.CDPRODUTO
               AND C.CDESPEPROD = V_CDESPEPROD
               AND C.CDTIPOCOMP = V_CDTIPOCOMP
               AND ((P_TCDPRODUTO = 'T') OR (P.CDARVPROD BETWEEN P_CDPRODINI AND P_CDPRODFIN))
               AND NOT EXISTS (SELECT 1 
                                 FROM PREVCONSCOC
                                WHERE CDFILIAL = C_REC.CDFILIAL
                                  AND CDCIA = C_REC.CDCIA
                                  AND DTPREVCONS = C_REC.DTPRODUCAO
                                  AND CDPRODUTO = P.CDPRODUTO
                                  AND IDPREVCONSCOC = 'A')
             
             UNION ALL
               /* Sub-receitas */ 
            SELECT C_REC.CDFILIAL, C_REC.CDCIA, C_REC.NRVOO,
                   C_REC.CDTRECHO, C_REC.CDSERVICO, C_REC.CDCLASSE, C_REC.CDCICLO,
                   C_REC.CDMANUAL, C_REC.CDSUBGRU, C_REC.CDRECEITA,
                   C_REC.DTPRODUCAO, C.CDPRODINSUMO, 
                   CASE WHEN NVL(V_QTPADESPEPRO, 0) = 0 THEN C.QTINSUMO
                        ELSE C.QTINSUMO/V_QTPADESPEPRO
                   END AS QUANTIDADE,
                   'R' AS IDTIPOPROD
              FROM COMPPROD C
                   INNER JOIN PRODUTO P ON P.CDPRODUTO = C.CDPRODINSUMO
             WHERE P.IDPRODCOMISS = '3'
               AND C.CDPRODUTO = C_REC.CDPRODUTO
               AND C.CDESPEPROD = V_CDESPEPROD
               AND C.CDTIPOCOMP = V_CDTIPOCOMP
            ) LOOP
               /*Atualiza o produto na previsao, se o mesmo ja existir, com a quantidade encontrada nessa receita*/
               UPDATE PREVISAOCONSUMOCOC
                  SET QUANTIDADE = QUANTIDADE + (C_PROD_REC.QUANTIDADE * C_REC.QUANTIDADE)
                WHERE CDFILIAL = C_PROD_REC.CDFILIAL                
                  AND CDCIA = C_PROD_REC.CDCIA
                  AND NRVOO = C_PROD_REC.NRVOO
                  AND CDTRECHO = C_PROD_REC.CDTRECHO
                  AND CDSERVICO = C_PROD_REC.CDSERVICO
                  AND CDCLASSE = C_PROD_REC.CDCLASSE                  
                  AND DTPRODUCAO = C_PROD_REC.DTPRODUCAO
                  AND CDPRODUTO = C_PROD_REC.CDPRODINSUMO;
               
               /* Se o produto nao existe na previsao ainda, inclui-o */
               IF SQL%ROWCOUNT = 0 THEN
                     INSERT INTO PREVISAOCONSUMOCOC
                     (CDFILIAL, CDCIA, NRVOO,
                      CDTRECHO, CDSERVICO, CDCLASSE, CDCICLO,
                      CDMANUAL, CDSUBGRU, CDRECEITA,
                      DTPRODUCAO, CDPRODUTO, QUANTIDADE, IDTIPOPROD,
                      IDTIPOPAX, QTREFPAX, QTTOTPAX,
                      IDPROPSERV, QTREFSERV, QTSERVICO, DTVOO)
                     VALUES
                     (C_PROD_REC.CDFILIAL, C_PROD_REC.CDCIA, C_PROD_REC.NRVOO,
                      C_PROD_REC.CDTRECHO, C_PROD_REC.CDSERVICO, C_PROD_REC.CDCLASSE, C_PROD_REC.CDCICLO,
                      C_PROD_REC.CDMANUAL, C_PROD_REC.CDSUBGRU, C_PROD_REC.CDRECEITA,
                      C_PROD_REC.DTPRODUCAO, C_PROD_REC.CDPRODINSUMO, C_REC.QUANTIDADE * C_PROD_REC.QUANTIDADE, C_PROD_REC.IDTIPOPROD,
                      C_REC.IDTIPOPAX, C_REC.QTREFPAX, C_REC.QTTOTPAX,
                      C_REC.IDPROPSERV, C_REC.QTREFSERV, C_REC.QTSERVICO, C_REC.DTVOO);
               END IF;
               
            END LOOP;
            
            /* Apaga da previsao a receita substituida por sua composicao */
            DELETE FROM PREVISAOCONSUMOCOC
            WHERE CDFILIAL = C_REC.CDFILIAL
              AND CDCIA = C_REC.CDCIA
              AND NRVOO = C_REC.NRVOO
              AND CDTRECHO = C_REC.CDTRECHO
              AND CDSERVICO = C_REC.CDSERVICO
              AND CDCLASSE = C_REC.CDCLASSE
              AND DTPRODUCAO = C_REC.DTPRODUCAO
              AND CDPRODUTO = C_REC.CDPRODUTO;

      END LOOP;
      
   END LOOP;
   
   /* Insere a previsao gerada na tabela consolidada, utilizada para geracao no sistema de compras */
   INSERT INTO PREVCONSCOC
   (CDFILIAL,CDCIA,CDPRODUTO,DTPREVCONS,QTPREVCONS,DTGERPREVCONS,CDOPERPREVCONS)
   SELECT CDFILIAL,CDCIA,CDPRODUTO, DTPRODUCAO, SUM(QUANTIDADE), SYSDATE, P_CDOPERADOR
     FROM PREVISAOCONSUMOCOC P
    WHERE CDFILIAL = P_CDFILIAL
      AND ((P_CDCIA = 'T') OR (INSTR(P_CDCIA, CDCIA) > 0))
      AND DTPRODUCAO BETWEEN P_DATAINI AND P_DATAFIN
      AND ((P_TCDPRODUTO = 'T') OR 
           EXISTS (SELECT 1
                    FROM PRODUTO PT
                   WHERE PT.CDPRODUTO = P.CDPRODUTO
                     AND PT.CDARVPROD BETWEEN P_CDPRODINI AND P_CDPRODFIN))
      AND NOT EXISTS (SELECT 1 
                        FROM PREVCONSCOC
                       WHERE CDFILIAL = P.CDFILIAL
                         AND CDCIA = P.CDCIA
                         AND DTPREVCONS = P.DTPRODUCAO
                         AND CDPRODUTO = P.CDPRODUTO
                         AND IDPREVCONSCOC = 'A')
    GROUP BY CDFILIAL,CDCIA,CDPRODUTO, DTPRODUCAO, P_CDOPERADOR;

END;
/