CREATE OR REPLACE PROCEDURE CALCULA_ESTORNO_CREDITO(
   P_CDEMPRESA      IN EMPRESA.CDEMPRESA%TYPE,
   P_CDINSCESTA     IN NOTAFISCAL.CDINSCESTA%TYPE,
   P_DTINICIAL      IN MAPAAPURAC.DTINIPERIODO%TYPE,
   P_DTFINAL        IN MAPAAPURAC.DTINIPERIODO%TYPE,
   P_NRSEQUMAPAPU   IN MAPAAPURAC.NRSEQUMAPAPU%TYPE)
AS
   V_CDICMS           VARCHAR2(02);
   V_VRICMSUNIDADE    FLOAT;
   V_NRSEQNFESTCRED   NUMBER;
   V_NRSEQESTCRED     NUMBER;
   V_QTNFSAIDA        FLOAT;
   V_QTNFENTRADA      FLOAT;
   V_QTUTILIZADA      FLOAT;
   V_VRICMSENTR       FLOAT;
   V_VRICMSSAID       FLOAT;
   V_VRESTORNO        FLOAT;
   V_NRSEQITMAPR      VARCHAR2(10);
   V_CDAJUSTEITMAPA   VARCHAR2(10);
   V_CDITPROCEDENCIA  VARCHAR2(10);
   V_CDAJUSTEITSEF    VARCHAR2(03);
   V_CDITEMOCOR       VARCHAR2(05);
   V_DSITEMOCOR       VARCHAR2(300);
   V_DSFLEGALOCOR     VARCHAR2(100);
   V_IDCALCESTCRED    VARCHAR2(01);
   V_DTINIESTCRED     DATE;
   V_CDIMPOSTO        VARCHAR2(02);
   V_IDSOMAFECP       VARCHAR2(01);

