create or replace PROCEDURE ESTOQUE_SEMIACABADO (
   P_CDFILIAL      IN FILIAL.CDFILIAL%TYPE,
   P_NRPEDIDO      IN PEDIDO.NRPEDIDO%TYPE,
   P_CDPRODUTO     IN PRODUTO.CDPRODUTO%TYPE,
   P_CDPROCFABRIC  IN TPROCFABRICA.CDPROCFABRIC%TYPE,
   P_QUANTIDADE    IN FLOAT
   ) AS
   V_CDPRODESTO     PRODUTO.CDPRODUTO%TYPE;
   V_CDPRODEMANDA   PRODUTO.CDPRODUTO%TYPE;
   V_QTESTOQDIA     FLOAT;
   V_NOVAQT         FLOAT;
   V_QTDEMANDA      FLOAT;
   V_QTESTOQUE      FLOAT;
BEGIN
   V_NOVAQT     := 0;
   V_QTDEMANDA  := 0;
   V_QTESTOQUE  := 0;
   V_QTESTOQDIA := 0;
   
   -- Consulta os semiacabados do produto passado com parametro.
   FOR C_SEMIACABADO IN (
      SELECT I.CDFILIAL,
             I.CDPRODUTO,
             I.CDPRODINSUMO,
             F.CDPROCFABRIC,
             (QTPREVI_MATPRIMA(I.CDFILIAL, I.CDPRODUTO, I.CDPROCFABRIC, I.CDETAPAPROD, I.CDPRODINSUMO, P_QUANTIDADE)) AS QTAINSUMPREOP
        FROM PROCFABRICA F,
             INSUMETAPA  I
       WHERE (I.IDSEMIACETAP = 'S'           )
         AND (F.IDPROFABPADR = 'S'           )
         AND (F.CDFILIAL     = I.CDFILIAL    )
         AND (F.CDPRODUTO    = I.CDPRODINSUMO)
         AND (I.CDFILIAL     = P_CDFILIAL    )
         AND (I.CDPRODUTO    = P_CDPRODUTO   )
         AND (I.CDPROCFABRIC = P_CDPROCFABRIC)
       ORDER BY I.CDPRODUTO, I.CDPRODINSUMO)
   LOOP

      IF C_SEMIACABADO.QTAINSUMPREOP > 0 THEN
      
         BEGIN
         -- Consulta o estoque do dia para o semiacabado.
            SELECT PE.CDPRODUTO, SUM(QTESTDIACON) AS QTESTOQDIA
              INTO V_CDPRODESTO, V_QTESTOQDIA
              FROM POSESTCONS PE, PARAMPEDIDO PA, PRODUTO PR
             WHERE (PE.QTESTDIACON <>  0             )
               AND (PE.CDPRODUTO   = PR.CDPRODESTO   )
               AND (PE.CDFILIAL    = PA.CDFILIAL     )
               AND (NVL(PA.IDCONSESTGEROP, 'N') = 'S')
               AND (PE.CDFILIAL    = C_SEMIACABADO.CDFILIAL    )
               AND (PR.CDPRODUTO   = C_SEMIACABADO.CDPRODINSUMO)
               AND (PE.DTPOSESTCON = (
                                      SELECT MAX(PO.DTPOSESTCON)
                                        FROM POSESTCONS PO
                                       WHERE (PO.CDFILIAL     = PE.CDFILIAL )
                                         AND (PO.CDPRODUTO    = PE.CDPRODUTO)
                                         AND (PO.DTPOSESTCON <= SYSDATE+1)
                                      )
                   )
             GROUP BY PE.CDPRODUTO;
          EXCEPTION
             WHEN NO_DATA_FOUND THEN
                V_CDPRODESTO := '';
                V_QTESTOQDIA := 0;
          END;

         IF V_QTESTOQDIA > 0 THEN

            -- Verifica se a quantidade em estoque ja esta salva na tabela temporaria.
            BEGIN
               SELECT CDPRODUTO, QTDEMANDA, QTESTOQUE
                 INTO V_CDPRODEMANDA, V_QTDEMANDA, V_QTESTOQUE
                 FROM ESTSEMIACAB
                WHERE (CDFILIAL  = C_SEMIACABADO.CDFILIAL)
                  AND (NRPEDIDO  = P_NRPEDIDO  )
                  AND (CDPRODUTO = V_CDPRODESTO);
             EXCEPTION
                WHEN NO_DATA_FOUND THEN
                   V_CDPRODEMANDA := '';
                   V_QTDEMANDA    := 0;
                   V_QTESTOQUE    := 0;
             END;
              
            IF (NOT V_CDPRODEMANDA IS NULL) THEN
            
               -- Altera a quantidade da demanda deste semiacabado.
               UPDATE ESTSEMIACAB
                  SET QTDEMANDA = V_QTDEMANDA + C_SEMIACABADO.QTAINSUMPREOP
                WHERE (CDFILIAL  = C_SEMIACABADO.CDFILIAL)
                  AND (NRPEDIDO = P_NRPEDIDO     )
                  AND (CDPRODUTO = V_CDPRODEMANDA);
            
            ELSE
               -- Insere a demanda e a quantidade disponivel do semiacabado.
               INSERT INTO ESTSEMIACAB (CDFILIAL, CDPRODUTO, QTDEMANDA, QTESTOQUE, NRPEDIDO)
               VALUES (C_SEMIACABADO.CDFILIAL, V_CDPRODESTO, C_SEMIACABADO.QTAINSUMPREOP, V_QTESTOQDIA, P_NRPEDIDO);
               
            END IF;
            
            V_NOVAQT := C_SEMIACABADO.QTAINSUMPREOP - V_QTESTOQDIA;

         END IF;
      END IF;
      
      IF V_NOVAQT > 0 THEN

         -- Chama a mesma ESTOQUE_SEMIACABADO recursivamente verificando estoque para os semiacabados dos semiacabados.
         ESTOQUE_SEMIACABADO(C_SEMIACABADO.CDFILIAL, P_NRPEDIDO, C_SEMIACABADO.CDPRODINSUMO, C_SEMIACABADO.CDPROCFABRIC, V_NOVAQT);

      END IF;
   END LOOP;
END;
/