CREATE OR REPLACE PROCEDURE PRECO_ECON_ITMAPURPREC
  (P_CDCENTITMAP  IN VARCHAR2,
   P_NRSEQITMAP   IN VARCHAR2,
   P_CDREGITMAP   IN VARCHAR2 DEFAULT NULL,
   P_CDFORNITMAP  IN VARCHAR2 DEFAULT NULL,
   P_NRCOLEITMAP  IN VARCHAR2 DEFAULT NULL,
   P_CDPRODITMAP  IN VARCHAR2 DEFAULT NULL,
   P_CDMARCITMAP  IN VARCHAR2 DEFAULT NULL)
IS
   V_DTCOLEPREC    COLETAPR.DTCOLEPREC%TYPE;
   V_DTPARCELA    DATE;
   V_NRDIAS       NUMBER;
   V_NRFATOR      NUMBER;
   V_VRINDICE     NUMBER;
   V_DTULDIAMES   DATE;
   V_DTULTAUX     DATE;
   V_FATORPARC    NUMBER;
   V_VRPRECECO    NUMBER;
   V_VRPZOPGT     NUMBER;
   V_CONTA        NUMBER;
   V_DTPRIPARC    DATE;
   V_TOTREST      NUMBER;

   V_VRPERDESITM  ITEMCOLE.VRPERDESITM%TYPE;
   V_VRIMPITM     IMPCOLET.VRADIMPCOL%TYPE;
   V_AUXVRIMPITM  IMPCOLET.VRADIMPCOL%TYPE;
   V_VRRENDATUMAR MARCPROD.VRRENDATUMAR%TYPE;
   V_CDEMPRESA    PARCMPSUP.CDEMPRESA%TYPE;
   V_INSCESTA     FILIAL.CDINSCESTA%TYPE;
   V_IDUTDESCBON  PARASUPRI.IDUTDESCBON%TYPE;
   V_IDTPDESCFORN FORNECEDOR.IDTPDESCFORN%TYPE;
   V_VRPEDESCFORN FORNECEDOR.VRPEDESCFORN%TYPE;

   V_TESTENR      NUMBER;
   V_VRPERPIFORN  NUMBER;
   V_VRPRECECOPI  NUMBER;

   V_TIPOOPER     VARCHAR2(02);

   V_IDDTREPRECON PARASUPRI.IDDTREPRECON%TYPE;
   TYPE CURTYPE             IS REF CURSOR;
   C_PARCELAS               CURTYPE;