BEGIN
   
   SELECT CDIMPOSTO
     INTO V_CDIMPOSTO
     FROM MAPAAPURAC
   	WHERE NRSEQUMAPAPU = P_NRSEQUMAPAPU;
	
    BEGIN 
      SELECT IDSOMAFECP 
        INTO V_IDSOMAFECP
        FROM AJUSTEFECP
       WHERE CDEMPRESA    = P_CDEMPRESA
         AND CDINSCESTA   = P_CDINSCESTA
         AND CDIMPOSTO    = V_CDIMPOSTO;
   EXCEPTION
      WHEN NO_DATA_FOUND THEN
         V_IDSOMAFECP := 'S';
   END;    
   V_IDSOMAFECP := NVL(V_IDSOMAFECP,'S');
    
   /*Verifica o parametro, se e realizado o calculo para a inscricao estadual*/
   BEGIN
      SELECT IDCALCESTCRED, DTINIESTCRED
        INTO V_IDCALCESTCRED, V_DTINIESTCRED
        FROM INSCRESTAD
       WHERE CDEMPRESA    = P_CDEMPRESA
         AND CDINSCESTA   = P_CDINSCESTA;
   EXCEPTION
      WHEN NO_DATA_FOUND THEN
         V_IDCALCESTCRED := 'N';
         V_DTINIESTCRED  := NULL;
   END;

   /*Caso seja utilizado, calcula o valor do estorno de credito*/
   IF V_IDCALCESTCRED = 'S' THEN
      V_CDICMS        := '00';
      V_VRICMSUNIDADE := 0;
      V_QTNFSAIDA     := 0;
      V_QTNFENTRADA   := 0;
      V_QTUTILIZADA   := 0;
      V_VRICMSENTR    := 0;
      V_VRICMSSAID    := 0;
      V_VRESTORNO     := 0;

      /*Busca os relacionamentos que foram gravados nesse mapa, em caso de reapuracao de mapas*/
      FOR C_ESTMAPA IN (SELECT NRSEQESTCRED, CDFILIALENTR,   NRLANCTONFENTR,  NRSEQITPRODENTR,
                               CDFILIALSAID, NRLANCTONFSAID, NRSEQITPRODSAID, QTUTILIZADA
                          FROM ESTORNOCRED
                         WHERE NRSEQUMAPAPU = P_NRSEQUMAPAPU) LOOP
          /*Atualiza o saldo na itemproduto*/
          UPDATE ITEMPRODUTO
             SET QTSALDOESTCRED = QTSALDOESTCRED + C_ESTMAPA.QTUTILIZADA,
                 IDUTILESTCRED  = DECODE((QTSALDOESTCRED + C_ESTMAPA.QTUTILIZADA),QTITEMPROD,'N','S')
           WHERE CDFILIAL     = C_ESTMAPA.CDFILIALENTR
             AND NRLANCTONF   = C_ESTMAPA.NRLANCTONFENTR
             AND NRSEQITPROD  = C_ESTMAPA.NRSEQITPRODENTR;

          UPDATE ITEMPRODUTO
             SET QTSALDOESTCRED = QTSALDOESTCRED + C_ESTMAPA.QTUTILIZADA,
                 IDUTILESTCRED  = DECODE((QTSALDOESTCRED + C_ESTMAPA.QTUTILIZADA),QTITEMPROD,'N','S')
           WHERE CDFILIAL     = C_ESTMAPA.CDFILIALSAID
             AND NRLANCTONF   = C_ESTMAPA.NRLANCTONFSAID
             AND NRSEQITPROD  = C_ESTMAPA.NRSEQITPRODSAID;

          /*Deleta o relacionamento*/
          DELETE FROM ESTORNOCRED
           WHERE NRSEQESTCRED = C_ESTMAPA.NRSEQESTCRED;
      END LOOP;

      /*Deleta o registro da Nota no caso de atualizacao dos valores da Nota em reapuracao de mapas*/
      DELETE FROM NFESTORNOCRED
       WHERE NRSEQUMAPAPU = P_NRSEQUMAPAPU;

      /*Busca o maximo sequencial das tabelas*/
      SELECT NVL(MAX(NRSEQESTCRED),0)
        INTO V_NRSEQESTCRED
        FROM ESTORNOCRED;

      SELECT NVL(MAX(NRSEQNFESTCRED),0)
        INTO V_NRSEQNFESTCRED
        FROM NFESTORNOCRED;

      /*Grava os dados referentes as notas do periodo*/
      FOR V_NFEST IN (SELECT NF.NRLANCTONF, NF.CDFILIAL, NF.IDENTRSAIDOP,  NF.NRSEQUMAPAPU, IP.NRSEQITPROD,
                             IP.CDPRODUTO,  SUM(ROUND(IT.VRIMPOSTOIT + DECODE( V_IDSOMAFECP, 'N', 0, 'S', NVL(IT.VRADICFECP,0) ),2)) AS VRIMPOSTO, IP.QTITEMPROD
                        FROM ITEMPROIMPOS IT, ITEMPRODUTO IP,
                             (SELECT DISTINCT N.NRLANCTONF, N.CDFILIAL, N.IDENTRSAIDOP, I.CDIMPOSTO, I.NRSEQUMAPAPU
                                FROM NOTAFISCAL N, IMPOSTONF I, IMPOSTO IM
                               WHERE N.CDFILIAL      = I.CDFILIAL
                                 AND N.NRLANCTONF    = I.NRLANCTONF
                                 AND I.NRSEQUMAPAPU  IS NOT NULL
                                 AND N.CDEMPRESA     = P_CDEMPRESA
                                 AND N.CDINSCESTA    = P_CDINSCESTA
                                 AND (((N.IDENTRSAIDOP = 'E') AND (N.DTENTRSAID BETWEEN V_DTINIESTCRED AND P_DTFINAL)) OR
                                      ((N.IDENTRSAIDOP = 'S') AND (I.NRSEQUMAPAPU = P_NRSEQUMAPAPU)))
                                 AND I.CDIMPOSTO     = IM.CDIMPOSTO
                                 AND IM.CDIMPOSTONFE = V_CDICMS
                                 AND I.VRIMPOSTONF + DECODE( V_IDSOMAFECP, 'N', 0, 'S', NVL(I.VRADICFECP,0) ) > 0) NF
                       WHERE NF.CDFILIAL     = IT.CDFILIAL
                         AND NF.NRLANCTONF   = IT.NRLANCTONF
                         AND NF.CDIMPOSTO    = IT.CDIMPOSTO
                         AND IT.CDFISCALIT   = '1'
                         AND IT.VRIMPOSTOIT + DECODE( V_IDSOMAFECP, 'N', 0, 'S', NVL(IT.VRADICFECP,0) ) > 0
                         AND IT.CDFILIAL     = IP.CDFILIAL
                         AND IT.NRLANCTONF   = IP.NRLANCTONF
                         AND IT.NRSEQITPROD  = IP.NRSEQITPROD
                         AND ((IP.IDUTILESTCRED = 'N') OR
                              (IP.IDUTILESTCRED = 'S' AND QTSALDOESTCRED > 0))
                         AND NOT EXISTS (SELECT NRLANCTONF, CDFILIAL
                                           FROM NFESTORNOCRED EC
                                          WHERE EC.NRLANCTONF = NF.NRLANCTONF
                                            AND EC.CDFILIAL   = NF.CDFILIAL)
                       GROUP BY NF.NRLANCTONF, NF.CDFILIAL, NF.IDENTRSAIDOP, NF.NRSEQUMAPAPU,
                                IP.NRSEQITPROD, IP.CDPRODUTO, IP.QTITEMPROD) LOOP

          IF V_NFEST.QTITEMPROD > 0 THEN
             V_VRICMSUNIDADE :=  V_NFEST.VRIMPOSTO/V_NFEST.QTITEMPROD;
          END IF;

          V_NRSEQNFESTCRED := NVL(V_NRSEQNFESTCRED,0) + 1;

          INSERT INTO NFESTORNOCRED
             (NRSEQNFESTCRED, CDFILIAL, NRLANCTONF, NRSEQITPROD, NRSEQUMAPAPU, CDPRODUTO,
              VRICMSUNIDADE, QTITEMPROD, IDENTRSAIDOP)
          VALUES
             (LPAD(V_NRSEQNFESTCRED,10,'0'), V_NFEST.CDFILIAL, V_NFEST.NRLANCTONF, V_NFEST.NRSEQITPROD, V_NFEST.NRSEQUMAPAPU,
              V_NFEST.CDPRODUTO, V_VRICMSUNIDADE, V_NFEST.QTITEMPROD, V_NFEST.IDENTRSAIDOP);

          UPDATE ITEMPRODUTO
             SET QTSALDOESTCRED = V_NFEST.QTITEMPROD,
                 IDUTILESTCRED  = 'N'
           WHERE CDFILIAL     = V_NFEST.CDFILIAL
             AND NRLANCTONF   = V_NFEST.NRLANCTONF
             AND NRSEQITPROD  = V_NFEST.NRSEQITPROD;
      END LOOP;

      /*Busca todas as notas de saida no mapa para verificar se houve estorno*/
      FOR C_NFSAID IN (SELECT NF.DTEMISSAO, NE.CDFILIAL, NE.NRLANCTONF, NE.NRSEQITPROD, NE.VRICMSUNIDADE, IT.QTSALDOESTCRED, NE.CDPRODUTO
                         FROM NFESTORNOCRED NE, NOTAFISCAL NF, ITEMPRODUTO IT
                        WHERE NE.IDENTRSAIDOP = 'S'
                          AND NE.CDFILIAL     = IT.CDFILIAL
                          AND NE.NRLANCTONF   = IT.NRLANCTONF
                          AND NE.NRSEQITPROD  = IT.NRSEQITPROD
                          AND NE.CDFILIAL     = NF.CDFILIAL
                          AND NE.NRLANCTONF   = NF.NRLANCTONF
                          AND NE.NRSEQUMAPAPU = P_NRSEQUMAPAPU
                        ORDER BY NF.DTEMISSAO, NF.NRLANCTONF) LOOP

         V_QTNFSAIDA := C_NFSAID.QTSALDOESTCRED;
         /*Busca a menor nota de entrada dentro do periodo de calculo do estorno que ainda nao tenha sido totalmente utilizada*/
         FOR C_NFENTR IN (SELECT NF.DTENTRSAID, NE.NRLANCTONF, NE.CDFILIAL, NE.NRSEQITPROD, IT.QTSALDOESTCRED, NE.VRICMSUNIDADE
                            FROM NFESTORNOCRED NE, NOTAFISCAL NF, ITEMPRODUTO IT
                           WHERE NE.IDENTRSAIDOP = 'E'
                             AND NE.NRLANCTONF   = IT.NRLANCTONF
                             AND NE.CDFILIAL     = IT.CDFILIAL
                             AND NE.NRSEQITPROD  = IT.NRSEQITPROD
                             AND ((IT.IDUTILESTCRED = 'N') OR
                                  (IT.IDUTILESTCRED = 'S' AND QTSALDOESTCRED > 0))
                             AND NE.CDFILIAL     = NF.CDFILIAL
                             AND NE.NRLANCTONF   = NF.NRLANCTONF
                             AND NE.CDPRODUTO    = C_NFSAID.CDPRODUTO
                             AND NF.DTENTRSAID BETWEEN V_DTINIESTCRED AND P_DTFINAL
                           ORDER BY NF.DTENTRSAID, NF.NRLANCTONF) LOOP

            V_QTNFENTRADA := C_NFENTR.QTSALDOESTCRED;

            /*Quando a saida tiver sido toda comparada, termina o Loop da entrada e passa para a proxima nota*/
            EXIT WHEN V_QTNFSAIDA = 0;

            IF V_QTNFSAIDA <= C_NFENTR.QTSALDOESTCRED THEN
               V_QTNFENTRADA := V_QTNFENTRADA - V_QTNFSAIDA;
               V_QTUTILIZADA := V_QTNFSAIDA;
               V_QTNFSAIDA   := 0;
            ELSE
               V_QTNFSAIDA   := V_QTNFSAIDA - V_QTNFENTRADA;
               V_QTUTILIZADA := V_QTNFENTRADA;
               V_QTNFENTRADA := 0;
            END IF;

            V_VRICMSENTR   := ROUND((V_QTUTILIZADA * C_NFENTR.VRICMSUNIDADE),2);
            V_VRICMSSAID   := ROUND((V_QTUTILIZADA * C_NFSAID.VRICMSUNIDADE),2);
            /*Conferir calculo do Estorno E SE DEVE TESTAR SE O ESTORNO E MAIOR QUE ZERO PARA INSERIR NA TABELA*/
            V_VRESTORNO    := V_VRICMSENTR - V_VRICMSSAID;

            IF V_VRESTORNO > 0 THEN

               V_NRSEQESTCRED := NVL(V_NRSEQESTCRED,0) + 1;

               /*Insere o relacionamento*/
               INSERT INTO ESTORNOCRED
                  (NRSEQESTCRED, CDFILIALENTR, NRLANCTONFENTR, NRSEQITPRODENTR, CDFILIALSAID, NRLANCTONFSAID,
                   NRSEQITPRODSAID, NRSEQUMAPAPU, CDPRODUTO, QTUTILIZADA, VRICMSENTR, VRICMSSAID, VRESTORNO)
               VALUES
                  (LPAD(V_NRSEQESTCRED,10,'0'), C_NFENTR.CDFILIAL, C_NFENTR.NRLANCTONF, C_NFENTR.NRSEQITPROD, C_NFSAID.CDFILIAL,
                   C_NFSAID.NRLANCTONF, C_NFSAID.NRSEQITPROD, P_NRSEQUMAPAPU, C_NFSAID.CDPRODUTO, V_QTUTILIZADA, V_VRICMSENTR,
                   V_VRICMSSAID, V_VRESTORNO);

               /*Atualiza os saldos das Notas*/
               UPDATE ITEMPRODUTO
                  SET QTSALDOESTCRED = V_QTNFENTRADA,
                      IDUTILESTCRED  = 'S'
                WHERE CDFILIAL     = C_NFENTR.CDFILIAL
                  AND NRLANCTONF   = C_NFENTR.NRLANCTONF
                  AND NRSEQITPROD  = C_NFENTR.NRSEQITPROD;

               UPDATE ITEMPRODUTO
                  SET QTSALDOESTCRED = V_QTNFSAIDA,
                      IDUTILESTCRED  = 'S'
                WHERE CDFILIAL     = C_NFSAID.CDFILIAL
                  AND NRLANCTONF   = C_NFSAID.NRLANCTONF
                  AND NRSEQITPROD  = C_NFSAID.NRSEQITPROD;

            END IF;

            V_QTUTILIZADA := 0;
            V_VRICMSENTR  := 0;
            V_VRICMSSAID  := 0;
            V_VRESTORNO   := 0;
         END LOOP;
      END LOOP;

      /*Busca o sequencial antigo do estorno de credito, em caso de reapuracao de mapas*/
      BEGIN
         SELECT NRSEQITMAPR, CDAJUSTEITMAPA, CDITPROCEDENCIA, CDAJUSTEITSEF, CDITEMOCOR, DSITEMOCOR, DSFLEGALOCOR
           INTO V_NRSEQITMAPR, V_CDAJUSTEITMAPA, V_CDITPROCEDENCIA, V_CDAJUSTEITSEF, V_CDITEMOCOR, V_DSITEMOCOR, V_DSFLEGALOCOR
           FROM ITMAPARECUP
          WHERE NRSEQUMAPAPU = P_NRSEQUMAPAPU
            AND IDTIPOITMAPR = 'EC'
            AND DSITEMMAPR   = 'ESTORNO DE CREDITO';
      EXCEPTION
         WHEN NO_DATA_FOUND THEN
              V_NRSEQITMAPR     := NULL;
              V_CDAJUSTEITMAPA  := NULL;
              V_CDITPROCEDENCIA := NULL;
              V_CDAJUSTEITSEF   := NULL;
              V_CDITEMOCOR      := NULL;
              V_DSITEMOCOR      := NULL;
              V_DSFLEGALOCOR    := NULL;
      END;

      /*Apaga o registro de estorno no mapa de apuracao, em caso de reapuracao de mapas*/
      DELETE FROM ITMAPARECUP
       WHERE NRSEQUMAPAPU = P_NRSEQUMAPAPU
         AND IDTIPOITMAPR = 'EC'
         AND DSITEMMAPR   = 'ESTORNO DE CREDITO';

      /*Insere o valor total do estorno no periodo no mapa de apuracao*/
      SELECT NVL(SUM(VRESTORNO),0)
        INTO V_VRESTORNO
        FROM ESTORNOCRED
       WHERE NRSEQUMAPAPU = P_NRSEQUMAPAPU;

      IF (V_VRESTORNO > 0) THEN
         /*Se for a primeira apuracao do Mapa, busca um novo sequencial*/
         IF (V_NRSEQITMAPR = '') OR (V_NRSEQITMAPR IS NULL) THEN
            SELECT NVL(MAX(NRSEQITMAPR),'0')
              INTO V_NRSEQITMAPR
              FROM ITMAPARECUP
             WHERE NRSEQUMAPAPU = P_NRSEQUMAPAPU
               AND IDTIPOITMAPR = 'EC';
            V_NRSEQITMAPR := V_NRSEQITMAPR + 1;
         END IF;

         INSERT INTO ITMAPARECUP
            (NRSEQUMAPAPU, IDTIPOITMAPR, NRSEQITMAPR, DSITEMMAPR, VRITEMMAPR, CDAJUSTEITMAPA, CDITPROCEDENCIA,
             CDAJUSTEITSEF, CDITEMOCOR, DSITEMOCOR, DSFLEGALOCOR)
         VALUES
            (P_NRSEQUMAPAPU, 'EC', LPAD(V_NRSEQITMAPR,10,'0'), 'ESTORNO DE CREDITO', V_VRESTORNO, V_CDAJUSTEITMAPA,
             V_CDITPROCEDENCIA, V_CDAJUSTEITSEF, V_CDITEMOCOR, V_DSITEMOCOR, V_DSFLEGALOCOR);
      END IF;
   ELSE
      /*Se utilizou a rotina em uma apuracao antiga e depois desmarcou o parametro, apaga os registros gerados*/
      FOR V_REG_EST IN (SELECT NRSEQESTCRED, CDFILIALENTR,   NRLANCTONFENTR,  NRSEQITPRODENTR,
                               CDFILIALSAID, NRLANCTONFSAID, NRSEQITPRODSAID, QTUTILIZADA
                          FROM ESTORNOCRED
                         WHERE NRSEQUMAPAPU = P_NRSEQUMAPAPU) LOOP

          /*Atualiza o saldo na ItemProduto*/
          UPDATE ITEMPRODUTO
             SET QTSALDOESTCRED = QTSALDOESTCRED + V_REG_EST.QTUTILIZADA,
                 IDUTILESTCRED  = DECODE((QTSALDOESTCRED + V_REG_EST.QTUTILIZADA),QTITEMPROD,'N','S')
           WHERE CDFILIAL     = V_REG_EST.CDFILIALENTR
             AND NRLANCTONF   = V_REG_EST.NRLANCTONFENTR
             AND NRSEQITPROD  = V_REG_EST.NRSEQITPRODENTR;

          UPDATE ITEMPRODUTO
             SET QTSALDOESTCRED = QTSALDOESTCRED + V_REG_EST.QTUTILIZADA,
                 IDUTILESTCRED  = DECODE((QTSALDOESTCRED + V_REG_EST.QTUTILIZADA),QTITEMPROD,'N','S')
           WHERE CDFILIAL     = V_REG_EST.CDFILIALSAID
             AND NRLANCTONF   = V_REG_EST.NRLANCTONFSAID
             AND NRSEQITPROD  = V_REG_EST.NRSEQITPRODSAID;

           /*Deleta o relacionamento do estorno*/
           DELETE FROM ESTORNOCRED
            WHERE NRSEQESTCRED = V_REG_EST.NRSEQESTCRED;
      END LOOP;

      /*Deleta o registro da Nota*/
      DELETE FROM NFESTORNOCRED
       WHERE NRSEQUMAPAPU = P_NRSEQUMAPAPU;
   END IF;
END;
/