Pendência de Cancelamento

Contexto

Esse recurso melhora a integridade no processo de cancelamento de notas fiscais de saída pela tela F140CAN. Esse processo é um complemento ao uso dos identificadores de regra VEN-140CANAE01 e VEN-140CANAE02.

Caso ocorra um erro durante o processo, após a nota ser enviada ao sistema de documentos eletrônicos, poderia ocorrer um rollback no sistema, deixando a nota com uma situação incorreta.

Parametrização

Para ativar a rotina, deve-se ativar o identificador de regras VEN-140CANAE01 na empresa desejada. Não é necessário vincular um código de regras.

Caso o processo de cancelamento seja feito por AcaoSID, o identificador VEN-140CANAE02 deverá ser utilizado.

Quando estiver sendo utilizado o Identificador de Regras VEN-140AESAL01, a tabela e os campos onde as informações das Pendencias de Cancelamentos são gravadas e alteradas, podem não ser nativos do sistema, mas sim de usuário.

Cancelando a Nota

1. Tela Emissão ou Cancelamento de Notas Fiscais de Saída (F140CAN)

Cancelando a Ação Eletrônica Pendente

Quando ocorrer um erro no cancelamento, será gerado um registro na tabela E140ADE com a situação "E", e a nota fiscal ficará como "Cancelada". No entanto, a situação eletrônica da nota continuará como "3 - Autorizada", pois a emissão do cancelamento não foi concluída.

Para solicitar novamente a emissão do cancelamento dessa nota, pode-se utilizar a função de programador ReexecutarAcaoEletronica(), que será executada por uma regra LSP e enviará ao sistema os dados salvos na tabela E140ADE ou na tabela de usuário informada pelo usuário do sistema no identificador VEN-140AESAL01.

Consideremos um processo automático que executará a regra:

Ao executar, será feita uma busca na tabela E140ADE ou na tabela de usuário por registros cuja situação seja:

Serão populadas as variáveis com os valores salvos para então chamar a função de programador ReexecutarAcaoEletronica() enviando os dados como parâmetro. Com isso o sistema executará a emissão do cancelamento novamente para aquela nota.

No caso da situação do registro estiver como "R" (Rejeição), a regra deve chamar o webservice com.senior.g5.co.int.eletronicos.documentos, porta ImportarRetornos para realizar a atualização da nota no sistema.

Quando ocorrer um erro no retorno ao ERP, ou seja, após enviar os dados para a SEFAZ, será necessário executar o processo automático 102 - Integração com o eDocs, para importar o retorno novamente, para maiores detalhes clique aqui.

Segue exemplo de regra LSP utilizando a tabela nativa do sistema (E140ADE):

Definir Funcao DefinirEstrutura();
Definir Funcao CursorVariaveis();
Definir Funcao TratarRegistroADE();
Definir Funcao AtualizarAcaoEletronica();
Definir Funcao RejeitarNotaWS();

@ Variaveis para indicar o nome dos campos @
Definir Alfa aTabela_Nome;
Definir Alfa aIdeUni_Nome;
Definir Alfa aCodEmp_Nome;
Definir Alfa aCodFil_Nome;
Definir Alfa aCodSnf_Nome;
Definir Alfa aAbrNfv_Nome;
Definir Alfa aTipAde_Nome;
Definir Alfa aSimEmi_Nome;
Definir Alfa aRotOri_Nome;
Definir Alfa aDatGer_Nome;
Definir Alfa aDatGer_Nome_Aux;
Definir Alfa aSitIex_Nome;
Definir Alfa aDatExe_Nome;
Definir Alfa aHorExe_Nome;

@ Variaveis com os valores dos campos @
Definir Numero nIdeUni;
Definir Numero nCodEmp;
Definir Numero nCodFil;
Definir Alfa aCodSnf;
Definir Alfa aAbrNfv;
Definir Alfa aTipAde;
Definir Alfa aSimEmi;
Definir Alfa aRotOri;
Definir Alfa aSitIex;
Definir Numero nSitDoe;

@ Variaveis auxiliares @
Definir Alfa aResultado;
Definir Alfa cE140ADE;
Definir Alfa aSQL;
Definir Alfa aDiasEntreDatas; 

DefinirEstrutura();

