diff --git a/src/OpenAC.Net.NFSe.Nacional/Common/Model/DFe.cs b/src/OpenAC.Net.NFSe.Nacional/Common/Model/DFe.cs index dc1103e..7dc171f 100644 --- a/src/OpenAC.Net.NFSe.Nacional/Common/Model/DFe.cs +++ b/src/OpenAC.Net.NFSe.Nacional/Common/Model/DFe.cs @@ -34,7 +34,7 @@ public class DFe /// [JsonPropertyName("TipoEvento")] [JsonConverter(typeof(JsonStringEnumConverter))] - public TipoEvento TipoEvento { get; set; } + public TipoEvento? TipoEvento { get; set; } /// /// Conteúdo do arquivo XML, possivelmente compactado. diff --git a/src/OpenAC.Net.NFSe.Nacional/Webservice/NFSeWebserviceBase.cs b/src/OpenAC.Net.NFSe.Nacional/Webservice/NFSeWebserviceBase.cs index 3f919d8..210d001 100644 --- a/src/OpenAC.Net.NFSe.Nacional/Webservice/NFSeWebserviceBase.cs +++ b/src/OpenAC.Net.NFSe.Nacional/Webservice/NFSeWebserviceBase.cs @@ -184,11 +184,11 @@ protected virtual void ValidarSchema(SchemaNFSe schema, string xml, VersaoNFSe v /// Nome do arquivo. /// Documento do prestador. /// Data de emissão. - protected virtual void GravarDpsEmDisco(string conteudoArquivo, string nomeArquivo, string? documento, DateTime data) + protected virtual void GravarDpsEmDisco(string conteudoArquivo, string nomeArquivo, string? documento, DateTime data, bool incrementarNome = false) { if (Configuracao.Arquivos.Salvar == false) return; - GravarArquivoEmDisco(TipoArquivo.Rps, conteudoArquivo, nomeArquivo, documento, data); + GravarArquivoEmDisco(TipoArquivo.Rps, conteudoArquivo, nomeArquivo, documento, data, incrementarNome); } /// @@ -198,11 +198,11 @@ protected virtual void GravarDpsEmDisco(string conteudoArquivo, string nomeArqui /// Nome do arquivo. /// Documento do prestador. /// Data de emissão. - protected virtual void GravarNFSeEmDisco(string conteudoArquivo, string nomeArquivo, string? documento, DateTime data) + protected virtual void GravarNFSeEmDisco(string conteudoArquivo, string nomeArquivo, string? documento, DateTime data, bool incrementarNome = false) { if (Configuracao.Arquivos.Salvar == false) return; - GravarArquivoEmDisco(TipoArquivo.NFSe, conteudoArquivo, nomeArquivo, documento, data); + GravarArquivoEmDisco(TipoArquivo.NFSe, conteudoArquivo, nomeArquivo, documento, data, incrementarNome); } /// @@ -226,17 +226,49 @@ protected virtual void GravarArquivoEmDisco(string conteudoArquivo, string nomeA /// Nome do arquivo. /// Documento do prestador. /// Data de emissão (opcional). - protected virtual void GravarArquivoEmDisco(TipoArquivo tipo, string conteudoArquivo, string nomeArquivo, string? documento, DateTime? data = null) + /// + /// Indica se o nome do arquivo deve ser incrementado caso já exista, + /// adicionando um sufixo numérico (_1, _2, etc.) para evitar sobrescrita. + /// + protected virtual void GravarArquivoEmDisco(TipoArquivo tipo, string conteudoArquivo, string nomeArquivo, string? documento, DateTime? data = null, bool incrementarNome = false) { - nomeArquivo = tipo switch + var diretorio = tipo switch { - TipoArquivo.Webservice => Path.Combine(Configuracao.Arquivos.GetPathEnvio(data ?? DateTime.Today, documento ?? string.Empty), nomeArquivo), - TipoArquivo.Rps => Path.Combine(Configuracao.Arquivos.GetPathDps(data ?? DateTime.Today, documento ?? string.Empty), nomeArquivo), - TipoArquivo.NFSe => Path.Combine(Configuracao.Arquivos.GetPathNFSe(data ?? DateTime.Today, documento ?? string.Empty), nomeArquivo), + TipoArquivo.Webservice => Path.Combine(Configuracao.Arquivos.GetPathEnvio(data ?? DateTime.Today, documento ?? string.Empty)), + TipoArquivo.Rps => Path.Combine(Configuracao.Arquivos.GetPathDps(data ?? DateTime.Today, documento ?? string.Empty)), + TipoArquivo.NFSe => Path.Combine(Configuracao.Arquivos.GetPathNFSe(data ?? DateTime.Today, documento ?? string.Empty)), _ => throw new ArgumentOutOfRangeException(nameof(tipo), tipo, null) }; - File.WriteAllText(nomeArquivo, conteudoArquivo, Encoding.UTF8); + var caminhoFinal = !incrementarNome ? GerarPathUnico(diretorio, nomeArquivo) : Path.Combine(diretorio, nomeArquivo); + + File.WriteAllText(caminhoFinal, conteudoArquivo, Encoding.UTF8); + } + + /// + /// Verifica se o arquivo já existe antes de escrever, e incrementa um sufixo numérico caso exista. + /// + /// Diretório onde o arquivo será salvo. + /// Nome do arquivo. + private static string GerarPathUnico(string diretorio, string nomeArquivo) + { + var caminho = Path.Combine(diretorio, nomeArquivo); + + if (!File.Exists(caminho)) + return caminho; + + var semExtensao = Path.GetFileNameWithoutExtension(nomeArquivo); + var extensao = Path.GetExtension(nomeArquivo); + var contador = 1; + + do + { + var novoNome = $"{semExtensao}_{contador++}{extensao}"; + caminho = Path.Combine(diretorio, novoNome); + } + while (File.Exists(caminho)); + + return caminho; } #endregion Methods diff --git a/src/OpenAC.Net.NFSe.Nacional/Webservice/Nacional/NacionalWebservice.cs b/src/OpenAC.Net.NFSe.Nacional/Webservice/Nacional/NacionalWebservice.cs index 740871a..d6c596e 100644 --- a/src/OpenAC.Net.NFSe.Nacional/Webservice/Nacional/NacionalWebservice.cs +++ b/src/OpenAC.Net.NFSe.Nacional/Webservice/Nacional/NacionalWebservice.cs @@ -29,17 +29,18 @@ // // *********************************************************************** +using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Json; using System.Text.Json; using System.Threading.Tasks; +using System.Xml.Linq; using OpenAC.Net.Core.Logging; -using OpenAC.Net.DFe.Core.Common; +using OpenAC.Net.DFe.Core.Extensions; using OpenAC.Net.NFSe.Nacional.Common; using OpenAC.Net.NFSe.Nacional.Common.Model; using OpenAC.Net.NFSe.Nacional.Common.Types; - namespace OpenAC.Net.NFSe.Nacional.Webservice.Nacional; /// @@ -54,7 +55,7 @@ public class NacionalWebservice : NFSeWebserviceBase /// /// Configuração da NFSe. /// Informações do serviço - public NacionalWebservice(ConfiguracaoNFSe configuracaoNFSe, NFSeServiceInfo serviceInfo) : + public NacionalWebservice(ConfiguracaoNFSe configuracaoNFSe, NFSeServiceInfo serviceInfo) : base(configuracaoNFSe, serviceInfo) { } @@ -192,8 +193,37 @@ public override async Task> EnviarEventoAsync( var documento = evento.Informacoes.CPFAutor ?? evento.Informacoes.CNPJAutor; - GravarDpsEmDisco(evento.Xml, $"{evento.Informacoes.ChNFSe}{evento.Informacoes.Evento}_evento.xml", - documento, evento.Informacoes.DhEvento.DateTime); + //var prefixoNomeArquivo = evento.Informacoes.ChNFSe; + + //if (!Configuracao.Arquivos.PadronizarNomes) + //{ + // try + // { + // var consulta = await ConsultaChaveAsync(evento.Informacoes.ChNFSe); + // var nfse = consulta.Resultado.Lote.FirstOrDefault(x => x.TipoDocumento == TipoDocumento.NFSE); + + // if (!string.IsNullOrWhiteSpace(nfse?.ArquivoXml)) + // { + // var numeroDoc = XDocument.Parse(nfse?.ArquivoXml) + // .Descendants() + // .FirstOrDefault(x => x.Name.LocalName == "nDPS") + // ?.Value.FillZeros(); + + // prefixoNomeArquivo = $"{numeroDoc}{evento.Informacoes.Evento}"; + // } + // } + // catch (System.Exception) + // { + + // } + //} + + var prefixoNomeArquivoDps = Configuracao.Arquivos.PadronizarNomes + ? evento.Informacoes.Id + : $"{evento.Informacoes.ChNFSe}{evento.Informacoes.Evento}"; + + GravarDpsEmDisco(evento.Xml, $"{prefixoNomeArquivoDps}_evento.xml", + documento, evento.Informacoes.DhEvento.DateTime, true); var envio = new EventoEnvio { @@ -205,7 +235,7 @@ public override async Task> EnviarEventoAsync( this.Log().Debug($"Webservice: [Evento][Envio] - {strEnvio}"); - GravarArquivoEmDisco(strEnvio, $"Evento-{evento.Informacoes.ChNFSe}{evento.Informacoes.Evento}-env.json", + GravarArquivoEmDisco(strEnvio, $"Evento-{prefixoNomeArquivoDps}-env.json", documento); var url = ServiceInfo[Configuracao.WebServices.Ambiente][TipoUrl.EnviarEvento]; @@ -215,7 +245,7 @@ public override async Task> EnviarEventoAsync( this.Log().Debug($"Webservice: [Evento][Resposta] - {strResponse}"); - GravarArquivoEmDisco(strResponse, $"Evento-{evento.Informacoes.ChNFSe}{evento.Informacoes.Evento}-resp.json", + GravarArquivoEmDisco(strResponse, $"Evento-{prefixoNomeArquivoDps}-resp.json", documento); var jsonOptions = new JsonSerializerOptions @@ -227,7 +257,17 @@ public override async Task> EnviarEventoAsync( httpResponse.IsSuccessStatusCode, jsonOptions); if (retorno.Sucesso) - GravarNFSeEmDisco(retorno.Resultado.XmlEvento, $"{evento.Informacoes.ChNFSe}_evento.xml", documento, evento.Informacoes.DhEvento.DateTime); + { + var prefixoNomeArquivoEventoNfse = Configuracao.Arquivos.PadronizarNomes + ? evento.Informacoes.ChNFSe + : $"{evento.Informacoes.ChNFSe}{evento.Informacoes.Evento}"; + + var nSeqEvento = XDocument.Parse(retorno.Resultado.XmlEvento) + .Descendants() + .FirstOrDefault(x => x.Name.LocalName == "nSeqEvento")?.Value ?? "00"; + + GravarNFSeEmDisco(retorno.Resultado.XmlEvento, $"{prefixoNomeArquivoEventoNfse}_evento_{nSeqEvento}.xml", documento, evento.Informacoes.DhEvento.DateTime, true); + } return retorno; } @@ -249,7 +289,11 @@ public override async Task> EnviarAsync(Dps dps) var documento = dps.Informacoes.Prestador.CPF ?? dps.Informacoes.Prestador.CNPJ; - GravarDpsEmDisco(dps.Xml, $"{dps.Informacoes.NumeroDps:000000}_dps.xml", + var prefixoNomeArquivoDps = Configuracao.Arquivos.PadronizarNomes + ? dps.Informacoes.Id + : dps.Informacoes.NumeroDps.FillZeros(); + + GravarDpsEmDisco(dps.Xml, $"{prefixoNomeArquivoDps}_dps.xml", documento, dps.Informacoes.DhEmissao.DateTime); var envio = new DpsEnvio @@ -262,7 +306,7 @@ public override async Task> EnviarAsync(Dps dps) this.Log().Debug($"Webservice: [Enviar][Envio] - {strEnvio}"); - GravarArquivoEmDisco(strEnvio, $"Enviar-{dps.Informacoes.NumeroDps:000000}-env.json", documento); + GravarArquivoEmDisco(strEnvio, $"Enviar-{prefixoNomeArquivoDps}-env.json", documento); var url = ServiceInfo[Configuracao.WebServices.Ambiente][TipoUrl.Enviar]; var httpResponse = await SendAsync(content, HttpMethod.Post, $"{url}/nfse"); @@ -271,12 +315,18 @@ public override async Task> EnviarAsync(Dps dps) this.Log().Debug($"Webservice: [Enviar][Resposta] - {strResponse}"); - GravarArquivoEmDisco(strResponse, $"Enviar-{dps.Informacoes.NumeroDps:000000}-resp.json", documento); + GravarArquivoEmDisco(strResponse, $"Enviar-{prefixoNomeArquivoDps}-resp.json", documento); var retorno = NFSeResponse.Create(dps.Xml, strEnvio, strResponse, httpResponse.IsSuccessStatusCode); if (retorno.Sucesso) - GravarNFSeEmDisco(retorno.Resultado.XmlNFSe, $"{dps.Informacoes.NumeroDps:000000}_nfse.xml", documento, dps.Informacoes.DhEmissao.DateTime); + { + var prefixoNomeArquivoNfse = Configuracao.Arquivos.PadronizarNomes + ? retorno?.Resultado?.ChaveAcesso + : dps.Informacoes.NumeroDps.FillZeros(); + + GravarNFSeEmDisco(retorno.Resultado.XmlNFSe, $"{prefixoNomeArquivoNfse}_nfse.xml", documento, dps.Informacoes.DhEmissao.DateTime); + } return retorno; }