BEGIN
   FOR C_PRODUTO IN (SELECT I.NRSEQITMAP, I.CDREGITMAP, I.CDFORNITMAP, I.NRCOLEITMAP, MIN(I.DTENTRAPUT) DTENTRAPUT, I.CDFILIAP, I.CDPRODITMAP,
                            I.CDMARCITMAP, I.IDTIPOFRETAP, I.VRPRECUNIAP, COLETAPR.DTCOLEPREC, COLETAPR.DTINIVALCOL,
                            NVL(I.VRPERDESIAP, 0) VRPERDESIAP, I.IDTPFORPGTAP, I.CDFORMPGTOAP, I.NRDIAPGFIAP, I.IDULTDIAPGTAF,
                            I.NRPARCPGTOAP
                       FROM ITMAPURPREC I, COLETAPR
                      WHERE I.CDCENTITMAP        = P_CDCENTITMAP
                        AND I.NRSEQITMAP         = P_NRSEQITMAP
                        AND COLETAPR.CDFILIAL    = P_CDCENTITMAP
                        AND COLETAPR.NRCOLEPRECO = I.NRCOLEITMAP
                        AND I.CDREGITMAP         = NVL(P_CDREGITMAP, I.CDREGITMAP)
                        AND I.CDFORNITMAP        = NVL(P_CDFORNITMAP, I.CDFORNITMAP)
                        AND I.NRCOLEITMAP        = NVL(P_NRCOLEITMAP, I.NRCOLEITMAP)
                        AND I.CDPRODITMAP        = NVL(P_CDPRODITMAP, I.CDPRODITMAP)
                        AND I.CDMARCITMAP        = NVL(P_CDMARCITMAP, I.CDMARCITMAP)
                      GROUP BY I.NRSEQITMAP, I.CDREGITMAP, I.CDFORNITMAP, I.NRCOLEITMAP, I.CDFILIAP, I.CDPRODITMAP,
                            I.CDMARCITMAP, I.IDTIPOFRETAP, I.VRPRECUNIAP, COLETAPR.DTCOLEPREC, COLETAPR.DTINIVALCOL,
                            NVL(I.VRPERDESIAP, 0), I.IDTPFORPGTAP, I.CDFORMPGTOAP, I.NRDIAPGFIAP, I.IDULTDIAPGTAF,
                            I.NRPARCPGTOAP
                      ORDER BY I.NRCOLEITMAP, I.CDREGITMAP, I.CDFILIAP, I.CDPRODITMAP, I.CDMARCITMAP)
   LOOP
      SELECT
        NVL(IDDTREPRECON, '1') INTO V_IDDTREPRECON
      FROM
        PARASUPRI
      WHERE
        CDFILIAL = P_CDCENTITMAP;

      IF V_IDDTREPRECON = '1' THEN
         SELECT MAX(DTCOLEPREC)
           INTO V_DTCOLEPREC -- Busca a data da Coleta
           FROM COLETAPR
          WHERE CDFILIAL    =  P_CDCENTITMAP
            AND NRCOLEPRECO =  C_PRODUTO.NRCOLEITMAP;
      ELSE
         V_DTCOLEPREC := C_PRODUTO.DTINIVALCOL;
      END IF;
      --Busca o valor de redimento para o produto e marca da coleta
      SELECT MAX(QFOMARPROD.VRRENDATU)
        INTO V_VRRENDATUMAR
        FROM QFOMARPROD
       WHERE QFOMARPROD.CDPRODUTO = C_PRODUTO.CDPRODITMAP
         AND QFOMARPROD.CDMARCA   = C_PRODUTO.CDMARCITMAP;
      --Busca o total do imposto calculado para o item da coleta
      SELECT NVL(SUM(VRADIMPOSTOIT), 0)
        INTO V_VRIMPITM
        FROM ITMAPURPRECIMPO
       WHERE CDCENTITMAP    = P_CDCENTITMAP
         AND NRSEQITMAP     = P_NRSEQITMAP
         AND CDREGITMAP     = C_PRODUTO.CDREGITMAP
         AND CDFORNITMAP    = C_PRODUTO.CDFORNITMAP
         AND NRCOLEITMAP    = C_PRODUTO.NRCOLEITMAP
         AND CDFILIAP       = C_PRODUTO.CDFILIAP
         AND CDPRODITMAP    = C_PRODUTO.CDPRODITMAP
         AND CDMARCITMAP    = C_PRODUTO.CDMARCITMAP;

      V_VRPERDESITM := C_PRODUTO.VRPERDESIAP;
      SELECT NVL(MAX(IDUTDESCBON), 'N')
        INTO V_IDUTDESCBON
        FROM PARASUPRI
       WHERE CDFILIAL = P_CDCENTITMAP;
      IF V_IDUTDESCBON = 'S' THEN
         SELECT NVL(MAX(IDTPDESCFORN), 'C'), MAX(VRPEDESCFORN)
           INTO V_IDTPDESCFORN, V_VRPEDESCFORN
           FROM FORNECEDOR
          WHERE CDFORNECED = C_PRODUTO.CDFORNITMAP;
         IF V_IDTPDESCFORN = 'B' THEN
            IF (V_VRPEDESCFORN IS NOT NULL) AND (V_VRPEDESCFORN <> 0) THEN
               V_VRPERDESITM := V_VRPEDESCFORN;
            END IF;
         END IF;
      END IF;

      IF (V_VRRENDATUMAR IS NULL) OR (V_VRRENDATUMAR = 0) THEN
         V_VRRENDATUMAR := 1;
      END IF;
      V_VRPRECECO := 0;
      V_VRPRECECOPI := 0;

      -- *** Se forma de pagamento for Variavel
      IF C_PRODUTO.IDTPFORPGTAP = 'V' THEN
        -- Busca a data da primeira parcela se basendo na media de dias entre uma
        -- parcela e outra.
        SELECT
         MIN(ROUND((TO_NUMBER(NVL(DIAPGTO.NRDIAFINPGTO,1)) - 1)/2) +
         V_DTCOLEPREC) INTO V_DTPRIPARC
        FROM
         DIAPGTO
        WHERE
         DIAPGTO.CDFORMPGTO               = C_PRODUTO.CDFORMPGTOAP AND
         TO_NUMBER(DIAPGTO.NRDIAINIPGTO ) = 1;

        IF V_DTPRIPARC IS NULL THEN
           V_DTPRIPARC := V_DTCOLEPREC;
        END IF;

        V_TOTREST := 0;
        OPEN C_PARCELAS FOR
           SELECT V_DTPRIPARC + PZOPGTITMCOL.NRDIASPGTCOL AS DTPARCELA,
                  PZOPGTITMCOL.VRPERCPGTCOL               AS VRPZOPGT
             FROM PZOPGTITMCOL
            WHERE PZOPGTITMCOL.CDFILIAL    = P_CDCENTITMAP
              AND PZOPGTITMCOL.NRCOLEPRECO = C_PRODUTO.NRCOLEITMAP
              AND PZOPGTITMCOL.CDFORNECED  = C_PRODUTO.CDFORNITMAP
              AND PZOPGTITMCOL.CDREGIAO    = C_PRODUTO.CDREGITMAP
              AND PZOPGTITMCOL.CDPRODUTO   = C_PRODUTO.CDPRODITMAP
              AND PZOPGTITMCOL.CDMARCA     = C_PRODUTO.CDMARCITMAP;
        LOOP
           FETCH C_PARCELAS INTO V_DTPARCELA, V_VRPZOPGT;
           EXIT WHEN C_PARCELAS%NOTFOUND;

           V_NRFATOR := 1;
           V_DTULDIAMES := LAST_DAY(V_DTCOLEPREC);
           V_NRDIAS := LAST_DAY(V_DTCOLEPREC)-V_DTCOLEPREC;
           V_DTULTAUX := V_DTCOLEPREC;

           IF V_DTULDIAMES = V_DTCOLEPREC THEN
              WHILE V_DTPARCELA > V_DTULDIAMES LOOP
                 -- Busca o indice a ser aplicado para correcao
                 SELECT MAX(MOVINDICE.VRINDICE)
                   INTO V_VRINDICE
                   FROM PARASUPRI, MOVINDICE
                  WHERE PARASUPRI.CDFILIAL  = P_CDCENTITMAP
                    AND TO_CHAR(MOVINDICE.DTREFIND,'MMYYYY') = TO_CHAR(V_DTULDIAMES,'MMYYYY')
                    AND PARASUPRI.CDTPINDICE = MOVINDICE.CDTPINDICE
                    AND PARASUPRI.IDPERVALOR = MOVINDICE.IDPERVALOR
                    AND PARASUPRI.CDINDICE   = MOVINDICE.CDINDICE;
                 IF V_VRINDICE IS NULL THEN
                    V_VRINDICE := 0;
                 END IF;
                 V_NRFATOR     := V_NRFATOR * (1 + (V_VRINDICE/100))**(V_NRDIAS/30);
                 V_DTULTAUX    := V_DTULDIAMES;
                 V_DTULDIAMES  := LAST_DAY(V_DTULDIAMES+1);
                 V_NRDIAS      := V_DTULDIAMES - V_DTULTAUX;
              END LOOP;
           ELSE
              WHILE V_DTPARCELA > V_DTULDIAMES LOOP
                 -- Busca o indice a ser aplicado para correcao
                 SELECT MAX(MOVINDICE.VRINDICE)
                   INTO V_VRINDICE
                   FROM PARASUPRI, MOVINDICE
                  WHERE PARASUPRI.CDFILIAL   = P_CDCENTITMAP
                     AND TO_CHAR(MOVINDICE.DTREFIND,'MMYYYY') = TO_CHAR(V_DTULDIAMES,'MMYYYY')
                     AND PARASUPRI.CDTPINDICE = MOVINDICE.CDTPINDICE
                     AND PARASUPRI.IDPERVALOR = MOVINDICE.IDPERVALOR
                     AND PARASUPRI.CDINDICE   = MOVINDICE.CDINDICE;
                 IF V_VRINDICE IS NULL THEN
                    V_VRINDICE := 0;
                 END IF;
                 V_NRFATOR     := V_NRFATOR * (1 + (V_VRINDICE/100))**(V_NRDIAS/30);
                 V_DTULTAUX    := V_DTULDIAMES;
                 V_DTULDIAMES  := LAST_DAY(V_DTULDIAMES+1);
                 V_NRDIAS      := V_DTULDIAMES - V_DTULTAUX;
              END LOOP;
           END IF;

           V_NRDIAS := V_DTPARCELA - V_DTULTAUX;
           -- Busca o indice a ser aplicado para correcao
           SELECT MAX(MOVINDICE.VRINDICE)
             INTO V_VRINDICE
             FROM PARASUPRI, MOVINDICE
            WHERE PARASUPRI.CDFILIAL                   = P_CDCENTITMAP
              AND TO_CHAR(MOVINDICE.DTREFIND,'MMYYYY') = TO_CHAR(V_DTPARCELA,'MMYYYY')
              AND PARASUPRI.CDTPINDICE                 = MOVINDICE.CDTPINDICE
              AND PARASUPRI.IDPERVALOR                 = MOVINDICE.IDPERVALOR
              AND PARASUPRI.CDINDICE                   = MOVINDICE.CDINDICE;
           IF V_VRINDICE IS NULL THEN
              V_VRINDICE := 0;
           END IF;
           V_NRFATOR := V_NRFATOR * (1 + (V_VRINDICE/100))**(V_NRDIAS/30);
           V_TOTREST := V_TOTREST + ((1 / V_NRFATOR) * (V_VRPZOPGT/100));
        END LOOP;
        CLOSE C_PARCELAS;
        V_VRPRECECO := ROUND((C_PRODUTO.VRPRECUNIAP - (C_PRODUTO.VRPRECUNIAP * (V_VRPERDESITM /100)) + V_VRIMPITM) *
                       (1/V_VRRENDATUMAR) * V_TOTREST,5);

        V_VRPRECECOPI := ROUND((C_PRODUTO.VRPRECUNIAP - (C_PRODUTO.VRPRECUNIAP * (V_VRPERDESITM /100)) + V_VRIMPITM) * V_TOTREST,5);

      -- *** Se forma de pagamento for Fixa
      ELSIF C_PRODUTO.IDTPFORPGTAP = 'F' THEN

         V_TESTENR := C_PRODUTO.NRDIAPGFIAP;
         IF C_PRODUTO.NRDIAPGFIAP > TO_NUMBER(TO_CHAR(LAST_DAY(V_DTCOLEPREC), 'DD')) THEN
           V_TESTENR := TO_NUMBER(TO_CHAR(LAST_DAY(V_DTCOLEPREC), 'DD'));
         END IF;

         -- Apura a data inicial de pagamento baseado na condicao informada
         IF TO_DATE(LPAD(TO_CHAR(V_TESTENR),2,'0') ||
            TO_CHAR(V_DTCOLEPREC,'MMYYYY'),'DDMMYYYY') >
            V_DTCOLEPREC AND C_PRODUTO.IDULTDIAPGTAF = 'I' THEN

            V_DTPARCELA := TO_DATE(LPAD(TO_CHAR(V_TESTENR),2,'0') ||
                           TO_CHAR(V_DTCOLEPREC,'MMYYYY'),'DDMMYYYY');
         END IF;
         IF (TO_DATE(LPAD(TO_CHAR(V_TESTENR),2,'0') ||
             TO_CHAR(V_DTCOLEPREC,'MMYYYY'),'DDMMYYYY') <=
             V_DTCOLEPREC AND C_PRODUTO.IDULTDIAPGTAF = 'I') OR
            (C_PRODUTO.IDULTDIAPGTAF = 'E') THEN

            V_DTPARCELA := C_PRODUTO.NRDIAPGFIAP + LAST_DAY(V_DTCOLEPREC);

         END IF;

         V_FATORPARC := 0;
         V_CONTA := 1;
         V_NRFATOR := 1;
         V_DTULTAUX := V_DTCOLEPREC;

         -- Calcula fator de correcao de acordo com o numero de parcelas informadas.
         FOR V_CONTA IN 1..C_PRODUTO.NRPARCPGTOAP LOOP
            V_DTULDIAMES  := LAST_DAY(V_DTCOLEPREC);
            V_NRDIAS      := LAST_DAY(V_DTCOLEPREC)-V_DTCOLEPREC;
            V_DTULTAUX    := V_DTCOLEPREC;

            IF V_DTCOLEPREC = V_DTULDIAMES THEN
               WHILE V_DTPARCELA > V_DTULDIAMES LOOP
                 -- Busca o indice a ser aplicado para correcao
                 SELECT MAX(MOVINDICE.VRINDICE)
                   INTO V_VRINDICE
                   FROM PARASUPRI, MOVINDICE
                  WHERE PARASUPRI.CDFILIAL                 = P_CDCENTITMAP
                    AND TO_CHAR(MOVINDICE.DTREFIND,'MMYYYY') = TO_CHAR(V_DTULDIAMES,'MMYYYY')
                    AND PARASUPRI.CDTPINDICE                 = MOVINDICE.CDTPINDICE
                    AND PARASUPRI.IDPERVALOR                 = MOVINDICE.IDPERVALOR
                    AND PARASUPRI.CDINDICE                   = MOVINDICE.CDINDICE;

                 IF V_VRINDICE IS NULL THEN
                    V_VRINDICE := 0;
                 END IF;
                 V_NRFATOR    := V_NRFATOR * (1 + (V_VRINDICE/100))**(V_NRDIAS/30);
                 V_DTULTAUX   := V_DTULDIAMES;
                 V_DTULDIAMES := LAST_DAY(V_DTULDIAMES+1);
                 V_NRDIAS     := V_DTULDIAMES - V_DTULTAUX;
               END LOOP;
            ELSE
               WHILE V_DTPARCELA > V_DTULDIAMES LOOP
                 -- Busca o indice a ser aplicado para correcao
                 SELECT MAX(MOVINDICE.VRINDICE)
                   INTO V_VRINDICE
                   FROM PARASUPRI, MOVINDICE
                  WHERE PARASUPRI.CDFILIAL                 = P_CDCENTITMAP
                    AND TO_CHAR(MOVINDICE.DTREFIND,'MMYYYY') = TO_CHAR(V_DTULDIAMES,'MMYYYY')
                    AND PARASUPRI.CDTPINDICE                 = MOVINDICE.CDTPINDICE
                    AND PARASUPRI.IDPERVALOR                 = MOVINDICE.IDPERVALOR
                    AND PARASUPRI.CDINDICE                   = MOVINDICE.CDINDICE;
                 IF V_VRINDICE IS NULL THEN
                    V_VRINDICE := 0;
                 END IF;
                 V_NRFATOR    := V_NRFATOR * (1 + (V_VRINDICE/100))**(V_NRDIAS/30);
                 V_DTULTAUX   := V_DTULDIAMES;
                 V_DTULDIAMES := LAST_DAY(V_DTULDIAMES+1);
                 V_NRDIAS     := V_DTULDIAMES - V_DTULTAUX;
                END LOOP;
            END IF;
            V_NRDIAS := V_DTPARCELA - V_DTULTAUX;
            -- Busca o indice a ser aplicado para correcao
            SELECT MAX(MOVINDICE.VRINDICE)
              INTO V_VRINDICE
              FROM PARASUPRI, MOVINDICE
             WHERE PARASUPRI.CDFILIAL                 = P_CDCENTITMAP
               AND TO_CHAR(MOVINDICE.DTREFIND,'MMYYYY') = TO_CHAR(V_DTPARCELA,'MMYYYY')
               AND PARASUPRI.CDTPINDICE                 = MOVINDICE.CDTPINDICE
               AND PARASUPRI.IDPERVALOR                 = MOVINDICE.IDPERVALOR
               AND PARASUPRI.CDINDICE                   = MOVINDICE.CDINDICE;
            IF V_VRINDICE IS NULL THEN
               V_VRINDICE := 0;
            END IF;
            V_NRFATOR            := V_NRFATOR * (1 + (V_VRINDICE/100))**(V_NRDIAS/30);
            V_FATORPARC          := V_FATORPARC + (1/V_NRFATOR);
            V_DTPARCELA := ADD_MONTHS(V_DTPARCELA,1);
         END LOOP;
         V_VRPRECECO := ROUND(((C_PRODUTO.VRPRECUNIAP -
                        (C_PRODUTO.VRPRECUNIAP * (V_VRPERDESITM /100)) +
                         V_VRIMPITM) / C_PRODUTO.NRPARCPGTOAP) *
                         (1/V_VRRENDATUMAR) *
                         V_FATORPARC,5);

         V_VRPRECECOPI := ROUND(((C_PRODUTO.VRPRECUNIAP -
                          (C_PRODUTO.VRPRECUNIAP * (V_VRPERDESITM /100)) +
                           V_VRIMPITM) / C_PRODUTO.NRPARCPGTOAP) *
                           V_FATORPARC,5);

      ELSIF C_PRODUTO.IDTPFORPGTAP IS NULL THEN
        -- Se nao foi informado forma de pagamento
         V_VRPRECECO := ROUND((C_PRODUTO.VRPRECUNIAP -
                        (C_PRODUTO.VRPRECUNIAP * (V_VRPERDESITM /100)) +
                         V_VRIMPITM) *
                         (1/V_VRRENDATUMAR),5);

         V_VRPRECECOPI := ROUND((C_PRODUTO.VRPRECUNIAP -
                          (C_PRODUTO.VRPRECUNIAP * (V_VRPERDESITM /100)) +
                           V_VRIMPITM), 5);
      END IF;
      SELECT NVL(MAX(VRPERPIPRFO), 0) INTO V_VRPERPIFORN /* PROCURA O PI NA PRODFORNCOMP*/
        FROM PRODFORNCOMP
      WHERE CDFORNECED = C_PRODUTO.CDFORNITMAP
        AND CDPRODCOMPL = C_PRODUTO.CDPRODITMAP;
      IF V_VRPERPIFORN = 0 THEN
         SELECT NVL(MAX(VRPERPIFORN), 0)
           INTO V_VRPERPIFORN /* SE NAO ACHAR NA PRODFORNCOMP ENTAO*/
           FROM FORNECEDOR                                    /*PROCURA NO FORNECEDOR*/
          WHERE CDFORNECED = C_PRODUTO.CDFORNITMAP;
      END IF;
      V_VRPRECECOPI := (V_VRPRECECOPI - (C_PRODUTO.VRPRECUNIAP*V_VRPERPIFORN)/100) * (1/V_VRRENDATUMAR); /*CALCULO DO PI(PURCHASE INCOME)*/
      UPDATE ITMAPURPREC
          SET VRPRECECOAP  = V_VRPRECECO,
              VRPRECONPIAP = V_VRPRECECOPI
        WHERE CDCENTITMAP  = P_CDCENTITMAP
          AND NRSEQITMAP   = P_NRSEQITMAP
          AND CDFILIAP     = C_PRODUTO.CDFILIAP
          AND CDPRODITMAP  = C_PRODUTO.CDPRODITMAP
          AND NRCOLEITMAP  = C_PRODUTO.NRCOLEITMAP
          AND CDFORNITMAP  = C_PRODUTO.CDFORNITMAP
          AND CDREGITMAP   = C_PRODUTO.CDREGITMAP
          AND CDMARCITMAP  = C_PRODUTO.CDMARCITMAP;
   END LOOP;
END;
/