/* Usa a funcao DiasEntreDatas para montar uma condicao SQL que traz uma quantidade de dias da geracao do registro ate a data atual. 
   @param pDataIni data inicial usada na condicao SQL;
   @param pDataFim data final. Opcional;
   @param pUsarDataAtual indicativo se deve usar a data atual do sistema na hora de montar a condicao SQL;
   @param pResultado variavel de retorno;  
*/
aDatGer_Nome_Aux = aTabela_Nome+"."+aDatGer_Nome; 
DiasEntreDatas(aDatGer_Nome_Aux, "", 1, aDiasEntreDatas);
  
aSQL =  "SELECT " + aTabela_Nome + "." + aIdeUni_Nome + 
             ", " + aTabela_Nome + "." + aCodEmp_Nome + 
             ", " + aTabela_Nome + "." + aCodFil_Nome + 
             ", " + aTabela_Nome + "." + aCodSnf_Nome + 
             ", " + aTabela_Nome + "." + aAbrNfv_Nome + 
             ", " + aTabela_Nome + "." + aTipAde_Nome + 
             ", " + aTabela_Nome + "." + aSimEmi_Nome + 
             ", " + aTabela_Nome + "." + aRotOri_Nome +
             ", " + aTabela_Nome + "." + aSitIex_Nome + 
             ", IDE.SITDOE \  
           FROM " + aTabela_Nome +
       "   LEFT JOIN E140IDE IDE ON (IDE.CODEMP = " + aTabela_Nome + "." + aCodEmp_Nome + 
                               " AND IDE.CODFIL = " + aTabela_Nome + "." + aCodFil_Nome + 
                               " AND IDE.CODSNF = " + aTabela_Nome + "." + aCodSnf_Nome + 
                               " AND IDE.NUMNFV = " + aTabela_Nome + "." + aAbrNfv_Nome + ") " + 
			 "  WHERE (" + aTabela_Nome + "." + aSitIex_Nome + " = 'E') " +
			 "     OR (" + aTabela_Nome + "." + aSitIex_Nome + " = 'R' AND IDE.SITDOE = 7) " +
       "     OR (" + aTabela_Nome + "." + aSitIex_Nome + " = 'P' AND " + aDiasEntreDatas + " > 1) ";
                       
          
Sql_Criar(cE140ADE);
Sql_UsarSQLSenior2(cE140ADE, 0);
Sql_UsarAbrangencia(cE140ADE, 0);
Sql_DefinirComando(cE140ADE, aSQL);

Sql_AbrirCursor(cE140ADE);

Enquanto (Sql_Eof(cE140ADE) = 0) 
Inicio
  CursorVariaveis();
  
  TratarRegistroADE();
	
	Sql_Proximo(cE140ADE);
Fim;

Sql_FecharCursor(cE140ADE);
Sql_Destruir(cE140ADE);          
        
@ Funcao para indicar os nomes dos campos da rotina de pendencia de cancelamento @
Funcao DefinirEstrutura();
Inicio
  aTabela_Nome = "E140ADE";
  aIdeUni_Nome = "IDEUNI";
  aCodEmp_Nome = "CODEMP";
  aCodFil_Nome = "CODFIL";
  aCodSnf_Nome = "CODSNF";
  aAbrNfv_Nome = "ABRNFV";
  aTipAde_Nome = "TIPADE";
  aSimEmi_Nome = "SIMEMI";
  aRotOri_Nome = "ROTORI";
  aDatGer_Nome = "DATGER";
  aSitIex_Nome = "SITIEX";
  aDatExe_Nome = "DATEXE";
  aHorExe_Nome = "HOREXE";
Fim;     
      
@ Funcao para passar os valores do select para as variaveis @                 
Funcao CursorVariaveis();
Inicio
  Sql_RetornarInteiro(cE140ADE, aIdeUni_Nome, nIdeUni);
  Sql_RetornarInteiro(cE140ADE, aCodEmp_Nome, nCodEmp);
  Sql_RetornarInteiro(cE140ADE, aCodFil_Nome, nCodFil);
  Sql_RetornarAlfa(cE140ADE, aCodSnf_Nome, aCodSnf);
  Sql_RetornarAlfa(cE140ADE, aAbrNfv_Nome, aAbrNfv);
  Sql_RetornarAlfa(cE140ADE, aTipAde_Nome, aTipAde);
  Sql_RetornarAlfa(cE140ADE, aSimEmi_Nome, aSimEmi);
  Sql_RetornarAlfa(cE140ADE, aRotOri_Nome, aRotOri);
  Sql_RetornarAlfa(cE140ADE, aSitIex_Nome, aSitIex);
  Sql_RetornarInteiro(cE140ADE, "SITDOE", nSitDoe);                     
