No artigo de hoje vamos demonstrar em como transmitir e monitorar uma NFe de saída via comandos em AdvPL ou TLPP.
Recentemente nos perguntaram se seria possível numa customização, acionar a transmissão do documento e monitorá-lo, sem exibir telas aos usuários.
Pensando nisso, montamos esse exemplo onde:
- É recebido por parâmetro a nota e série da SF2
- É feito a busca do ident, ambiente e modalidade
- Se conseguiu buscar as informações aciona a SpedNfeTrf para transmitir
- Em seguida é acionado a ProcMonitorDoc
- Se deu tudo certo, ou algum erro, é definido num array que será retornado
Supondo então, que você tenha a nota 000123789 com a série 1, pra acionar a customização iria ficar:
aInfo := u_zTransNfe("000123789", "1")
E abaixo o código completo da zTransNfe:
//Bibliotecas #Include "TOTVS.ch" /*/{Protheus.doc} zTransNfe Função para transmitir a SF2 para a SEFAZ e Monitorar o resultado @type user function @author Atilio @since 13/06/2025 @version version @param cDocumento, Caractere, Número do Documento que vai ser transmitido @param cSerie, Caractere, Série do Documento @return aRetorno, Array, Array com duas posição, primeira se deu certo (.T. ou .F.) e segunda a mensagem (com observações) @example aInfo := u_zTransNfe("000123456", "1") /*/ User Function zTransNfe(cDocumento, cSerie) Local aArea := FWGetArea() //Transmissão e Monitoramento Local cModelo := "55" Local cIdEnt := "" Local cError := "" //Transmissão Local cAmbiente := "" Local cModalidade := "" Local cVersao := "" Local lCte := .F. //( cModelo == "57" ) Local lEnd := .F. //Monitoramento Local nVezes := 0 Local cURL := PadR(GetNewPar("MV_SPEDURL", "http://"), 250) Local aParam := {} Local nTpMonitor := 1 Local aRetMonit := {} //Retorno da Função Local lDeuCerto := .F. Local cMensagem := "" Local aRetorno := {.F., ""} //Posiciona na Nota (que não tenha chave de acesso ainda) Dbselectarea('SF2') SF2->(DbSetOrder(1)) // F2_FILIAL + F2_DOC + F2_SERIE + F2_CLIENTE + F2_LOJA + F2_FORMUL + F2_TIPO If SF2->(MsSeek(FWxFilial('SF2') + cDocumento + cSerie)) .And. Empty(SF2->F2_CHVNFE) cIdEnt := getCfgEntidade(@cError) //Se encontrou a entidade If ! Empty( cIdEnt ) //Busca o ambiente, modalidade e versão cAmbiente := getCfgAmbiente(@cError, cIdEnt, cModelo) If ! Empty(cAmbiente) cModalidade := getCfgModalidade(@cError, cIdEnt, cModelo) If ! Empty(cModalidade) cVersao := getCfgVersao(@cError, cIdEnt, cModelo) EndIf EndIf //Se conseguiu buscar as informações If ! Empty(cVersao) //Aciona a transmissão da Nota para o Sefaz cRetorno := SpedNFeTrf(; "SF2",; //cAlias SF2->F2_SERIE,; //cSerie SF2->F2_DOC,; //cNotaIni SF2->F2_DOC,; //cNotaFim cIdEnt,; //cIDEnt cAmbiente,; //cAmbiente cModalidade,; //cModalidade cVersao,; //cVersao @lEnd,; //lEnd lCte,; //lCte .T.,; //lAuto Nil,; //dDataDe Nil; //dDataAte ) //Se tiver a mensagem de sucesso, tenta acionar o monitoramento If "SUCESSO" $ Upper(cRetorno) //Monta o array de parâmetros para monitorar aParam := Array(5) aParam[1] := SF2->F2_SERIE aParam[2] := SF2->F2_DOC aParam[3] := SF2->F2_DOC aParam[4] := MonthSub(SF2->F2_EMISSAO, 1) aParam[5] := MonthSum(SF2->F2_EMISSAO, 1) //Tenta monitorar 3 vezes While nVezes < 3 aRetMonit := procMonitorDoc(; cIdent,; //cIdEnt cUrl,; //cUrl aParam,; //aParam nTpMonitor,; //nTpMonitor (1=Range de Notas; 2=Lote de Id;3=Tempo) "0" + cModelo,; //cModelo lCte,; //lCte @cError; //cAviso ) //Se teve retorno o monitoramento If Len(aRetMonit) > 0 //Se começar com 001, deu certo o monitoramento If Left(Alltrim(aRetMonit[1][9]), 3) == '001' lDeuCerto := .T. cMensagem := "Sucesso na transmissão e monitoramento da Nota!" Exit EndIf EndIf //Aguarda 3 segundos antes da próxima tentativa Sleep(3000) nVezes++ EndDo //Se mesmo ao acionar o monitoramento, não der certo, atualiza a variável de retorno If ! lDeuCerto cMensagem := "Falha ao tentar acionar o monitoramento! " + cError EndIf Else cMensagem := "Falha na transmissão da Nota! " + cRetorno EndIf Else cMensagem := "Falha ao buscar informações (Ambiente, Modalidade e Versão)! " + cError EndIf Else cMensagem := "Falha ao buscar o IdEnt da Empresa! " + cError EndIf Else cMensagem := "Nota e Série não encontradas na SF2!" EndIf //Define o retorno aRetorno[1] := lDeuCerto aRetorno[2] := cMensagem FWRestArea(aArea) Return aRetorno
Bom pessoal, por hoje é só.
Abraços e até a próxima.