CREATE OR REPLACE FUNCTION QTPREVI_MATPRIMA(
   P_CDFILIAL      IN FILIAL.CDFILIAL%TYPE,
   P_CDPRODUTO     IN PRODUTO.CDPRODUTO%TYPE,
   P_CDPROCFABRIC  IN TPROCFABRICA.CDPROCFABRIC%TYPE,
   P_CDETAPAPROD   IN ETAPAPROD.CDETAPAPROD%TYPE,
   P_CDPRODINSUMO  IN PRODUTO.CDPRODUTO%TYPE,
   P_QUANTIDADE    IN FLOAT,
   P_IDPROPORCAO   IN VARCHAR2 DEFAULT 'S',
   P_NRORDPROD     IN VARCHAR2 DEFAULT 'N',
   P_NRSUBORDPROD  IN VARCHAR2 DEFAULT 'N',
   P_IDLOTEPRETAP  IN VARCHAR2 DEFAULT 'N') RETURN FLOAT IS

   V_TIPPROPORCAO       VARCHAR2(01);
   V_TIPOARREDOND       VARCHAR2(01);
   V_QTINSUMETAPA       FLOAT;
   V_QTRENDINSU         FLOAT;
   V_QTDEPREVI          FLOAT;
   V_QTPADPROCFAB       FLOAT;
   V_IDUNIDADEVRINT     VARCHAR2(01);
   V_DSUNIDMEDIDA       VARCHAR2(1000);
   V_CONTUNIDMEDIDA     INT;

   V_IDPRODDIMEVAR      VARCHAR2(1); -- Identificar de Produto Dimensionavel
   V_ALTURA_PADRAO      FLOAT;       -- Valor da Altura Padrao do Produto
   V_COMPRIMENTO_PADRAO FLOAT;       -- Valor do Comprimento Padrao do Produto
   V_ALTURA_PEDIDO      FLOAT;       -- Valor da altura do produto pedido
   V_COMPRIMENTO_PEDIDO FLOAT;       -- Valor do comprimento do produto pedido
   V_CALCULA_PROPORCAO  BOOLEAN;     -- Variavel de controle para saber se existe possibilidade de calcular dimensao
   V_DIMENSAO_PADRAO    FLOAT;       -- Dimensao padrao do produto
   V_DIMENSAO_PEDIDO    FLOAT;       -- Dimensao pedida do produto

   V_CDESPEPROD    VARCHAR2(10);
   V_QTPRACABADO   FLOAT;
   V_QTAPRODPREOP  FLOAT;
