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',
   P_IDPRODSUBST   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 (SELECT I.CDPRODUTO, I.CDPROCFABRIC, I.CDFILIAL, P.CDPRODUTO AS CDPRODINSUMO, I.IDTIPOPROPOR, I.IDTIPOARREDO, S.QTBRUTA AS QTINSUMETAPA, I.QTRENDINSU, I.CDETAPAPROD
           FROM INSUMETAPA I 
          INNER JOIN PRODSUBST S
             ON I.CDPRODINSUMO = S.CDMATPRIMA
          INNER JOIN PRODUTO P
             ON P.CDPRODUTO    = S.CDPRODUTO
          WHERE I.CDPRODUTO    = P_CDPRODUTO 
            AND I.CDPROCFABRIC = P_CDPROCFABRIC
            AND I.CDFILIAL     = P_CDFILIAL
            AND P_IDPRODSUBST  = 'S'
          UNION
         SELECT I.CDPRODUTO, I.CDPROCFABRIC, I.CDFILIAL, P.CDPRODUTO AS CDPRODINSUMO, I.IDTIPOPROPOR, I.IDTIPOARREDO, I.QTINSUMETAPA, I.QTRENDINSU, I.CDETAPAPROD
           FROM INSUMETAPA I 
          INNER JOIN PRODUTO P
             ON P.CDPRODUTO     = I.CDPRODINSUMO                      
          WHERE I.CDPRODUTO     = P_CDPRODUTO
            AND I.CDPROCFABRIC  = P_CDPROCFABRIC
            AND I.CDFILIAL      = P_CDFILIAL
            AND P_IDPRODSUBST   = 'N') INS
   LEFT JOIN PROCFABRICA PR 
     ON INS.CDFILIAL     = PR.CDFILIAL    
    AND INS.CDPRODUTO    = PR.CDPRODUTO   
    AND INS.CDPROCFABRIC = PR.CDPROCFABRIC
  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 ;

   
   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;   
      
   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;
/