CREATE OR REPLACE PROCEDURE GERA_RETROATIVO_GD
(
   P_CDFILIAL IN VARCHAR2,
   P_CDCLIENTE IN VARCHAR2,
   P_LISTAAPURAC IN VARCHAR2,
   P_DTINICIAL IN DATE,
   P_DTFINAL IN DATE,
   P_DTSAIDAPUR IN DATE,
   P_NRCTRLTRABRETROFAT IN NUMBER,
   P_CDOPERADOR VARCHAR2,
   P_NRORG IN NUMBER,
   P_CDTIPOOPER IN VARCHAR2,
   P_NRLISTAERROS OUT NUMBER
)
AS
   V_NRAPURACFAT VARCHAR2(10);
     
   /* VARIAVEIS PARA CONTROLE DE GRAVACAO DA NOTA FISCAL */
   V_CHAVECST     VARCHAR2(14);
   V_CSTTEMP      VARCHAR2(03);
   V_IDPRODSUBS   VARCHAR2(01);
   V_IDPRODANTE   VARCHAR2(01);
   V_CDPTOVNDFATURTAP VARCHAR2(30);
   
   V_CDSERIE      SERIENF.CDSERIE%TYPE;
   V_CDSERIEVANTECIPA SERIENF.CDSERIE%TYPE;
   V_CDSERIEAUTO  SERIENF.CDSERIE%TYPE;
   V_IDSERIEAUTO  VARCHAR2(01);
   V_TTITENSNF    NUMBER;
   V_CONTITEM     NUMBER;
   V_NRLANCTONF   VARCHAR2(20);
   V_NRSEQITPROD  NUMBER;
   V_CDEMPRESA    FILIAL.CDEMPRESA%TYPE;
   V_CDINSCMUNI   FILIAL.CDINSCMUNI%TYPE;
   V_CDINSCESTA   FILIAL.CDINSCESTA%TYPE;
   V_IDTPIJURCLIE CLIENTE.IDTPIJURCLIE%TYPE;
   V_NRINSJURCLIE CLIENTE.NRINSJURCLIE%TYPE;
   v_NRINSJURTRAN CLIENTE.NRINSJURTRAN%TYPE;
   V_IDTPIJURTRAN CLIENTE.IDTPIJURTRAN%TYPE;
   V_IDPGTOFRETE  CLIENTE.IDPGFRETTRANCLI%TYPE;
   V_NRPLACAVEIC  VIATURA.NRPLACA%TYPE;
   V_SGUFVEICULO  VIATURA.SGUFVEICULO%TYPE;
   V_IDNOVANOTA   VARCHAR2(01);
   V_VRNOTAFISC   NUMBER;
   V_PRXLANCESTQ  VARCHAR2(10);
   V_VRCREDIDEBI  NOTAFISCAL.VRNOTAFISC%TYPE;
   
   V_DSAJUCTREC      AJCTRECEBER.DSAJUSTEREC%TYPE;
   V_ENCARGO         ENCARGO.CDENCARGO%TYPE;
   V_IDCOPALTEFEPLA  PARAMFILIAL.IDCOPALTEFEPLA%TYPE;
   V_CDPRODPRESTSERV VARCHAR2(10);

   V_CDGRUPOFISC  VARCHAR2(03);
   V_DESCDOTACAO  VARCHAR2(01);
   V_CDAJUSTPADR  VARCHAR2(02);
   V_CDENCREDITO  VARCHAR2(02);
   V_CDENCDEBITO  VARCHAR2(02);
   V_IDUTPROPEMIS VARCHAR2(01);
   V_CDARVPROD    PRODUTO.CDARVPROD%TYPE;
   V_NMPRODUTO    PRODUTO.NMPRODUTO%TYPE;
   V_CDSERVFILIAP SERVICO.CDSERVFILI%TYPE;
   V_MINEFETFAT   VARCHAR2(01);
   V_IDUTILEQUI   VARCHAR2(01);
   V_NREFETAUX    NUMBER;
   V_NREFETAUXGD  NUMBER;
   V_NREFETAUXTU  NUMBER;
   V_VRUNITARIO   NUMBER;
   V_CDTIPOFATUR  PARAMFILIAL.CDTIPOFATUR%TYPE;
   V_IDENDCFOP      VARCHAR2(01);
   V_PAISORIG       VARCHAR2(04);
   V_ESTAORIG       VARCHAR2(02);
   V_MUNIORIG       VARCHAR2(04);
   V_ORIGDESTOP     VARCHAR2(01);
   V_CDORIGDESTNF   VARCHAR2(21);
   V_IDENDEMIS      VARCHAR2(01);
   V_PAISDEST       VARCHAR2(04);
   V_ESTADEST       VARCHAR2(02);
   V_MUNIDEST       VARCHAR2(04);
   V_CDEMPRESADEST  VARCHAR2(02);
   V_CDINSCESTADEST VARCHAR2(16);
   V_IDINTEREST     VARCHAR2(01);
   V_IDINTERNA      VARCHAR2(01);
   
   /* VARIAVEL DO TIPO DE OPERACAO */
   V_CDTIPOOPER   VARCHAR2(02);
   V_IDATIVATABCOR VARCHAR2(1);
   V_IDCOREFECLIFILI VARCHAR2(1);
   V_VRAPURFATTABCOR NUMBER;
   V_VRAPURACAOFATU NUMBER;
   V_VRSERVICOCORRI NUMBER;
   
   V_CDSERVFILIAPGD VARCHAR2(05);
   V_IDUTILADIANT  VARCHAR2(1);
   V_IDCLIENPRIN VARCHAR2(1);
   V_COMPENSACAO VARCHAR2(1); /*VERIFICA SE A APURAÇÃO FOI CHAMADA PELO CONTROLE DE COMPESACAO*/
   V_QTPRODFATU NUMBER; /*Variavel retorna se o produto será faturado por n produtos */
   V_CONTPRODFATURAM NUMBER; /*variavel para contar qdte de produtos inseridos e arredondar no último*/
   V_SOMAPRODFATURAM FLOAT; /*variavel para contar valor unitario acumulado dos produtos inseridos e aplicar diferença no último*/
   V_VRPRODFATURAM FLOAT; /*variavel para corrigir o valor unitario do produto rateado quando arredondado*/
   V_DSEMISSAO VARCHAR2(2000);
   V_NREFETIVOS_SERV FLOAT(126);
   V_VRSERVICO_SERV FLOAT(126);
   V_CDCLIENTE VARCHAR2(21);
   V_SEQUENCIAL NUMBER;

   V_NRGRUPONF NUMBER;
   V_CDSERVFILI VARCHAR2(5);
   V_CDGRSERVFAT VARCHAR2(3);   

   V_STIDTIPNFEMP VARCHAR2(1);
   V_STIDMINIEFET VARCHAR2(1);
   V_STIDQTDEPREC VARCHAR2(1);
   V_STIDUTEFEPLA VARCHAR2(1);

   V_DTSAIDAPUR DATE;
   V_NRRETROFAT NUMBER;
   V_NRCTRLAPURRETROFAT NUMBER;
   V_CDFILIAPUR VARCHAR2(4);
   
   V_MENSAGEM VARCHAR2(255);
   V_NUM_APURAC NUMBER;
   V_MINDATE DATE;
   V_MAXDATE DATE;

   -- Procedure auxiliar para agilizar inclusão na lista de erros
   PROCEDURE I_L(MENSAGEM IN VARCHAR2)
   AS
   BEGIN
      INSERE_LISTA_ERROS(P_CDFILIAL, MENSAGEM,
                         P_CDOPERADOR, P_NRORG, P_NRLISTAERROS);
   END;