BEGIN

   SELECT
      MAX(INS.IDTIPOPROPOR),
      MAX(INS.IDTIPOARREDO),
      MAX(INS.QTINSUMETAPA),
      MAX(INS.QTRENDINSU),
      MAX(PR.QTPADPROCFAB)
   INTO
      V_TIPPROPORCAO,
      V_TIPOARREDOND,
      V_QTINSUMETAPA,
      V_QTRENDINSU,
      V_QTPADPROCFAB
   FROM
      INSUMETAPA INS,
      PROCFABRICA PR
   WHERE
      (INS.CDFILIAL     = P_CDFILIAL)     AND
      (INS.CDPRODUTO    = P_CDPRODUTO)    AND
      (INS.CDPROCFABRIC = P_CDPROCFABRIC) AND
      (INS.CDETAPAPROD  = P_CDETAPAPROD)  AND
      (INS.CDPRODINSUMO = P_CDPRODINSUMO) AND
      (INS.CDFILIAL     = PR.CDFILIAL)    AND
      (INS.CDPRODUTO    = PR.CDPRODUTO)   AND
      (INS.CDPROCFABRIC = PR.CDPROCFABRIC);

   /* O numero da ordem de producao e informado geralmente
   na inicializacao da OP. Nesse caso e necessario verificar se o produto e um produto de dimensao variavel( Cadastro de Produto).
   Em caso positivo, verifica se a OP informada esta ligada a algum pedido.
   E necessario verificar tambem se o produto possui Dimensao Padrao informado (Processo de Fabricacao) e Dimensao Pedida(Lancamento
   de Pedidos).
   Se todas essas condicoes estiverem OK, o sistema consegue calcular a quantidade proporcional do insumo, senao
   a funcao e chamada novamente (com a variavel P_NRORDPROD = '') para calcular os insumos normalmente*/
   SELECT MAX(CDESPEPROD)
     INTO V_CDESPEPROD
     FROM ESPEPROD
    WHERE (CDFILIAL = P_CDFILIAL)
      AND (CDPRODUTO  = P_CDPRODUTO)
      AND (DTVALESPEPRO = (SELECT MAX(DTVALESPEPRO)
                             FROM ESPEPROD
                            WHERE (CDFILIAL = P_CDFILIAL)
                              AND (CDPRODUTO  = P_CDPRODUTO)
                              AND (DTVALESPEPRO < SYSDATE)));
   IF V_CDESPEPROD IS NULL THEN
      SELECT MAX(E1.CDESPEPROD)
        INTO V_CDESPEPROD
        FROM ESPEPROD E1
       WHERE (E1.CDPRODUTO  = P_CDPRODUTO)
         AND (E1.DTVALESPEPRO = (SELECT MAX(E2.DTVALESPEPRO)
                                FROM ESPEPROD E2
                               WHERE (E1.CDFILIAL = E2.CDFILIAL)
                                 AND (E1.CDPRODUTO  = E2.CDPRODUTO)
                                 AND (E2.DTVALESPEPRO < SYSDATE)));
   END IF;

   IF V_CDESPEPROD IS NOT NULL THEN
      BEGIN
         SELECT MAX(QTPRODTCOMP)
           INTO V_QTRENDINSU
           FROM TCOMPPRO TC
          WHERE (TC.CDPRODUTO  = P_CDPRODUTO)
            AND (TC.CDESPEPROD = V_CDESPEPROD)
            AND (NVL(TC.IDTCOMPPROC,'N') = 'S');
      EXCEPTION
          WHEN NO_DATA_FOUND THEN
               V_QTRENDINSU := 0;
      END;
      IF  V_QTRENDINSU = 0 THEN
          SELECT MAX(QTPRODTCOMP)
            INTO V_QTRENDINSU
            FROM TCOMPPRO TC
           WHERE (TC.CDPRODUTO  = P_CDPRODUTO)
             AND (TC.CDESPEPROD = V_CDESPEPROD);
      END IF;
   END IF;

   IF (NVL(P_IDLOTEPRETAP, 'N') <> 'S') THEN
      IF P_IDPROPORCAO = 'S' THEN
         IF V_TIPPROPORCAO = 'N' THEN
            IF V_TIPOARREDOND = '1' THEN
               V_QTDEPREVI := TRUNC((P_QUANTIDADE * V_QTINSUMETAPA) / V_QTRENDINSU)+1;
            ELSE
               IF V_TIPOARREDOND = '2' THEN
                  V_QTDEPREVI := TRUNC((P_QUANTIDADE * V_QTINSUMETAPA) / V_QTRENDINSU);
               ELSE
                  V_QTDEPREVI := ((P_QUANTIDADE * V_QTINSUMETAPA) / V_QTRENDINSU);
               END IF;
            END IF;
         ELSE
            IF V_TIPPROPORCAO = 'L' THEN
               IF V_TIPOARREDOND = '1' THEN
                  IF (MOD(P_QUANTIDADE, V_QTPADPROCFAB) <> 0) THEN
                     V_QTDEPREVI := ((TRUNC(P_QUANTIDADE / V_QTPADPROCFAB) + 1) * V_QTINSUMETAPA);
                  ELSE
                     V_QTDEPREVI := ((P_QUANTIDADE / V_QTPADPROCFAB) * V_QTINSUMETAPA);
                  END IF;
               ELSE
                  IF V_TIPOARREDOND = '2' THEN
                     V_QTDEPREVI := ((TRUNC(P_QUANTIDADE / V_QTPADPROCFAB)) * V_QTINSUMETAPA);
                  END IF;
               END IF;
            ELSE
               IF V_TIPPROPORCAO = 'U' THEN
                  V_QTDEPREVI := V_QTINSUMETAPA;
               ELSE
                  IF V_TIPPROPORCAO = 'I' THEN
                     IF V_TIPOARREDOND = '0' THEN
                        V_QTDEPREVI := (ROUND((P_QUANTIDADE / V_QTPADPROCFAB) * V_QTINSUMETAPA));
                     ELSE
                        IF V_TIPOARREDOND = '1' THEN
                           IF (MOD(P_QUANTIDADE, V_QTINSUMETAPA) <> 0) THEN
                              IF (MOD(ROUND(((P_QUANTIDADE / V_QTPADPROCFAB) * V_QTINSUMETAPA)),1)= 0) THEN
                                  V_QTDEPREVI := (ROUND((P_QUANTIDADE / V_QTPADPROCFAB) * V_QTINSUMETAPA));
                              ELSE
                                  V_QTDEPREVI := (TRUNC((P_QUANTIDADE / V_QTPADPROCFAB) * V_QTINSUMETAPA)+ 1);
                              END IF;
                           ELSE
                              V_QTDEPREVI := ((P_QUANTIDADE / V_QTPADPROCFAB) * V_QTINSUMETAPA);
                           END IF;
                        ELSE
                           IF V_TIPOARREDOND = '2' THEN
                              V_QTDEPREVI := (TRUNC((P_QUANTIDADE / V_QTPADPROCFAB) * V_QTINSUMETAPA));
                           END IF;
                        END IF;
                     END IF;
                  END IF;
               END IF;
            END IF;
         END IF;
      ELSE
         V_QTDEPREVI := ((P_QUANTIDADE * V_QTINSUMETAPA) / V_QTRENDINSU);
      END IF;
   ELSE
      IF (NVL(P_NRORDPROD, 'N') <> 'N') THEN
         SELECT SUM(P.QTPRACABADO) QTPRACABADO, SUM(O.QTAPRODPREOP) QTAPRODPREOP
           INTO V_QTPRACABADO, V_QTAPRODPREOP
           FROM ORDPRODUCAO O, PRODACABADO P
          WHERE O.CDFILIAL     = P_CDFILIAL
            AND O.NRORDPROD    = P_NRORDPROD
            AND O.NRSUBORDPROD = TO_CHAR(TO_NUMBER(P_NRSUBORDPROD)-1)
            AND O.CDFILIAL     = P.CDFILIAL
            AND O.CDPRODUTO    = P.CDPRODUTO
            AND O.NRORDPROD    = P.NRORDPROD
            AND O.NRSUBORDPROD = P.NRSUBORDPROD
            AND O.CDPRODUTO    = P.CDPRODUTO;

         V_QTDEPREVI := V_QTPRACABADO;
      ELSE
         IF P_IDPROPORCAO = 'S' THEN
            IF V_TIPPROPORCAO = 'N' THEN
               IF V_TIPOARREDOND = '1' THEN
                  V_QTDEPREVI := TRUNC((P_QUANTIDADE * V_QTINSUMETAPA) / V_QTRENDINSU)+1;
               ELSE
                  IF V_TIPOARREDOND = '2' THEN
                     V_QTDEPREVI := TRUNC((P_QUANTIDADE * V_QTINSUMETAPA) / V_QTRENDINSU);
                  ELSE
                     V_QTDEPREVI := ((P_QUANTIDADE * V_QTINSUMETAPA) / V_QTRENDINSU);
                  END IF;
               END IF;
            ELSE
               IF V_TIPPROPORCAO = 'L' THEN
                  IF V_TIPOARREDOND = '1' THEN
                     IF (MOD(P_QUANTIDADE, V_QTPADPROCFAB) <> 0) THEN
                        V_QTDEPREVI := ((TRUNC(P_QUANTIDADE / V_QTPADPROCFAB) + 1) * V_QTINSUMETAPA);
                     ELSE
                        V_QTDEPREVI := ((P_QUANTIDADE / V_QTPADPROCFAB) * V_QTINSUMETAPA);
                     END IF;
                  ELSE
                     IF V_TIPOARREDOND = '2' THEN
                        V_QTDEPREVI := ((TRUNC(P_QUANTIDADE / V_QTPADPROCFAB)) * V_QTINSUMETAPA);
                     END IF;
                  END IF;
               ELSE
                  IF V_TIPPROPORCAO = 'U' THEN
                     V_QTDEPREVI := V_QTINSUMETAPA;
                  ELSE
                     IF V_TIPPROPORCAO = 'I' THEN
                        IF V_TIPOARREDOND = '0' THEN
                           V_QTDEPREVI := (ROUND((P_QUANTIDADE / V_QTPADPROCFAB) * V_QTINSUMETAPA));
                        ELSE
                           IF V_TIPOARREDOND = '1' THEN
                              IF (MOD(P_QUANTIDADE, V_QTINSUMETAPA) <> 0) THEN
                                 IF (MOD(ROUND(((P_QUANTIDADE / V_QTPADPROCFAB) * V_QTINSUMETAPA)),1)= 0) THEN
                                    V_QTDEPREVI := (ROUND((P_QUANTIDADE / V_QTPADPROCFAB) * V_QTINSUMETAPA));
                                 ELSE
                                    V_QTDEPREVI := (TRUNC((P_QUANTIDADE / V_QTPADPROCFAB) * V_QTINSUMETAPA)+ 1);
                                 END IF;
                              ELSE
                                 V_QTDEPREVI := ((P_QUANTIDADE / V_QTPADPROCFAB) * V_QTINSUMETAPA);
                              END IF;
                           ELSE
                              IF V_TIPOARREDOND = '2' THEN
                                 V_QTDEPREVI := (TRUNC((P_QUANTIDADE / V_QTPADPROCFAB) * V_QTINSUMETAPA));
                              END IF;
                           END IF;
                        END IF;
                     END IF;
                  END IF;
               END IF;
            END IF;
         ELSE
            V_QTDEPREVI := ((P_QUANTIDADE * V_QTINSUMETAPA) / V_QTRENDINSU);
         END IF;
      END IF;   
      /*  
      -- Proporcao deve ser normal
      IF V_TIPPROPORCAO = 'N' THEN
         V_CALCULA_PROPORCAO := TRUE;
      ELSE
         V_CALCULA_PROPORCAO := FALSE;
      END IF;

      -- Produto Dimensionavel
      IF V_CALCULA_PROPORCAO THEN
         BEGIN
            SELECT NVL(IDPRODDIMEVAR, 'N') IDPRODDIMEVAR
              INTO V_IDPRODDIMEVAR
              FROM PRODUTO
             WHERE CDPRODUTO = P_CDPRODUTO;
         EXCEPTION
            WHEN NO_DATA_FOUND THEN
               V_IDPRODDIMEVAR := 'N';
         END;
      END IF;

      IF V_IDPRODDIMEVAR = 'S' THEN
         V_CALCULA_PROPORCAO := TRUE;
      ELSE
         V_CALCULA_PROPORCAO := FALSE;
      END IF;

      -- Verifica se existe dimensao padrao cadastrada
      IF V_CALCULA_PROPORCAO THEN
         BEGIN
            SELECT NVL(P.VRALTPADRPROD, 0) VRALTPADRPROD,
                   NVL(P.VRCOMPADRPROD, 0) VRCOMPADRPROD
              INTO V_ALTURA_PADRAO, V_COMPRIMENTO_PADRAO
              FROM PROCFABRICA P, ORDPRODUCAO O
             WHERE P.CDPRODUTO      = P_CDPRODUTO    AND
                   P.CDFILIAL       = P_CDFILIAL     AND
                   P.CDFILIAL       = O.CDFILIAL     AND
                   P.CDPRODUTO      = O.CDPRODUTO    AND
                   P.CDPROCFABRIC   = O.CDPROCFABRIC AND
                   O.NRORDPROD      = P_NRORDPROD    AND
                   O.NRSUBORDPROD   = P_NRSUBORDPROD AND
                   P.IDCALCINSUPROP = 'S';
         EXCEPTION
            WHEN NO_DATA_FOUND THEN
               V_ALTURA_PADRAO      := 0;
               V_COMPRIMENTO_PADRAO := 0;
         END;

         IF ((V_ALTURA_PADRAO = 0) OR (V_COMPRIMENTO_PADRAO = 0)) THEN
            V_CALCULA_PROPORCAO := FALSE;
         END IF;

      END IF;

      IF V_CALCULA_PROPORCAO THEN
         -- Verifica se existe dimensao informada no pedido
         BEGIN
            SELECT NVL(I.VRALTURAPROD, 0) VRALTURAPROD,
                   NVL(I.VRCOMPRIPROD, 0) VRCOMPRIPROD
              INTO V_ALTURA_PEDIDO, V_COMPRIMENTO_PEDIDO
              FROM ITEMPEDIDO I, ORDPRODUCAO O
             WHERE I.CDFILIAL     = P_CDFILIAL  AND
                   I.CDPRODUTO    = P_CDPRODUTO AND
                   I.CDFILIAL     = O.CDFILIAL  AND
                   I.CDPRODUTO    = O.CDPRODUTO AND
                   I.NRPEDIDO     = O.NRPEDIDO  AND
                   I.NRITEMPED    = O.NRITEMPED AND
                   O.NRORDPROD    = P_NRORDPROD AND
                   O.NRSUBORDPROD = P_NRSUBORDPROD;
         EXCEPTION
            WHEN NO_DATA_FOUND THEN
               V_ALTURA_PEDIDO      := 0;
               V_COMPRIMENTO_PEDIDO := 0;
         END;

         IF ((V_ALTURA_PEDIDO = 0) OR (V_COMPRIMENTO_PEDIDO = 0)) THEN
            V_CALCULA_PROPORCAO := FALSE;
         END IF;

      END IF;

      -- Se nao for possivel calcular a quantidade de materia prima de acordo com os parametros informados de dimensoes,
      -- o sistema calcula a quantidade proporcional normalmente chamando novamente a funcao (Informando N para o parametro de OP)

      IF NOT V_CALCULA_PROPORCAO THEN
         V_QTDEPREVI := QTPREVI_MATPRIMA(P_CDFILIAL, P_CDPRODUTO, P_CDPROCFABRIC, P_CDETAPAPROD, P_CDPRODINSUMO, P_QUANTIDADE, P_IDPROPORCAO, 'N', 'N');
      ELSE
         -- Realiza o calculo da dimensao
         -- Dimensao_Padrao(area padrao)     ------- Quantidade_Materia_Prima
         -- Dimensao_Pedida(area do pedido)  ------- X
         

         V_DIMENSAO_PADRAO := V_ALTURA_PADRAO * V_COMPRIMENTO_PADRAO;
         V_DIMENSAO_PEDIDO := V_ALTURA_PEDIDO * V_COMPRIMENTO_PEDIDO;

         V_QTDEPREVI := ((V_DIMENSAO_PEDIDO * V_QTINSUMETAPA) / V_DIMENSAO_PADRAO);
      END IF;
      */
   END IF;

   -- Verifica, de acordo com a unidade de medida, se o valor encontrado deve somente valor inteiro
   BEGIN
      SELECT NVL(P.IDUNIDADEVRINT, 'N'), P.DSUNIDMEDIDA, INSTR(P.DSUNIDMEDIDA, PR.SGUNIDADE)
        INTO V_IDUNIDADEVRINT, V_DSUNIDMEDIDA, V_CONTUNIDMEDIDA
        FROM PARAMAN P, PRODUTO PR
       WHERE P.CDFILIAL   = P_CDFILIAL
         AND PR.CDPRODUTO = P_CDPRODINSUMO;
   EXCEPTION
      WHEN NO_DATA_FOUND THEN
      V_IDUNIDADEVRINT := NULL;
      V_DSUNIDMEDIDA   := NULL;
      V_CONTUNIDMEDIDA := 0;
   END;

   IF (V_IDUNIDADEVRINT = 'S') AND (V_CONTUNIDMEDIDA > 0) THEN
      IF TRUNC(V_QTDEPREVI, 0) > 0 THEN
         IF (V_QTDEPREVI / TRUNC(V_QTDEPREVI, 0)) <> 1 THEN
            V_QTDEPREVI := V_QTDEPREVI + 1;
            V_QTDEPREVI := TRUNC(V_QTDEPREVI, 0);
         END IF;
      ELSE
         V_QTDEPREVI := V_QTDEPREVI + 1;
         V_QTDEPREVI := TRUNC(V_QTDEPREVI, 0);      
      END IF;
   END IF;

   RETURN(V_QTDEPREVI);
END;
/