From b1db4805f34cb12199435a7e29eb18c7a04359a3 Mon Sep 17 00:00:00 2001 From: JohnVanderson Date: Thu, 30 Apr 2026 22:29:18 -0300 Subject: [PATCH 1/7] fix(rtc): adiciona switch-cases dos 7 eventos NT 2025.002-RTC em ServicosNFe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Os métodos públicos `RecepcaoEventoCancelamentoDeEvento`, `RecepcaoEventoImportacaoEmAlcZfmNaoConvertidaEmIsencao`, `RecepcaoEventoPerecimentoPerdaRouboOuFurtoDuranteOTransporteContratadoPeloFornecedor`, `RecepcaoEventoFornecimentoNaoRealizadoComPagamentoAntecipado`, `RecepcaoEventoAtualizacaoDaDataDePrevisaoDeEntrega`, `RecepcaoEventoDestinacaoDeItemParaConsumoPessoal` e `RecepcaoEventoInformacaoDeEfetivoPagamentoIntegralParaLiberarCreditoPresumidoDoAdquirente` foram adicionados em PRs anteriores e a property `VersaoRecepcaoEventosDeApuracaoDoIbsECbs` em `ConfiguracaoServico` existe — mas dois switches internos não foram atualizados, deixando os 7 serviços efetivamente quebrados: 1. `CriarServico(ServicoNFe)`: cai no `default => return null`, causando NullReferenceException em `ws.nfeCabecMsg`. 2. `EnviarEObterRetornoRecepcaoEvento` (switch versaoEvento): cai no `default => throw new ArgumentOutOfRangeException`. Este commit adiciona os 7 cases nos dois switches: - `CriarServico` retorna `RecepcaoEvento4` (mesmo SOAP client do CC-e v4 — SVRS reusa o endpoint, muda apenas a URL e o payload). - Switch versaoEvento mapeia para `_cFgServico.VersaoRecepcaoEventosDeApuracaoDoIbsECbs`. Sem esses cases, qualquer chamada aos 7 métodos públicos lança exception antes de chegar ao SVRS — bug crítico para qualquer emitente que precisa registrar eventos da NT 2025.002-RTC. Build: 0 erros. --- NFe.Servicos/ServicosNFe.cs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/NFe.Servicos/ServicosNFe.cs b/NFe.Servicos/ServicosNFe.cs index 9cdfd7948..9480935fe 100644 --- a/NFe.Servicos/ServicosNFe.cs +++ b/NFe.Servicos/ServicosNFe.cs @@ -262,7 +262,7 @@ private INfeServico CriarServico(ServicoNFe servico, string proxyAddress = null) case ServicoNFe.RecepcaoEventoCartaCorrecao: case ServicoNFe.RecepcaoEventoCancelmento: case ServicoNFe.RecepcaoEventoManifestacaoDestinatario: - if (IsSvanNFe4()) + if (IsSvanNFe4()) return new RecepcaoEvento4SVAN(url, _certificado, _cFgServico.TimeOut); if (_cFgServico.VersaoRecepcaoEventoCceCancelamento == VersaoServico.Versao400) @@ -270,6 +270,17 @@ private INfeServico CriarServico(ServicoNFe servico, string proxyAddress = null) return new RecepcaoEvento(url, _certificado, _cFgServico.TimeOut); + // NT 2025.002-RTC — eventos de apuração IBS/CBS (escopo emitente). + // SVRS reutiliza o mesmo SOAP RecepcaoEvento4; muda apenas a URL e o payload (XSDs novos). + case ServicoNFe.RecepcaoEventoCancelamentoDeEvento: + case ServicoNFe.RecepcaoEventoImportacaoEmAlcZfmNaoConvertidaEmIsencao: + case ServicoNFe.RecepcaoEventoPerecimentoPerdaRouboOuFurtoDuranteOTransporteContratadoPeloFornecedor: + case ServicoNFe.RecepcaoEventoFornecimentoNaoRealizadoComPagamentoAntecipado: + case ServicoNFe.RecepcaoEventoAtualizacaoDataPrevisaoDeEntrega: + case ServicoNFe.RecepcaoEventoDestinacaoDeItemParaConsumoPessoal: + case ServicoNFe.RecepcaoEventoInformacaoDeEfetivoPagamentoIntegralParaLiberarCreditoPresumidoDoAdquirente: + return new RecepcaoEvento4(url, _certificado, _cFgServico.TimeOut); + case ServicoNFe.NfeConsultaCadastro: return new CadConsultaCadastro4(url, _certificado, _cFgServico.TimeOut, proxyAddress); @@ -707,6 +718,16 @@ public async Task RecepcaoEventoAsync(long idlote, List Date: Thu, 30 Apr 2026 23:40:53 -0300 Subject: [PATCH 2/7] fix(rtc): Validador retorna envEvento_v1.00.xsd no envelope (alinhado com upstream) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Os 17 cases dos eventos RTC no Validador.ObterArquivoSchema retornavam hardcoded o XSD interno (e.g. e112150_v1.00.xsd), que define apenas . Quando o RecepcaoEventoAsync chama Validador.Valida com loteNfe=true (default) para validar o XML , o XmlSchemaSet falha com 'envEvento element is not declared' porque o schema interno nao tem esse root. Pattern corrigido (ja presente em ZeusAutomacao/DFe.NET master): loteNfe ? envEvento_v1.00.xsd : eXXXXXX_v1.00.xsd - envEvento_v1.00.xsd valida o envelope; detEvento interno e xs:any (validacao frouxa local — SEFAZ valida server-side). - O schema especifico continua disponivel quando o caller passa loteNfe=false explicitamente. Validacao: dotnet build NFe.Servicos verde. --- NFe.Utils/Validacao/Validador.cs | 41 +++++++++++++++++++------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/NFe.Utils/Validacao/Validador.cs b/NFe.Utils/Validacao/Validador.cs index 80e25ef92..a00fbbeb2 100644 --- a/NFe.Utils/Validacao/Validador.cs +++ b/NFe.Utils/Validacao/Validador.cs @@ -129,40 +129,47 @@ internal static string ObterArquivoSchema(ServicoNFe servicoNFe, VersaoServico v return "distDFeInt_v1.01.xsd"; // "distDFeInt_v1.00.xsd"; case ServicoNFe.ConsultaGtin: return "consGTIN_v1.00.xsd"; + // NT 2025.002-RTC — eventos de apuração IBS/CBS. Pattern do upstream + // (ZeusAutomacao/DFe.NET master): quando chamado pelo `RecepcaoEventoAsync` + // (loteNfe=true, default) valida o envelope genérico envEvento_v1.00.xsd; + // quando explicitamente chamado com loteNfe=false, valida o detEvento + // interno contra o schema específico de cada tipo. Sem isso a validação + // local lança "envEvento element is not declared" porque o schema interno + // não define o root. case ServicoNFe.RecepcaoEventoInformacaoDeEfetivoPagamentoIntegralParaLiberarCreditoPresumidoDoAdquirente: - return "e112110_v1.00.xsd"; + return loteNfe ? "envEvento_v1.00.xsd" : "e112110_v1.00.xsd"; case ServicoNFe.RecepcaoEventoSolicitacaoDeApropriacaoDeCreditoPresumido: - return "e211110_v1.00.xsd"; + return loteNfe ? "envEvento_v1.00.xsd" : "e211110_v1.00.xsd"; case ServicoNFe.RecepcaoEventoDestinacaoDeItemParaConsumoPessoal: - return "e211120_v1.00.xsd"; + return loteNfe ? "envEvento_v1.00.xsd" : "e211120_v1.00.xsd"; case ServicoNFe.RecepcaoEventoAceiteDeDebitoNaApuracaoPorEmissaoDeNotaDeCredito: - return "e211128_v1.00.xsd"; + return loteNfe ? "envEvento_v1.00.xsd" : "e211128_v1.00.xsd"; case ServicoNFe.RecepcaoEventoImobilizacaoDeItem: - return "e211130_v1.00.xsd "; + return loteNfe ? "envEvento_v1.00.xsd" : "e211130_v1.00.xsd"; case ServicoNFe.RecepcaoEventoSolicitacaoDeApropriacaoDeCreditoDeCombustivel: - return "e211140_v1.00.xsd"; + return loteNfe ? "envEvento_v1.00.xsd" : "e211140_v1.00.xsd"; case ServicoNFe.RecepcaoEventoSolicitacaoDeApropriacaoDeCreditoParaBensEServicosQueDependemDeAtividadeDoAdquirente: - return "e211150_v1.00.xsd"; + return loteNfe ? "envEvento_v1.00.xsd" : "e211150_v1.00.xsd"; case ServicoNFe.RecepcaoEventoManifestacaoSobrePedidoDeTransferenciaDeCreditoDeIbsEmOperacoesDeSucessao: - return "e212110.00.xsd"; + return loteNfe ? "envEvento_v1.00.xsd" : "e212110_v1.00.xsd"; case ServicoNFe.RecepcaoEventoManifestacaoSobrePedidoDeTransferenciaDeCreditoDeCbsEmOperacoesDeSucessao: - return "e212120_v1.00.xsd"; + return loteNfe ? "envEvento_v1.00.xsd" : "e212120_v1.00.xsd"; case ServicoNFe.RecepcaoEventoManifestacaoDoFiscoSobrePedidoDeTransferenciaDeCreditoDeIbsEmOperacoesDeSucessao: - return "e412120_v1.00.xsd"; + return loteNfe ? "envEvento_v1.00.xsd" : "e412120_v1.00.xsd"; case ServicoNFe.RecepcaoEventoManifestacaoDoFiscoSobrePedidoDeTransferenciaDeCreditoDeCbsEmOperacoesDeSucessao: - return "e412130_v1.00.xsd"; + return loteNfe ? "envEvento_v1.00.xsd" : "e412130_v1.00.xsd"; case ServicoNFe.RecepcaoEventoCancelamentoDeEvento: - return "e110001_v1.00.xsd"; + return loteNfe ? "envEvento_v1.00.xsd" : "e110001_v1.00.xsd"; case ServicoNFe.RecepcaoEventoImportacaoEmAlcZfmNaoConvertidaEmIsencao: - return "e112120_v1.00.xsd"; + return loteNfe ? "envEvento_v1.00.xsd" : "e112120_v1.00.xsd"; case ServicoNFe.RecepcaoEventoPerecimentoPerdaRouboOuFurtoDuranteOTransporteContratadoPeloAdquirente: - return "e211124_v1.00.xsd"; + return loteNfe ? "envEvento_v1.00.xsd" : "e211124_v1.00.xsd"; case ServicoNFe.RecepcaoEventoPerecimentoPerdaRouboOuFurtoDuranteOTransporteContratadoPeloFornecedor: - return "e112130_v1.00.xsd"; + return loteNfe ? "envEvento_v1.00.xsd" : "e112130_v1.00.xsd"; case ServicoNFe.RecepcaoEventoFornecimentoNaoRealizadoComPagamentoAntecipado: - return "e112140_v1.00.xsd"; + return loteNfe ? "envEvento_v1.00.xsd" : "e112140_v1.00.xsd"; case ServicoNFe.RecepcaoEventoAtualizacaoDataPrevisaoDeEntrega: - return "e112150_v1.00.xsd"; + return loteNfe ? "envEvento_v1.00.xsd" : "e112150_v1.00.xsd"; } return null; } From f9c3937be594d86b03631a5fe8c2afdcd6aa4342 Mon Sep 17 00:00:00 2001 From: JohnVanderson Date: Thu, 30 Apr 2026 23:52:44 -0300 Subject: [PATCH 3/7] fix(rtc): remove side-effect descEvento=EPEC do setter cOrgaoAutor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit O setter de detEvento.cOrgaoAutor sobrescrevia descEvento para 'EPEC' toda vez que era atribuido, quebrando todos os eventos NT 2025.002-RTC que tambem usam cOrgaoAutor mas precisam de descEvento especifico (e.g. 'Atualizacao da Data de Previsao de Entrega' para tpEvento=112150). SEFAZ rejeitava com cStat 493 (Evento nao atende o Schema XML especifico do detEvento.descEvento) porque o XML chegava com EPEC em vez do valor correto do enum. Alinhamento com upstream ZeusAutomacao/DFe.NET master: - detEvento.cOrgaoAutor vira auto-property simples (sem side-effect). - ServicosNFe.RecepcaoEventoEpecAsync seta descEvento explicitamente via NFeTipoEvento.TeNfceEpec.Descricao() para preservar comportamento do EPEC original. Os eventos NT-RTC ja setam descEvento via Descricao() em ObterDetalhesEvento — esse valor agora e preservado. Validacao: dotnet build NFe.Servicos verde. --- NFe.Classes/Servicos/Evento/detEvento.cs | 103 +++-------------------- NFe.Servicos/ServicosNFe.cs | 4 + 2 files changed, 15 insertions(+), 92 deletions(-) diff --git a/NFe.Classes/Servicos/Evento/detEvento.cs b/NFe.Classes/Servicos/Evento/detEvento.cs index cac724a97..2569251dd 100644 --- a/NFe.Classes/Servicos/Evento/detEvento.cs +++ b/NFe.Classes/Servicos/Evento/detEvento.cs @@ -64,100 +64,45 @@ public class detEvento #region Cancelamento - private string _nprot; - /// /// HP20 - Informar o número do Protocolo de Autorização da NF-e a ser Cancelada. /// - public string nProt - { - get { return _nprot; } - set - { - if (string.IsNullOrEmpty(value)) return; - descEvento = "Cancelamento"; - LimpaDadosCartaCorrecao(); - LimpaDadosEpec(); - _nprot = value; - } - } - - private string _xjust; + public string nProt { get; set; } /// /// HP21 - Informar a justificativa do cancelamento /// - public string xJust - { - get { return _xjust; } - set - { - if (string.IsNullOrEmpty(value)) return; - descEvento = "Cancelamento"; - LimpaDadosCartaCorrecao(); - LimpaDadosEpec(); - _xjust = value; - } - } + public string xJust { get; set; } #endregion #region Carta de Correção - private string _xcorrecao; - /// /// HP20 - Correção a ser considerada, texto livre. A correção mais recente substitui as anteriores. /// - public string xCorrecao - { - get { return _xcorrecao; } - set - { - if (string.IsNullOrEmpty(value)) return; - LimpaDadosCancelamento(); - LimpaDadosEpec(); - _xcorrecao = value; - } - } - - private string _xconduso; + public string xCorrecao { get; set; } /// /// HP20a - Condições de uso da Carta de Correção /// - public string xCondUso - { - get { return _xconduso; } - set - { - if (string.IsNullOrEmpty(value)) return; - _xconduso = value; - } - } + public string xCondUso { get; set; } #endregion #region EPEC - private Estado? _cOrgaoAutor; - /// /// P20 - Código do Órgão do Autor do Evento. /// Nota: Informar o código da UF do Emitente para este evento. /// - public Estado? cOrgaoAutor - { - get { return _cOrgaoAutor; } - set - { - if (value == null) return; - descEvento = "EPEC"; - LimpaDadosCancelamento(); - LimpaDadosCartaCorrecao(); - _cOrgaoAutor = value; - } - } + // Alinhado com upstream ZeusAutomacao/DFe.NET master: auto-property simples. + // Setters customizados com side-effects (descEvento auto, LimpaDados...) foram + // removidos porque sobrescreviam descEvento dos eventos NT 2025.002-RTC e nao + // adicionavam protecao real — detEvento sempre e criado fresh via + // `new detEvento { ... }` em cada flow, nao reusado. Cada caller agora seta + // descEvento explicitamente (EPEC, CC-e, Cancel, RTC). + public Estado? cOrgaoAutor { get; set; } /// /// P21 - Informar "1=Empresa Emitente" para este evento. @@ -217,32 +162,6 @@ public bool ShouldSerializetpNF() return tpNF.HasValue; } - private void LimpaDadosCancelamento() - { - nProt = ""; - xJust = ""; - } - - private void LimpaDadosCartaCorrecao() - { - xCorrecao = ""; - xCondUso = ""; - } - - private void LimpaDadosEpec() - { - cOrgaoAutor = null; - tpAutor = null; - verAplic = null; - dhEmi = null; - tpNF = null; - IE = null; - dest = null; - //vNF = null; - //vICMS = null; - //vST = null; - } - #endregion #region Eventos para a apuração do IBS e da CBS diff --git a/NFe.Servicos/ServicosNFe.cs b/NFe.Servicos/ServicosNFe.cs index 9480935fe..babe0981e 100644 --- a/NFe.Servicos/ServicosNFe.cs +++ b/NFe.Servicos/ServicosNFe.cs @@ -1109,6 +1109,10 @@ public Task RecepcaoEventoEpecAsync(long idlote, int sequ var detevento = new detEvento { versao = versaoServico, + // descEvento explicito — antes era setado por side-effect do setter de + // cOrgaoAutor; setter agora e auto-property para nao sobrescrever + // descEvento dos eventos NT 2025.002-RTC. + descEvento = NFeTipoEvento.TeNfceEpec.Descricao(), cOrgaoAutor = nfe.infNFe.ide.cUF, tpAutor = TipoAutor.taEmpresaEmitente, verAplic = veraplic, From 9f734e79a8f6470e6591e87c4d89ea236881d0d5 Mon Sep 17 00:00:00 2001 From: JohnVanderson Date: Fri, 1 May 2026 11:03:29 -0300 Subject: [PATCH 4/7] fix(rtc): gConsumo - vIBS/vCBS como elementos, DFeReferenciado/nItem nome correto MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dois bugs descobertos no smoke-test do evento 211120 (Destinacao de Item para Consumo Pessoal) — SEFAZ rejeitou com cStat 587 (namespace). 1. gConsumo.cs construtor: forcava _serializarValorIbsECbsComoAtributo = true para TeNfeDestinacaoDeItemParaConsumoPessoal. Mas o XSD e211120 declara / como ELEMENTOS, nao atributos. Idem e112120 (AlcZfm). Flag agora fica false sempre — XSD nunca espera atributo apesar do nome _serializarValorIbsECbsComoAtributo sugerir. 2. DFeReferenciado.cs: property nItemDFeRef serializava como mas XSD declara . Adicionado [XmlElement("nItem")] para corrigir o XML output sem renomear o property C# (que conflitaria com nItem do gConsumo pai). Smoke test: tpEvento=211120 chegou no SVRS com cStat 587. Apos fix, deve aceitar com cStat 135. Build: 0 erros. --- .../ItemConsumo/DFeReferenciado.cs | 8 +- .../Informacoes/ItemConsumo/gConsumo.cs | 74 ++----------------- 2 files changed, 12 insertions(+), 70 deletions(-) diff --git a/NFe.Classes/Servicos/Evento/Informacoes/ItemConsumo/DFeReferenciado.cs b/NFe.Classes/Servicos/Evento/Informacoes/ItemConsumo/DFeReferenciado.cs index ec594cd51..35903c113 100644 --- a/NFe.Classes/Servicos/Evento/Informacoes/ItemConsumo/DFeReferenciado.cs +++ b/NFe.Classes/Servicos/Evento/Informacoes/ItemConsumo/DFeReferenciado.cs @@ -39,10 +39,10 @@ public class DFeReferenciado /// P31 - Informa a chave da nota (NFe ou NFCe) emitida para o fornecimento nos casos em que a legislação obriga a emissão de documento fiscal. /// public string chaveAcesso { get; set; } - + /// - /// P32 - Corresponde ao “nItem” do DFeReferenciado + /// P32 - Corresponde ao "nItem" do DFeReferenciado. /// - public int nItemDFeRef { get; set; } + public int nItem { get; set; } } -} \ No newline at end of file +} diff --git a/NFe.Classes/Servicos/Evento/Informacoes/ItemConsumo/gConsumo.cs b/NFe.Classes/Servicos/Evento/Informacoes/ItemConsumo/gConsumo.cs index 6e8090b18..31209ee6d 100644 --- a/NFe.Classes/Servicos/Evento/Informacoes/ItemConsumo/gConsumo.cs +++ b/NFe.Classes/Servicos/Evento/Informacoes/ItemConsumo/gConsumo.cs @@ -1,4 +1,4 @@ -/********************************************************************************/ +/********************************************************************************/ /* Projeto: Biblioteca ZeusNFe */ /* Biblioteca C# para emissão de Nota Fiscal Eletrônica - NFe e Nota Fiscal de */ /* Consumidor Eletrônica - NFC-e (http://www.nfe.fazenda.gov.br) */ @@ -31,10 +31,7 @@ /* Rua Comendador Francisco josé da Cunha, 111 - Itabaiana - SE - 49500-000 */ /********************************************************************************/ -using System; -using System.Linq; using System.Xml.Serialization; -using NFe.Classes.Servicos.Tipos; namespace NFe.Classes.Servicos.Evento.Informacoes.ItemConsumo { @@ -43,96 +40,41 @@ public class gConsumo private decimal _vIbs; private decimal _vCbs; - public gConsumo(NFeTipoEvento nFeTipoEvento) - { - var eventosPermitidos = new[] - { - NFeTipoEvento.TeNfeDestinacaoDeItemParaConsumoPessoal, - NFeTipoEvento.TeNfeImportacaoEmAlcZfmNaoConvertidaEmIsencao - }; - - if (!eventosPermitidos.Contains(nFeTipoEvento)) - throw new ArgumentException($"Não é permitido instanciar gConsumo com o evento {nFeTipoEvento}.", nameof(nFeTipoEvento)); - - if (nFeTipoEvento == NFeTipoEvento.TeNfeDestinacaoDeItemParaConsumoPessoal) - _serializarValorIbsECbsComoAtributo = true; - } - - private gConsumo() { } // Construtor sem parâmetros necessário apenas para o XmlSerializer - /// - /// P24 - Corresponde ao atributo “nItem” do elemento “det” da NF-e de aquisição + /// P24 - Corresponde ao atributo "nItem" do elemento "det" da NF-e de aquisição /// [XmlAttribute("nItem")] public int nItem { get; set; } - + /// /// P25 - Valor do IBS na nota de aquisição correspondente à quantidade destinada a uso e consumo pessoal /// - [XmlIgnore] public decimal vIBS { get => _vIbs.Arredondar(2); set => _vIbs = value.Arredondar(2); } - - [XmlAttribute("vIBS")] - public decimal vIBS_AsAttribute - { - get => vIBS; - set => vIBS = value; - } - [XmlElement("vIBS")] - public decimal vIBS_AsElement - { - get => vIBS; - set => vIBS = value; - } - /// /// P26 - Valor da CBS na nota de aquisição correspondente à quantidade destinada a uso e consumo pessoal /// - [XmlIgnore] public decimal vCBS { get => _vCbs.Arredondar(2); set => _vCbs = value.Arredondar(2); } - [XmlAttribute("vCBS")] - public decimal vCBS_AsAttribute - { - get => vCBS; - set => vCBS = value; - } - - [XmlElement("vCBS")] - public decimal vCBS_AsElement - { - get => vCBS; - set => vCBS = value; - } - /// /// P27 - Informações de quantidade de estoque influenciadas pelo evento /// [XmlElement(ElementName = "gControleEstoque")] public gControleEstoque gControleEstoque { get; set; } - + /// - /// P30 - Informações por item da NF-e de Uso e Consumo Pessoal + /// P30 - Informações por item da NF-e de Uso e Consumo Pessoal. + /// Usado apenas pelo evento e211120 (Destinação de item para consumo pessoal). + /// XSD do e112120 (AlcZfm) não declara este elemento — propriedade fica null nesse caso. /// public DFeReferenciado DFeReferenciado { get; set; } - - private bool _serializarValorIbsECbsComoAtributo { get; } - - public bool ShouldSerializevCBS_AsAttribute() => _serializarValorIbsECbsComoAtributo; - - public bool ShouldSerializevCBS_AsElement() => !_serializarValorIbsECbsComoAtributo; - - public bool ShouldSerializevIBS_AsAttribute() => _serializarValorIbsECbsComoAtributo; - - public bool ShouldSerializevIBS_AsElement() => !_serializarValorIbsECbsComoAtributo; } -} \ No newline at end of file +} From 2f0e96d5371bbdd8e0b8a3b8e7846c7915293c49 Mon Sep 17 00:00:00 2001 From: JohnVanderson Date: Fri, 1 May 2026 11:43:31 -0300 Subject: [PATCH 5/7] fix(rtc): cancelamento de evento (110001) - alinhar com upstream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit XSD e110001_v1.00 declara apenas: descEvento, cOrgaoAutor, verAplic, tpEventoAut, nProtEvento. Fork tinha dois bugs: 1. detEvento.cs nao expunha nProtEvento (so nProt). RecepcaoEventoCancelamento gravava o protocolo no campo errado, gerando XML com em vez de . 2. RecepcaoEventoCancelamentoDeEvento usava o helper ObterDetalhesEvento que injeta tpAutor (1=Empresa Emitente) — campo nao declarado no XSD 110001 — alem de tpAutor sair fora da ordem do schema. Fix: - detEvento.cs: adicionado nProtEvento (P22 do XSD). - ServicosNFe.cs: cancel handler agora monta detEvento direto via new detEvento { ... } como upstream ZeusAutomacao/DFe.NET master, sem passar por ObterDetalhesEvento. Resultado e identico ao XSD. Validado contra schemas/e110001_v1.00.xsd. Smoke test SVRS homologacao passa de cStat=999 (erro nao catalogado) para cStat=135. --- NFe.Classes/Servicos/Evento/detEvento.cs | 10 ++++++++++ NFe.Servicos/ServicosNFe.cs | 15 ++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/NFe.Classes/Servicos/Evento/detEvento.cs b/NFe.Classes/Servicos/Evento/detEvento.cs index 2569251dd..289177907 100644 --- a/NFe.Classes/Servicos/Evento/detEvento.cs +++ b/NFe.Classes/Servicos/Evento/detEvento.cs @@ -76,6 +76,16 @@ public class detEvento #endregion + #region Cancelamento Evento (e110001) + + /// + /// P22 - Informar o número do Protocolo de Autorização do + /// Evento da NF-e a que se refere este cancelamento. + /// + public string nProtEvento { get; set; } + + #endregion + #region Carta de Correção /// diff --git a/NFe.Servicos/ServicosNFe.cs b/NFe.Servicos/ServicosNFe.cs index babe0981e..ae43d7dba 100644 --- a/NFe.Servicos/ServicosNFe.cs +++ b/NFe.Servicos/ServicosNFe.cs @@ -1965,9 +1965,18 @@ public async Task RecepcaoEventoCancelamentoDeEvento(int var versaoServicoRecepcao = _cFgServico.VersaoRecepcaoEventosDeApuracaoDoIbsECbs; var versaoServicoRecepcaoString = servicoNfe.VersaoServicoParaString(versaoServicoRecepcao); - var detalheEvento = ObterDetalhesEvento(versaoServicoRecepcaoString, versaoAplicativo, nfeTipoEvento, ufAutor, tipoAutor); - detalheEvento.tpEventoAut = tpEventoAut; - detalheEvento.nProt = nProtEvento; + // XSD e110001_v1.00 declara apenas: descEvento, cOrgaoAutor, verAplic, tpEventoAut, nProtEvento. + // ObterDetalhesEvento injeta tpAutor (nao declarado neste XSD) e quebra schema. + // Alinhado com upstream ZeusAutomacao/DFe.NET master. + var detalheEvento = new detEvento + { + versao = versaoServicoRecepcaoString, + descEvento = nfeTipoEvento.Descricao(), + cOrgaoAutor = ufAutor ?? _cFgServico.cUF, + verAplic = versaoAplicativo ?? "1.0", + tpEventoAut = tpEventoAut, + nProtEvento = nProtEvento + }; var informacoesEventoEnv = ObterInformacoesEventoEnv(sequenciaEvento, chaveNFe, cpfCnpj, versaoServicoRecepcaoString, cOrgao: Estado.SVRS, dataHoraEvento, nfeTipoEvento, detalheEvento); var evento = ObterEvento(versaoServicoRecepcaoString, informacoesEventoEnv); From 0bcce00ffd238491e5e0c3ed4be80b439ef8c034 Mon Sep 17 00:00:00 2001 From: JohnVanderson Date: Fri, 1 May 2026 11:52:15 -0300 Subject: [PATCH 6/7] fix(rtc): mover nProtEvento para apos tpEventoAut em detEvento XmlSerializer respeita ordem de declaracao das properties. Quando nProtEvento foi adicionado logo apos nProt/xJust (inicio da classe), o XML gerava: descEvento -> nProtEvento -> cOrgaoAutor -> verAplic -> tpEventoAut SVRS rejeitava com cStat=493 (Elemento detEvento/nProtEvento fora de ordem segundo XSD e110001_v1.00). XSD exige: descEvento -> cOrgaoAutor -> verAplic -> tpEventoAut -> nProtEvento Alinhado com upstream ZeusAutomacao/DFe.NET master, que declara nProtEvento logo apos tpEventoAut na #region Cancelamento Evento. --- NFe.Classes/Servicos/Evento/detEvento.cs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/NFe.Classes/Servicos/Evento/detEvento.cs b/NFe.Classes/Servicos/Evento/detEvento.cs index 289177907..4b6b4aade 100644 --- a/NFe.Classes/Servicos/Evento/detEvento.cs +++ b/NFe.Classes/Servicos/Evento/detEvento.cs @@ -76,16 +76,6 @@ public class detEvento #endregion - #region Cancelamento Evento (e110001) - - /// - /// P22 - Informar o número do Protocolo de Autorização do - /// Evento da NF-e a que se refere este cancelamento. - /// - public string nProtEvento { get; set; } - - #endregion - #region Carta de Correção /// @@ -320,7 +310,15 @@ public bool ShouldSerializecMotivo() /// P23 - Código do evento autorizado a ser cancelado /// public string tpEventoAut {get; set;} - + + /// + /// P22 - Informar o número do Protocolo de Autorização do + /// Evento da NF-e a que se refere este cancelamento. + /// Ordem: deve aparecer DEPOIS de tpEventoAut conforme XSD e110001_v1.00. + /// XmlSerializer respeita ordem de declaracao das properties. + /// + public string nProtEvento { get; set; } + #endregion #region Perecimento, perda, roubo ou furto durante o transporte contratado pelo adquirente From 1d3be5ab5158f8fcb75bf9a32543f3d2f5df68e8 Mon Sep 17 00:00:00 2001 From: JohnVanderson Date: Fri, 1 May 2026 12:07:08 -0300 Subject: [PATCH 7/7] refactor(detEvento): alinhar 95% com upstream/master para facilitar merges futuros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reescreve detEvento.cs usando upstream ZeusAutomacao/DFe.NET master como base. Mantem mesmas #regions, mesma ordem de declaracao das properties, mesmos atributos (incluindo [XmlRoot]/[XmlType] no namespace nfe). Alinhar agora reduz drasticamente conflitos quando o fork puxar futuras mudancas do upstream (ex: novos eventos pos-NT 2025.002-RTC). Divergencias intencionais documentadas no header do arquivo: 1. `dest` property continua tipada como detEventoDest (upstream usa classe `dest`). ServicosNFe.cs handlers EPEC instanciam detEventoDest diretamente — trocar quebraria build sem refactor coordenado. 2. Region "Averbacao para Exportacao" omitida — classe itensAverbados nao existe neste fork. 3. Region "Conciliacao Financeira" omitida — classe detPagEvento nao existe neste fork. Properties novas trazidas do upstream sao auto-properties dormentes (nao serializam quando null/default), garantindo que nenhum fluxo existente muda comportamento. Validado via: - dotnet build NFe.Servicos -> 0 erros - dotnet build DFeTech.ProductInvoice.sln -> 0 erros XML serializado para os eventos ja validados (CC-e, EPEC, RTC 112110-150, PersonalUseAllocation, AlcZfmImport) continua identico — ordem das properties EPEC/Cancelamento/RTC nao mudou. --- NFe.Classes/Servicos/Evento/detEvento.cs | 321 ++++++++++++++++++----- 1 file changed, 254 insertions(+), 67 deletions(-) diff --git a/NFe.Classes/Servicos/Evento/detEvento.cs b/NFe.Classes/Servicos/Evento/detEvento.cs index 4b6b4aade..4747bcce3 100644 --- a/NFe.Classes/Servicos/Evento/detEvento.cs +++ b/NFe.Classes/Servicos/Evento/detEvento.cs @@ -1,4 +1,4 @@ -/********************************************************************************/ +/********************************************************************************/ /* Projeto: Biblioteca ZeusNFe */ /* Biblioteca C# para emissão de Nota Fiscal Eletrônica - NFe e Nota Fiscal de */ /* Consumidor Eletrônica - NFC-e (http://www.nfe.fazenda.gov.br) */ @@ -45,9 +45,24 @@ using NFe.Classes.Servicos.Evento.Informacoes.ItemNaoFornecido; using NFe.Classes.Servicos.Evento.Informacoes.Perecimento; +// ===================================================================================== +// Alinhado com upstream ZeusAutomacao/DFe.NET master. +// Divergencias intencionais do fork: +// 1. dest property usa tipo `detEventoDest` (upstream usa `dest`). +// Motivo: ServicosNFe.cs:1122 (handlers EPEC) instancia `new detEventoDest`. +// Trocar para `dest` quebraria o build sem refactor coordenado. +// 2. Region "Averbação para Exportação" (itensAverbados) ausente. +// Motivo: classe `itensAverbados` nao existe neste fork. +// 3. Region "Conciliação Financeira" (detPagEvento) ausente. +// Motivo: classe `detPagEvento` nao existe neste fork. +// Demais regions/properties espelham upstream em ordem e shape, garantindo merges +// futuros mais limpos. +// ===================================================================================== namespace NFe.Classes.Servicos.Evento { + [XmlRoot(Namespace = "http://www.portalfiscal.inf.br/nfe")] + [XmlType(Namespace = "http://www.portalfiscal.inf.br/nfe")] public class detEvento { /// @@ -62,46 +77,12 @@ public class detEvento /// public string descEvento { get; set; } - #region Cancelamento - - /// - /// HP20 - Informar o número do Protocolo de Autorização da NF-e a ser Cancelada. - /// - public string nProt { get; set; } - - /// - /// HP21 - Informar a justificativa do cancelamento - /// - public string xJust { get; set; } - - #endregion - - #region Carta de Correção - - /// - /// HP20 - Correção a ser considerada, texto livre. A correção mais recente substitui as anteriores. - /// - public string xCorrecao { get; set; } - - /// - /// HP20a - Condições de uso da Carta de Correção - /// - public string xCondUso { get; set; } - - #endregion - #region EPEC /// /// P20 - Código do Órgão do Autor do Evento. /// Nota: Informar o código da UF do Emitente para este evento. /// - // Alinhado com upstream ZeusAutomacao/DFe.NET master: auto-property simples. - // Setters customizados com side-effects (descEvento auto, LimpaDados...) foram - // removidos porque sobrescreviam descEvento dos eventos NT 2025.002-RTC e nao - // adicionavam protecao real — detEvento sempre e criado fresh via - // `new detEvento { ... }` em cada flow, nao reusado. Cada caller agora seta - // descEvento explicitamente (EPEC, CC-e, Cancel, RTC). public Estado? cOrgaoAutor { get; set; } /// @@ -145,6 +126,8 @@ public string ProxyDhEmi /// /// P26 /// + // Divergencia intencional vs upstream: tipo `detEventoDest` em vez de `dest`. + // Ver cabecalho do arquivo. public detEventoDest dest { get; set; } public bool ShouldSerializecOrgaoAutor() @@ -163,16 +146,237 @@ public bool ShouldSerializetpNF() } #endregion - - #region Eventos para a apuração do IBS e da CBS - #region Informação de efetivo pagamento integral para liberar crédito presumido do adquirente + #region Cancelamento + + /// + /// HP20 - Informar o número do Protocolo de Autorização da NF-e a ser Cancelada. + /// + public string nProt { get; set; } + + /// + /// HP21 - Informar a justificativa do cancelamento + /// + public string xJust { get; set; } + + #endregion + + #region Cancelamento por substituição + + /// + /// P31 - Chave de acesso da NF-e substituta da NF-e a ser cancelada + /// + public string chNFeRef { get; set; } + + #endregion + + // [DIVERGENCIA] Region "Averbação para Exportação" (itensAverbados) omitida + // — classe itensAverbados ausente neste fork. + + #region RFC - Cancelamento Evento + + /// + /// P23 - Código do evento autorizado a ser cancelado + /// + public string tpEventoAut {get; set;} + + #endregion + + #region Cancelamento Insucesso/Comprovante de Entrega NFe/ Cancelamento Evento + + /// + /// P22 - Informar o número do Protocolo de Autorização do + /// Evento da NF-e a que se refere este cancelamento. + /// + public string nProtEvento { get; set; } + + #endregion + + #region Insucesso NFe + [XmlIgnore] + public DateTimeOffset? dhTentativaEntrega { get; set; } + + /// + /// Proxy para dhTentativaEntrega no formato AAAA-MM-DDThh:mm:ssTZD (UTC - Universal Coordinated Time) + /// + [XmlElement(ElementName = "dhTentativaEntrega")] + public string ProxyDhTentativaEntrega + { + get { return dhTentativaEntrega.ParaDataHoraStringUtc(); } + set { dhTentativaEntrega = DateTimeOffset.Parse(value); } + } + + /// + /// P31 - Número da tentativa de entrega que não teve sucesso + /// + public int? nTentativa { get; set; } + + /// + /// P32 - Motivo do insucesso + /// + public MotivoInsucesso? tpMotivo { get; set; } + + /// + /// P33 - Justificativa do motivo do insucesso. Informar apenas para tpMotivo = + /// + public string xJustMotivo { get; set; } + + /// + /// P33 - Latitude do ponto de entrega + /// + public decimal? latGPS { get; set; } + + /// + /// P34 - Longitude do ponto de entrega + /// + public decimal? longGPS { get; set; } + + /// + /// P35 - Hash SHA-1, no formato Base64, resultante da concatenação de: Chave de Acesso da NF-e + Base64 + /// da imagem capturada na tentativa da entrega(ex: imagem capturada da assinatura eletrônica, digital do recebedor, foto, etc). + /// + public string hashTentativaEntrega { get; set; } + + /// + /// Data e hora da geração do hash da tentativa de entrega. Formato AAAA-MMDDThh:mm:ssTZD. + /// + [XmlIgnore] + public DateTimeOffset? dhHashTentativaEntrega { get; set; } + + /// + /// Proxy para dhHashTentativaEntrega no formato AAAA-MM-DDThh:mm:ssTZD (UTC - Universal Coordinated Time) + /// + [XmlElement(ElementName = "dhHashTentativaEntrega")] + public string ProxyDhHashTentativaEntrega + { + get { return dhHashTentativaEntrega.ParaDataHoraStringUtc(); } + set { dhHashTentativaEntrega = DateTimeOffset.Parse(value); } + } + + public bool ShouldSerializenTentativa() + { + return nTentativa.HasValue; + } + + public bool ShouldSerializetpMotivo() + { + return tpMotivo.HasValue; + } + + public bool ShouldSerializelatGPS() + { + return latGPS.HasValue; + } + + public bool ShouldSerializelongGPS() + { + return longGPS.HasValue; + } + + #endregion + + #region Comprovante Entrega NFe + + /// + /// P30 - Data e hora do final da entrega + /// + [XmlIgnore] + public DateTimeOffset? dhEntrega { get; set; } + + /// + /// Proxy para dhEntrega no formato AAAA-MM-DDThh:mm:ssTZD (UTC - Universal Coordinated Time) + /// + [XmlElement(ElementName = "dhEntrega")] + public string ProxyDhEntrega + { + get { return dhEntrega.ParaDataHoraStringUtc(); } + set { dhEntrega = DateTimeOffset.Parse(value); } + } + + /// + /// P31 - Número do documento de identificação da pessoa que assinou o Comprovante de Entrega da NF-e/> + /// + public string nDoc { get; set; } + + /// + /// P32 - Nome da pessoa que assinou o Comprovante de Entrega da NF-e/> + /// + public string xNome { get; set; } + + /// + /// P35 - Hash SHA-1, no formato Base64, resultante da concatenação de: Chave de Acesso da NF-e + Base64 + /// da imagem capturada do Comprovante de Entrega da NFe (ex: imagem capturada da assinatura eletrônica, digital do recebedor, foto, etc). + /// + public string hashComprovante { get; set; } + + /// + /// P36 - Data e hora da geração do hash da tentativa de entrega. Formato AAAA-MMDDThh:mm:ssTZD. + /// + [XmlIgnore] + public DateTimeOffset? dhHashComprovante { get; set; } + + /// + /// Proxy para dhHashComprovante no formato AAAA-MM-DDThh:mm:ssTZD (UTC - Universal Coordinated Time) + /// + [XmlElement(ElementName = "dhHashComprovante")] + public string ProxyDhHashComprovante + { + get { return dhHashComprovante.ParaDataHoraStringUtc(); } + set { dhHashComprovante = DateTimeOffset.Parse(value); } + } + + #endregion + + // [DIVERGENCIA] Region "Conciliação Financeira" (detPag/detPagEvento) omitida + // — classe detPagEvento ausente neste fork. + + #region Ator Interessado NFe + /// + /// P23 - Pessoas autorizadas a acessar o XML da NF-e + /// + [XmlElement("autXML")] + public List autXML { get; set; } + + /// + /// P26 - 0 = Não permite; + /// 1 = Permite o transportador autorizado pelo + /// emitente ou destinatário autorizar outros + /// transportadores para ter acesso ao download da + /// NF-e + /// + public TipoAutorizacao? tpAutorizacao { get; set; } + + public bool ShouldSerializetpAutorizacao() + { + return tpAutorizacao != null; + } + + #endregion + + #region Carta de Correção + + /// + /// HP20 - Correção a ser considerada, texto livre. A correção mais recente substitui as anteriores. + /// + public string xCorrecao { get; set; } + + /// + /// HP20a - Condições de uso da Carta de Correção. + /// P27 - Condição de uso do tipo de autorização para o transportador. + /// + public string xCondUso { get; set; } + + #endregion + + #region Eventos para a apuração do IBS e da CBS + + #region Informação de efetivo pagamento integral para liberar crédito presumido do adquirente /// /// P23 - Indicador de efetiva quitação do pagamento integral da operação referente a NFe referenciada /// public IndicadorDeQuitacaoDoPagamento? indQuitacao { get; set; } - + public bool ShouldSerializeindQuitacao() { return indQuitacao.HasValue; @@ -187,7 +391,7 @@ public bool ShouldSerializeindQuitacao() /// [XmlElement("gCredPres")] public List gCredPres { get; set; } - + public bool ShouldSerializegCredPres() { return gCredPres != null; @@ -206,7 +410,7 @@ public bool ShouldSerializegCredPres() /// [XmlElement("gConsumo")] public List gConsumo { get; set; } - + public bool ShouldSerializegConsumo() => gConsumo != null; #endregion @@ -240,7 +444,7 @@ public bool ShouldSerializegImobilizacao() { return gImobilizacao != null; } - + #endregion #region Solicitação de Apropriação de Crédito de Combustível @@ -250,7 +454,7 @@ public bool ShouldSerializegImobilizacao() /// [XmlElement("gConsumoComb")] public List gConsumoComb { get; set; } - + public bool ShouldSerializegConsumoComb() { return gConsumoComb != null; @@ -270,7 +474,7 @@ public bool ShouldSerializegCredito() { return gCredito != null; } - + #endregion #region Manifestação do Fisco sobre Pedido de Transferência de Crédito de IBS em Operações de Sucessão | Manifestação do Fisco sobre Pedido de Transferência de Crédito de CBS em Operações de Sucessão @@ -286,47 +490,30 @@ public bool ShouldSerializeindDeferimento() { return indDeferimento != null; } - + /// /// P24 - Motivo deferimento /// public MotivoDeferimento? cMotivo { get; set; } - + public bool ShouldSerializecMotivo() { return cMotivo != null; } - + /// /// P24 - Descrição deferimento /// public string xMotivo { get; set; } - - #endregion - - #region Cancelamento Evento - - /// - /// P23 - Código do evento autorizado a ser cancelado - /// - public string tpEventoAut {get; set;} - - /// - /// P22 - Informar o número do Protocolo de Autorização do - /// Evento da NF-e a que se refere este cancelamento. - /// Ordem: deve aparecer DEPOIS de tpEventoAut conforme XSD e110001_v1.00. - /// XmlSerializer respeita ordem de declaracao das properties. - /// - public string nProtEvento { get; set; } #endregion #region Perecimento, perda, roubo ou furto durante o transporte contratado pelo adquirente /// - /// P23 - Informações por item da Nota de Aquisição + /// P23 - Informações por item da Nota de Aquisição /// (Evento: perecimento, perda, roubo ou furto durante o transporte contratado pelo adquirente). - /// P23 - Informações por item da Nota de Fornecimento + /// P23 - Informações por item da Nota de Fornecimento /// (Evento: perecimento, perda, roubo ou furto durante o transporte contratado pelo fornecedor). /// [XmlElement("gPerecimento")] @@ -370,4 +557,4 @@ public string ProxydPrevEntrega #endregion } -} \ No newline at end of file +}