Fim;

Funcao TratarRegistroADE();
Inicio
  Se (nSitDoe = 9) 
  Inicio
    AtualizarAcaoEletronica();
  Fim   
  Senao
  Inicio
    Se (aSitIex = "R") 
    Inicio
      RejeitarNotaWS();
      AtualizarAcaoEletronica();
    Fim
    Senao   
    Inicio
     	ReexecutarAcaoEletronica(nIdeUni, nCodEmp, nCodFil, aCodSnf, aAbrNfv, aTipAde, aSimEmi, aRotOri, aResultado);
 	  Fim;
 	Fim;  
                 
Fim;

@ Funcao para atualizar a situação para S - Sucesso na tabela de pendência @
Funcao AtualizarAcaoEletronica();
Inicio
  Definir Numero xDataAtual;
  Definir Alfa xDataAtualAlfa;
  Definir Alfa xIdeUniAlfa;
  Definir Alfa xSql;
  Definir Alfa xParalela;
  Definir Alfa xLinhasAfetadas;
  Definir Alfa xResultado; 
                             
  DataHoje(xDataAtual);
  ConverteDataBanco(xDataAtual, xDataAtualAlfa); 
  IntParaAlfa(nIdeUni, xIdeUniAlfa);
  xParalela = "N";

  xSql = "UPDATE " + aTabela_Nome + " SET " + aSitIex_Nome + " = 'S', " + aDatExe_Nome + " = " + xDataAtualAlfa + " WHERE " + aIdeUni_Nome + " = " + xIdeUniAlfa;
               
  ExecutarComandoSQL(xSql, xParalela, xLinhasAfetadas, xResultado); 
Fim;

@ Funcao para chamar o WS com um retorno de rejeição de cancelamento @
Funcao RejeitarNotaWS(); 
Inicio
  Definir interno.com.senior.g5.co.int.eletronicos.documentos.ImportarRetornos_6 WSImpNfv;
  Definir Alfa DatSisAlfa;
  Definir Alfa HorSisAlfa;
  Definir Alfa aChave;
  Definir Alfa aProtocolo;
  Definir Cursor cE140IDE;
  
  DatSisAux = DatSis;
  HorSisAux = HorSis;         
  ConverteMascara(3, DatSisAux, DatSisAlfa, "YYYY-MM-DD");
  ConverteMascara(4, HorSisAux, HorSisAlfa, "hh:mm");  
  
  cE140IDE.Sql "SELECT E140IDE.CHVDOE, E140IDE.NUMPRT              \
		              FROM E140IDE                                     \
								 WHERE E140IDE.CODEMP =:nCodEmp                    \
									 AND E140IDE.CODFIL =:nCodFil                    \
									 AND E140IDE.CODSNF =:aCodSnf                    \
									 AND E140IDE.NUMNFV =:aAbrNfv ";                   			             
  cE140IDE.AbrirCursor();
  SE (cE140IDE.Achou) {
		aChave = cE140IDE.CHVDOE;
    aProtocolo = cE140IDE.NUMPRT;
		cE140IDE.FecharCursor();
  } SENAO {
		cE140IDE.FecharCursor();
  }
  
  WSImpNfv.EntradaDoRetornoNFEletronica.ChvNel = aChave;  
  WSImpNfv.EntradaDoRetornoNFEletronica.NumPrt = aProtocolo;
  WSImpNfv.EntradaDoRetornoNFEletronica.DatHor = DatSisAlfa+"T"+HorSisAlfa;
  WSImpNfv.EntradaDoRetornoNFEletronica.SitNel = "11";
	WSImpNfv.EntradaDoRetornoNFEletronica.TipDoe = "5";
	WSImpNfv.ModoExecucao = 1;
  WSImpNfv.Executar();  
Fim;

Confira nas seguintes tabelas de Arquivo XML e eDocs, os valores do sistema em cada passo do cancelamento, demonstrando o que pode ser feito caso ocorra um erro no processo:

Este artigo ajudou você?