BEGIN   
   -- Apuração retroativo
   V_NRAPURACFAT := RETORNA_NOVO_CODIGO('APURACFATUR' || P_CDFILIAL, 1, 10);
   INSERT INTO CTRLAPURFAT
   (CDFILIAL, NRAPURACFAT, CDFILIAPUR,
     CDCLIENTE, DTINIAPURAC, DTFIMAPURAC)
   VALUES
   (P_CDFILIAL,V_NRAPURACFAT, P_CDFILIAL,
    P_CDCLIENTE, P_DTINICIAL, P_DTFINAL);
   
   V_DTSAIDAPUR := NVL(P_DTSAIDAPUR, TRUNC(SYSDATE));

   -- Insere retroativo
   V_NRRETROFAT := TO_NUMBER(RETORNA_NOVO_CODIGO('RETROFAT', 1));
   INSERT INTO RETROFAT
   (NRRETROFAT, CDCLIENTE, 
    DTINICIAL, DTFINAL,
    CDFILIAL, NRAPURACFAT,    
    NRORG, NRORGINCLUSAO, NRORGULTATU,
    DTINCLUSAO, DTULTATU,
    CDOPERINCLUSAO, CDOPERULTATU)
   VALUES
   (V_NRRETROFAT, P_CDCLIENTE, 
    P_DTINICIAL, P_DTFINAL,
    P_CDFILIAL, V_NRAPURACFAT,    
    P_NRORG, P_NRORG, P_NRORG,
    SYSDATE, SYSDATE,
    P_CDOPERADOR, P_CDOPERADOR);

   -- Insere os controles de apuração retroativo
   V_NUM_APURAC := 0;
   V_MENSAGEM := 'PERÍODO DE APURAÇÃO ';
   FOR C_CTRL IN 
      (SELECT C.CDFILIAL, C.NRAPURACFAT, DTINIAPURAC, DTFIMAPURAC
          FROM CTRLAPURFAT C
         WHERE C.CDFILIAPUR = P_CDFILIAL
           AND C.CDCLIENTE = P_CDCLIENTE
           AND VALOR_NA_LISTA(C.CDFILIAL || '|' || C.NRAPURACFAT, P_LISTAAPURAC) > 0
           AND ( ( C.DTINIAPURAC BETWEEN P_DTINICIAL AND P_DTFINAL )
                 OR ( C.DTFIMAPURAC BETWEEN P_DTINICIAL AND P_DTFINAL )
                 OR ( P_DTINICIAL BETWEEN C.DTINIAPURAC AND C.DTFIMAPURAC )
                 OR ( P_DTFINAL BETWEEN C.DTINIAPURAC AND C.DTFIMAPURAC ) )
           AND NOT EXISTS (SELECT 1 FROM CTRLVENDAANTEC CV WHERE CV.CDFILIAL = C.CDFILIAL AND CV.NRAPURACFAT = C.NRAPURACFAT)
           AND NOT EXISTS (SELECT 1 FROM RETROFAT R WHERE R.CDFILIAL = C.CDFILIAL AND R.NRAPURACFAT = C.NRAPURACFAT)
           AND EXISTS (SELECT 1 FROM NOTAFISCAL NF WHERE NF.CDFILIAL = C.CDFILIAL AND NF.NRAPURACFAT = C.NRAPURACFAT AND IDBLOQUEADO = 'S')
   ) LOOP
      V_NRCTRLAPURRETROFAT := TO_NUMBER(RETORNA_NOVO_CODIGO('CTRLAPURRETROFAT', 1));
      INSERT INTO CTRLAPURRETROFAT
      (NRCTRLAPURRETROFAT, NRRETROFAT, CDFILIAL, NRAPURACFAT,
       NRORG, NRORGINCLUSAO, NRORGULTATU,
       CDOPERINCLUSAO, CDOPERULTATU,
       DTINCLUSAO, DTULTATU)
      VALUES
      (V_NRCTRLAPURRETROFAT, V_NRRETROFAT, C_CTRL.CDFILIAL, C_CTRL.NRAPURACFAT,
       P_NRORG, P_NRORG, P_NRORG,       
       P_CDOPERADOR, P_CDOPERADOR,
       SYSDATE, SYSDATE);
       
      IF(V_MINDATE IS NULL OR C_CTRL.DTINIAPURAC < V_MINDATE) THEN
         V_MINDATE := C_CTRL.DTINIAPURAC;
      END IF;
      
      IF(V_MAXDATE IS NULL OR C_CTRL.DTFIMAPURAC > V_MAXDATE) THEN
         V_MAXDATE := C_CTRL.DTFIMAPURAC;
      END IF;
      
      IF V_NUM_APURAC > 0 THEN
         V_MENSAGEM := V_MENSAGEM  || ', ';
      END IF;
      IF V_NUM_APURAC <= 8 THEN
        V_MENSAGEM := V_MENSAGEM || TO_CHAR(C_CTRL.DTINIAPURAC, 'DD/MM/YYYY') || ' A ' || TO_CHAR(C_CTRL.DTFIMAPURAC, 'DD/MM/YYYY');
      END IF;
      V_NUM_APURAC := V_NUM_APURAC + 1;
      
   END LOOP;   
   
   IF V_NUM_APURAC > 8 THEN
      V_MENSAGEM := 'PERÍODO DE APURAÇÃO '|| TO_CHAR(V_MINDATE, 'DD/MM/YYYY') || ' A ' || TO_CHAR(V_MAXDATE, 'DD/MM/YYYY');
   END IF;
   
   -- Busca dados para geração nota fiscal

   /*TIPO DE OPERACAO PARA AS NFS, SERAO GRAVADAS POR DEFAULT NA TRAB_APURAC_GD E TRAB_APURAC_TU E PODEM SER ALTERADAS NA TELA DE APURACAO*/
   IF ((P_CDTIPOOPER IS NULL) OR (P_CDTIPOOPER = '') OR (P_CDTIPOOPER = ' ')) THEN
      V_CDTIPOOPER := '01';
   ELSE
      V_CDTIPOOPER := P_CDTIPOOPER;
   END IF;

   V_VRCREDIDEBI := 0;
     
   V_CDFILIAPUR := P_CDFILIAL;
  

   /* BUSCA AS INFORMAÇÕES PARA CADASTRAMENTO DA NOTA FISCAL */
   SELECT MAX(CDEMPRESA), MAX(CDINSCMUNI), MAX(CDINSCESTA), MAX(CDSERIE), MAX(CDSERIEVANTECIPA)
   INTO V_CDEMPRESA, V_CDINSCMUNI, V_CDINSCESTA, V_CDSERIE, V_CDSERIEVANTECIPA
   FROM FILIAL
   WHERE CDFILIAL = V_CDFILIAPUR;

   SELECT NVL(MAX(IDSERIEAUTO), 'N')
   INTO V_IDSERIEAUTO
   FROM TIPOOPERAC
   WHERE CDTIPOOPER   = V_CDTIPOOPER AND
         IDENTRSAIDOP = 'S';

   IF V_IDSERIEAUTO = 'S' THEN
      SELECT MAX(P.CDSERIE)
        INTO V_CDSERIEAUTO
        FROM PARAMSERIE P, FILIAL F, CLIENTE C
       WHERE F.CDFILIAL      = V_CDFILIAPUR AND
            NVL(F.CDFILIFISC, F.CDFILIAL) = P.CDFILIAL   AND
            P.CDEMPRESA     = V_CDEMPRESA  AND
            P.CDINSCESTA    = V_CDINSCESTA AND
            P.CDINSCMUNI    = V_CDINSCMUNI AND
            P.CDTIPOOPER    = V_CDTIPOOPER AND
            C.CDCLIENTE     = P_CDCLIENTE  AND
            P.CDCONDICAOIVA = C.CDCONDIVACLI AND
            P.IDENTRSAIDOP  = 'S';
   END IF;

   IF V_CDSERIEAUTO IS NOT NULL THEN      
     V_CDSERIE := V_CDSERIEAUTO;
   END IF;

   SELECT NVL(MAX(NRMAXITNF),10)
   INTO V_TTITENSNF
   FROM SERIENF
   WHERE CDEMPRESA  = V_CDEMPRESA  AND
         CDINSCESTA = V_CDINSCESTA AND
         CDINSCMUNI = V_CDINSCMUNI AND
         CDSERIE    = V_CDSERIE;

   /*DADOS DO EMITENTE*/
   SELECT NVL(MAX(IDENDCFOPFIL),'I'), MAX(CDEMPRESA), MAX(CDINSCESTA)
   INTO   V_IDENDCFOP,                V_CDEMPRESA,    V_CDINSCESTA
   FROM   FILIAL
   WHERE  (CDFILIAL = V_CDFILIAPUR);

   IF V_IDENDCFOP = 'I' THEN
      SELECT MAX(CDPAIS), MAX(SGESTADO), MAX(CDMUNICIPIO)
      INTO   V_PAISORIG,  V_ESTAORIG,    V_MUNIORIG
      FROM   INSCRESTAD
      WHERE  CDEMPRESA  = V_CDEMPRESA AND
             CDINSCESTA = V_CDINSCESTA;
   ELSE
      SELECT MAX(CDPAIS), MAX(SGESTADO), MAX(CDMUNICIPIO)
      INTO   V_PAISORIG,  V_ESTAORIG,    V_MUNIORIG
      FROM   ENDEFILI
      WHERE  (CDFILIAL     = V_CDFILIAPUR) AND
             (IDTPENDEFILI = V_IDENDCFOP);
   END IF;

   /*DADOS DO DESTINIATARIO */
   SELECT MAX(IDORIGDESTOP)
   INTO   V_ORIGDESTOP
   FROM   TIPOOPERAC
   WHERE  IDENTRSAIDOP = 'S' AND
          CDTIPOOPER   = P_CDTIPOOPER;

   IF V_ORIGDESTOP = 'L' THEN /*QUANDO O DESTINATARIO UMA FILIAL */
      SELECT NVL(MAX(IDENDEMISFIL),'I'), MAX(CDEMPRESA), MAX(CDINSCESTA)
      INTO   V_IDENDEMIS,                V_CDEMPRESADEST,    V_CDINSCESTADEST
      FROM   FILIAL
      WHERE  (CDFILIAL = P_CDCLIENTE);

      IF V_IDENDEMIS = 'I' THEN
         SELECT MAX(CDPAIS), MAX(SGESTADO), MAX(CDMUNICIPIO)
         INTO   V_PAISDEST,  V_ESTADEST,    V_MUNIDEST
         FROM   INSCRESTAD
         WHERE  CDEMPRESA  = V_CDEMPRESADEST AND
                CDINSCESTA = V_CDINSCESTADEST;
      ELSE
         SELECT MAX(CDPAIS), MAX(SGESTADO), MAX(CDMUNICIPIO)
         INTO   V_PAISDEST,  V_ESTADEST,    V_MUNIDEST
         FROM   ENDEFILI
         WHERE  CDFILIAL     = P_CDCLIENTE AND
                IDTPENDEFILI = V_IDENDEMIS;
      END IF;
   ELSIF V_ORIGDESTOP = 'F' THEN /*QUANDO O DESTINATARIO FORNECEDOR*/
      SELECT NVL(MAX(IDENDEMISFOR),'P')
      INTO   V_IDENDEMIS
      FROM   FORNECEDOR
      WHERE  (CDFORNECED = P_CDCLIENTE);

      SELECT MAX(CDPAIS), MAX(SGESTADO), MAX(CDMUNICIPIO)
      INTO   V_PAISDEST,  V_ESTADEST,    V_MUNIDEST
      FROM   ENDEFORN
      WHERE  (CDFORNECED   = P_CDCLIENTE) AND
             (IDTPENDEFORN = V_IDENDEMIS);
   ELSE /*QUANDO O DESTINATARIO CLIENTE */
      SELECT NVL(MAX(IDENDEMISCLI),'P')
      INTO   V_IDENDEMIS
      FROM   CLIENTE
      WHERE  (CDCLIENTE = P_CDCLIENTE);

      SELECT MAX(CDPAIS), MAX(SGESTADO), MAX(CDMUNICIPIO)
      INTO   V_PAISDEST,  V_ESTADEST,    V_MUNIDEST
      FROM   ENDECLIE
      WHERE  (CDCLIENTE    = P_CDCLIENTE) AND
             (IDTPENDECLIE = V_IDENDEMIS);
   END IF;
   /*VERIFICANDO OS PARAMETROS INTERESTADUAL E INTERNACIONAL*/
   V_IDINTEREST := 'N';
   V_IDINTERNA  := 'N';
   IF ((V_PAISDEST = V_PAISORIG) AND (V_ESTADEST <> V_ESTAORIG)) THEN
      V_IDINTEREST := 'S';
   ELSIF (V_PAISDEST <> V_PAISORIG) THEN
      V_IDINTERNA := 'S';
   END IF;

   /* BUSCA AS INFORMAÇÕES PARA CADASTRAMENTO DE AJUSTE */
   SELECT MAX(SUBSTR(DSAJUCTREC,1,20))
   INTO V_DSAJUCTREC
   FROM TIPOAJRECEBER
   WHERE V_CDAJUSTPADR = CDAJUCTREC;

   /* BUSCA OS PARAMETROS DA PARAMGERAL E PARAMFILIAL */
   SELECT MAX(SUBSTR(DSPARAMFATGE,11,1)), NVL(MAX(IDUTPROPEMIS),'N'), MAX(SUBSTR(DSPARAMFATGE,1,10))
   INTO V_STIDTIPNFEMP, V_IDUTPROPEMIS, V_CDPRODPRESTSERV
   FROM PARAMGERAL;

  SELECT MAX(SUBSTR(DSPARAMFATFI,01,1)),
          MAX(SUBSTR(DSPARAMFATFI,02,1)),
          MAX(SUBSTR(DSPARAMFATFI,15,1)),
          MAX(SUBSTR(DSPARAMFATFI,56,1)),          /*DESCONTO DE DOTAÇÃO */
          MAX(SUBSTR(DSPARAMFATFI,57,2)),          /*AJUSTE PADRAO*/
          MAX(SUBSTR(DSPARAMFATFI,59,2)),          /*ENCARGO DEBITO*/
          MAX(SUBSTR(DSPARAMFATFI,61,2)),           /*ENCARGO CREDITO*/
          MAX(CDTIPOFATUR),
          MAX(IDCOPALTEFEPLA)
   INTO V_STIDMINIEFET,  V_STIDQTDEPREC,  V_STIDUTEFEPLA,
        V_DESCDOTACAO, V_CDAJUSTPADR, V_CDENCREDITO,
        V_CDENCDEBITO, V_CDTIPOFATUR, V_IDCOPALTEFEPLA
   FROM PARAMFILIAL
   WHERE CDFILIAL = V_CDFILIAPUR;

   IF V_CDTIPOFATUR = '002' THEN
      V_STIDTIPNFEMP := '1';

      SELECT MAX(SUBSTR(DSPARAMFATGE,12,10))
      INTO V_CDPRODPRESTSERV
      FROM PARAMGERAL;
   ELSE
      IF (V_STIDTIPNFEMP IS NULL) OR (RTRIM(V_STIDTIPNFEMP) = '') THEN
         V_STIDTIPNFEMP := '2';
         -- REFEIÇÃO
      END IF;
   END IF;

   IF (V_STIDMINIEFET IS NULL) OR (V_STIDMINIEFET = ' ') THEN
      V_STIDMINIEFET := '1';
      -- POR DIA
   END IF;
   IF (V_STIDQTDEPREC IS NULL) OR (V_STIDQTDEPREC = ' ') THEN
      V_STIDQTDEPREC := '1';
      -- POR QUANTIDADE
   END IF;
   IF (V_STIDUTEFEPLA IS NULL) OR (V_STIDUTEFEPLA = ' ') THEN
      V_STIDUTEFEPLA := 'N';
      -- NAO UTILIZA EFETIVOS DO PLANEJAMENTO
   END IF;

   SELECT SUM(VRNOTAFISC)
   INTO V_VRCREDIDEBI
   FROM NOTAFISCAL N
   WHERE (N.CDFILIAL     = V_CDFILIAPUR)                  AND
         (N.CDTIPOOPER   = '12')                          AND
         (N.IDENTRSAIDOP = 'S')                           AND
         (N.DTENTRSAID BETWEEN P_DTINICIAL AND P_DTFINAL);

   IF V_VRCREDIDEBI < 0 THEN
      V_VRCREDIDEBI := V_VRCREDIDEBI * (-1);
      V_ENCARGO    := V_CDENCDEBITO;
   ELSIF V_VRCREDIDEBI > 0 THEN
      V_ENCARGO    :=  V_CDENCREDITO;
   END IF;

   CONSULTA_GRUPOFISCAL('C', P_CDCLIENTE, V_CDFILIAPUR, 'S', V_CDTIPOOPER, V_CDGRUPOFISC);

   -- Seta agrupamento de nota dos itens conforme parametrizametrizações atuais
   V_NRGRUPONF := 0;
   V_CDGRSERVFAT := 'XXX';
   V_CONTITEM := 1;
   V_CDSERVFILI := 'XXXXX';   

   FOR C_ITEM IN
   (
      SELECT T.NRTRABRETROFAT, T.CDFILIAL, T.CDSERVFILI, SC.CDCLIENTE, SC.CDGRSERVFAT, S.IDSERVFATSEP 
        FROM TRABRETROFAT T
             LEFT JOIN SERVCLIE SC ON SC.CDCLIENTE = P_CDCLIENTE AND
                                      SC.CDFILIAL = T.CDFILIAL AND
                                      SC.CDSERVFILI = T.CDSERVFILI
             LEFT JOIN SERVICO S ON S.CDFILIAL = T.CDFILIAL AND
                                    S.CDSERVFILI = T.CDSERVFILI
       WHERE T.NRCTRLTRABRETROFAT = P_NRCTRLTRABRETROFAT
       ORDER BY T.CDSERVFILI
   ) LOOP
      IF (V_CONTITEM = V_TTITENSNF) OR (V_CDGRSERVFAT <> C_ITEM.CDGRSERVFAT) OR (C_ITEM.IDSERVFATSEP = 'S' AND V_CDSERVFILI <> C_ITEM.CDSERVFILI) THEN
         V_NRGRUPONF := V_NRGRUPONF + 1;   
         V_CONTITEM := 1;
      END IF;

      UPDATE TRABRETROFAT
         SET NRGRUPONF = V_NRGRUPONF
       WHERE NRTRABRETROFAT = C_ITEM.NRTRABRETROFAT;
      
      V_CDGRSERVFAT := C_ITEM.CDGRSERVFAT;
      V_CONTITEM := V_CONTITEM + 1;
      V_CDSERVFILI := C_ITEM.CDSERVFILI;
      V_SEQUENCIAL := V_SEQUENCIAL + 1;
   END LOOP;
   
   /*SE FILIAL PARAMETRIZADA PARA GERAR NF DE PRESTACAO DE SERVICO - GERA APENAS UMA NF COM UM ITEM CONSOLIDANDO OS EFETIVOS*/      
   IF V_STIDTIPNFEMP  = '1' THEN            
      
      SELECT SUM(NREFETIVOS), SUM(NREFETIVOS * VRUNAFATURAR), MAX(CDSERVFILI)
        INTO V_NREFETIVOS_SERV, V_VRSERVICO_SERV, V_CDSERVFILIAPGD
        FROM TRABRETROFAT
       WHERE NRCTRLTRABRETROFAT = P_NRCTRLTRABRETROFAT;
      
      IF  V_NREFETIVOS_SERV <> 0 THEN

         V_VRUNITARIO :=  V_VRSERVICO_SERV/V_NREFETIVOS_SERV;
         
         GERA_NOTAFISCAL_CORPO(P_CDFILIAL,     V_CDFILIAPUR, V_CDEMPRESA,
                               V_CDTIPOOPER,   V_CDSERIE,    P_CDCLIENTE,
                               V_DTSAIDAPUR,
                               'FAI',        V_NRLANCTONF,
                               V_PRXLANCESTQ, 'N',          V_NRAPURACFAT,
                               V_NRLANCTONF, V_IDTPIJURTRAN, V_NRINSJURTRAN,
                               V_NRPLACAVEIC, V_SGUFVEICULO,V_IDPGTOFRETE,
                               NULL,          NULL,         NULL,
                               NULL,          NULL,         NULL,
                               NULL,          NULL,         NULL,
                               NULL,          V_DTSAIDAPUR,    NULL);

         GERA_NOTAFISCAL_DADOSADIC(P_CDFILIAL,V_NRLANCTONF,P_DTINICIAL,P_DTFINAL, V_MENSAGEM);
                           
         IF ((V_DESCDOTACAO = '1') AND (V_VRCREDIDEBI <> 0))  THEN
            GERA_NOTAFISCAL_ENCARGO(P_CDFILIAL, V_NRLANCTONF, V_ENCARGO, V_VRCREDIDEBI);
         END IF;

         SELECT MAX(CDARVPROD), MAX(NMPRODUTO)
         INTO V_CDARVPROD, V_NMPRODUTO
         FROM PRODUTO
         WHERE CDPRODUTO = V_CDPRODPRESTSERV;

         GERA_NOTAFISCAL_PRODUTO(P_CDFILIAL  , V_NRLANCTONF, V_CDPRODPRESTSERV,
                                 V_CDARVPROD , V_NMPRODUTO , V_NREFETIVOS_SERV,
                                 V_VRUNITARIO, 0           , NULL             ,
                                 NULL        , NULL        , NULL             ,
                                 NULL        , NULL        , NULL             ,
                                 NULL        , NULL        , NULL             ,
                                 'S'         , NULL        , 0                ,
                                 V_CDSERVFILIAPGD);

         GERA_NOTAFISCAL_FECHAMENTO(P_CDFILIAL, V_NRLANCTONF);
         
         UPDATE HISTCTRLAPURFAT H
            SET NRRETROFAT = V_NRRETROFAT
          WHERE H.CDFILIAPUR = P_CDFILIAL
            AND H.CDCLIENTE = P_CDCLIENTE
            AND H.DTAPURACAO BETWEEN P_DTINICIAL AND P_DTFINAL
            AND H.CDFILIAL || H.NRAPURACFAT IN (SELECT CDFILIAL || NRAPURACFAT FROM CTRLAPURRETROFAT WHERE NRRETROFAT = V_NRRETROFAT)
            AND EXISTS (SELECT 1 FROM TRABRETROFAT T 
                         WHERE T.NRTRABRETROFAT = P_NRCTRLTRABRETROFAT AND 
                               T.CDSERVFILI = H.CDSERVFILI AND 
                               T.VRPRECUNIT = H.VRPRECUNIT AND
                               CASE
                                 WHEN H.CDTURNO IS NULL
                                 THEN UTIL_APURAC.CALCVALRSERV(H.CDFILIAPUR, H.CDCLIENTE, H.CDSERVFILI, H.DTAPURACAO, NULL, TRUNC(SYSDATE))
                                 ELSE UTIL_APURAC.CALCVALRSERV(H.CDFILIAPUR, H.CDCLIENTE, H.CDSERVFILI, H.DTAPURACAO, H.CDTURNO, TRUNC(SYSDATE))
                               END = T.VRPRECUNITATUAL AND
                               ((H.CDTURNO IS NULL AND T.CDTURNO IS NULL) OR (H.CDTURNO = T.CDTURNO)));
      END IF;
   /*SE FILIAL PARAMETRIZADA PARA GERAR NF DE REFEICAO - GERA NFS DE ACORDO COM AS PARAMETRIZACOES POR SERVICO, GRUPO DE SERVICO ETC*/
   ELSE
   
      V_NRGRUPONF := 0;
      V_IDNOVANOTA := 'N';
      V_CDCLIENTE := '_';
      /*CURSOR PARA TRAZER OS ITENS PARA GERAÇÃO DAS NFS*/
      FOR CURS_APURAC IN
      (
         SELECT P_CDCLIENTE AS CDCLIENTE,
                T.CDSERVFILI, T.CDTURNO,
                T.NREFETIVOS,
                T.VRPRECUNIT AS VRUNIT_ANTERIOR,
                T.VRPRECUNITATUAL AS VRUNIT_ATUAL,
                T.VRUNAFATURAR AS VRPRECOUNIT,
                T.NRGRUPONF,
                V_CDTIPOOPER AS CDTIPOOPER,
                0.00 AS VRDESCONTO,
                NULL AS NRPEDIDO,
                NULL AS NRITEMPED,
                NULL AS DSJUSTIFICATIVA,
                P.CDPRODUTO, P.CDARVPROD,
                P.NMPRODUTO AS DSPRODUTO,
                P.NMPRODUTO, S.NMSERVICO
           FROM TRABRETROFAT T
                LEFT JOIN SERVICO S ON S.CDFILIAL = T.CDFILIAL AND
                                        S.CDSERVFILI = T.CDSERVFILI
                LEFT JOIN PRODUTO P ON P.CDPRODUTO = S.CDPRODUTO
             WHERE T.NRCTRLTRABRETROFAT = P_NRCTRLTRABRETROFAT
      ) LOOP         
         IF (V_NRGRUPONF <> CURS_APURAC.NRGRUPONF) OR (V_CDCLIENTE <> CURS_APURAC.CDCLIENTE) THEN
            V_NRGRUPONF := CURS_APURAC.NRGRUPONF;
            V_CDCLIENTE := CURS_APURAC.CDCLIENTE;
            IF (V_IDNOVANOTA = 'S') THEN
               GERA_NOTAFISCAL_FECHAMENTO(P_CDFILIAL, V_NRLANCTONF);   
            END IF;
            V_IDNOVANOTA := 'S';
         
            /*GERA NOVO CODIGO PARA NRO DE LANCAMENTO DA NF*/
            NOVO_CODIGO_NT('LANCNF/FILIAL' || P_CDFILIAL,V_NRLANCTONF);
            V_NRLANCTONF := SUBSTR(V_NRLANCTONF,11,10);  
            
            GERA_NOTAFISCAL_CORPO(P_CDFILIAL, V_CDFILIAPUR, V_CDEMPRESA,
                                  CURS_APURAC.CDTIPOOPER, V_CDSERIE, CURS_APURAC.CDCLIENTE,
                                  V_DTSAIDAPUR,
                                  'FAI',        V_NRLANCTONF,
                                  V_PRXLANCESTQ, 'N',          V_NRAPURACFAT,
                                  V_NRLANCTONF, V_IDTPIJURTRAN, V_NRINSJURTRAN,
                                  V_NRPLACAVEIC, V_SGUFVEICULO,V_IDPGTOFRETE,
                                  NULL,          NULL,         NULL,
                                  NULL,          NULL,         NULL,
                                  NULL,          NULL,         NULL,
                                  NULL,          V_DTSAIDAPUR,    NULL);

            IF (V_DESCDOTACAO = '1') AND (V_VRCREDIDEBI <> 0) THEN
               GERA_NOTAFISCAL_ENCARGO(P_CDFILIAL, V_NRLANCTONF, V_ENCARGO, V_VRCREDIDEBI);
            END IF;
               
            GERA_NOTAFISCAL_DADOSADIC(P_CDFILIAL,V_NRLANCTONF,P_DTINICIAL,P_DTFINAL, V_MENSAGEM);
         END IF;            
         
         /*VERIFICA SE UTILIZA RATEIO DE PRODUTO PARA FATURAMENTO POR SERVICO*/
         SELECT COUNT(1), 1 AS QTDE, 0 AS VALOR 
           INTO V_QTPRODFATU, V_CONTPRODFATURAM, V_SOMAPRODFATURAM
           FROM PRODFATURAM
          WHERE CDFILIAL = V_CDFILIAPUR
            AND CDSERVFILI = CURS_APURAC.CDSERVFILI;
            
         IF V_QTPRODFATU = 0 THEN /* GERAR APENAS PRODUTO SEM RATEIO (N PRODUTO POR FATURAMENTO) */  
         
            GERA_NOTAFISCAL_PRODUTO(P_CDFILIAL,
                                    V_NRLANCTONF,
                                    CURS_APURAC.CDPRODUTO,
                                    CASE WHEN V_IDUTPROPEMIS = 'S' 
                                         THEN CURS_APURAC.CDARVPROD
                                         ELSE CURS_APURAC.CDSERVFILI END,
                                    CASE WHEN V_IDUTPROPEMIS = 'S'
                                         THEN NVL(CURS_APURAC.DSPRODUTO,CURS_APURAC.NMPRODUTO)
                                         ELSE NVL(CURS_APURAC.DSPRODUTO,CURS_APURAC.NMSERVICO) END,
                                    CURS_APURAC.NREFETIVOS,
                                    CURS_APURAC.VRPRECOUNIT,
                                    CURS_APURAC.VRDESCONTO   , NULL, CURS_APURAC.NRPEDIDO,
                                    CURS_APURAC.NRITEMPED, NULL, NULL,
                                    NULL, NULL, NULL,
                                    NULL, NULL, 'S' ,
                                    NULL, 0   , CURS_APURAC.CDSERVFILI,
                                    NULL, NULL, CURS_APURAC.CDSERVFILI,
                                    'N','S',0,CURS_APURAC.DSJUSTIFICATIVA);
                                    
         ELSE /* O PRODUTO DE FATURAMENTO PARAMETRIZADO PARA GERAR PARA N PRODUTOS */
            FOR C_PRODFATURAM IN
               (SELECT PF.CDPRODUTO, PD.CDARVPROD, PD.NMPRODUTO, TRUNC(CURS_APURAC.VRPRECOUNIT*PF.VRPERCENTUAL/100, 2) AS VRPRODFATU
                FROM PRODFATURAM PF, PRODUTO PD
                WHERE PF.CDFILIAL = V_CDFILIAPUR
                  AND PF.CDSERVFILI = CURS_APURAC.CDSERVFILI
                  AND PD.CDPRODUTO = PF.CDPRODUTO
            ) LOOP
               V_SOMAPRODFATURAM := V_SOMAPRODFATURAM + C_PRODFATURAM.VRPRODFATU;
               /*se cursor chegou ao ultimo produto, e a soma dos itens é diferente do total do servico então aplica a diferença no valor do ultimo item*/
               IF (V_CONTPRODFATURAM = V_QTPRODFATU) AND (CURS_APURAC.VRPRECOUNIT <> V_SOMAPRODFATURAM) THEN 
                  V_VRPRODFATURAM := C_PRODFATURAM.VRPRODFATU + (CURS_APURAC.VRPRECOUNIT - V_SOMAPRODFATURAM);         
               ELSE
                  V_VRPRODFATURAM := C_PRODFATURAM.VRPRODFATU;
               END IF;
            
               V_CONTPRODFATURAM := V_CONTPRODFATURAM + 1;
               GERA_NOTAFISCAL_PRODUTO(P_CDFILIAL,
                                       V_NRLANCTONF,
                                       C_PRODFATURAM.CDPRODUTO,
                                       C_PRODFATURAM.CDARVPROD,
                                       C_PRODFATURAM.NMPRODUTO,
                                       CURS_APURAC.NREFETIVOS,
                                       V_VRPRODFATURAM,
                                       CURS_APURAC.VRDESCONTO   , NULL, CURS_APURAC.NRPEDIDO,
                                       CURS_APURAC.NRITEMPED, NULL, NULL,
                                       NULL, NULL, NULL,
                                       NULL, NULL, 'S' ,
                                       NULL, 0   , CURS_APURAC.CDSERVFILI,
                                       NULL, NULL, CURS_APURAC.CDSERVFILI,
                                       'N','S',0,CURS_APURAC.DSJUSTIFICATIVA);
            END LOOP;
         END IF;
         
         UPDATE HISTCTRLAPURFAT H
            SET NRRETROFAT = V_NRRETROFAT
          WHERE H.CDFILIAPUR = P_CDFILIAL
            AND H.CDCLIENTE = P_CDCLIENTE
            AND H.CDSERVFILI = CURS_APURAC.CDSERVFILI
            AND ((CURS_APURAC.CDTURNO IS NULL AND H.CDTURNO IS NULL) OR (H.CDTURNO = CURS_APURAC.CDTURNO))
            AND H.VRPRECUNIT = CURS_APURAC.VRUNIT_ANTERIOR
            AND CASE
                  WHEN H.CDTURNO IS NULL
                  THEN UTIL_APURAC.CALCVALRSERV(H.CDFILIAPUR, H.CDCLIENTE, H.CDSERVFILI, H.DTAPURACAO, NULL, TRUNC(SYSDATE))
                  ELSE UTIL_APURAC.CALCVALRSERV(H.CDFILIAPUR, H.CDCLIENTE, H.CDSERVFILI, H.DTAPURACAO, H.CDTURNO, TRUNC(SYSDATE))
                END = CURS_APURAC.VRUNIT_ATUAL
            AND H.DTAPURACAO BETWEEN P_DTINICIAL AND P_DTFINAL
            AND H.CDFILIAL || H.NRAPURACFAT IN (SELECT CDFILIAL || NRAPURACFAT FROM CTRLAPURRETROFAT WHERE NRRETROFAT = V_NRRETROFAT);
      END LOOP;      
      /* EFETUA O FECHAMENTO DA NOTA, GERACAO DE IMPOSTOS */
      IF (V_IDNOVANOTA = 'S') THEN
         GERA_NOTAFISCAL_FECHAMENTO(P_CDFILIAL, V_NRLANCTONF);

         IF (V_DESCDOTACAO = '2') AND (V_VRCREDIDEBI <> 0) THEN
            INSERT INTO AJCTRECEBER
            (CDFILIAL,    NRLANCTONF,  DTAJUSTEREC, CDAJUCTREC,
             DSAJUSTEREC, VRAJUSTEREC, NRSEQVENREC, NRPARCELAREC)
            (SELECT MAX(CDFILIAL),  MAX(NRLANCTONF), SYSDATE , V_CDAJUSTPADR,
                    V_DSAJUCTREC,   ROUND(V_VRCREDIDEBI, 2),    MAX(NRSEQVENREC), MAX(NRPARCELAREC)
             FROM CONTARECEBER
             WHERE (CDFILIAL    =  P_CDFILIAL)    AND
                   (NRLANCTONF  =  V_NRLANCTONF)); 
         END IF;         
      END IF;
   END IF;
   
   -- Apaga tabela de trabalho
   DELETE FROM TRABRETROFAT
    WHERE NRCTRLTRABRETROFAT = P_NRCTRLTRABRETROFAT;
END;
/

-- VERSAO --
BEGIN ATUVEROBJ('GERA_RETROATIVO_GD','6.29.000'); END;
/