diff --git a/CTe.AppTeste.NetCore/Program.cs b/CTe.AppTeste.NetCore/Program.cs
index 6ed940b80..e348f7241 100644
--- a/CTe.AppTeste.NetCore/Program.cs
+++ b/CTe.AppTeste.NetCore/Program.cs
@@ -111,6 +111,9 @@ private static async void Menu()
case 10:
await EventoDesacordoCTe();
break;
+ case 11:
+ await EventoCancelaDesacordoCTe();
+ break;
}
if (Convert.ToInt32(option) > 0)
@@ -370,6 +373,23 @@ private static async Task EventoDesacordoCTe()
OnSucessoSync(new RetornoEEnvio(retorno));
}
+ private static async Task EventoCancelaDesacordoCTe()
+ {
+ var config = new ConfiguracaoDao().BuscarConfiguracao();
+ //CarregarConfiguracoes(config);
+ var configuracaoServico = MontarConfiguracoes(config);
+
+ var cnpj = RequisitarInput("CNPJ Tomador");
+ var chave = RequisitarInput("Chave CTe");
+ var sequenciaEvento = int.Parse(RequisitarInput("Sequencia Evento"));
+ var nProtEventoDesacordo = RequisitarInput("Número do Protocolo do Evento de Desacordo");
+
+ var servico = new EventoCancelamentoDesacordo(sequenciaEvento, chave, cnpj, nProtEventoDesacordo);
+ var retorno = await servico.CancelarDesacordoAsync(configuracaoServico);
+
+ OnSucessoSync(new RetornoEEnvio(retorno));
+ }
+
private static async Task CartaCorrecao()
{
var config = new ConfiguracaoDao().BuscarConfiguracao();
diff --git a/CTe.AppTeste/CTeTesteModel.cs b/CTe.AppTeste/CTeTesteModel.cs
index 3add5291d..d5772b197 100644
--- a/CTe.AppTeste/CTeTesteModel.cs
+++ b/CTe.AppTeste/CTeTesteModel.cs
@@ -826,6 +826,22 @@ public void EventoDesacordoCTe()
OnSucessoSync(new RetornoEEnvio(retorno));
}
+ public void EventoCancelaDesacordoCTe()
+ {
+ var config = new ConfiguracaoDao().BuscarConfiguracao();
+ CarregarConfiguracoes(config);
+
+ var cnpj = (InputBoxTuche("CNPJ Tomador"));
+ var chave = (InputBoxTuche("Chave CTe"));
+ var sequenciaEvento = int.Parse(InputBoxTuche("Sequencia Evento"));
+ var nProtEventoDesacordo = InputBoxTuche("Número do Protocolo do Evento de Desacordo");
+
+ var servico = new EventoCancelamentoDesacordo(sequenciaEvento, chave, cnpj, nProtEventoDesacordo);
+ var retorno = servico.CancelarDesacordo();
+
+ OnSucessoSync(new RetornoEEnvio(retorno));
+ }
+
public void CartaCorrecao()
{
var config = new ConfiguracaoDao().BuscarConfiguracao();
diff --git a/CTe.AppTeste/MainWindow.xaml b/CTe.AppTeste/MainWindow.xaml
index f928d0d3c..d576a74b3 100644
--- a/CTe.AppTeste/MainWindow.xaml
+++ b/CTe.AppTeste/MainWindow.xaml
@@ -228,6 +228,7 @@
+
@@ -243,8 +244,9 @@
+
-
+
diff --git a/CTe.AppTeste/MainWindow.xaml.cs b/CTe.AppTeste/MainWindow.xaml.cs
index 6f1511e49..0f847b006 100644
--- a/CTe.AppTeste/MainWindow.xaml.cs
+++ b/CTe.AppTeste/MainWindow.xaml.cs
@@ -120,6 +120,11 @@ private void EventoDesacordoCTe_Click(object sender, RoutedEventArgs e)
_model.EventoDesacordoCTe();
}
+ private void EventoCancelaDesacordoCTe_Click(object sender, RoutedEventArgs e)
+ {
+ _model.EventoCancelaDesacordoCTe();
+ }
+
private void CartaCorrecao_Click(object sender, RoutedEventArgs e)
{
_model.CartaCorrecao();
diff --git a/CTe.Classes/CTeOutrosServicos/Informacoes/Impostos/impOs.cs b/CTe.Classes/CTeOutrosServicos/Informacoes/Impostos/impOs.cs
index 058428168..378cdb677 100644
--- a/CTe.Classes/CTeOutrosServicos/Informacoes/Impostos/impOs.cs
+++ b/CTe.Classes/CTeOutrosServicos/Informacoes/Impostos/impOs.cs
@@ -24,5 +24,21 @@ public decimal? vTotTrib
public infTribFed infTribFed { get; set; }
public IBSCBS IBSCBS { get; set; }
+
+ private decimal? _vTotDFe;
+ ///
+ /// O total geral do DFe deverá ser a soma do total da prestação + IBS + CBS
+ /// vTotDFe = vPrest / vTPrest + gIBSCBS / vIBS + gCBS / vCBS
+ ///
+ /// Exceção: Em 2026 não somar IBS e CBS
+ /// Observação: Implementação futura
+ ///
+ public decimal? vTotDFe
+ {
+ get { return _vTotDFe.Arredondar(2); }
+ set { _vTotDFe = value.Arredondar(2); }
+ }
+
+ public bool vTotDFeSpecified { get { return vTotDFe.HasValue; } }
}
}
\ No newline at end of file
diff --git a/CTe.Classes/Informacoes/Tipos/tpEmis.cs b/CTe.Classes/Informacoes/Tipos/tpEmis.cs
index 154f06900..32554c433 100644
--- a/CTe.Classes/Informacoes/Tipos/tpEmis.cs
+++ b/CTe.Classes/Informacoes/Tipos/tpEmis.cs
@@ -36,6 +36,7 @@ namespace CTe.Classes.Informacoes.Tipos
///
/// Forma de emissão da CT-e
/// 1 - Emissão normal (não em contingência)
+ /// 3 - Regime Especial NFF
/// 4 - Contingência EPEC pela SVC
/// 5 - Contingência FS-DA, com impressão do DANFE em formulário de segurança
/// 7 - Contingência SVC-RS (SEFAZ Virtual de Contingência do RS)
@@ -45,6 +46,8 @@ public enum tpEmis
{
[XmlEnum("1")]
teNormal = 1,
+ [XmlEnum("3")]
+ teNFF = 3,
[XmlEnum("4")]
teEPEC = 4,
[XmlEnum("5")]
@@ -54,4 +57,4 @@ public enum tpEmis
[XmlEnum("8")]
teSVCSP = 8
}
-}
\ No newline at end of file
+}
diff --git a/CTe.Classes/Informacoes/autXML.cs b/CTe.Classes/Informacoes/autXML.cs
index e49bd4c29..ed8e8b204 100644
--- a/CTe.Classes/Informacoes/autXML.cs
+++ b/CTe.Classes/Informacoes/autXML.cs
@@ -49,13 +49,12 @@ public string CNPJ
get { return cnpj; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(cpf))
- cnpj = value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(cpf))
throw new ArgumentException(ErroCpfCnpjPreenchidos);
- }
+
+ cnpj = value;
}
}
@@ -67,13 +66,12 @@ public string CPF
get { return cpf; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(cnpj))
- cpf = value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(cnpj))
throw new ArgumentException(ErroCpfCnpjPreenchidos);
- }
+
+ cpf = value;
}
}
}
diff --git a/CTe.Classes/Servicos/DistribuicaoDFe/Schemas/procEventoCTe.cs b/CTe.Classes/Servicos/DistribuicaoDFe/Schemas/procEventoCTe.cs
index 72e81ee2a..571ea6796 100644
--- a/CTe.Classes/Servicos/DistribuicaoDFe/Schemas/procEventoCTe.cs
+++ b/CTe.Classes/Servicos/DistribuicaoDFe/Schemas/procEventoCTe.cs
@@ -64,7 +64,5 @@ public class procEventoCTe
///
[XmlElement(Namespace = "http://www.portalfiscal.inf.br/cte")]
public retEventoCTe retEventoCTe { get; set; }
-
-
}
}
diff --git a/CTe.Classes/Servicos/DistribuicaoDFe/Schemas/resCTe.cs b/CTe.Classes/Servicos/DistribuicaoDFe/Schemas/resCTe.cs
new file mode 100644
index 000000000..638022f1a
--- /dev/null
+++ b/CTe.Classes/Servicos/DistribuicaoDFe/Schemas/resCTe.cs
@@ -0,0 +1,123 @@
+using DFe.Utils;
+using System;
+using System.ComponentModel;
+using System.Xml.Serialization;
+
+namespace CTe.Classes.Servicos.DistribuicaoDFe.Schemas
+{
+ ///
+ /// Resumo de CT-e retornado no docZip com schema resCTe_v1.03.xsd
+ /// Ref: NT 2015/002 - CTeDistribuicaoDFe
+ ///
+ [Serializable()]
+ [DesignerCategory("code")]
+ [XmlType(AnonymousType = true, Namespace = "http://www.portalfiscal.inf.br/cte")]
+ [XmlRoot(Namespace = "http://www.portalfiscal.inf.br/cte", IsNullable = false)]
+ public class resCTe
+ {
+ ///
+ /// Chave de acesso do CT-e (44 dígitos)
+ ///
+ [XmlElement("chCTe")]
+ public string chCTe { get; set; }
+
+ ///
+ /// CNPJ do emitente (14 dígitos)
+ ///
+ [XmlElement("CNPJ")]
+ public string CNPJ { get; set; }
+
+ ///
+ /// Razão social ou nome do emitente
+ ///
+ [XmlElement("xNome")]
+ public string xNome { get; set; }
+
+ ///
+ /// Inscrição Estadual do emitente
+ ///
+ [XmlElement("IE")]
+ public string IE { get; set; }
+
+ ///
+ /// Modal do CT-e
+ ///
+ /// - 01=Rodoviário
+ /// - 02=Aéreo
+ /// - 03=Aquaviário
+ /// - 04=Ferroviário
+ /// - 05=Dutoviário
+ /// - 06=Multimodal
+ ///
+ ///
+ [XmlElement("modal")]
+ public string modal { get; set; }
+
+ ///
+ /// Data e hora de emissão do CT-e
+ ///
+ [XmlIgnore]
+ public DateTimeOffset dhEmi { get; set; }
+
+ [XmlElement(ElementName = "dhEmi")]
+ public string ProxydhEmi
+ {
+ get { return dhEmi.ParaDataHoraStringUtc(); }
+ set { dhEmi = DateTimeOffset.Parse(value); }
+ }
+
+ ///
+ /// Tipo do CT-e
+ ///
+ /// - 0=CT-e Normal
+ /// - 1=CT-e de Complemento de Valores
+ /// - 2=CT-e de Anulação
+ /// - 3=CT-e de Substituição
+ ///
+ ///
+ [XmlElement("tpCTe")]
+ public string tpCTe { get; set; }
+
+ ///
+ /// Digest value da assinatura do CT-e
+ ///
+ [XmlElement("digVal")]
+ public string digVal { get; set; }
+
+ ///
+ /// Data e hora do recebimento pelo Ambiente Nacional
+ ///
+ [XmlIgnore]
+ public DateTimeOffset dhRecbto { get; set; }
+
+ [XmlElement(ElementName = "dhRecbto")]
+ public string ProxydhRecbto
+ {
+ get { return dhRecbto.ParaDataHoraStringUtc(); }
+ set { dhRecbto = DateTimeOffset.Parse(value); }
+ }
+
+ ///
+ /// Número do protocolo de autorização
+ ///
+ [XmlElement("nProt")]
+ public string nProt { get; set; }
+
+ ///
+ /// Valor a receber pelo transportador
+ ///
+ [XmlElement("vRec")]
+ public string vRec { get; set; }
+
+ ///
+ /// Situação do CT-e
+ ///
+ /// - 100=Autorizado o uso do CT-e
+ /// - 101=Cancelamento de CT-e homologado
+ /// - 110=Uso denegado
+ ///
+ ///
+ [XmlElement("cSitCTe")]
+ public string cSitCTe { get; set; }
+ }
+}
diff --git a/CTe.Classes/Servicos/DistribuicaoDFe/distDFeInt.cs b/CTe.Classes/Servicos/DistribuicaoDFe/distDFeInt.cs
index b61e0d2cd..f40503365 100644
--- a/CTe.Classes/Servicos/DistribuicaoDFe/distDFeInt.cs
+++ b/CTe.Classes/Servicos/DistribuicaoDFe/distDFeInt.cs
@@ -71,13 +71,12 @@ public string CNPJ
get { return _cNPJ; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(_cPF))
- _cNPJ = value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(_cPF))
throw new ArgumentException(ErroCpfCnpjPreenchidos);
- }
+
+ _cNPJ = value;
}
}
@@ -89,13 +88,12 @@ public string CPF
get { return _cPF; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(_cNPJ))
- _cPF = value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(_cNPJ))
throw new ArgumentException(ErroCpfCnpjPreenchidos);
- }
+
+ _cPF = value;
}
}
@@ -107,8 +105,6 @@ public string CPF
///
/// A09 - Grupo para consultar um DF-e a partir de um NSU específico
///
- public consNSU consNSU { get; set; }
-
-
+ public consNSU consNSU { get; set; }
}
}
diff --git a/CTe.Classes/Servicos/DistribuicaoDFe/loteDistDFeInt.cs b/CTe.Classes/Servicos/DistribuicaoDFe/loteDistDFeInt.cs
index 5a12f9988..3e0dbf8ab 100644
--- a/CTe.Classes/Servicos/DistribuicaoDFe/loteDistDFeInt.cs
+++ b/CTe.Classes/Servicos/DistribuicaoDFe/loteDistDFeInt.cs
@@ -31,6 +31,7 @@
/* Rua Comendador Francisco josé da Cunha, 111 - Itabaiana - SE - 49500-000 */
/********************************************************************************/
+using CTe.Classes.Servicos.DistribuicaoDFe.Schemas;
using System;
using System.ComponentModel;
using System.Xml.Serialization;
@@ -69,5 +70,21 @@ public class loteDistDFeInt
///
[XmlText(DataType = "base64Binary")]
public byte[] XmlNfe { get; set; }
+
+ #region Objetos possíveis para descompactar o conteúdo do campo XmlNfe, dependendo do valor do campo schema
+ [XmlIgnore]
+ public cteProc cteProc { get; set; }
+
+ [XmlIgnore]
+ public resCTe resCTe { get; set; }
+
+ [XmlIgnore]
+ public CTeOSDocumento.CTe.CTeOS.Retorno.cteOSProc cteOSProc { get; set; }
+
+ [XmlIgnore]
+ public Classes.Servicos.DistribuicaoDFe.Schemas.procEventoCTe procEventoCTe { get; set; }
+
+ //TO DO: Adicionar no futuro o procGTVe adicionando na versão 1.04 do schema de distribuição de DFe
+ #endregion
}
}
diff --git a/CTe.Classes/Servicos/Evento/dest.cs b/CTe.Classes/Servicos/Evento/dest.cs
index 9ac0e13ed..204a57316 100644
--- a/CTe.Classes/Servicos/Evento/dest.cs
+++ b/CTe.Classes/Servicos/Evento/dest.cs
@@ -60,13 +60,12 @@ public string CNPJ
get { return _cnpj; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(CPF) & string.IsNullOrEmpty(idEstrangeiro))
- _cnpj = value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(CPF) || !string.IsNullOrEmpty(idEstrangeiro))
throw new ArgumentException(ErroCpfCnpjIdEstrangeiroPreenchidos);
- }
+
+ _cnpj = value;
}
}
@@ -78,13 +77,12 @@ public string CPF
get { return _cpf; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(CNPJ) & string.IsNullOrEmpty(idEstrangeiro))
- _cpf = value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(CNPJ) || !string.IsNullOrEmpty(idEstrangeiro))
throw new ArgumentException(ErroCpfCnpjIdEstrangeiroPreenchidos);
- }
+
+ _cpf = value;
}
}
@@ -96,13 +94,12 @@ public string idEstrangeiro
get { return _idEstrangeiro; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(CNPJ) & string.IsNullOrEmpty(CPF))
- _idEstrangeiro = value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(CNPJ) || !string.IsNullOrEmpty(CPF))
throw new ArgumentException(ErroCpfCnpjIdEstrangeiroPreenchidos);
- }
+
+ _idEstrangeiro = value;
}
}
diff --git a/CTe.Classes/Servicos/Evento/detEvento.cs b/CTe.Classes/Servicos/Evento/detEvento.cs
index 17c3d2563..e840e81d3 100644
--- a/CTe.Classes/Servicos/Evento/detEvento.cs
+++ b/CTe.Classes/Servicos/Evento/detEvento.cs
@@ -44,6 +44,7 @@ public class detEvento
[XmlElement("evCancCTe", typeof(evCancCTe), Namespace = "http://www.portalfiscal.inf.br/cte")]
[XmlElement("evCCeCTe", typeof(evCCeCTe), Namespace = "http://www.portalfiscal.inf.br/cte")]
[XmlElement("evPrestDesacordo", typeof(evPrestDesacordo), Namespace = "http://www.portalfiscal.inf.br/cte")]
+ [XmlElement("evCancPrestDesacordo", typeof(evCancPrestDesacordo), Namespace = "http://www.portalfiscal.inf.br/cte")]
public EventoContainer EventoContainer { get; set; }
}
}
\ No newline at end of file
diff --git a/CTe.Classes/Servicos/Evento/evCancPrestDesacordo.cs b/CTe.Classes/Servicos/Evento/evCancPrestDesacordo.cs
new file mode 100644
index 000000000..f50233dc4
--- /dev/null
+++ b/CTe.Classes/Servicos/Evento/evCancPrestDesacordo.cs
@@ -0,0 +1,18 @@
+using System.Xml.Serialization;
+
+namespace CTe.Classes.Servicos.Evento
+{
+ [XmlRoot(Namespace = "http://www.portalfiscal.inf.br/cte")]
+ public class evCancPrestDesacordo : EventoContainer
+ {
+ public evCancPrestDesacordo()
+ {
+ this.descEvento = "Cancelamento Prestação do Serviço em Desacordo";
+ }
+
+ public string descEvento { get; set; }
+
+ public string nProtEvPrestDes { get; set; }
+
+ }
+}
diff --git a/CTe.Servicos/ConsultaStatus/StatusServico.cs b/CTe.Servicos/ConsultaStatus/StatusServico.cs
index 296f79b6b..d1c8063d2 100644
--- a/CTe.Servicos/ConsultaStatus/StatusServico.cs
+++ b/CTe.Servicos/ConsultaStatus/StatusServico.cs
@@ -61,6 +61,9 @@ public retConsStatServCte ConsultaStatus(ConfiguracaoServico configuracaoServico
public retConsStatServCTe ConsultaStatusV4(ConfiguracaoServico configuracaoServico = null)
{
+ if (configuracaoServico == null)
+ configuracaoServico = ConfiguracaoServico.Instancia;
+
var consStatServCte = ClassesFactory.CriaConsStatServCTe(configuracaoServico);
if (configuracaoServico.IsValidaSchemas)
diff --git a/CTe.Servicos/DistribuicaoDFe/ServicoCTeDistribuicaoDFe.cs b/CTe.Servicos/DistribuicaoDFe/ServicoCTeDistribuicaoDFe.cs
index e068c9f3e..d4b7db967 100644
--- a/CTe.Servicos/DistribuicaoDFe/ServicoCTeDistribuicaoDFe.cs
+++ b/CTe.Servicos/DistribuicaoDFe/ServicoCTeDistribuicaoDFe.cs
@@ -98,27 +98,33 @@ public RetornoCteDistDFeInt CTeDistDFeInteresse(string ufAutor, string documento
{
for (int i = 0; i < retConsulta.loteDistDFeInt.Length; i++)
{
- string conteudo = Compressao.Unzip(retConsulta.loteDistDFeInt[i].XmlNfe).RemoverDeclaracaoXml();
+ var loteAtual = retConsulta.loteDistDFeInt[i];
+ string conteudo = Compressao.Unzip(loteAtual.XmlNfe).RemoverDeclaracaoXml();
string chCTe = string.Empty;
if (conteudo.StartsWith("(conteudo);
- chCTe = retConteudo.protCTe.infProt.chCTe;
+ var cteConteudo = FuncoesXml.XmlStringParaClasse(conteudo);
+ chCTe = cteConteudo.protCTe.infProt.chCTe;
+ loteAtual.cteProc = cteConteudo;
}
else if (conteudo.StartsWith("(conteudo);
chCTe = procEventoNFeConteudo.eventoCTe.infEvento.chCTe;
+ loteAtual.procEventoCTe = procEventoNFeConteudo;
}
else if (conteudo.StartsWith("(conteudo);
- chCTe = retConteudo.protCTe.infProt.chCTe;
+ var cteOSConteudo = FuncoesXml.XmlStringParaClasse(conteudo);
+ chCTe = cteOSConteudo.protCTe.infProt.chCTe;
+ loteAtual.cteOSProc = cteOSConteudo;
}
- else
+ else if (conteudo.StartsWith("(conteudo);
+ chCTe = resCTeConteudo.chCTe;
+ loteAtual.resCTe = resCTeConteudo;
}
string[] schema = retConsulta.loteDistDFeInt[i].schema.Split('_');
diff --git a/CTe.Servicos/Enderecos/Helpers/UrlHelper.cs b/CTe.Servicos/Enderecos/Helpers/UrlHelper.cs
index 827cd2a1e..6c007186b 100644
--- a/CTe.Servicos/Enderecos/Helpers/UrlHelper.cs
+++ b/CTe.Servicos/Enderecos/Helpers/UrlHelper.cs
@@ -42,36 +42,51 @@ namespace CTe.Servicos.Enderecos.Helpers
{
public class UrlHelper
{
- public static UrlCTe ObterUrlServico(ConfiguracaoServico configuracaoServico = null)
+ ///
+ /// Obtem a url de Serviço. Por padrão pega as informações de ConfiguracaoServico, mas pode ser customizada individualmente. Motivo: em alguns casos a url de destino de um evento de CTe pode seguir as informações do xml e não da empresa emissora / com certificado ativo
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static UrlCTe ObterUrlServico(ConfiguracaoServico configuracaoServico = null, tpEmis? tipoEmissao = null , TipoAmbiente? tipoAmbiente = null, Estado? ufRecepcao = null, versao? versaoLayout = null)
{
var configServico = configuracaoServico ?? ConfiguracaoServico.Instancia;
- switch (configServico.tpAmb)
+ var tipoEmissaoUtilizado = tipoEmissao ?? configServico.TipoEmissao;
+ var tipoAmbienteUtilizado = tipoAmbiente ?? configServico.tpAmb;
+ var ufUtilizada = ufRecepcao ?? configServico.cUF;
+ var versaoUtilizada = versaoLayout ?? configServico.VersaoLayout;
+
+ switch (tipoAmbienteUtilizado)
{
case TipoAmbiente.Homologacao:
- if (configServico.TipoEmissao == tpEmis.teSVCRS)
+ if (tipoEmissaoUtilizado == tpEmis.teSVCRS)
{
- return UrlHomologacaoSvrs(configServico);
+ return UrlHomologacaoSvrs(versaoUtilizada);
}
- if (configServico.TipoEmissao == tpEmis.teSVCSP)
+ if (tipoEmissaoUtilizado == tpEmis.teSVCSP)
{
- return UrlHomologacaoSvcsp(configServico);
+ return UrlHomologacaoSvcsp(versaoUtilizada);
}
- return UrlHomologacao(configServico);
+ return UrlHomologacao(ufUtilizada, versaoUtilizada);
case TipoAmbiente.Producao:
- if (configServico.TipoEmissao == tpEmis.teSVCRS)
+ if (tipoEmissaoUtilizado == tpEmis.teSVCRS)
{
- return UrlProducaoSvrs(configServico);
+ return UrlProducaoSvrs(versaoUtilizada);
}
- if (configServico.TipoEmissao == tpEmis.teSVCSP)
+ if (tipoEmissaoUtilizado == tpEmis.teSVCSP)
{
- return UrlProducaoSvcsp(configServico);
+ return UrlProducaoSvcsp(versaoUtilizada);
}
- return UrlProducao(configServico);
+ return UrlProducao(ufUtilizada, versaoUtilizada);
}
throw new InvalidOperationException("Tipo Ambiente inválido");
@@ -84,17 +99,17 @@ public static string ObterUrlQrCode(ConfiguracaoServico configuracaoServico = nu
switch (configServico.tpAmb)
{
case TipoAmbiente.Homologacao:
- return UrlHomologacao(configServico).QrCode;
+ return UrlHomologacao(configServico.cUF, configServico.VersaoLayout).QrCode;
case TipoAmbiente.Producao:
- return UrlProducao(configServico).QrCode;
+ return UrlProducao(configServico.cUF, configServico.VersaoLayout).QrCode;
}
throw new InvalidOperationException("Tipo Ambiente inválido");
}
- private static UrlCTe UrlProducaoSvcsp(ConfiguracaoServico configuracaoServico)
+ private static UrlCTe UrlProducaoSvcsp(versao VersaoLayout)
{
- if (configuracaoServico.VersaoLayout == versao.ve400)
+ if (VersaoLayout == versao.ve400)
{
return new UrlCTe
{
@@ -119,9 +134,9 @@ private static UrlCTe UrlProducaoSvcsp(ConfiguracaoServico configuracaoServico)
};
}
- private static UrlCTe UrlHomologacaoSvcsp(ConfiguracaoServico configuracaoServico)
+ private static UrlCTe UrlHomologacaoSvcsp(versao VersaoLayout)
{
- if (configuracaoServico.VersaoLayout == versao.ve400)
+ if (VersaoLayout == versao.ve400)
{
return new UrlCTe
{
@@ -146,9 +161,9 @@ private static UrlCTe UrlHomologacaoSvcsp(ConfiguracaoServico configuracaoServic
};
}
- private static UrlCTe UrlHomologacaoSvrs(ConfiguracaoServico configuracaoServico)
+ private static UrlCTe UrlHomologacaoSvrs(versao VersaoLayout)
{
- if (configuracaoServico.VersaoLayout == versao.ve400)
+ if (VersaoLayout == versao.ve400)
{
return new UrlCTe
{
@@ -174,9 +189,9 @@ private static UrlCTe UrlHomologacaoSvrs(ConfiguracaoServico configuracaoServico
};
}
- private static UrlCTe UrlProducaoSvrs(ConfiguracaoServico configuracaoServico)
+ private static UrlCTe UrlProducaoSvrs(versao VersaoLayout)
{
- if (configuracaoServico.VersaoLayout == versao.ve400)
+ if (VersaoLayout == versao.ve400)
{
return new UrlCTe
{
@@ -202,12 +217,12 @@ private static UrlCTe UrlProducaoSvrs(ConfiguracaoServico configuracaoServico)
};
}
- private static UrlCTe UrlProducao(ConfiguracaoServico configuracaoServico)
+ private static UrlCTe UrlProducao(Estado UFRecepcao, versao VersaoLayout)
{
- switch (configuracaoServico.cUF)
+ switch (UFRecepcao)
{
case Estado.MT:
- if (configuracaoServico.VersaoLayout == versao.ve400)
+ if (VersaoLayout == versao.ve400)
{
return new UrlCTe
{
@@ -233,7 +248,7 @@ private static UrlCTe UrlProducao(ConfiguracaoServico configuracaoServico)
CTeDistribuicaoDFe = "https://www1.cte.fazenda.gov.br/CTeDistribuicaoDFe/CTeDistribuicaoDFe.asmx"
};
case Estado.MS:
- if (configuracaoServico.VersaoLayout == versao.ve400)
+ if (VersaoLayout == versao.ve400)
{
return new UrlCTe
{
@@ -259,7 +274,7 @@ private static UrlCTe UrlProducao(ConfiguracaoServico configuracaoServico)
CTeDistribuicaoDFe = "https://www1.cte.fazenda.gov.br/CTeDistribuicaoDFe/CTeDistribuicaoDFe.asmx"
};
case Estado.MG:
- if (configuracaoServico.VersaoLayout == versao.ve400)
+ if (VersaoLayout == versao.ve400)
{
return new UrlCTe
{
@@ -285,7 +300,7 @@ private static UrlCTe UrlProducao(ConfiguracaoServico configuracaoServico)
CTeDistribuicaoDFe = "https://www1.cte.fazenda.gov.br/CTeDistribuicaoDFe/CTeDistribuicaoDFe.asmx"
};
case Estado.PR:
- if (configuracaoServico.VersaoLayout == versao.ve400)
+ if (VersaoLayout == versao.ve400)
{
return new UrlCTe
{
@@ -311,7 +326,7 @@ private static UrlCTe UrlProducao(ConfiguracaoServico configuracaoServico)
CTeDistribuicaoDFe = "https://www1.cte.fazenda.gov.br/CTeDistribuicaoDFe/CTeDistribuicaoDFe.asmx"
};
case Estado.SP:
- if (configuracaoServico.VersaoLayout == versao.ve400)
+ if (VersaoLayout == versao.ve400)
{
return new UrlCTe
{
@@ -359,7 +374,7 @@ private static UrlCTe UrlProducao(ConfiguracaoServico configuracaoServico)
case Estado.SE:
case Estado.TO:
case Estado.RS:
- if (configuracaoServico.VersaoLayout == versao.ve400)
+ if (VersaoLayout == versao.ve400)
{
return new UrlCTe
{
@@ -390,7 +405,7 @@ private static UrlCTe UrlProducao(ConfiguracaoServico configuracaoServico)
case Estado.AP:
case Estado.PE:
case Estado.RR:
- if (configuracaoServico.VersaoLayout == versao.ve400)
+ if (VersaoLayout == versao.ve400)
{
return new UrlCTe
{
@@ -422,12 +437,12 @@ private static UrlCTe UrlProducao(ConfiguracaoServico configuracaoServico)
}
- private static UrlCTe UrlHomologacao(ConfiguracaoServico configuracaoServico)
+ private static UrlCTe UrlHomologacao(Estado UFRecepcao, versao VersaoLayout)
{
- switch (configuracaoServico.cUF)
+ switch (UFRecepcao)
{
case Estado.MT:
- if (configuracaoServico.VersaoLayout == versao.ve400)
+ if (VersaoLayout == versao.ve400)
{
return new UrlCTe
{
@@ -454,7 +469,7 @@ private static UrlCTe UrlHomologacao(ConfiguracaoServico configuracaoServico)
CTeDistribuicaoDFe = @"https://hom1.cte.fazenda.gov.br/CTeDistribuicaoDFe/CTeDistribuicaoDFe.asmx"
};
case Estado.MS:
- if (configuracaoServico.VersaoLayout == versao.ve400)
+ if (VersaoLayout == versao.ve400)
{
return new UrlCTe
{
@@ -478,7 +493,7 @@ private static UrlCTe UrlHomologacao(ConfiguracaoServico configuracaoServico)
CTeDistribuicaoDFe = @"https://hom1.cte.fazenda.gov.br/CTeDistribuicaoDFe/CTeDistribuicaoDFe.asmx"
};
case Estado.MG:
- if (configuracaoServico.VersaoLayout == versao.ve400)
+ if (VersaoLayout == versao.ve400)
{
return new UrlCTe
{
@@ -504,7 +519,7 @@ private static UrlCTe UrlHomologacao(ConfiguracaoServico configuracaoServico)
CTeDistribuicaoDFe = @"https://hom1.cte.fazenda.gov.br/CTeDistribuicaoDFe/CTeDistribuicaoDFe.asmx"
};
case Estado.PR:
- if (configuracaoServico.VersaoLayout == versao.ve400)
+ if (VersaoLayout == versao.ve400)
{
return new UrlCTe
{
@@ -545,7 +560,7 @@ private static UrlCTe UrlHomologacao(ConfiguracaoServico configuracaoServico)
CTeDistribuicaoDFe = @"https://hom1.cte.fazenda.gov.br/CTeDistribuicaoDFe/CTeDistribuicaoDFe.asmx"
};
case Estado.SP:
- if (configuracaoServico.VersaoLayout == versao.ve400)
+ if (VersaoLayout == versao.ve400)
{
return new UrlCTe
{
@@ -588,7 +603,7 @@ private static UrlCTe UrlHomologacao(ConfiguracaoServico configuracaoServico)
case Estado.SC:
case Estado.SE:
case Estado.TO:
- if (configuracaoServico.VersaoLayout == versao.ve400)
+ if (VersaoLayout == versao.ve400)
{
return new UrlCTe
{
@@ -619,7 +634,7 @@ private static UrlCTe UrlHomologacao(ConfiguracaoServico configuracaoServico)
case Estado.AP:
case Estado.PE:
case Estado.RR:
- if (configuracaoServico.VersaoLayout == versao.ve400)
+ if (VersaoLayout == versao.ve400)
{
return new UrlCTe
{
diff --git a/CTe.Servicos/Eventos/EventoCancelamentoDesacordo.cs b/CTe.Servicos/Eventos/EventoCancelamentoDesacordo.cs
new file mode 100644
index 000000000..f4040a0d2
--- /dev/null
+++ b/CTe.Servicos/Eventos/EventoCancelamentoDesacordo.cs
@@ -0,0 +1,49 @@
+using CTe.Classes;
+using CTe.Classes.Servicos.Evento;
+using CTe.Classes.Servicos.Evento.Flags;
+using CTe.Servicos.Factory;
+using System.Threading.Tasks;
+
+namespace CTe.Servicos.Eventos
+{
+ public class EventoCancelamentoDesacordo
+ {
+ private readonly int _sequenciaEvento;
+ private readonly string _cnpj;
+ private readonly string _chave;
+ private readonly string _nProtEvPrestDes;
+
+ public eventoCTe EventoEnviado { get; private set; }
+ public retEventoCTe RetornoSefaz { get; private set; }
+
+ public EventoCancelamentoDesacordo(int sequenciaEvento, string chave, string cnpj, string nProtEvPrestDes)
+ {
+ _chave = chave;
+ _cnpj = cnpj;
+ _sequenciaEvento = sequenciaEvento;
+ _nProtEvPrestDes = nProtEvPrestDes;
+ }
+
+ public retEventoCTe CancelarDesacordo(ConfiguracaoServico configuracaoServico = null, DFe.Classes.Entidades.Estado? orgaoEmissor = null)
+ {
+ var configServico = configuracaoServico ?? ConfiguracaoServico.Instancia;
+ var eventoCancelaDiscordar = ClassesFactory.CriaEvCancPrestDesacordo(_nProtEvPrestDes);
+
+ EventoEnviado = FactoryEvento.CriaEvento(CTeTipoEvento.CancelamentoPrestacaodoServicoemDesacordo, _sequenciaEvento, _chave, _cnpj, eventoCancelaDiscordar, configServico, orgaoEmissor);
+ RetornoSefaz = new ServicoController().Executar(CTeTipoEvento.CancelamentoPrestacaodoServicoemDesacordo, _sequenciaEvento, _chave, _cnpj, eventoCancelaDiscordar, configServico, orgaoEmissor);
+
+ return RetornoSefaz;
+ }
+
+ public async Task CancelarDesacordoAsync(ConfiguracaoServico configuracaoServico = null, DFe.Classes.Entidades.Estado? orgaoEmissor = null)
+ {
+ var configServico = configuracaoServico ?? ConfiguracaoServico.Instancia;
+ var eventoCancelaDiscordar = ClassesFactory.CriaEvCancPrestDesacordo(_nProtEvPrestDes);
+
+ EventoEnviado = FactoryEvento.CriaEvento(CTeTipoEvento.CancelamentoPrestacaodoServicoemDesacordo, _sequenciaEvento, _chave, _cnpj, eventoCancelaDiscordar, configServico, orgaoEmissor);
+ RetornoSefaz = await new ServicoController().ExecutarAsync(CTeTipoEvento.CancelamentoPrestacaodoServicoemDesacordo, _sequenciaEvento, _chave, _cnpj, eventoCancelaDiscordar, configServico, orgaoEmissor);
+
+ return RetornoSefaz;
+ }
+ }
+}
diff --git a/CTe.Servicos/Eventos/EventoDesacordo.cs b/CTe.Servicos/Eventos/EventoDesacordo.cs
index d2cef837a..a90db0d8d 100644
--- a/CTe.Servicos/Eventos/EventoDesacordo.cs
+++ b/CTe.Servicos/Eventos/EventoDesacordo.cs
@@ -59,23 +59,35 @@ public EventoDesacordo(int sequenciaEvento, string chave, string cnpj, string in
_observacao = observacao;
}
- public retEventoCTe Discordar(ConfiguracaoServico configuracaoServico = null)
+ ///
+ /// Gera o evento de desacordo de CTe
+ ///
+ ///
+ /// Sempre considera a UF que gerou o xml. Então a empresa pode estar configurada para uma UF X e gerar o desacordo de um xml gerado na UF Y, sendo o evento, portanto, enviado para UF Y
+ ///
+ public retEventoCTe Discordar(ConfiguracaoServico configuracaoServico = null, DFe.Classes.Entidades.Estado? orgaoEmissor = null)
{
+ var configServico = configuracaoServico ?? ConfiguracaoServico.Instancia;
var eventoDiscordar = ClassesFactory.CriaEvPrestDesacordo(_indicadorDesacordo, _observacao);
- EventoEnviado = FactoryEvento.CriaEvento(CTeTipoEvento.Desacordo, _sequenciaEvento, _chave, _cnpj, eventoDiscordar, configuracaoServico);
- RetornoSefaz = new ServicoController().Executar(CTeTipoEvento.Desacordo, _sequenciaEvento, _chave, _cnpj, eventoDiscordar, configuracaoServico);
-
+ EventoEnviado = FactoryEvento.CriaEvento(CTeTipoEvento.Desacordo, _sequenciaEvento, _chave, _cnpj, eventoDiscordar, configServico, orgaoEmissor);
+ RetornoSefaz = new ServicoController().Executar(CTeTipoEvento.Desacordo, _sequenciaEvento, _chave, _cnpj, eventoDiscordar, configServico, orgaoEmissor);
return RetornoSefaz;
}
- public async Task DiscordarAsync(ConfiguracaoServico configuracaoServico = null)
+ ///
+ /// Gera o evento de desacordo de CTe de forma assíncrona
+ ///
+ ///
+ /// Sempre considera a UF que gerou o xml. Então a empresa pode estar configurada para uma UF X e gerar o desacordo de um xml gerado na UF Y, sendo o evento, portanto, enviado para UF Y
+ ///
+ public async Task DiscordarAsync(ConfiguracaoServico configuracaoServico = null, DFe.Classes.Entidades.Estado? orgaoEmissor = null)
{
+ var configServico = configuracaoServico ?? ConfiguracaoServico.Instancia;
var eventoDiscordar = ClassesFactory.CriaEvPrestDesacordo(_indicadorDesacordo, _observacao);
- EventoEnviado = FactoryEvento.CriaEvento(CTeTipoEvento.Desacordo, _sequenciaEvento, _chave, _cnpj, eventoDiscordar, configuracaoServico);
- RetornoSefaz = await new ServicoController().ExecutarAsync(CTeTipoEvento.Desacordo, _sequenciaEvento, _chave, _cnpj, eventoDiscordar, configuracaoServico);
-
+ EventoEnviado = FactoryEvento.CriaEvento(CTeTipoEvento.Desacordo, _sequenciaEvento, _chave, _cnpj, eventoDiscordar, configServico, orgaoEmissor);
+ RetornoSefaz = await new ServicoController().ExecutarAsync(CTeTipoEvento.Desacordo, _sequenciaEvento, _chave, _cnpj, eventoDiscordar, configServico, orgaoEmissor);
return RetornoSefaz;
}
}
diff --git a/CTe.Servicos/Eventos/FactoryEvento.cs b/CTe.Servicos/Eventos/FactoryEvento.cs
index f862794e2..465732105 100644
--- a/CTe.Servicos/Eventos/FactoryEvento.cs
+++ b/CTe.Servicos/Eventos/FactoryEvento.cs
@@ -51,7 +51,7 @@ public static eventoCTe CriaEvento(CTeEletronico cte, CTeTipoEvento cTeTipoEvent
return CriaEvento(cTeTipoEvento, sequenciaEvento, cte.Chave(), cte.infCte.emit.CNPJ, container, configServico);
}
- public static eventoCTe CriaEvento(CTeTipoEvento cTeTipoEvento, int sequenciaEvento, string chave, string cnpj, EventoContainer container, ConfiguracaoServico configuracaoServico = null)
+ public static eventoCTe CriaEvento(CTeTipoEvento cTeTipoEvento, int sequenciaEvento, string chave, string cnpj, EventoContainer container, ConfiguracaoServico configuracaoServico = null, DFe.Classes.Entidades.Estado? cOrgao = null)
{
var configServico = configuracaoServico ?? ConfiguracaoServico.Instancia;
@@ -72,7 +72,7 @@ public static eventoCTe CriaEvento(CTeTipoEvento cTeTipoEvento, int sequenciaEve
{
tpAmb = configServico.tpAmb,
CNPJ = cnpj,
- cOrgao = configServico.cUF,
+ cOrgao = cOrgao ?? configServico.cUF,
chCTe = chave,
dhEvento = DateTimeOffset.Now,
nSeqEvento = sequenciaEvento,
diff --git a/CTe.Servicos/Eventos/ServicoController.cs b/CTe.Servicos/Eventos/ServicoController.cs
index 5e319f335..751b9e719 100644
--- a/CTe.Servicos/Eventos/ServicoController.cs
+++ b/CTe.Servicos/Eventos/ServicoController.cs
@@ -66,10 +66,10 @@ public async Task ExecutarAsync(CteEletronico cte, int sequenciaEv
return await ExecutarAsync(cTeTipoEvento, sequenciaEvento, cte.Chave(), cte.infCte.emit.CNPJ, container, configServico);
}
- public retEventoCTe Executar(CTeTipoEvento cTeTipoEvento, int sequenciaEvento, string chave, string cnpj, EventoContainer container, ConfiguracaoServico configuracaoServico = null)
+ public retEventoCTe Executar(CTeTipoEvento cTeTipoEvento, int sequenciaEvento, string chave, string cnpj, EventoContainer container, ConfiguracaoServico configuracaoServico = null, DFe.Classes.Entidades.Estado? cOrgao = null)
{
var configServico = configuracaoServico ?? ConfiguracaoServico.Instancia;
- var evento = FactoryEvento.CriaEvento(cTeTipoEvento, sequenciaEvento, chave, cnpj, container, configServico);
+ var evento = FactoryEvento.CriaEvento(cTeTipoEvento, sequenciaEvento, chave, cnpj, container, configServico, cOrgao);
evento.Assina(configServico);
if (configServico.IsValidaSchemas)
@@ -81,13 +81,13 @@ public retEventoCTe Executar(CTeTipoEvento cTeTipoEvento, int sequenciaEvento, s
if (evento.versao == versao.ve200 || evento.versao == versao.ve300)
{
- var webService = WsdlFactory.CriaWsdlCteEvento(configServico);
+ var webService = WsdlFactory.CriaWsdlCteEvento(configServico, ufUrl: cOrgao);
retornoXml = webService.cteRecepcaoEvento(evento.CriaXmlRequestWs());
}
if (evento.versao == versao.ve400)
{
- var webService = WsdlFactory.CriaWsdlCteEventoV4(configServico);
+ var webService = WsdlFactory.CriaWsdlCteEventoV4(configServico, ufUrl: cOrgao);
retornoXml = webService.cteRecepcaoEvento(evento.CriaXmlRequestWs());
}
@@ -97,15 +97,11 @@ public retEventoCTe Executar(CTeTipoEvento cTeTipoEvento, int sequenciaEvento, s
return retorno;
}
- public async Task ExecutarAsync(CTeTipoEvento cTeTipoEvento,
- int sequenciaEvento,
- string chave, string
- cnpj, EventoContainer container,
- ConfiguracaoServico configuracaoServico = null)
+ public async Task ExecutarAsync(CTeTipoEvento cTeTipoEvento, int sequenciaEvento, string chave, string cnpj, EventoContainer container, ConfiguracaoServico configuracaoServico = null, DFe.Classes.Entidades.Estado? cOrgao = null)
{
var configServico = configuracaoServico ?? ConfiguracaoServico.Instancia;
- var evento = FactoryEvento.CriaEvento(cTeTipoEvento, sequenciaEvento, chave, cnpj, container, configServico);
+ var evento = FactoryEvento.CriaEvento(cTeTipoEvento, sequenciaEvento, chave, cnpj, container, configServico, cOrgao);
evento.Assina(configServico);
if (configServico.IsValidaSchemas)
@@ -117,16 +113,15 @@ public async Task ExecutarAsync(CTeTipoEvento cTeTipoEvento,
if (evento.versao == versao.ve200 || evento.versao == versao.ve300)
{
- var webService = WsdlFactory.CriaWsdlCteEvento(configServico);
+ var webService = WsdlFactory.CriaWsdlCteEvento(configServico, ufUrl: cOrgao);
retornoXml = await webService.cteRecepcaoEventoAsync(evento.CriaXmlRequestWs());
}
if (evento.versao == versao.ve400)
{
- var webService = WsdlFactory.CriaWsdlCteEventoV4(configServico);
+ var webService = WsdlFactory.CriaWsdlCteEventoV4(configServico, ufUrl: cOrgao);
retornoXml = await webService.cteRecepcaoEventoAsync(evento.CriaXmlRequestWs());
}
-
var retorno = retEventoCTe.LoadXml(retornoXml.OuterXml, evento);
retorno.SalvarXmlEmDisco(configServico);
diff --git a/CTe.Servicos/Factory/ClassesFactory.cs b/CTe.Servicos/Factory/ClassesFactory.cs
index 03492279d..646c6428e 100644
--- a/CTe.Servicos/Factory/ClassesFactory.cs
+++ b/CTe.Servicos/Factory/ClassesFactory.cs
@@ -164,6 +164,22 @@ public static evPrestDesacordo CriaEvPrestDesacordo(string indicadorDesacordo, s
return evPrestDesacordo;
}
+ public static evCancPrestDesacordo CriaEvCancPrestDesacordo(string nProtEvPrestDes, ConfiguracaoServico configuracaoServico = null)
+ {
+ var configServico = configuracaoServico ?? ConfiguracaoServico.Instancia;
+
+ var evPrestDesacordo = new evCancPrestDesacordo
+ {
+ nProtEvPrestDes = nProtEvPrestDes
+ };
+
+ if (configServico.cUF == Estado.MT)//sem acentuação issue #1386
+ {
+ evPrestDesacordo.descEvento = "Cancelamento Prestacao do Servico em Desacordo";
+ }
+
+ return evPrestDesacordo;
+ }
public static enviCTe CriaEnviCTe(int lote, List cteEletronicoList, ConfiguracaoServico configuracaoServico = null)
{
diff --git a/CTe.Servicos/Factory/WsdlFactory.cs b/CTe.Servicos/Factory/WsdlFactory.cs
index fb633d0e2..cc0bd4591 100644
--- a/CTe.Servicos/Factory/WsdlFactory.cs
+++ b/CTe.Servicos/Factory/WsdlFactory.cs
@@ -47,6 +47,7 @@
using CTe.Wsdl.Evento.V4;
using CTe.Wsdl.Recepcao.Sincrono;
using System.Security.Cryptography.X509Certificates;
+using DFe.Classes.Entidades;
namespace CTe.Servicos.Factory
{
@@ -123,22 +124,22 @@ public static CteRecepcaoSincronoOSV4 CriaWsdlCteRecepcaoSincronoOSV4(Configurac
return new CteRecepcaoSincronoOSV4(configuracaoWsdl);
}
- public static CteRecepcaoEvento CriaWsdlCteEvento(ConfiguracaoServico configuracaoServico = null, X509Certificate2 certificado = null)
+ public static CteRecepcaoEvento CriaWsdlCteEvento(ConfiguracaoServico configuracaoServico = null, X509Certificate2 certificado = null, Estado? ufUrl = null)
{
- var url = UrlHelper.ObterUrlServico(configuracaoServico).CteRecepcaoEvento;
+ var url = UrlHelper.ObterUrlServico(configuracaoServico, ufRecepcao: ufUrl).CteRecepcaoEvento;
- var configuracaoWsdl = CriaConfiguracao(url, configuracaoServico, certificado);
+ var configuracaoWsdl = CriaConfiguracao(url, configuracaoServico, certificado, ufUrl);
return new CteRecepcaoEvento(configuracaoWsdl);
}
- public static CteRecepcaoEventoV4 CriaWsdlCteEventoV4(ConfiguracaoServico configuracaoServico = null, X509Certificate2 certificado = null)
+ public static CteRecepcaoEventoV4 CriaWsdlCteEventoV4(ConfiguracaoServico configuracaoServico = null, X509Certificate2 certificado = null, Estado? ufUrl = null)
{
var configServico = configuracaoServico ?? ConfiguracaoServico.Instancia;
- var url = UrlHelper.ObterUrlServico(configServico).CteRecepcaoEvento;
+ var url = UrlHelper.ObterUrlServico(configServico, ufRecepcao: ufUrl).CteRecepcaoEvento;
- var configuracaoWsdl = CriaConfiguracao(url, configServico, certificado);
+ var configuracaoWsdl = CriaConfiguracao(url, configServico, certificado, ufUrl);
return new CteRecepcaoEventoV4(configuracaoWsdl);
}
@@ -154,11 +155,11 @@ public static CTeDistDFeInteresse CriaWsdlCTeDistDFeInteresse(ConfiguracaoServic
}
- private static WsdlConfiguracao CriaConfiguracao(string url, ConfiguracaoServico configuracaoServico, X509Certificate2 certificado)
+ private static WsdlConfiguracao CriaConfiguracao(string url, ConfiguracaoServico configuracaoServico, X509Certificate2 certificado, Estado? ufUrl = null)
{
var configServico = configuracaoServico ?? ConfiguracaoServico.Instancia;
- var codigoEstado = configServico.cUF.GetCodigoIbgeEmString();
+ var codigoEstado = ufUrl.HasValue ? ufUrl.Value.GetCodigoIbgeEmString() : configServico.cUF.GetCodigoIbgeEmString();
var certificadoDigital = certificado ?? configServico.X509Certificate2;
var versaoEmString = configServico.VersaoLayout.GetString();
var timeOut = configServico.TimeOut;
diff --git a/DFe.Testes/DFe.Testes.csproj b/DFe.Testes/DFe.Testes.csproj
index cc90271e4..a7deb0021 100644
--- a/DFe.Testes/DFe.Testes.csproj
+++ b/DFe.Testes/DFe.Testes.csproj
@@ -18,8 +18,10 @@
+
+
diff --git a/DFe.Testes/Gerais/ChaveFiscalTestes.cs b/DFe.Testes/Gerais/ChaveFiscalTestes.cs
new file mode 100644
index 000000000..4d761043b
--- /dev/null
+++ b/DFe.Testes/Gerais/ChaveFiscalTestes.cs
@@ -0,0 +1,261 @@
+using System;
+using DFe.Classes.Entidades;
+using DFe.Classes.Flags;
+using DFe.Utils;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace DFe.Testes.Gerais
+{
+ ///
+ /// Testes da chave de acesso do DF-e cobrindo o fluxo antigo (CNPJ 100% numérico)
+ /// e o novo fluxo com CNPJ alfanumérico da NT Conjunta 2025.001
+ ///
+ [TestClass]
+ public class ChaveFiscalTestes
+ {
+ //Chave real de NFC-e homologação (CNPJ numérico) usada como âncora de regressão do fluxo antigo
+ private const string ChaveNumericaReal = "23190811820016000167650010000000221100000227";
+
+ //Vetor ouro da NT: NFe de GO, emitida em 07/2025 pelo CNPJ alfanumérico de teste da Receita PC3D315K000193
+ private const string ChaveAlfanumericaOuro = "522507PC3D315K000193550010000000011000000018";
+
+ #region Fluxo novo - CNPJ alfanumérico
+
+ [TestMethod]
+ public void ObterChave_ComCnpjAlfanumerico_GeraAChaveDoVetorOuro()
+ {
+ // Arrange
+ var dataEmissao = new DateTimeOffset(2025, 7, 15, 10, 0, 0, TimeSpan.FromHours(-3));
+
+ // Act
+ var dados = ChaveFiscal.ObterChave(Estado.GO, dataEmissao, "PC3D315K000193", ModeloDocumento.NFe, 1, 1, 1, 1);
+
+ // Assert
+ Assert.AreEqual(ChaveAlfanumericaOuro, dados.Chave);
+ Assert.AreEqual((byte)8, dados.DigitoVerificador);
+ }
+
+ [TestMethod]
+ public void ObterChave_ComCnpjAlfanumerico_ChaveTemLayoutCorreto()
+ {
+ var dados = ChaveFiscal.ObterChave(Estado.GO, new DateTime(2025, 7, 15), "PC3D315K000193", ModeloDocumento.NFe, 1, 1, 1, 1);
+
+ Assert.AreEqual(44, dados.Chave.Length);
+ Assert.AreEqual("52", dados.Chave.Substring(0, 2), "cUF");
+ Assert.AreEqual("2507", dados.Chave.Substring(2, 4), "AAMM");
+ Assert.AreEqual("PC3D315K000193", dados.Chave.Substring(6, 14), "CNPJ");
+ Assert.AreEqual("55", dados.Chave.Substring(20, 2), "modelo");
+ }
+
+ [TestMethod]
+ public void ChaveValida_ComChaveAlfanumericaDoVetorOuro_RetornaVerdadeiro()
+ {
+ Assert.IsTrue(ChaveFiscal.ChaveValida(ChaveAlfanumericaOuro));
+ }
+
+ [TestMethod]
+ [DataRow("0")]
+ [DataRow("1")]
+ [DataRow("5")]
+ [DataRow("9")]
+ public void ChaveValida_ComChaveAlfanumericaComDvErrado_RetornaFalso(string dvErrado)
+ {
+ var chaveComDvErrado = ChaveAlfanumericaOuro.Substring(0, 43) + dvErrado;
+
+ Assert.IsFalse(ChaveFiscal.ChaveValida(chaveComDvErrado));
+ }
+
+ [TestMethod]
+ public void ObterChave_ComVariosCnpjsAlfanumericos_DvIgualAoDaImplementacaoDeReferenciaDaNT()
+ {
+ // Arrange - bases alfanuméricas com DVs calculados pela regra oficial de CNPJ
+ var basesCnpj = new[] { "12ABC34501DE", "PC3D315K0001", "A1B2C3D4E5F6", "ZZZZZZZZZZZZ", "0000000000AB", "H9J8K7L6M5N4" };
+ var ufs = new[] { Estado.GO, Estado.SP, Estado.CE, Estado.RS, Estado.AM, Estado.DF };
+ var modelos = new[] { ModeloDocumento.NFe, ModeloDocumento.NFCe };
+
+ for (var i = 0; i < basesCnpj.Length; i++)
+ {
+ var cnpj = basesCnpj[i] + CnpjFiscal.ObterDigitosVerificadores(basesCnpj[i]);
+
+ foreach (var modelo in modelos)
+ {
+ // Act
+ var dados = ChaveFiscal.ObterChave(ufs[i], new DateTime(2026, 7, 1), cnpj, modelo, i + 1, 1000 + i, 1, 77000 + i);
+
+ // Assert
+ var dvReferencia = CalcularDvReferenciaNt(dados.Chave.Substring(0, 43));
+ Assert.AreEqual(dvReferencia, (int)dados.DigitoVerificador, "CNPJ {0}, modelo {1}", cnpj, modelo);
+ Assert.IsTrue(ChaveFiscal.ChaveValida(dados.Chave), "ChaveValida deveria aceitar {0}", dados.Chave);
+ }
+ }
+ }
+
+ [TestMethod]
+ public void ObterChave_ComCnpjAlfanumericoMinusculo_LancaArgumentException()
+ {
+ Assert.ThrowsException(() =>
+ ChaveFiscal.ObterChave(Estado.GO, new DateTime(2025, 7, 15), "pc3d315k000193", ModeloDocumento.NFe, 1, 1, 1, 1));
+ }
+
+ [TestMethod]
+ [DataRow(':')]
+ [DataRow(';')]
+ [DataRow('<')]
+ [DataRow('=')]
+ [DataRow('>')]
+ [DataRow('?')]
+ [DataRow('@')]
+ public void ObterChave_ComCaractereEntreDigitosELetras_LancaArgumentException(char caractereInvalido)
+ {
+ //os caracteres ASCII 58 a 64 ficam entre '9' e 'A' e produziriam DV errado sem erro se aceitos
+ var cnpjInvalido = "PC3D315K0001" + caractereInvalido + "3";
+
+ Assert.ThrowsException(() =>
+ ChaveFiscal.ObterChave(Estado.GO, new DateTime(2025, 7, 15), cnpjInvalido, ModeloDocumento.NFe, 1, 1, 1, 1));
+ }
+
+ [TestMethod]
+ public void ChaveValida_ComLetraMinusculaNaChave_LancaArgumentException()
+ {
+ var chaveComMinuscula = "522507pC3D315K000193550010000000011000000018";
+
+ Assert.ThrowsException(() => ChaveFiscal.ChaveValida(chaveComMinuscula));
+ }
+
+ #endregion
+
+ #region Fluxo antigo - CNPJ numérico (regressão)
+
+ [TestMethod]
+ public void ObterChave_ComCnpjNumerico_GeraChaveRealConhecida()
+ {
+ // Arrange - componentes da chave real de homologação (NFC-e do CE, 08/2019)
+ var dataEmissao = new DateTimeOffset(2019, 8, 10, 12, 0, 0, TimeSpan.FromHours(-3));
+
+ // Act
+ var dados = ChaveFiscal.ObterChave(Estado.CE, dataEmissao, "11820016000167", ModeloDocumento.NFCe, 1, 22, 1, 10000022);
+
+ // Assert
+ Assert.AreEqual(ChaveNumericaReal, dados.Chave);
+ Assert.AreEqual((byte)7, dados.DigitoVerificador);
+ }
+
+ [TestMethod]
+ public void ChaveValida_ComChaveNumericaRealConhecida_RetornaVerdadeiro()
+ {
+ Assert.IsTrue(ChaveFiscal.ChaveValida(ChaveNumericaReal));
+ }
+
+ [TestMethod]
+ public void ChaveValida_ComChaveNumericaComDvErrado_RetornaFalso()
+ {
+ var chaveComDvErrado = ChaveNumericaReal.Substring(0, 43) + "9";
+
+ Assert.IsFalse(ChaveFiscal.ChaveValida(chaveComDvErrado));
+ }
+
+ [TestMethod]
+ public void ObterChave_ComVariosCnpjsNumericos_DvIdenticoAoAlgoritmoLegado()
+ {
+ // Arrange - regressão: para chave 100% numérica o DV novo deve ser idêntico ao da implementação antiga
+ var cnpjs = new[] { "11222333000181", "00000000000191", "11444777000161", "99999999999999", "00000000000000", "12345678000195" };
+ var ufs = new[] { Estado.SP, Estado.GO, Estado.CE, Estado.RS, Estado.MG, Estado.BA };
+
+ for (var i = 0; i < cnpjs.Length; i++)
+ {
+ foreach (var modelo in new[] { ModeloDocumento.NFe, ModeloDocumento.NFCe })
+ {
+ // Act
+ var dados = ChaveFiscal.ObterChave(ufs[i], new DateTime(2024, 12, 31), cnpjs[i], modelo, 883 + i, 999999990 + i, 2, 10000000 - i);
+
+ // Assert
+ var dvLegado = CalcularDvAlgoritmoLegado(dados.Chave.Substring(0, 43));
+ Assert.AreEqual(dvLegado, dados.DigitoVerificador.ToString(), "CNPJ {0}, modelo {1}", cnpjs[i], modelo);
+ Assert.IsTrue(ChaveFiscal.ChaveValida(dados.Chave));
+ }
+ }
+ }
+
+ [TestMethod]
+ public void ObterChave_ComCpfDe11Posicoes_PreencheComZerosAEsquerda()
+ {
+ // Act
+ var dados = ChaveFiscal.ObterChave(Estado.SP, new DateTime(2026, 7, 1), "12345678901", ModeloDocumento.NFe, 1, 123, 1, 55555);
+
+ // Assert
+ Assert.AreEqual(44, dados.Chave.Length);
+ Assert.AreEqual("00012345678901", dados.Chave.Substring(6, 14));
+ Assert.IsTrue(ChaveFiscal.ChaveValida(dados.Chave));
+ }
+
+ #endregion
+
+ #region Validação do documento do emitente
+
+ [TestMethod]
+ [DataRow("PC3D315K0001", DisplayName = "12 posições - base de CNPJ truncada")]
+ [DataRow("1122233300018", DisplayName = "13 posições")]
+ [DataRow("112223330001811", DisplayName = "15 posições")]
+ [DataRow("1234567890", DisplayName = "10 posições")]
+ public void ObterChave_ComDocumentoDeComprimentoInvalido_LancaArgumentException(string documento)
+ {
+ //um CNPJ truncado não pode virar silenciosamente uma chave bem-formada porém errada
+ Assert.ThrowsException(() =>
+ ChaveFiscal.ObterChave(Estado.GO, new DateTime(2026, 7, 1), documento, ModeloDocumento.NFe, 1, 1, 1, 1));
+ }
+
+ [TestMethod]
+ public void ObterChave_ComDocumentoVazio_LancaArgumentException()
+ {
+ Assert.ThrowsException(() =>
+ ChaveFiscal.ObterChave(Estado.GO, new DateTime(2026, 7, 1), "", ModeloDocumento.NFe, 1, 1, 1, 1));
+ }
+
+ [TestMethod]
+ public void ObterChave_ComDocumentoNulo_LancaArgumentException()
+ {
+ Assert.ThrowsException(() =>
+ ChaveFiscal.ObterChave(Estado.GO, new DateTime(2026, 7, 1), null, ModeloDocumento.NFe, 1, 1, 1, 1));
+ }
+
+ #endregion
+
+ ///
+ /// Implementação de referência do Anexo II da NT Conjunta 2025.001, portada para C#
+ ///
+ private static int CalcularDvReferenciaNt(string chave43)
+ {
+ var soma = 0;
+ var peso = 2;
+ for (var i = chave43.Length - 1; i >= 0; i--)
+ {
+ soma += (chave43[i] - '0') * peso;
+ peso = peso == 9 ? 2 : peso + 1;
+ }
+ var dv = 11 - soma % 11;
+ return dv >= 10 ? 0 : dv;
+ }
+
+ ///
+ /// Algoritmo do DV como era antes da correção (só funciona com dígitos),
+ /// usado para garantir que chaves numéricas não sofreram regressão
+ ///
+ private static string CalcularDvAlgoritmoLegado(string chave43)
+ {
+ var soma = 0;
+ var peso = 2;
+ for (var i = chave43.Length - 1; i != -1; i--)
+ {
+ var ch = Convert.ToInt32(chave43[i].ToString());
+ soma += ch * peso;
+ if (peso < 9)
+ peso += 1;
+ else
+ peso = 2;
+ }
+ var mod = soma % 11;
+ var dv = mod == 0 || mod == 1 ? 0 : 11 - mod;
+ return dv.ToString();
+ }
+ }
+}
diff --git a/DFe.Testes/Gerais/CnpjFiscalTestes.cs b/DFe.Testes/Gerais/CnpjFiscalTestes.cs
new file mode 100644
index 000000000..a91b7240c
--- /dev/null
+++ b/DFe.Testes/Gerais/CnpjFiscalTestes.cs
@@ -0,0 +1,128 @@
+using System;
+using DFe.Utils;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace DFe.Testes.Gerais
+{
+ ///
+ /// Testes do cálculo de dígitos verificadores e validação de CNPJ,
+ /// cobrindo CNPJs numéricos (fluxo antigo) e alfanuméricos (NT Conjunta 2025.001)
+ ///
+ [TestClass]
+ public class CnpjFiscalTestes
+ {
+ #region ObterDigitosVerificadores - vetores ouro
+
+ [TestMethod]
+ [DataRow("112223330001", "81", DisplayName = "Base numérica")]
+ [DataRow("12ABC34501DE", "35", DisplayName = "Exemplo da NT Conjunta 2025.001")]
+ [DataRow("PC3D315K0001", "93", DisplayName = "CNPJ de teste da Receita Federal")]
+ [DataRow("000000000000", "00", DisplayName = "Base zerada - o DV confere, o bloqueio é do Valido")]
+ public void ObterDigitosVerificadores_ComBaseDe12Posicoes_RetornaDvsEsperados(string baseCnpj, string dvsEsperados)
+ {
+ Assert.AreEqual(dvsEsperados, CnpjFiscal.ObterDigitosVerificadores(baseCnpj));
+ }
+
+ [TestMethod]
+ [DataRow("000000000001", "91", DisplayName = "Banco do Brasil")]
+ [DataRow("114447770001", "61", DisplayName = "CNPJ numérico clássico de testes")]
+ [DataRow("123456780001", "95", DisplayName = "CNPJ numérico sequencial")]
+ public void ObterDigitosVerificadores_ComBasesNumericasHistoricas_MantemComportamentoAntigo(string baseCnpj, string dvsEsperados)
+ {
+ Assert.AreEqual(dvsEsperados, CnpjFiscal.ObterDigitosVerificadores(baseCnpj));
+ }
+
+ #endregion
+
+ #region ObterDigitosVerificadores - entradas inválidas
+
+ [TestMethod]
+ [DataRow("pc3d315k0001", DisplayName = "Minúsculas")]
+ [DataRow("12ABC34501D", DisplayName = "11 posições")]
+ [DataRow("12ABC34501DEF", DisplayName = "13 posições")]
+ [DataRow("12ABC34501D@", DisplayName = "Caractere @ (ASCII 64)")]
+ [DataRow("12ABC34501D:", DisplayName = "Caractere : (ASCII 58)")]
+ [DataRow("12.ABC.345/01", DisplayName = "Com máscara")]
+ [DataRow("", DisplayName = "Vazia")]
+ public void ObterDigitosVerificadores_ComBaseInvalida_LancaArgumentException(string baseCnpj)
+ {
+ Assert.ThrowsException(() => CnpjFiscal.ObterDigitosVerificadores(baseCnpj));
+ }
+
+ [TestMethod]
+ public void ObterDigitosVerificadores_ComBaseNula_LancaArgumentNullException()
+ {
+ Assert.ThrowsException(() => CnpjFiscal.ObterDigitosVerificadores(null));
+ }
+
+ #endregion
+
+ #region Valido - CNPJs aceitos
+
+ [TestMethod]
+ [DataRow("11222333000181", DisplayName = "Numérico do vetor ouro")]
+ [DataRow("12ABC34501DE35", DisplayName = "Alfanumérico do exemplo da NT")]
+ [DataRow("PC3D315K000193", DisplayName = "Alfanumérico de teste da Receita")]
+ [DataRow("00000000000191", DisplayName = "Numérico clássico - Banco do Brasil")]
+ [DataRow("11444777000161", DisplayName = "Numérico clássico de testes")]
+ public void Valido_ComCnpjCorreto_RetornaVerdadeiro(string cnpj)
+ {
+ Assert.IsTrue(CnpjFiscal.Valido(cnpj));
+ }
+
+ #endregion
+
+ #region Valido - CNPJs rejeitados
+
+ [TestMethod]
+ public void Valido_ComCnpjZerado_RetornaFalso()
+ {
+ //o DV do CNPJ zerado confere, mas a NT veda o seu uso
+ Assert.IsFalse(CnpjFiscal.Valido("00000000000000"));
+ }
+
+ [TestMethod]
+ [DataRow("11222333000182", DisplayName = "Numérico com DV errado")]
+ [DataRow("12ABC34501DE36", DisplayName = "Alfanumérico com segundo DV errado")]
+ [DataRow("12ABC34501DE45", DisplayName = "Alfanumérico com primeiro DV errado")]
+ [DataRow("PC3D315K000139", DisplayName = "Alfanumérico com DVs trocados")]
+ public void Valido_ComDvIncorreto_RetornaFalso(string cnpj)
+ {
+ Assert.IsFalse(CnpjFiscal.Valido(cnpj));
+ }
+
+ [TestMethod]
+ [DataRow("pc3d315k000193", DisplayName = "Minúsculas")]
+ [DataRow("PC3D315K00019", DisplayName = "13 posições")]
+ [DataRow("PC3D315K0001935", DisplayName = "15 posições")]
+ [DataRow("12ABC34501DEA5", DisplayName = "Letra na posição dos DVs")]
+ [DataRow("12ABC34501D:93", DisplayName = "Caractere : (ASCII 58)")]
+ [DataRow("12ABC34501D@93", DisplayName = "Caractere @ (ASCII 64)")]
+ [DataRow("11.222.333/0001-81", DisplayName = "Com máscara")]
+ [DataRow("", DisplayName = "Vazio")]
+ [DataRow(null, DisplayName = "Nulo")]
+ public void Valido_ComFormatoInvalido_RetornaFalso(string cnpj)
+ {
+ Assert.IsFalse(CnpjFiscal.Valido(cnpj));
+ }
+
+ #endregion
+
+ #region Coerência entre ObterDigitosVerificadores e Valido
+
+ [TestMethod]
+ public void Valido_ComDvsCalculadosPelaPropriaClasse_RetornaVerdadeiro()
+ {
+ var bases = new[] { "112223330001", "12ABC34501DE", "PC3D315K0001", "A1B2C3D4E5F6", "ZZZZZZZZZZZZ", "0000000000AB", "999999999999" };
+
+ foreach (var baseCnpj in bases)
+ {
+ var cnpj = baseCnpj + CnpjFiscal.ObterDigitosVerificadores(baseCnpj);
+
+ Assert.IsTrue(CnpjFiscal.Valido(cnpj), "O CNPJ {0} deveria ser válido", cnpj);
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/DFe.Testes/Gerais/Code128HibridoTestes.cs b/DFe.Testes/Gerais/Code128HibridoTestes.cs
new file mode 100644
index 000000000..9696207ba
--- /dev/null
+++ b/DFe.Testes/Gerais/Code128HibridoTestes.cs
@@ -0,0 +1,252 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using NFe.Danfe.PdfClown.Tools;
+
+namespace DFe.Testes.Gerais
+{
+ ///
+ /// Testes do codificador CODE-128 híbrido (subconjuntos C e A) da seção 6 da NT Conjunta 2025.001,
+ /// usado no código de barras da chave de acesso do DANFE
+ ///
+ [TestClass]
+ public class Code128HibridoTestes
+ {
+ private const byte StartC = 105;
+ private const byte TrocaParaCodeA = 101;
+ private const byte TrocaParaCodeC = 99;
+ private const byte Stop = 106;
+
+ #region Exemplos literais da NT Conjunta 2025.001 - seção 6
+
+ [TestMethod]
+ public void ObterSimbolos_ExemploLiteralDaNT_5225AB83()
+ {
+ // Arrange - sequência completa dada pela NT: start, dados, DV 30 e stop
+ var esperado = new byte[] { 105, 52, 25, 101, 33, 34, 99, 83, 30, 106 };
+
+ // Act
+ var simbolos = Code128Hibrido.ObterSimbolos("5225AB83");
+
+ // Assert
+ CollectionAssert.AreEqual(esperado, simbolos);
+ }
+
+ [TestMethod]
+ public void ObterSimbolos_ExemploLiteralDaNT_123A()
+ {
+ // Arrange - "12" em Code C, troca para o Code A (101), '3' (19) e 'A' (33) no Code A
+ var dadosEsperados = new byte[] { 105, 12, 101, 19, 33 };
+
+ // Act
+ var simbolos = Code128Hibrido.ObterSimbolos("123A");
+
+ // Assert
+ CollectionAssert.AreEqual(dadosEsperados, simbolos.Take(5).ToArray());
+ AssertDigitoVerificadorEStop(simbolos);
+ }
+
+ #endregion
+
+ #region Chave de acesso com CNPJ alfanumérico
+
+ [TestMethod]
+ public void ObterSimbolos_ChaveDeAcessoAlfanumericaDoVetorOuro_CodificaConformeAsRegrasDaNT()
+ {
+ // Arrange
+ //6 dígitos iniciais em Code C (3 pares); letras e corridas curtas do CNPJ no Code A;
+ //corrida final de 30 dígitos de volta ao Code C (15 pares)
+ var dadosEsperados = new byte[]
+ {
+ 105, //Start C
+ 52, 25, 7, //"522507"
+ 101, //troca para Code A
+ 48, 35, //'P' 'C'
+ 19, //'3' (corrida de 1 dígito fica no Code A)
+ 36, //'D'
+ 19, 17, 21, //'3' '1' '5' (corrida de 3 dígitos fica no Code A)
+ 43, //'K'
+ 99, //volta ao Code C (corrida final par)
+ 0, 1, 93, 55, 0, 10, 0, 0, 0, 1, 10, 0, 0, 0, 18
+ };
+
+ // Act
+ var simbolos = Code128Hibrido.ObterSimbolos("522507PC3D315K000193550010000000011000000018");
+
+ // Assert
+ CollectionAssert.AreEqual(dadosEsperados, simbolos.Take(dadosEsperados.Length).ToArray());
+ AssertDigitoVerificadorEStop(simbolos);
+ }
+
+ #endregion
+
+ #region Regressão - conteúdo 100% numérico deve gerar exatamente o CODE-128 C puro
+
+ [TestMethod]
+ public void ObterSimbolos_ComChavesNumericas_IdenticoAoCode128CPuroDaImplementacaoAntiga()
+ {
+ var chavesNumericas = new[]
+ {
+ "23190811820016000167650010000000221100000227",
+ "11222333000181112223330001811122233300018111",
+ "00000000000000000000000000000000000000000000",
+ "99999999999999999999999999999999999999999999",
+ "35150300822602000124550010009923461099234656"
+ };
+
+ foreach (var chave in chavesNumericas)
+ {
+ // Act
+ var simbolos = Code128Hibrido.ObterSimbolos(chave);
+
+ // Assert
+ CollectionAssert.AreEqual(CodificarCode128CPuroLegado(chave), simbolos, "Divergência na chave {0}", chave);
+ }
+ }
+
+ #endregion
+
+ #region Regras de troca de subconjunto
+
+ [TestMethod]
+ public void ObterSimbolos_ComLetraInicial_TrocaParaCodeAAposOStartC()
+ {
+ var simbolos = Code128Hibrido.ObterSimbolos("A");
+
+ CollectionAssert.AreEqual(new byte[] { StartC, TrocaParaCodeA, 33 }, simbolos.Take(3).ToArray());
+ AssertDigitoVerificadorEStop(simbolos);
+ }
+
+ [TestMethod]
+ public void ObterSimbolos_CorridaDe4DigitosEntreLetras_VoltaAoCodeC()
+ {
+ //"AB" no Code A, "1234" volta ao Code C (2 pares), "CD" troca novamente para o Code A
+ var simbolos = Code128Hibrido.ObterSimbolos("AB1234CD");
+
+ CollectionAssert.AreEqual(new byte[] { StartC, TrocaParaCodeA, 33, 34, TrocaParaCodeC, 12, 34, TrocaParaCodeA, 35, 36 }, simbolos.Take(10).ToArray());
+ AssertDigitoVerificadorEStop(simbolos);
+ }
+
+ [TestMethod]
+ public void ObterSimbolos_CorridaDe3DigitosEntreLetras_PermaneceNoCodeA()
+ {
+ //corrida curta (menos de 4 dígitos) não justifica a troca
+ var simbolos = Code128Hibrido.ObterSimbolos("AB123C");
+
+ CollectionAssert.AreEqual(new byte[] { StartC, TrocaParaCodeA, 33, 34, 17, 18, 19, 35 }, simbolos.Take(8).ToArray());
+ AssertDigitoVerificadorEStop(simbolos);
+ }
+
+ [TestMethod]
+ public void ObterSimbolos_CorridaImparDe5DigitosAntesDeLetra_UltimoDigitoFicaNoCodeA()
+ {
+ //"12345" antes de letra: pares "12" "34" no Code C e o dígito ímpar '5' fica no Code A
+ var simbolos = Code128Hibrido.ObterSimbolos("AB12345C");
+
+ CollectionAssert.AreEqual(new byte[] { StartC, TrocaParaCodeA, 33, 34, TrocaParaCodeC, 12, 34, TrocaParaCodeA, 21, 35 }, simbolos.Take(10).ToArray());
+ AssertDigitoVerificadorEStop(simbolos);
+ }
+
+ [TestMethod]
+ public void ObterSimbolos_CorridaFinalParDe2Digitos_VoltaAoCodeC()
+ {
+ //final com quantidade par de dígitos volta ao Code C, como no exemplo 5225AB83 da NT
+ var simbolos = Code128Hibrido.ObterSimbolos("AB12");
+
+ CollectionAssert.AreEqual(new byte[] { StartC, TrocaParaCodeA, 33, 34, TrocaParaCodeC, 12 }, simbolos.Take(6).ToArray());
+ AssertDigitoVerificadorEStop(simbolos);
+ }
+
+ [TestMethod]
+ public void ObterSimbolos_CorridaFinalImparDe3Digitos_PermaneceNoCodeA()
+ {
+ var simbolos = Code128Hibrido.ObterSimbolos("AB123");
+
+ CollectionAssert.AreEqual(new byte[] { StartC, TrocaParaCodeA, 33, 34, 17, 18, 19 }, simbolos.Take(7).ToArray());
+ AssertDigitoVerificadorEStop(simbolos);
+ }
+
+ [TestMethod]
+ public void ObterSimbolos_CorridaFinalImparDe5Digitos_PrimeiroDigitoNoCodeAEDemaisNoCodeC()
+ {
+ //corrida final ímpar de 4+ dígitos: um dígito fica no Code A para a parte restante ser par
+ var simbolos = Code128Hibrido.ObterSimbolos("AB12345");
+
+ CollectionAssert.AreEqual(new byte[] { StartC, TrocaParaCodeA, 33, 34, 17, TrocaParaCodeC, 23, 45 }, simbolos.Take(8).ToArray());
+ AssertDigitoVerificadorEStop(simbolos);
+ }
+
+ [TestMethod]
+ public void ObterSimbolos_NumericoImpar_ParesNoCodeCEUltimoDigitoNoCodeA()
+ {
+ var simbolos = Code128Hibrido.ObterSimbolos("123");
+
+ CollectionAssert.AreEqual(new byte[] { StartC, 12, TrocaParaCodeA, 19 }, simbolos.Take(4).ToArray());
+ AssertDigitoVerificadorEStop(simbolos);
+ }
+
+ #endregion
+
+ #region Entradas inválidas
+
+ [TestMethod]
+ [DataRow("")]
+ [DataRow(null)]
+ public void ObterSimbolos_ComCodigoVazioOuNulo_LancaArgumentException(string codigo)
+ {
+ Assert.ThrowsException(() => Code128Hibrido.ObterSimbolos(codigo));
+ }
+
+ [TestMethod]
+ [DataRow("12a4", DisplayName = "Letra minúscula")]
+ [DataRow("12-4", DisplayName = "Hífen")]
+ [DataRow("12 34", DisplayName = "Espaço")]
+ [DataRow("12@34", DisplayName = "Caractere @")]
+ public void ObterSimbolos_ComCaractereForaDeDigitosELetrasMaiusculas_LancaArgumentException(string codigo)
+ {
+ Assert.ThrowsException(() => Code128Hibrido.ObterSimbolos(codigo));
+ }
+
+ #endregion
+
+ ///
+ /// Confere as duas últimas posições da sequência: o DV módulo 103
+ /// (soma ponderada com o start valendo peso 1) e o símbolo de Stop (106)
+ ///
+ private static void AssertDigitoVerificadorEStop(byte[] simbolos)
+ {
+ Assert.AreEqual(Stop, simbolos[simbolos.Length - 1], "O último símbolo deve ser o Stop (106)");
+
+ var soma = (int)simbolos[0];
+ for (var i = 1; i < simbolos.Length - 2; i++)
+ soma += i * simbolos[i];
+
+ Assert.AreEqual((byte)(soma % 103), simbolos[simbolos.Length - 2], "Dígito verificador módulo 103 incorreto");
+ }
+
+ ///
+ /// Comportamento da implementação antiga (Barcode128C do DANFE PdfClown): Start C,
+ /// dados aos pares, DV módulo 103 e Stop - referência de regressão para conteúdo numérico
+ ///
+ private static byte[] CodificarCode128CPuroLegado(string codigo)
+ {
+ var codeBytes = new List { 105 };
+
+ for (var i = 0; i < codigo.Length; i += 2)
+ codeBytes.Add(byte.Parse(codigo.Substring(i, 2)));
+
+ var cd = 105;
+ for (var i = 1; i < codeBytes.Count; i++)
+ {
+ cd += i * codeBytes[i];
+ cd %= 103;
+ }
+
+ codeBytes.Add((byte)cd);
+ codeBytes.Add(106);
+
+ return codeBytes.ToArray();
+ }
+ }
+}
diff --git a/DFe.Testes/Gerais/DanfePdfClownChaveAlfanumericaTestes.cs b/DFe.Testes/Gerais/DanfePdfClownChaveAlfanumericaTestes.cs
new file mode 100644
index 000000000..1599753fa
--- /dev/null
+++ b/DFe.Testes/Gerais/DanfePdfClownChaveAlfanumericaTestes.cs
@@ -0,0 +1,76 @@
+using System;
+using System.IO;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using NFe.Danfe.PdfClown;
+using NFe.Danfe.PdfClown.Modelo;
+
+namespace DFe.Testes.Gerais
+{
+ ///
+ /// Smoke test do DANFE PdfClown: o PDF deve ser gerado com o código de barras CODE-128 híbrido
+ /// tanto para chave 100% numérica (fluxo antigo) quanto para chave com CNPJ alfanumérico
+ ///
+ [TestClass]
+ public class DanfePdfClownChaveAlfanumericaTestes
+ {
+ private static DanfeViewModel CriarViewModelMinimo(string chaveAcesso)
+ {
+ var model = new DanfeViewModel
+ {
+ ChaveAcesso = chaveAcesso,
+ NfNumero = 1,
+ NfSerie = 1,
+ TipoNF = 1,
+ TipoAmbiente = 2,
+ DataHoraEmissao = new DateTime(2025, 7, 15),
+ NaturezaOperacao = "VENDA",
+ ProtocoloAutorizacao = "352250000000001 15/07/2025 10:00:00"
+ };
+
+ model.Emitente.RazaoSocial = "EMITENTE DE TESTE LTDA";
+ model.Emitente.CnpjCpf = chaveAcesso.Substring(6, 14);
+ model.Emitente.EnderecoLogadrouro = "RUA DE TESTE";
+ model.Emitente.EnderecoNumero = "1";
+ model.Emitente.EnderecoBairro = "CENTRO";
+ model.Emitente.Municipio = "GOIANIA";
+ model.Emitente.EnderecoUf = "GO";
+ model.Emitente.EnderecoCep = "74000000";
+
+ model.Destinatario.RazaoSocial = "DESTINATARIO DE TESTE";
+ model.Destinatario.CnpjCpf = "11222333000181";
+ model.Destinatario.EnderecoLogadrouro = "AVENIDA DE TESTE";
+ model.Destinatario.EnderecoNumero = "2";
+ model.Destinatario.EnderecoBairro = "CENTRO";
+ model.Destinatario.Municipio = "GOIANIA";
+ model.Destinatario.EnderecoUf = "GO";
+ model.Destinatario.EnderecoCep = "74000001";
+
+ return model;
+ }
+
+ [TestMethod]
+ [DataRow("522507PC3D315K000193550010000000011000000018", DisplayName = "Chave com CNPJ alfanumérico")]
+ [DataRow("23190811820016000167650010000000221100000227", DisplayName = "Chave numérica (regressão)")]
+ public void Gerar_DanfeComChave_ProduzPdf(string chaveAcesso)
+ {
+ // Arrange
+ var model = CriarViewModelMinimo(chaveAcesso);
+
+ using (var danfe = new DanfeDoc(model))
+ {
+ // Act
+ danfe.Gerar();
+
+ using (var ms = new MemoryStream())
+ {
+ danfe.Salvar(ms);
+
+ // Assert - PDF gerado, não vazio e com o cabeçalho %PDF
+ var bytes = ms.ToArray();
+ Assert.IsTrue(bytes.Length > 1000, "O PDF gerado está vazio ou pequeno demais ({0} bytes)", bytes.Length);
+ Assert.AreEqual("%PDF", System.Text.Encoding.ASCII.GetString(bytes, 0, 4));
+ }
+ }
+ }
+ }
+}
diff --git a/DFe.Testes/Gerais/FormatadorDanfeTestes.cs b/DFe.Testes/Gerais/FormatadorDanfeTestes.cs
new file mode 100644
index 000000000..f98d60239
--- /dev/null
+++ b/DFe.Testes/Gerais/FormatadorDanfeTestes.cs
@@ -0,0 +1,77 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using NFe.Danfe.PdfClown.Tools;
+
+namespace DFe.Testes.Gerais
+{
+ ///
+ /// Testes da formatação de CNPJ, CPF e chave de acesso do DANFE (PdfClown),
+ /// cobrindo documentos numéricos (fluxo antigo) e o CNPJ alfanumérico da NT Conjunta 2025.001
+ ///
+ [TestClass]
+ public class FormatadorDanfeTestes
+ {
+ #region FormatarCnpj
+
+ [TestMethod]
+ [DataRow("11222333000181", "11.222.333/0001-81", DisplayName = "CNPJ numérico")]
+ [DataRow("00000000000191", "00.000.000/0001-91", DisplayName = "CNPJ numérico com zeros")]
+ [DataRow("12ABC34501DE35", "12.ABC.345/01DE-35", DisplayName = "CNPJ alfanumérico da NT")]
+ [DataRow("PC3D315K000193", "PC.3D3.15K/0001-93", DisplayName = "CNPJ alfanumérico de teste da Receita")]
+ public void FormatarCnpj_ComCnpjSemMascara_AplicaAMascaraPosicional(string cnpj, string esperado)
+ {
+ Assert.AreEqual(esperado, Formatador.FormatarCnpj(cnpj));
+ }
+
+ [TestMethod]
+ [DataRow("11.222.333/0001-81", "11.222.333/0001-81", DisplayName = "Numérico já com máscara")]
+ [DataRow("12.ABC.345/01DE-35", "12.ABC.345/01DE-35", DisplayName = "Alfanumérico já com máscara")]
+ public void FormatarCnpj_ComCnpjJaFormatado_MantemAMascara(string cnpj, string esperado)
+ {
+ Assert.AreEqual(esperado, Formatador.FormatarCnpj(cnpj));
+ }
+
+ [TestMethod]
+ [DataRow("12abc34501de35", DisplayName = "Minúsculas não formatam")]
+ [DataRow("12ABC34501DEA5", DisplayName = "Letra nos DVs não formata")]
+ [DataRow("123", DisplayName = "Curto demais não formata")]
+ public void FormatarCnpj_ComConteudoForaDoPadrao_DevolveOTextoOriginal(string cnpj)
+ {
+ Assert.AreEqual(cnpj, Formatador.FormatarCnpj(cnpj));
+ }
+
+ #endregion
+
+ #region FormatarCpfCnpj
+
+ [TestMethod]
+ [DataRow("12345678901", "123.456.789-01", DisplayName = "CPF continua com máscara de CPF")]
+ [DataRow("11222333000181", "11.222.333/0001-81", DisplayName = "CNPJ numérico")]
+ [DataRow("12ABC34501DE35", "12.ABC.345/01DE-35", DisplayName = "CNPJ alfanumérico")]
+ public void FormatarCpfCnpj_EscolheAMascaraCorreta(string documento, string esperado)
+ {
+ Assert.AreEqual(esperado, Formatador.FormatarCpfCnpj(documento));
+ }
+
+ #endregion
+
+ #region FormatarChaveAcesso
+
+ [TestMethod]
+ public void FormatarChaveAcesso_ComChaveAlfanumerica_AgrupaDeQuatroEmQuatro()
+ {
+ var formatada = Formatador.FormatarChaveAcesso("522507PC3D315K000193550010000000011000000018");
+
+ Assert.AreEqual("5225 07PC 3D31 5K00 0193 5500 1000 0000 0110 0000 0018", formatada);
+ }
+
+ [TestMethod]
+ public void FormatarChaveAcesso_ComChaveNumerica_AgrupaDeQuatroEmQuatro()
+ {
+ var formatada = Formatador.FormatarChaveAcesso("23190811820016000167650010000000221100000227");
+
+ Assert.AreEqual("2319 0811 8200 1600 0167 6500 1000 0000 2211 0000 0227", formatada);
+ }
+
+ #endregion
+ }
+}
diff --git a/DFe.Testes/Gerais/ObterIdTestes.cs b/DFe.Testes/Gerais/ObterIdTestes.cs
new file mode 100644
index 000000000..2733d6e47
--- /dev/null
+++ b/DFe.Testes/Gerais/ObterIdTestes.cs
@@ -0,0 +1,61 @@
+using DFe.Classes.Entidades;
+using DFe.Classes.Flags;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using NFe.Classes.Servicos.Tipos;
+using NFe.Utils.Evento;
+using NFe.Utils.Inutilizacao;
+
+namespace DFe.Testes.Gerais
+{
+ ///
+ /// Vetores ouro do Id assinável de evento (infEvento/@Id) e de inutilização (infInut/@Id).
+ ///
+ /// Esses Ids também são calculados internamente pelos métodos que assinam (ServicosNFe). Se o formato
+ /// divergir, o digest da assinatura não bate e o SEFAZ rejeita — por isso os valores esperados aqui são
+ /// literais do layout, e não o resultado do próprio método.
+ ///
+ ///
+ [TestClass]
+ public class ObterIdTestes
+ {
+ /// Chave de NF-e (modelo 55) com CNPJ alfanumérico, conforme NT Conjunta 2025.001
+ private const string ChaveNFe = "522507PC3D315K000193550010000000011000000018";
+
+ /// Chave de NFC-e (modelo 65), 100% numérica
+ private const string ChaveNFCe = "23190811820016000167650010000000221100000227";
+
+ private const string CnpjNumerico = "11820016000167";
+ private const string CnpjAlfanumerico = "PC3D315K000193";
+
+ [TestMethod]
+ [DataRow(NFeTipoEvento.TeNfeCancelamento, ChaveNFe, 1, "ID110111" + ChaveNFe + "01",
+ DisplayName = "Cancelamento, chave com CNPJ alfanumérico")]
+ [DataRow(NFeTipoEvento.TeNfeCartaCorrecao, ChaveNFe, 2, "ID110110" + ChaveNFe + "02",
+ DisplayName = "Carta de Correção, 2ª sequência")]
+ [DataRow(NFeTipoEvento.TeMdCienciaDaOperacao, ChaveNFCe, 1, "ID210210" + ChaveNFCe + "01",
+ DisplayName = "Ciência da Operação, chave numérica")]
+ [DataRow(NFeTipoEvento.TeMdCienciaDaOperacao, ChaveNFCe, 11, "ID210210" + ChaveNFCe + "11",
+ DisplayName = "Sequência com 2 dígitos não recebe zero à esquerda")]
+ public void ObterIdEvento_SegueOLayout(NFeTipoEvento tpEvento, string chNFe, int nSeqEvento, string esperado)
+ {
+ Assert.AreEqual(esperado, Extevento.ObterId(tpEvento, chNFe, nSeqEvento));
+ }
+
+ [TestMethod]
+ [DataRow(ModeloDocumento.NFe, CnpjNumerico, 1, 1, 10,
+ "ID3525" + CnpjNumerico + "55" + "001" + "000000001" + "000000010",
+ DisplayName = "NF-e, modelo 55")]
+ [DataRow(ModeloDocumento.NFCe, CnpjNumerico, 1, 1, 10,
+ "ID3525" + CnpjNumerico + "65" + "001" + "000000001" + "000000010",
+ DisplayName = "NFC-e, modelo 65")]
+ [DataRow(ModeloDocumento.NFe, CnpjAlfanumerico, 12, 5, 5,
+ "ID3525" + CnpjAlfanumerico + "55" + "012" + "000000005" + "000000005",
+ DisplayName = "CNPJ alfanumérico, faixa de um número só")]
+ public void ObterIdInutilizacao_SegueOLayout(ModeloDocumento modelo, string cnpj, int serie,
+ int numeroInicial, int numeroFinal, string esperado)
+ {
+ Assert.AreEqual(esperado,
+ ExtinutNFe.ObterId(Estado.SP, 25, cnpj, modelo, serie, numeroInicial, numeroFinal));
+ }
+ }
+}
diff --git a/DFe.Utils/Assinatura/CertificadoDigital.cs b/DFe.Utils/Assinatura/CertificadoDigital.cs
index 8104d944d..7f29bcbe0 100644
--- a/DFe.Utils/Assinatura/CertificadoDigital.cs
+++ b/DFe.Utils/Assinatura/CertificadoDigital.cs
@@ -52,9 +52,9 @@ public static class CertificadoDigital
///
///
///
- public static X509Store ObterX509Store(OpenFlags openFlags)
+ public static X509Store ObterX509Store(OpenFlags openFlags, StoreLocation storeLocation = StoreLocation.CurrentUser)
{
- var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
+ X509Store store = new X509Store(StoreName.My, storeLocation);
store.Open(openFlags);
return store;
}
@@ -89,7 +89,7 @@ private static X509Certificate2 ObterDoArrayBytes(byte[] arrayBytes, string senh
{
try
{
- var certificado = new X509Certificate2(arrayBytes, senha, keyStorageFlag);
+ X509Certificate2 certificado = new X509Certificate2(arrayBytes, senha, keyStorageFlag);
return certificado;
}
catch (Exception ex)
@@ -102,12 +102,12 @@ private static X509Certificate2 ObterDoArrayBytes(byte[] arrayBytes, string senh
/// Obtém um objeto pelo serial passado no parÂmetro
///
///
- private static X509Certificate2 ObterDoRepositorio(string serial, OpenFlags opcoesDeAbertura)
+ private static X509Certificate2 ObterDoRepositorio(string serial, OpenFlags opcoesDeAbertura, StoreLocation storeLocation = StoreLocation.CurrentUser)
{
if (string.IsNullOrEmpty(serial))
throw new ArgumentException("O número de série do certificado digital não foi informado!");
X509Certificate2 certificado = null;
- var store = ObterX509Store(opcoesDeAbertura);
+ var store = ObterX509Store(opcoesDeAbertura, storeLocation);
try
{
foreach (var item in store.Certificates)
@@ -133,9 +133,9 @@ private static X509Certificate2 ObterDoRepositorio(string serial, OpenFlags opco
///
///
///
- private static X509Certificate2 ObterDoRepositorioPassandoPin(string serial, string senha = null)
+ private static X509Certificate2 ObterDoRepositorioPassandoPin(string serial, string senha = null, StoreLocation storeLocation = StoreLocation.CurrentUser)
{
- var certificado = ObterDoRepositorio(serial, OpenFlags.ReadOnly);
+ var certificado = ObterDoRepositorio(serial, OpenFlags.ReadOnly, storeLocation);
if (string.IsNullOrEmpty(senha)) return certificado;
certificado.DefinirPinParaChavePrivada(senha);
return certificado;
@@ -187,13 +187,13 @@ private static X509Certificate2 ObterDadosCertificado(ConfiguracaoCertificado co
switch (configuracaoCertificado.TipoCertificado)
{
case TipoCertificado.A1Repositorio:
- return ObterDoRepositorio(configuracaoCertificado.Serial, OpenFlags.MaxAllowed);
+ return ObterDoRepositorio(configuracaoCertificado.Serial, OpenFlags.MaxAllowed, configuracaoCertificado.StoreLocation);
case TipoCertificado.A1ByteArray:
return ObterDoArrayBytes(configuracaoCertificado.ArrayBytesArquivo, configuracaoCertificado.Senha, configuracaoCertificado.KeyStorageFlags);
case TipoCertificado.A1Arquivo:
return ObterDeArquivo(configuracaoCertificado.Arquivo, configuracaoCertificado.Senha, configuracaoCertificado.KeyStorageFlags);
case TipoCertificado.A3:
- return ObterDoRepositorioPassandoPin(configuracaoCertificado.Serial, configuracaoCertificado.Senha);
+ return ObterDoRepositorioPassandoPin(configuracaoCertificado.Serial, configuracaoCertificado.Senha, configuracaoCertificado.StoreLocation);
default:
throw new ArgumentOutOfRangeException();
}
diff --git a/DFe.Utils/CertificadoDigitalUtils.cs b/DFe.Utils/CertificadoDigitalUtils.cs
index 178f71ea8..9b9067c37 100644
--- a/DFe.Utils/CertificadoDigitalUtils.cs
+++ b/DFe.Utils/CertificadoDigitalUtils.cs
@@ -16,9 +16,9 @@ public class CertificadoDigitalUtils
/// Exibe a lista de certificados instalados no PC e devolve o certificado selecionado
///
///
- public static X509Certificate2 ListareObterDoRepositorio()
+ public static X509Certificate2 ListareObterDoRepositorio(StoreLocation storeLocation = StoreLocation.CurrentUser)
{
- var store = CertificadoDigital.ObterX509Store(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
+ var store = CertificadoDigital.ObterX509Store(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly, storeLocation);
var collection = store.Certificates;
var fcollection = collection.Find(X509FindType.FindByTimeValid, DateTime.Now, true);
var scollection = X509Certificate2UI.SelectFromCollection(fcollection, "Certificados válidos:", "Selecione o certificado que deseja usar",
diff --git a/DFe.Utils/ChaveFiscal.cs b/DFe.Utils/ChaveFiscal.cs
index 30c7ed088..75cfe3dc6 100644
--- a/DFe.Utils/ChaveFiscal.cs
+++ b/DFe.Utils/ChaveFiscal.cs
@@ -57,16 +57,24 @@ public class ChaveFiscal
/// Retorna um objeto com os dados da chave de acesso
public static DadosChaveFiscal ObterChave(Estado ufEmitente, DateTimeOffset dataEmissao, string cnpjEmitente, ModeloDocumento modelo, int serie, long numero, int tipoEmissao, int cNf)
{
- var chave = new StringBuilder();
+ if (string.IsNullOrEmpty(cnpjEmitente))
+ throw new ArgumentException("O CNPJ/CPF do emitente deve ser informado.", "cnpjEmitente");
- if (cnpjEmitente.Length < 14)
- {
- cnpjEmitente = cnpjEmitente.PadLeft(14, '0');
- }
+ // NT Conjunta 2025.001: o CNPJ pode ser alfanumérico ([A-Z0-9]{12}[0-9]{2}) e ocupa 14 posições na chave.
+ // Somente CPF (11 posições) é completado com zeros à esquerda; qualquer outro comprimento seria um
+ // documento truncado e geraria uma chave bem-formada porém errada.
+ var documentoEmitente = cnpjEmitente.Length == 11 ? cnpjEmitente.PadLeft(14, '0') : cnpjEmitente;
+
+ if (documentoEmitente.Length != 14)
+ throw new ArgumentException(
+ string.Format("O documento do emitente deve ter 14 posições (CNPJ) ou 11 posições (CPF); o valor informado \"{0}\" tem {1}.", cnpjEmitente, cnpjEmitente.Length),
+ "cnpjEmitente");
+
+ var chave = new StringBuilder();
chave.Append(((int)ufEmitente).ToString("D2"))
.Append(dataEmissao.ToString("yyMM"))
- .Append(cnpjEmitente)
+ .Append(documentoEmitente)
.Append(((int)modelo).ToString("D2"))
.Append(serie.ToString("D3"))
.Append(numero.ToString("D9"))
@@ -116,15 +124,20 @@ private static string ObterDigitoVerificador(string chave)
}
///
- /// Obtem o valor de um caractere
+ /// Obtém o valor numérico de um caractere da chave para o cálculo do dígito verificador,
+ /// conforme a NT Conjunta 2025.001: valor = código ASCII - 48 ('0'-'9' => 0 a 9; 'A'-'Z' => 17 a 42)
///
///
///
internal static int ObterValorDoCaractere(char caractere)
{
- const int zeroASCII = 48;
- var valor = caractere - zeroASCII;
- return valor;
+ // A chave admite somente dígitos e letras maiúsculas; qualquer outro caractere
+ // (minúsculas, símbolos, ASCII 58-64) produziria um DV errado sem nenhum erro.
+ if ((caractere < '0' || caractere > '9') && (caractere < 'A' || caractere > 'Z'))
+ throw new ArgumentException(
+ string.Format("Caractere inválido na chave do DF-e: '{0}'. São aceitos somente dígitos (0-9) e letras maiúsculas (A-Z).", caractere));
+
+ return caractere - '0';
}
///
diff --git a/DFe.Utils/CnpjFiscal.cs b/DFe.Utils/CnpjFiscal.cs
new file mode 100644
index 000000000..27bbd6b5a
--- /dev/null
+++ b/DFe.Utils/CnpjFiscal.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace DFe.Utils
+{
+ ///
+ /// Classe com métodos para tratamento do CNPJ, incluindo o CNPJ alfanumérico da NT Conjunta 2025.001
+ /// (12 posições [A-Z0-9] + 2 dígitos verificadores numéricos)
+ ///
+ public static class CnpjFiscal
+ {
+ private static readonly Regex FormatoCnpj = new Regex("^[A-Z0-9]{12}[0-9]{2}$", RegexOptions.Compiled);
+ private static readonly Regex FormatoBaseCnpj = new Regex("^[A-Z0-9]{12}$", RegexOptions.Compiled);
+
+ ///
+ /// Calcula os dois dígitos verificadores para as 12 primeiras posições de um CNPJ,
+ /// conforme a NT Conjunta 2025.001: módulo 11 sobre o valor de cada caractere (código ASCII - 48),
+ /// com pesos de 2 a 9 aplicados da direita para a esquerda
+ ///
+ /// 12 primeiras posições do CNPJ ([A-Z0-9]{12})
+ /// Os dois dígitos verificadores, ex.: "93"
+ public static string ObterDigitosVerificadores(string cnpjBase)
+ {
+ if (cnpjBase == null)
+ throw new ArgumentNullException("cnpjBase");
+
+ if (!FormatoBaseCnpj.IsMatch(cnpjBase))
+ throw new ArgumentException(
+ string.Format("A base do CNPJ deve ter 12 posições contendo somente dígitos e letras maiúsculas; valor informado: \"{0}\".", cnpjBase),
+ "cnpjBase");
+
+ var dv1 = CalcularDigito(cnpjBase);
+ var dv2 = CalcularDigito(cnpjBase + dv1);
+
+ return string.Concat(dv1, dv2);
+ }
+
+ ///
+ /// Informa se um CNPJ de 14 posições é válido: formato [A-Z0-9]{12}[0-9]{2},
+ /// dígitos verificadores corretos e diferente do CNPJ zerado (vedado pela NT Conjunta 2025.001)
+ ///
+ /// CNPJ com 14 posições, sem máscara
+ public static bool Valido(string cnpj)
+ {
+ if (string.IsNullOrEmpty(cnpj) || !FormatoCnpj.IsMatch(cnpj))
+ return false;
+
+ //CNPJ zerado tem dígitos verificadores que conferem, mas é vedado
+ if (cnpj.All(c => c == '0'))
+ return false;
+
+ return cnpj.Substring(12, 2) == ObterDigitosVerificadores(cnpj.Substring(0, 12));
+ }
+
+ private static int CalcularDigito(string valor)
+ {
+ var soma = 0;
+ var peso = 2;
+
+ //pesos de 2 a 9, aplicados da direita para a esquerda
+ for (var i = valor.Length - 1; i != -1; i--)
+ {
+ //NT Conjunta 2025.001: valor do caractere = código ASCII - 48 ('0'-'9' => 0 a 9; 'A'-'Z' => 17 a 42)
+ soma += (valor[i] - '0') * peso;
+ peso = peso == 9 ? 2 : peso + 1;
+ }
+
+ var resto = soma % 11;
+ return resto < 2 ? 0 : 11 - resto;
+ }
+ }
+}
diff --git a/DFe.Utils/ConfiguracaoCertificado.cs b/DFe.Utils/ConfiguracaoCertificado.cs
index 158e28bf5..28ad75948 100644
--- a/DFe.Utils/ConfiguracaoCertificado.cs
+++ b/DFe.Utils/ConfiguracaoCertificado.cs
@@ -61,9 +61,11 @@ public class ConfiguracaoCertificado
private string _cacheId;
private byte[] _arrayBytesArquivo;
private X509KeyStorageFlags _keyStorageFlags;
+ private StoreLocation _storeLocation;
public ConfiguracaoCertificado()
{
+ StoreLocation = StoreLocation.CurrentUser;
KeyStorageFlags = X509KeyStorageFlags.MachineKeySet;
SignatureMethodSignedXml = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
DigestMethodReference = "http://www.w3.org/2000/09/xmldsig#sha1";
@@ -195,5 +197,19 @@ public X509KeyStorageFlags KeyStorageFlags
_keyStorageFlags = value;
}
}
+
+ ///
+ ///
+ ///
+ public StoreLocation StoreLocation
+ {
+ get { return _storeLocation; }
+ set
+ {
+ if (value == _storeLocation)
+ return;
+ _storeLocation = value;
+ }
+ }
}
}
diff --git a/MDFe.Servicos/EventosMDFe/Contratos/IServicoController.cs b/MDFe.Servicos/EventosMDFe/Contratos/IServicoController.cs
index 161ea4685..4f523579b 100644
--- a/MDFe.Servicos/EventosMDFe/Contratos/IServicoController.cs
+++ b/MDFe.Servicos/EventosMDFe/Contratos/IServicoController.cs
@@ -42,5 +42,7 @@ namespace MDFe.Servicos.EventosMDFe.Contratos
public interface IServicoController
{
MDFeRetEventoMDFe Executar(MDFeEletronico mdfe, byte sequenciaEvento, MDFeEventoContainer eventoContainer, MDFeTipoEvento tipoEvento, MDFeConfiguracao cfgMdfe = null);
+
+ MDFeRetEventoMDFe Executar(MDFeComandoEvento comando, MDFeEventoContainer eventoContainer, MDFeTipoEvento tipoEvento, MDFeConfiguracao cfgMdfe = null);
}
}
\ No newline at end of file
diff --git a/MDFe.Servicos/EventosMDFe/EventoCancelar.cs b/MDFe.Servicos/EventosMDFe/EventoCancelar.cs
index 4a9f55e5c..b74350df5 100644
--- a/MDFe.Servicos/EventosMDFe/EventoCancelar.cs
+++ b/MDFe.Servicos/EventosMDFe/EventoCancelar.cs
@@ -51,5 +51,12 @@ public MDFeRetEventoMDFe MDFeEventoCancelar(MDFeEletronico mdfe, byte sequenciaE
return retorno;
}
+
+ public MDFeRetEventoMDFe MDFeEventoCancelar(MDFeComandoCancelamento comando, MDFeConfiguracao cfgMdfe = null)
+ {
+ var config = cfgMdfe ?? MDFeConfiguracao.Instancia;
+ var evento = ClassesFactory.CriaEvCancMDFe(comando.Protocolo, comando.Justificativa);
+ return new ServicoController().Executar(comando, evento, MDFeTipoEvento.Cancelamento, config);
+ }
}
}
\ No newline at end of file
diff --git a/MDFe.Servicos/EventosMDFe/EventoEncerramento.cs b/MDFe.Servicos/EventosMDFe/EventoEncerramento.cs
index e7de8b41c..1ae049cba 100644
--- a/MDFe.Servicos/EventosMDFe/EventoEncerramento.cs
+++ b/MDFe.Servicos/EventosMDFe/EventoEncerramento.cs
@@ -63,5 +63,12 @@ public MDFeRetEventoMDFe MDFeEventoEncerramento(MDFeEletronico mdfe, Estado esta
return retorno;
}
+
+ public MDFeRetEventoMDFe MDFeEventoEncerramento(MDFeComandoEncerramento comando, MDFeConfiguracao cfgMdfe = null)
+ {
+ var config = cfgMdfe ?? MDFeConfiguracao.Instancia;
+ var evento = ClassesFactory.CriaEvEncMDFe(comando.EstadoEncerramento, comando.CodigoMunicipioEncerramento, comando.Protocolo);
+ return new ServicoController().Executar(comando, evento, MDFeTipoEvento.Encerramento, config);
+ }
}
}
\ No newline at end of file
diff --git a/MDFe.Servicos/EventosMDFe/EventoInclusaoCondutor.cs b/MDFe.Servicos/EventosMDFe/EventoInclusaoCondutor.cs
index 32d640724..c3798ff2a 100644
--- a/MDFe.Servicos/EventosMDFe/EventoInclusaoCondutor.cs
+++ b/MDFe.Servicos/EventosMDFe/EventoInclusaoCondutor.cs
@@ -46,10 +46,14 @@ public MDFeRetEventoMDFe MDFeEventoIncluirCondutor(MDFeEletronico mdfe, byte seq
var config = cfgMdfe ?? MDFeConfiguracao.Instancia;
var incluirCodutor = ClassesFactory.CriaEvIncCondutorMDFe(nome, cpf);
+ return new ServicoController().Executar(mdfe, sequenciaEvento, incluirCodutor, MDFeTipoEvento.InclusaoDeCondutor, config);
+ }
- var retorno = new ServicoController().Executar(mdfe, sequenciaEvento, incluirCodutor, MDFeTipoEvento.InclusaoDeCondutor, config);
-
- return retorno;
+ public MDFeRetEventoMDFe MDFeEventoIncluirCondutor(MDFeComandoInclusaoCondutor comando, MDFeConfiguracao cfgMdfe = null)
+ {
+ var config = cfgMdfe ?? MDFeConfiguracao.Instancia;
+ var evento = ClassesFactory.CriaEvIncCondutorMDFe(comando.Nome, comando.CpfCondutor);
+ return new ServicoController().Executar(comando, evento, MDFeTipoEvento.InclusaoDeCondutor, config);
}
}
}
\ No newline at end of file
diff --git a/MDFe.Servicos/EventosMDFe/EventoInclusaoDFe.cs b/MDFe.Servicos/EventosMDFe/EventoInclusaoDFe.cs
index 9dd35c33c..953f86882 100644
--- a/MDFe.Servicos/EventosMDFe/EventoInclusaoDFe.cs
+++ b/MDFe.Servicos/EventosMDFe/EventoInclusaoDFe.cs
@@ -49,8 +49,14 @@ public MDFeRetEventoMDFe MDFeEventoIncluirDFe(MDFeEletronico mdfe, byte sequenci
var config = cfgMdfe ?? MDFeConfiguracao.Instancia;
var inclusao = ClassesFactory.CriaEvIncDFeMDFe(protocolo, codigoMunicipioCarregamento, nomeMunicipioCarregamento, informacoesDocumentos);
-
return new ServicoController().Executar(mdfe, sequenciaEvento, inclusao, MDFeTipoEvento.InclusaoDFe, config);
}
+
+ public MDFeRetEventoMDFe MDFeEventoIncluirDFe(MDFeComandoInclusaoDFe comando, MDFeConfiguracao cfgMdfe = null)
+ {
+ var config = cfgMdfe ?? MDFeConfiguracao.Instancia;
+ var evento = ClassesFactory.CriaEvIncDFeMDFe(comando.Protocolo, comando.CodigoMunicipioCarregamento, comando.NomeMunicipioCarregamento, comando.InformacoesDocumentos);
+ return new ServicoController().Executar(comando, evento, MDFeTipoEvento.InclusaoDFe, config);
+ }
}
}
\ No newline at end of file
diff --git a/MDFe.Servicos/EventosMDFe/EventoPagamentoOperacao.cs b/MDFe.Servicos/EventosMDFe/EventoPagamentoOperacao.cs
index 26e27ef71..21ba82430 100644
--- a/MDFe.Servicos/EventosMDFe/EventoPagamentoOperacao.cs
+++ b/MDFe.Servicos/EventosMDFe/EventoPagamentoOperacao.cs
@@ -47,15 +47,18 @@ public MDFeRetEventoMDFe MDFeEventoPagamentoOperacao(Classes.Informacoes.MDFe md
{
var config = cfgMdfe ?? MDFeConfiguracao.Instancia;
- var eventoPagamento = ClassesFactory.CriaEvPagtoOperMDFe(
- protocolo,
- infViagens,
- infPagamentos
- );
+ var eventoPagamento = ClassesFactory.CriaEvPagtoOperMDFe(protocolo, infViagens, infPagamentos);
var retorno = new ServicoController().Executar(mdfe, sequencia, eventoPagamento, MDFeTipoEvento.PagamentoOperacaoMDFe, config);
return retorno;
}
+
+ public MDFeRetEventoMDFe MDFeEventoPagamentoOperacao(MDFeComandoPagamentoOperacao comando, MDFeConfiguracao cfgMdfe = null)
+ {
+ var config = cfgMdfe ?? MDFeConfiguracao.Instancia;
+ var evento = ClassesFactory.CriaEvPagtoOperMDFe(comando.Protocolo, comando.InfViagens, comando.Pagamentos);
+ return new ServicoController().Executar(comando, evento, MDFeTipoEvento.PagamentoOperacaoMDFe, config);
+ }
}
}
\ No newline at end of file
diff --git a/MDFe.Servicos/EventosMDFe/FactoryEvento.cs b/MDFe.Servicos/EventosMDFe/FactoryEvento.cs
index f566c4bf0..416ae76a4 100644
--- a/MDFe.Servicos/EventosMDFe/FactoryEvento.cs
+++ b/MDFe.Servicos/EventosMDFe/FactoryEvento.cs
@@ -78,5 +78,40 @@ public static MDFeEventoMDFe CriaEvento(MDFeEletronico MDFe, MDFeTipoEvento tipo
return eventoMDFe;
}
+
+ public static MDFeEventoMDFe CriaEvento(MDFeComandoEvento comando, MDFeTipoEvento tipoEvento, MDFeEventoContainer evento, MDFeConfiguracao cfgMdfe = null)
+ {
+ var config = cfgMdfe ?? MDFeConfiguracao.Instancia;
+ var eventoMDFe = new MDFeEventoMDFe
+ {
+ Versao = config.VersaoWebService.VersaoLayout,
+ InfEvento = new MDFeInfEvento(config.VersaoWebService.VersaoLayout)
+ {
+ Id = "ID" + (long)tipoEvento + comando.Chave + comando.SequenciaEvento.ToString("D2"),
+ TpAmb = config.VersaoWebService.TipoAmbiente,
+ COrgao = comando.UfEmitente,
+ ChMDFe = comando.Chave,
+ DetEvento = new MDFeDetEvento
+ {
+ VersaoServico = config.VersaoWebService.VersaoLayout,
+ EventoContainer = evento
+ },
+ DhEvento = DateTime.Now,
+ NSeqEvento = comando.SequenciaEvento,
+ TpEvento = tipoEvento
+ }
+ };
+
+ eventoMDFe.InfEvento.CNPJ = comando.CnpjEmitente;
+
+ if (!string.IsNullOrEmpty(comando.CpfEmitente))
+ {
+ eventoMDFe.InfEvento.CPF = comando.CpfEmitente;
+ }
+
+ eventoMDFe.Assinar(config);
+
+ return eventoMDFe;
+ }
}
}
\ No newline at end of file
diff --git a/MDFe.Servicos/EventosMDFe/MDFeComandoCancelamento.cs b/MDFe.Servicos/EventosMDFe/MDFeComandoCancelamento.cs
new file mode 100644
index 000000000..f93c59411
--- /dev/null
+++ b/MDFe.Servicos/EventosMDFe/MDFeComandoCancelamento.cs
@@ -0,0 +1,11 @@
+namespace MDFe.Servicos.EventosMDFe
+{
+ ///
+ /// Dados para emitir o evento de cancelamento de MDFe.
+ ///
+ public class MDFeComandoCancelamento : MDFeComandoEvento
+ {
+ public string Protocolo { get; set; }
+ public string Justificativa { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/MDFe.Servicos/EventosMDFe/MDFeComandoEncerramento.cs b/MDFe.Servicos/EventosMDFe/MDFeComandoEncerramento.cs
new file mode 100644
index 000000000..91c165bb9
--- /dev/null
+++ b/MDFe.Servicos/EventosMDFe/MDFeComandoEncerramento.cs
@@ -0,0 +1,14 @@
+using DFe.Classes.Entidades;
+
+namespace MDFe.Servicos.EventosMDFe
+{
+ ///
+ /// Dados para emitir o evento de encerramento de MDFe.
+ ///
+ public class MDFeComandoEncerramento : MDFeComandoEvento
+ {
+ public string Protocolo { get; set; }
+ public Estado EstadoEncerramento { get; set; }
+ public long CodigoMunicipioEncerramento { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/MDFe.Servicos/EventosMDFe/MDFeComandoEvento.cs b/MDFe.Servicos/EventosMDFe/MDFeComandoEvento.cs
new file mode 100644
index 000000000..5c3d60faa
--- /dev/null
+++ b/MDFe.Servicos/EventosMDFe/MDFeComandoEvento.cs
@@ -0,0 +1,18 @@
+using DFe.Classes.Entidades;
+
+namespace MDFe.Servicos.EventosMDFe
+{
+ ///
+ /// Base abstrata com os dados mínimos necessários
+ /// para emitir um evento de MDFe sem depender
+ /// do objeto "" completo.
+ ///
+ public abstract class MDFeComandoEvento
+ {
+ public string Chave { get; set; }
+ public Estado UfEmitente { get; set; }
+ public string CnpjEmitente { get; set; }
+ public string CpfEmitente { get; set; }
+ public byte SequenciaEvento { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/MDFe.Servicos/EventosMDFe/MDFeComandoInclusaoCondutor.cs b/MDFe.Servicos/EventosMDFe/MDFeComandoInclusaoCondutor.cs
new file mode 100644
index 000000000..80dd508f1
--- /dev/null
+++ b/MDFe.Servicos/EventosMDFe/MDFeComandoInclusaoCondutor.cs
@@ -0,0 +1,11 @@
+namespace MDFe.Servicos.EventosMDFe
+{
+ ///
+ /// Dados para emitir o evento de inclusão de condutor no MDFe.
+ ///
+ public class MDFeComandoInclusaoCondutor : MDFeComandoEvento
+ {
+ public string Nome { get; set; }
+ public string CpfCondutor { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/MDFe.Servicos/EventosMDFe/MDFeComandoInclusaoDFe.cs b/MDFe.Servicos/EventosMDFe/MDFeComandoInclusaoDFe.cs
new file mode 100644
index 000000000..aa4dcda39
--- /dev/null
+++ b/MDFe.Servicos/EventosMDFe/MDFeComandoInclusaoDFe.cs
@@ -0,0 +1,16 @@
+using MDFe.Classes.Informacoes.Evento.CorpoEvento;
+using System.Collections.Generic;
+
+namespace MDFe.Servicos.EventosMDFe
+{
+ ///
+ /// Dados para emitir o evento de inclusão de DF-e no MDFe.
+ ///
+ public class MDFeComandoInclusaoDFe : MDFeComandoEvento
+ {
+ public string Protocolo { get; set; }
+ public string CodigoMunicipioCarregamento { get; set; }
+ public string NomeMunicipioCarregamento { get; set; }
+ public List InformacoesDocumentos { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/MDFe.Servicos/EventosMDFe/MDFeComandoPagamentoOperacao.cs b/MDFe.Servicos/EventosMDFe/MDFeComandoPagamentoOperacao.cs
new file mode 100644
index 000000000..5e3615fd1
--- /dev/null
+++ b/MDFe.Servicos/EventosMDFe/MDFeComandoPagamentoOperacao.cs
@@ -0,0 +1,15 @@
+using MDFe.Classes.Informacoes;
+using System.Collections.Generic;
+
+namespace MDFe.Servicos.EventosMDFe
+{
+ ///
+ /// Dados para emitir o evento de pagamento de operação de transporte.
+ ///
+ public class MDFeComandoPagamentoOperacao : MDFeComandoEvento
+ {
+ public string Protocolo { get; set; }
+ public MDFeInfViagens InfViagens { get; set; }
+ public List Pagamentos { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/MDFe.Servicos/EventosMDFe/ServicoController.cs b/MDFe.Servicos/EventosMDFe/ServicoController.cs
index 72bf4a0c7..5a32c60f0 100644
--- a/MDFe.Servicos/EventosMDFe/ServicoController.cs
+++ b/MDFe.Servicos/EventosMDFe/ServicoController.cs
@@ -67,5 +67,22 @@ public MDFeRetEventoMDFe Executar(MDFeEletronico mdfe, byte sequenciaEvento, MDF
return retorno;
}
+
+ public MDFeRetEventoMDFe Executar(MDFeComandoEvento comando, MDFeEventoContainer eventoContainer, MDFeTipoEvento tipoEvento, MDFeConfiguracao cfgMdfe = null)
+ {
+ var config = cfgMdfe ?? MDFeConfiguracao.Instancia;
+ var evento = FactoryEvento.CriaEvento(comando, tipoEvento, eventoContainer, config);
+
+ evento.ValidarSchema(config);
+ evento.SalvarXmlEmDisco(comando.Chave, config);
+
+ var webService = WsdlFactory.CriaWsdlMDFeRecepcaoEvento(config);
+ var retornoXml = webService.mdfeRecepcaoEvento(evento.CriaXmlRequestWs());
+
+ var retorno = MDFeRetEventoMDFe.LoadXml(retornoXml.OuterXml, evento);
+ retorno.SalvarXmlEmDisco(comando.Chave, config);
+
+ return retorno;
+ }
}
}
\ No newline at end of file
diff --git a/MDFe.Servicos/EventosMDFe/ServicoMDFeEvento.cs b/MDFe.Servicos/EventosMDFe/ServicoMDFeEvento.cs
index 653dae482..78b9a3fa1 100644
--- a/MDFe.Servicos/EventosMDFe/ServicoMDFeEvento.cs
+++ b/MDFe.Servicos/EventosMDFe/ServicoMDFeEvento.cs
@@ -54,6 +54,11 @@ public MDFeRetEventoMDFe MDFeEventoIncluirCondutor(
return eventoIncluirCondutor.MDFeEventoIncluirCondutor(mdfe, sequenciaEvento, nome, cpf, config);
}
+ public MDFeRetEventoMDFe MDFeEventoIncluirCondutor(MDFeComandoInclusaoCondutor cmd, MDFeConfiguracao cfgMdfe = null)
+ {
+ return new EventoInclusaoCondutor().MDFeEventoIncluirCondutor(cmd, cfgMdfe);
+ }
+
public MDFeRetEventoMDFe MDFeEventoIncluirDFe(
MDFeEletronica mdfe, byte sequenciaEvento, string protocolo,
string codigoMunicipioCarregamento, string nomeMunicipioCarregamento, List informacoesDocumentos,
@@ -66,6 +71,11 @@ public MDFeRetEventoMDFe MDFeEventoIncluirDFe(
return eventoIncluirDFe.MDFeEventoIncluirDFe(mdfe, sequenciaEvento, protocolo, codigoMunicipioCarregamento, nomeMunicipioCarregamento, informacoesDocumentos, config);
}
+ public MDFeRetEventoMDFe MDFeEventoIncluirDFe(MDFeComandoInclusaoDFe cmd, MDFeConfiguracao cfgMdfe = null)
+ {
+ return new EventoInclusaoDFe().MDFeEventoIncluirDFe(cmd, cfgMdfe);
+ }
+
public MDFeRetEventoMDFe MDFeEventoEncerramentoMDFeEventoEncerramento(MDFeEletronica mdfe, byte sequenciaEvento, string protocolo, MDFeConfiguracao cfgMdfe = null)
{
var config = cfgMdfe ?? MDFeConfiguracao.Instancia;
@@ -85,6 +95,11 @@ public MDFeRetEventoMDFe MDFeEventoEncerramentoMDFeEventoEncerramento(MDFeEletro
return eventoEncerramento.MDFeEventoEncerramento(mdfe, estadoEncerramento, codigoMunicipioEncerramento, sequenciaEvento, protocolo, config);
}
+ public MDFeRetEventoMDFe MDFeEventoEncerramentoMDFeEventoEncerramento(MDFeComandoEncerramento cmd, MDFeConfiguracao cfgMdfe = null)
+ {
+ return new EventoEncerramento().MDFeEventoEncerramento(cmd, cfgMdfe);
+ }
+
public MDFeRetEventoMDFe MDFeEventoCancelar(MDFeEletronica mdfe, byte sequenciaEvento, string protocolo,
string justificativa, MDFeConfiguracao cfgMdfe = null)
{
@@ -95,6 +110,11 @@ public MDFeRetEventoMDFe MDFeEventoCancelar(MDFeEletronica mdfe, byte sequenciaE
return eventoCancelamento.MDFeEventoCancelar(mdfe, sequenciaEvento, protocolo, justificativa, config);
}
+ public MDFeRetEventoMDFe MDFeEventoCancelar(MDFeComandoCancelamento cmd, MDFeConfiguracao cfgMdfe = null)
+ {
+ return new EventoCancelar().MDFeEventoCancelar(cmd, cfgMdfe);
+ }
+
public MDFeRetEventoMDFe MDFeEventoPagamentoOperacaoTransporte(MDFeEletronica mdfe, byte sequenciaEvneto,
string protocolo, MDFeInfViagens infViagens, List infPagamentos, MDFeConfiguracao cfgMdfe = null)
{
@@ -105,5 +125,10 @@ public MDFeRetEventoMDFe MDFeEventoPagamentoOperacaoTransporte(MDFeEletronica md
return eventoPagamentoOperacao.MDFeEventoPagamentoOperacao(mdfe, sequenciaEvneto, protocolo,
infViagens, infPagamentos, config);
}
+
+ public MDFeRetEventoMDFe MDFeEventoPagamentoOperacaoTransporte(MDFeComandoPagamentoOperacao cmd, MDFeConfiguracao cfgMdfe = null)
+ {
+ return new EventoPagamentoOperacao().MDFeEventoPagamentoOperacao(cmd, cfgMdfe);
+ }
}
}
\ No newline at end of file
diff --git a/NFe.AppTeste/MainWindow.xaml.cs b/NFe.AppTeste/MainWindow.xaml.cs
index df1180be2..38b287f21 100644
--- a/NFe.AppTeste/MainWindow.xaml.cs
+++ b/NFe.AppTeste/MainWindow.xaml.cs
@@ -1870,7 +1870,8 @@ protected virtual dest GetDestinatario(VersaoServico versao, ModeloDocumento mod
{
var dest = new dest(versao)
{
- CNPJ = "99999999000191",
+ CNPJ = "0ZEN3MS8000127",
+ //CNPJ = "99999999000191",
//CPF = "99999999999",
};
dest.xNome = "NF-E EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL"; //Obrigatório para NFe e opcional para NFCe
@@ -2106,7 +2107,7 @@ protected virtual det GetDetalhe(int i, CRT crt, ModeloDocumento modelo)
{
qTrib = 1,
uTrib = "PC",
- pISEspec = 0,
+ adRemIS = 0,
pIS = 0,
vIS = 0,
cClassTribIS = "000001",
@@ -2593,18 +2594,15 @@ private void BtnAdminCsc_Click(object sender, RoutedEventArgs e)
var raizCnpj = Funcoes.InpuBox(
this,
"Administração do CSC",
- "Raiz do CNPJ do contribuinte que está efetuando a consulta (oito primeiros dígitos do CNPJ):"
+ "Raiz do CNPJ do contribuinte que está efetuando a consulta (oito primeiras posições do CNPJ):"
);
if (string.IsNullOrEmpty(raizCnpj))
throw new Exception("A Raiz do CNPJ do contribuinte deve ser informada!");
- long l;
- var longo = long.TryParse(raizCnpj, out l);
- if (!longo)
+ //NT Conjunta 2025.001: o CNPJ pode ser alfanumérico nas 12 primeiras posições
+ if (!System.Text.RegularExpressions.Regex.IsMatch(raizCnpj, "^[0-9A-Z]{8}$"))
throw new Exception(
- "A Raiz do CNPJ do contribuinte deve conter apenas números!"
+ "A Raiz do CNPJ do contribuinte deve conter 8 caracteres, apenas números e letras maiúsculas!"
);
- if (raizCnpj.Length != 8)
- throw new Exception("A Raiz do CNPJ do contribuinte deve conter 8 caracteres!");
var idCsc = "";
var codigoCsc = "";
diff --git a/NFe.AppTeste/Schemas/DFeTiposBasicos_v1.00.xsd b/NFe.AppTeste/Schemas/DFeTiposBasicos_v1.00.xsd
index a5051dd02..d204e4061 100644
--- a/NFe.AppTeste/Schemas/DFeTiposBasicos_v1.00.xsd
+++ b/NFe.AppTeste/Schemas/DFeTiposBasicos_v1.00.xsd
@@ -1,6 +1,16 @@
+
+
+ Tipo Chave de Documento Fiscal Eletrônico
+
+
+
+
+
+
+
Tipo string genérico
@@ -55,6 +65,24 @@
+
+
+ Tipo CNPJ Base
+
+
+
+
+
+
+
+
+ Tipo CNPJ
+
+
+
+
+
+
Tipo Decimal com 15 dígitos, sendo 13 de corpo e 2 decimais
@@ -81,6 +109,23 @@
+
+
+
+
+
+
+ Tipo de Receita Bruta do SN
+
+
+
+
+
+
+
+
+
+
@@ -93,6 +138,8 @@
+
+
@@ -115,6 +162,14 @@
+
+
+ Ano e mês referência do período de apuração (AAAA-MM)
+
+
+
+
+
Grupo de informações da Tributação da NFCom
@@ -163,6 +218,26 @@
+
+
+ Grupo de informações da Tributação da NFGas
+
+
+
+
+ Código Situação Tributária do IBS/CBS
+
+
+
+
+
+
+
+ Informado conforme indicador no cClassTrib
+
+
+
+
Grupo de informações da Tributação da NFAg
@@ -240,7 +315,7 @@
-
+
@@ -262,7 +337,7 @@
-
+
Informar essa opção da Choice para Monofasia (CST 620)
@@ -298,33 +373,6 @@
-
-
- Grupo de informações da Tributação da NFGas
-
-
-
-
- Código Situação Tributária do IBS/CBS
-
-
-
-
-
-
-
-
- Informar essa opção da Choice para Monofasia
-
-
-
-
-
- Informado conforme indicador no cClassTrib
-
-
-
-
Grupo de informações do Imposto Seletivo
@@ -347,7 +395,7 @@
Alíquota do Imposto Seletivo (percentual)
-
+
Alíquota do Imposto Seletivo (por valor)
@@ -949,6 +997,152 @@
Grupo de campos da redução de aliquota
+
+
+ Grupo de operações em áreas incentivadas (ALC/ZFM) - CBS (alíquota zero)
+ Grupo de informações para identificação de operações em áreas incentivadas (ALC/ZFM) com alíquota zero da CBS, conforme arts. 451 e 466 da LC 214/2025, quando fornecedor e destinatário estiverem nessas áreas, distinguindo a existência de processo aprovado na Suframa.
+
+
+
+
+ Valor da CBS
+
+
+
+
+
+
+
+ Grupo de informações da Tributação Regular. Informar como seria a tributação caso não cumprida a condição resolutória/suspensiva. Exemplo 1: Art. 442, §4. Operações com ZFM e ALC. Exemplo 2: Operações com suspensão do tributo.
+
+
+
+
+ Grupo de informações da composição do valor do IBS e da CBS em compras governamental
+
+
+
+
+
+
+ Tipo CBS IBS Completo NFe
+
+
+
+ IBS / CBS
+
+
+
+ Valor do BC
+
+
+
+
+
+ Grupo de informações do IBS na UF
+
+
+
+
+
+ Aliquota do IBS de competência das UF (em percentual)
+
+
+
+
+ Grupo de campos do Diferimento
+
+
+
+
+ Grupo de Informações da devolução de tributos
+
+
+
+
+ Grupo de campos da redução de aliquota
+
+
+
+
+ Valor do IBS de competência das UF
+
+
+
+
+
+
+
+ Grupo de Informações do IBS no Município
+
+
+
+
+
+ Aliquota do IBS Municipal (em percentual)
+
+
+
+
+ Grupo de campos do Diferimento
+
+
+
+
+ Grupo de Informações da devolução de tributos
+
+
+
+
+ Grupo de campos da redução de aliquota
+
+
+
+
+ Valor do IBS Municipal
+
+
+
+
+
+
+
+ Valor do IBS
+
+
+
+
+
+ Grupo de Tributação da CBS
+
+
+
+
+
+ Aliquota da CBS (em percentual)
+
+
+
+
+ Grupo de campos do Diferimento
+
+
+
+
+ Grupo de Informações da devolução de tributos
+
+
+
+
+ Grupo de campos da redução de aliquota
+
+
+
+
+ Grupo de operações em áreas incentivadas (ALC/ZFM) - CBS (alíquota zero)
+ Grupo de informações para identificação de operações em áreas incentivadas (ALC/ZFM) com alíquota zero da CBS, conforme arts. 451 e 466 da LC 214/2025, quando fornecedor e destinatário estiverem nessas áreas, distinguindo a existência de processo aprovado na Suframa.
+
+
Valor da CBS
@@ -1032,10 +1226,14 @@
Tipo Devolução Tributo
+
+
+ Percentual de devolução do tributo, conforme LC 214/25 art. 118.
+
+
- Valor do tributo devolvido. No fornecimento de energia elétrica, água, esgoto e
-gás natural e em outras hipóteses definidas no regulamento
+ Valor do tributo devolvido ("cashback" de desconto na própria Nota Fiscal / Fatura)
@@ -1131,7 +1329,9 @@ gás natural e em outras hipóteses definidas no regulamento
1=União
2=Estados
3=Distrito Federal
-4=Municípios
+4=Municípios
+5=Consórcio Público
+6=Comitê Gestor do IBS
@@ -1139,6 +1339,29 @@ gás natural e em outras hipóteses definidas no regulamento
Percentual de redução de aliquota em compra governamental
+
+
+ Tipo da operação com ente governamental:
+1 – Fornecimento com pagamento posterior;
+
+2 - Recebimento do pagamento com fornecimento já realizado;
+
+3 – Fornecimento com pagamento já realizado;
+
+4 – Recebimento do pagamento com fornecimento posterior;
+
+
+
+
+ Chave de acesso do documento fiscal anterior.
+
+Deverá ser informado para tpOperGov 2 e 3 e vedado para os tipos 1 e 4.
+
+No caso do tpOperGov 2 aceitará apenas uma chave referenciada, no tipo 3 poderá aceitar múltiplas chaves
+
+Obs: a chave de acesso deverá ser de um emitente com o mesmo CNPJ base
+
+
@@ -1153,19 +1376,49 @@ gás natural e em outras hipóteses definidas no regulamento
1=União
2=Estados
3=Distrito Federal
-4=Municípios
+4=Municípios
+5=Consórcio Público
+6=Comitê Gestor do IBS
- Percentual de redução de aliquota em compra governamental
+ Percentual de redução de alíquota em compra governamental
Tipo da operação com ente governamental:
-1 - Fornecimento
-2 - Recebimento do Pagamento
+1 – Fornecimento com pagamento posterior;
+2 - Recebimento do pagamento com fornecimento já realizado;
+3 – Fornecimento com pagamento já realizado;
+4 – Recebimento do pagamento com fornecimento posterior;
+
+
+
+
+ Chave de acesso do documento fiscal anterior.
+
+Deverá ser informado para tpOperGov 2 e 3 e vedado para os tipos 1 e 4.
+
+No caso do tpOperGov 2 aceitará apenas uma chave referenciada, no tipo 3 poderá aceitar múltiplas chaves
+
+Obs: a chave de acesso deverá ser de um emitente com o mesmo CNPJ base
+
+
+
+
+
+
+ Tipo Pagamento que ocorre em DFe emitdo anteriormente
+ Informado para abater as parcelas de antecipação de pagamento, conforme art. 10 §4
+
+
+
+
+ Chave de acesso do documento fiscal de antecipação de pagamento
+
+Obs: esse DFe deverá ter o indAntecipacaoPgto marcado no grupo ide
@@ -1187,6 +1440,68 @@ gás natural e em outras hipóteses definidas no regulamento
+
+
+ Tipo Operações em areas incentivadas com CBS Zero
+
+
+
+
+ Percentual efetivo sem a redução
+ Alíquota efetiva de referência da CBS aplicável à operação fora de áreas ou regimes incentivados.
+
+
+
+
+ Valor efetivo sem a redução
+ Valor da CBS calculado para a operação fora de áreas ou regimes incentivado
+
+
+
+
+
+
+ Tipo Operações em áreas incentivadas (ALC/ZFM) - CBS (alíquota zero)
+
+
+
+
+ Tipo de aplicação da alíquota zero da CBS.
+
+
+
+
+
+
+
+
+
+
+
+ Número do processo na Suframa para o item
+comercializado.
+
+
+
+
+
+
+
+
+
+
+ Percentual efetivo sem a redução
+ Alíquota efetiva de referência da CBS aplicável à operação fora de áreas ou regimes incentivados.
+
+
+
+
+ Valor efetivo sem a redução
+ Valor da CBS calculado para a operação fora de áreas ou regimes incentivado
+
+
+
+
Tipo Estorno de Crédito
@@ -1204,14 +1519,6 @@ gás natural e em outras hipóteses definidas no regulamento
-
-
- Ano e mês referência do período de apuração (AAAA-MM)
-
-
-
-
-
Tipo Ajuste de Competência
diff --git a/NFe.AppTeste/Schemas/leiauteNFe_v4.00.xsd b/NFe.AppTeste/Schemas/leiauteNFe_v4.00.xsd
index 8c6ade56e..9e86de93b 100644
--- a/NFe.AppTeste/Schemas/leiauteNFe_v4.00.xsd
+++ b/NFe.AppTeste/Schemas/leiauteNFe_v4.00.xsd
@@ -111,13 +111,19 @@
Informar o município de ocorrência do fato gerador do fato gerador do IBS / CBS.
-Campo preenchido somente quando “indPres = 5 (Operação presencial, fora do estabelecimento) ”, e não tiver endereço do destinatário (Grupo: E05) ou local de entrega (Grupo: G01).
+Campo preenchido somente quando "indPres = 5 (Operação presencial, fora do estabelecimento)", e não estiver preenchido o endereço do destinatário (grupo: E05) nem o local de entrega (grupo: G01).
- Formato de impressão do DANFE (0-sem DANFE;1-DANFe Retrato; 2-DANFe Paisagem;3-DANFe Simplificado;
- 4-DANFe NFC-e;5-DANFe NFC-e em mensagem eletrônica)
+ Formato de impressão do DANFE:
+0 - Sem DANFE;
+1 - DANFE Retrato;
+2 - DANFE Paisagem;
+3 - DANFE Simplificado;
+4 - DANFE NFC-e;
+5 - DANFE NFC-e em mensagem eletrônica;
+6 - DANFE Simplificado Tipo 2 (nas condições do Ajuste SINIEF 13/26).
@@ -128,20 +134,21 @@ Campo preenchido somente quando “indPres = 5 (Operação presencial, fora do e
+
- Forma de emissão da NF-e
+ Forma de emissão da NF-e:
1 - Normal;
-2 - Contingência FS
-3 - Regime Especial NFF (NT 2021.002)
-4 - Contingência DPEC
-5 - Contingência FSDA
-6 - Contingência SVC - AN
-7 - Contingência SVC - RS
-9 - Contingência off-line NFC-e
+2 - Contingência FS;
+3 - Regime Especial NFF (NT 2021.002);
+4 - Contingência DPEC;
+5 - Contingência FSDA;
+6 - Contingência SVC - AN;
+7 - Contingência SVC - RS;
+9 - Contingência off-line da NFC-e e da NF-e com DANFE Simplificado Tipo 2.
@@ -188,13 +195,7 @@ Campo preenchido somente quando “indPres = 5 (Operação presencial, fora do e
- Tipo de Nota de Débito:
-01=Transferência de créditos para Cooperativas;
-02=Anulação de Crédito por Saídas Imunes/Isentas;
-03=Débitos de notas fiscais não processadas na apuração;
-04=Multa e juros;
-05=Transferência de crédito de sucessão.
-
+ Tipo de Nota de Débito
@@ -216,8 +217,14 @@ Campo preenchido somente quando “indPres = 5 (Operação presencial, fora do e
- Indicador de presença do comprador no estabelecimento comercial no momento da oepração
- (0-Não se aplica (ex.: Nota Fiscal complementar ou de ajuste;1-Operação presencial;2-Não presencial, internet;3-Não presencial, teleatendimento;4-NFC-e entrega em domicílio;5-Operação presencial, fora do estabelecimento;9-Não presencial, outros)
+ Indicador de presença do comprador no estabelecimento comercial no momento da oepração:
+0 - Não se aplica (ex.: Nota Fiscal complementar ou de ajuste);
+1 - Operação presencial;
+2 - Operação não presencial, internet;
+3 - Operação não presencial, teleatendimento;
+4 - Operação não presencial com NFC-e e NFe com DANFE Simplificado Tipo 2 (com entrega);
+5 - Operação presencial, fora do estabelecimento;
+9 - Operação não presencial, outros.
@@ -246,6 +253,17 @@ Campo preenchido somente quando “indPres = 5 (Operação presencial, fora do e
+
+
+ Código indicador do local da operação de fornecimento
+
+
+
+
+
+
+
+
Processo de emissão utilizado com a seguinte codificação:
@@ -599,6 +617,17 @@ Este campo será obrigatoriamente preenchido com:
+
+
+ Inscrição do emitente na Suframa
+
+
+
+
+
+
+
+
@@ -6633,7 +6662,7 @@ tipo de ato concessório:
-
+
@@ -6707,7 +6736,7 @@ tipo de ato concessório:
Descrição literal do status do serviço solicitado.
-
+
Código da Mensagem.
@@ -6726,7 +6755,7 @@ tipo de ato concessório:
-
+
@@ -7462,7 +7491,7 @@ alterado para tamanho variavel 1-4. (NT2011/004)
04=Multa e juros;
05=Transferência de crédito na sucessão;
06=Pagamento antecipado;
- 07=Perda em estoque;
+ 07=Perda em estoque (Perecimento, Perda, Furto, Roubo);
08=Desenquadramento do SN;
@@ -7485,6 +7514,7 @@ alterado para tamanho variavel 1-4. (NT2011/004)
03=Retorno por recusa na entrega ou por não localização do destinatário na tentativa de entrega;
04=Redução de valores;
05=Transferência de crédito na sucessão;
+ 06=Retorno por recusa parcial na entrega;
@@ -7494,6 +7524,7 @@ alterado para tamanho variavel 1-4. (NT2011/004)
+
diff --git a/NFe.Classes/Informacoes/Destinatario/dest.cs b/NFe.Classes/Informacoes/Destinatario/dest.cs
index 3cb1a1f73..8c9cd5fec 100644
--- a/NFe.Classes/Informacoes/Destinatario/dest.cs
+++ b/NFe.Classes/Informacoes/Destinatario/dest.cs
@@ -30,18 +30,19 @@
/* http://www.zeusautomacao.com.br/ */
/* Rua Comendador Francisco josé da Cunha, 111 - Itabaiana - SE - 49500-000 */
/********************************************************************************/
+
+using DFe.Classes.Flags;
using System;
using System.Xml.Serialization;
-using DFe.Classes.Flags;
-using NFe.Classes.Servicos.Tipos;
namespace NFe.Classes.Informacoes.Destinatario
{
public class dest
{
- private const string ErroCpfCnpjPreenchidos = "Somente preencher um dos campos: CNPJ ou CPF, para um objeto do tipo dest!";
+ private const string ErroCpfCnpjIdEstrangeiroPreenchidos = "Somente preencher um dos campos: CNPJ, CPF ou idEstrangeiro, para um objeto do tipo dest!";
private string cnpj;
private string cpf;
+ private string _idEstrangeiro;
private readonly VersaoServico _versao;
///
@@ -66,13 +67,12 @@ public string CNPJ
get { return cnpj; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(cpf))
- cnpj = value;
- else
- {
- throw new ArgumentException(ErroCpfCnpjPreenchidos);
- }
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(cpf) || !string.IsNullOrEmpty(idEstrangeiro))
+ throw new ArgumentException(ErroCpfCnpjIdEstrangeiroPreenchidos);
+
+ cnpj = value;
}
}
@@ -84,20 +84,31 @@ public string CPF
get { return cpf; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(cnpj))
- cpf = value;
- else
- {
- throw new ArgumentException(ErroCpfCnpjPreenchidos);
- }
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(cnpj) || !string.IsNullOrEmpty(idEstrangeiro))
+ throw new ArgumentException(ErroCpfCnpjIdEstrangeiroPreenchidos);
+
+ cpf = value;
}
}
///
/// E03a - Identificador do destinatário, em caso de comprador estrangeiro
///
- public string idEstrangeiro { get; set; }
+ public string idEstrangeiro
+ {
+ get { return _idEstrangeiro; }
+ set
+ {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(CNPJ) || !string.IsNullOrEmpty(CPF))
+ throw new ArgumentException(ErroCpfCnpjIdEstrangeiroPreenchidos);
+
+ _idEstrangeiro = value;
+ }
+ }
///
/// E04 - Razão Social ou nome do destinatário
diff --git a/NFe.Classes/Informacoes/Detalhe/Tributacao/Federal/IS.cs b/NFe.Classes/Informacoes/Detalhe/Tributacao/Federal/IS.cs
index 951d93b15..06ad15da1 100644
--- a/NFe.Classes/Informacoes/Detalhe/Tributacao/Federal/IS.cs
+++ b/NFe.Classes/Informacoes/Detalhe/Tributacao/Federal/IS.cs
@@ -80,7 +80,7 @@ public decimal pIS
/// UB07 - Alíquota específica por unidade de medida apropriada (em percentual)
///
[XmlElement(Order = 5)]
- public decimal? pISEspec
+ public decimal? adRemIS
{
get => _pIsEspec.Arredondar(4);
set => _pIsEspec = value.Arredondar(4);
@@ -112,6 +112,6 @@ public decimal vIS
set => _vIs = value.Arredondar(2);
}
- public bool ShouldSerializepISEspec() => pISEspec.HasValue;
+ public bool ShouldSerializeadRemIS() => adRemIS.HasValue;
}
}
\ No newline at end of file
diff --git a/NFe.Classes/Informacoes/Detalhe/Tributacao/Federal/Tipos/IPITipos.cs b/NFe.Classes/Informacoes/Detalhe/Tributacao/Federal/Tipos/IPITipos.cs
index b6d87d258..c318df8bb 100644
--- a/NFe.Classes/Informacoes/Detalhe/Tributacao/Federal/Tipos/IPITipos.cs
+++ b/NFe.Classes/Informacoes/Detalhe/Tributacao/Federal/Tipos/IPITipos.cs
@@ -58,97 +58,97 @@ public enum CSTIPI
///
[Description("Entrada com recuperação de crédito")]
[XmlEnum("00")]
- ipi00,
-
- ///
- /// 49 - Outras entradas
- ///
- [Description("Outras entradas")]
- [XmlEnum("49")]
- ipi49,
-
- ///
- /// 50 - Saída tributada
- ///
- [Description("Saída tributada")]
- [XmlEnum("50")]
- ipi50,
-
- ///
- /// 99 - Outras saídas
- ///
- [Description("Outras saídas")]
- [XmlEnum("99")]
- ipi99,
+ ipi00 = 0,
///
/// 01 - Entrada tributada com alíquota zero
///
[Description("Entrada tributada com alíquota zero")]
[XmlEnum("01")]
- ipi01,
+ ipi01 = 1,
///
/// 02 - Entrada isenta
///
[Description("Entrada isenta")]
[XmlEnum("02")]
- ipi02,
+ ipi02 = 2,
///
/// 03 - Entrada não-tributada
///
[Description("Entrada não-tributada")]
[XmlEnum("03")]
- ipi03,
+ ipi03 = 3,
///
/// 04 - Entrada imune
///
[Description("Entrada imune")]
[XmlEnum("04")]
- ipi04,
+ ipi04 = 4,
///
/// 05 - Entrada com suspensão
///
[Description("Entrada com suspensão")]
[XmlEnum("05")]
- ipi05,
+ ipi05 = 5,
+
+ ///
+ /// 49 - Outras entradas
+ ///
+ [Description("Outras entradas")]
+ [XmlEnum("49")]
+ ipi49 = 49,
+
+ ///
+ /// 50 - Saída tributada
+ ///
+ [Description("Saída tributada")]
+ [XmlEnum("50")]
+ ipi50 = 50,
///
/// 51 - Saída tributada com alíquota zero
///
[Description("Saída tributada com alíquota zero")]
[XmlEnum("51")]
- ipi51,
+ ipi51 = 51,
///
/// 52 - Saída isenta
///
[Description("Saída isenta")]
[XmlEnum("52")]
- ipi52,
+ ipi52 = 52,
///
/// 53 - Saída não-tributada
///
[Description("Saída não-tributada")]
[XmlEnum("53")]
- ipi53,
+ ipi53 = 53,
///
/// 54 - Saída imune
///
[Description("Saída imune")]
[XmlEnum("54")]
- ipi54,
+ ipi54 = 54,
///
/// 55 - Saída com suspensão
///
[Description("Saída com suspensão")]
[XmlEnum("55")]
- ipi55
+ ipi55 = 55,
+
+ ///
+ /// 99 - Outras saídas
+ ///
+ [Description("Outras saídas")]
+ [XmlEnum("99")]
+ ipi99 = 99
}
}
\ No newline at end of file
diff --git a/NFe.Classes/Informacoes/Emitente/emit.cs b/NFe.Classes/Informacoes/Emitente/emit.cs
index 238d8f5c4..fdd7b8abf 100644
--- a/NFe.Classes/Informacoes/Emitente/emit.cs
+++ b/NFe.Classes/Informacoes/Emitente/emit.cs
@@ -50,14 +50,12 @@ public string CNPJ
get { return _cnpj; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(_cpf))
- _cnpj = Regex.Match(value, @"[0-9A-Z]+").Value;
-
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(_cpf))
throw new ArgumentException(ErroCpfCnpjPreenchidos);
- }
+
+ _cnpj = Regex.Match(value, @"[0-9A-Z]+").Value;
}
}
@@ -69,13 +67,12 @@ public string CPF
get { return _cpf; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(_cnpj))
- _cpf = Regex.Match(value, @"\d+").Value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(_cnpj))
throw new ArgumentException(ErroCpfCnpjPreenchidos);
- }
+
+ _cpf = Regex.Match(value, @"\d+").Value;
}
}
diff --git a/NFe.Classes/Informacoes/Identificacao/Tipos/ideTipos.cs b/NFe.Classes/Informacoes/Identificacao/Tipos/ideTipos.cs
index 065164a7e..73d2160d6 100644
--- a/NFe.Classes/Informacoes/Identificacao/Tipos/ideTipos.cs
+++ b/NFe.Classes/Informacoes/Identificacao/Tipos/ideTipos.cs
@@ -148,6 +148,7 @@ public enum DestinoOperacao
/// 3 - DANFe Simplificado;
/// 4 - DANFe NFC-e;
/// 5 - DANFe NFC-e em mensagem eletrônica
+ /// 6 - DANFe Simplificado Tipo 2
///
public enum TipoImpressao
{
@@ -191,7 +192,14 @@ public enum TipoImpressao
///
[Description("DANFe NFC-e em mensagem eletrônica")]
[XmlEnum("5")]
- tiMsgEletronica = 5
+ tiMsgEletronica = 5,
+
+ ///
+ /// 6 - DANFe Simplificado Tipo 2
+ ///
+ [Description("DANFe Simplificado Tipo 2")]
+ [XmlEnum("6")]
+ tiSimplificadoTp2 = 6
}
///
@@ -591,7 +599,8 @@ public enum TpNotaDebito
/// 02 - Apropriação de crédito presumido de IBS sobre o saldo devedor na ZFM (art. 450, § 1º, LC 214/25)
/// 03 - Retorno por recusa na entrega ou por não localização do destinatário na tentativa de entrega
/// 04 - Redução de valores
- /// 05 - Transferência de crédito na sucessão;
+ /// 05 - Transferência de crédito na sucessão
+ /// 06 - Retorno por recusa parcial na entrega
///
public enum TpNotaCredito
{
@@ -611,9 +620,13 @@ public enum TpNotaCredito
[XmlEnum("04")]
ReducaoDeValores,
- [Description("Transferência de crédito na sucessão;")]
+ [Description("Transferência de crédito na sucessão")]
[XmlEnum("05")]
- TfCreditoSucessao
+ TfCreditoSucessao,
+
+ [Description("Retorno por recusa parcial na entrega")]
+ [XmlEnum("06")]
+ RetornoPorRecusaParcialNaEntrega
}
///
diff --git a/NFe.Classes/Informacoes/Transporte/transporta.cs b/NFe.Classes/Informacoes/Transporte/transporta.cs
index 288fddaec..fdca1caa0 100644
--- a/NFe.Classes/Informacoes/Transporte/transporta.cs
+++ b/NFe.Classes/Informacoes/Transporte/transporta.cs
@@ -48,13 +48,12 @@ public string CNPJ
get { return cnpj; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(cpf))
- cnpj = value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(cpf))
throw new ArgumentException(ErroCpfCnpjPreenchidos);
- }
+
+ cnpj = value;
}
}
@@ -66,13 +65,12 @@ public string CPF
get { return cpf; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(cnpj))
- cpf = value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(cnpj))
throw new ArgumentException(ErroCpfCnpjPreenchidos);
- }
+
+ cpf = value;
}
}
diff --git a/NFe.Classes/Informacoes/autXML.cs b/NFe.Classes/Informacoes/autXML.cs
index 026bfc4d2..335d01b0d 100644
--- a/NFe.Classes/Informacoes/autXML.cs
+++ b/NFe.Classes/Informacoes/autXML.cs
@@ -48,13 +48,12 @@ public string CNPJ
get { return cnpj; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(cpf))
- cnpj = value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(cpf))
throw new ArgumentException(ErroCpfCnpjPreenchidos);
- }
+
+ cnpj = value;
}
}
@@ -66,13 +65,12 @@ public string CPF
get { return cpf; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(cnpj))
- cpf = value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(cnpj))
throw new ArgumentException(ErroCpfCnpjPreenchidos);
- }
+
+ cpf = value;
}
}
}
diff --git a/NFe.Classes/Informacoes/entrega.cs b/NFe.Classes/Informacoes/entrega.cs
index fbe1f8e07..83852d663 100644
--- a/NFe.Classes/Informacoes/entrega.cs
+++ b/NFe.Classes/Informacoes/entrega.cs
@@ -49,13 +49,12 @@ public string CNPJ
get { return cnpj; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(cpf))
- cnpj = value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(cpf))
throw new ArgumentException(ErroCpfCnpjPreenchidos);
- }
+
+ cnpj = value;
}
}
@@ -67,13 +66,12 @@ public string CPF
get { return cpf; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(cnpj))
- cpf = value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(cnpj))
throw new ArgumentException(ErroCpfCnpjPreenchidos);
- }
+
+ cpf = value;
}
}
diff --git a/NFe.Classes/Informacoes/retirada.cs b/NFe.Classes/Informacoes/retirada.cs
index 72d3b0138..f90977335 100644
--- a/NFe.Classes/Informacoes/retirada.cs
+++ b/NFe.Classes/Informacoes/retirada.cs
@@ -49,13 +49,12 @@ public string CNPJ
get { return cnpj; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(cpf))
- cnpj = value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(cpf))
throw new ArgumentException(ErroCpfCnpjPreenchidos);
- }
+
+ cnpj = value;
}
}
@@ -67,13 +66,12 @@ public string CPF
get { return cpf; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(cnpj))
- cpf = value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(cnpj))
throw new ArgumentException(ErroCpfCnpjPreenchidos);
- }
+
+ cpf = value;
}
}
diff --git a/NFe.Classes/Servicos/ConsultaCadastro/infConsEnv.cs b/NFe.Classes/Servicos/ConsultaCadastro/infConsEnv.cs
index fddac9e5e..6cf172235 100644
--- a/NFe.Classes/Servicos/ConsultaCadastro/infConsEnv.cs
+++ b/NFe.Classes/Servicos/ConsultaCadastro/infConsEnv.cs
@@ -65,13 +65,12 @@ public string IE
get { return _ie; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(CNPJ) & string.IsNullOrEmpty(CPF))
- _ie = value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(CNPJ) || !string.IsNullOrEmpty(CPF))
throw new ArgumentException(ErroCpfCnpjIePreenchidos);
- }
+
+ _ie = value;
}
}
@@ -84,13 +83,12 @@ public string CNPJ
get { return _cnpj; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(CPF) & string.IsNullOrEmpty(IE))
- _cnpj = value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(CPF) || !string.IsNullOrEmpty(IE))
throw new ArgumentException(ErroCpfCnpjIePreenchidos);
- }
+
+ _cnpj = value;
}
}
@@ -103,13 +101,12 @@ public string CPF
get { return _cpf; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(CNPJ) & string.IsNullOrEmpty(IE))
- _cpf = value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(CNPJ) || !string.IsNullOrEmpty(IE))
throw new ArgumentException(ErroCpfCnpjIePreenchidos);
- }
+
+ _cpf = value;
}
}
}
diff --git a/NFe.Classes/Servicos/DistribuicaoDFe/distDFeInt.cs b/NFe.Classes/Servicos/DistribuicaoDFe/distDFeInt.cs
index 8015a9795..5ad92bd01 100644
--- a/NFe.Classes/Servicos/DistribuicaoDFe/distDFeInt.cs
+++ b/NFe.Classes/Servicos/DistribuicaoDFe/distDFeInt.cs
@@ -71,13 +71,12 @@ public string CNPJ
get { return _cNPJ; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(_cPF))
- _cNPJ = value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(_cPF))
throw new ArgumentException(ErroCpfCnpjPreenchidos);
- }
+
+ _cNPJ = value;
}
}
@@ -89,13 +88,12 @@ public string CPF
get { return _cPF; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(_cNPJ))
- _cPF = value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(_cNPJ))
throw new ArgumentException(ErroCpfCnpjPreenchidos);
- }
+
+ _cPF = value;
}
}
diff --git a/NFe.Classes/Servicos/Evento/dest.cs b/NFe.Classes/Servicos/Evento/dest.cs
index 725018543..7e6c820ae 100644
--- a/NFe.Classes/Servicos/Evento/dest.cs
+++ b/NFe.Classes/Servicos/Evento/dest.cs
@@ -58,13 +58,12 @@ public string CNPJ
get { return _cnpj; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(CPF) & string.IsNullOrEmpty(idEstrangeiro))
- _cnpj = value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(CPF) || !string.IsNullOrEmpty(idEstrangeiro))
throw new ArgumentException(ErroCpfCnpjIdEstrangeiroPreenchidos);
- }
+
+ _cnpj = value;
}
}
@@ -76,13 +75,12 @@ public string CPF
get { return _cpf; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(CNPJ) & string.IsNullOrEmpty(idEstrangeiro))
- _cpf = value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(CNPJ) || !string.IsNullOrEmpty(idEstrangeiro))
throw new ArgumentException(ErroCpfCnpjIdEstrangeiroPreenchidos);
- }
+
+ _cpf = value;
}
}
@@ -95,12 +93,10 @@ public string idEstrangeiro
set
{
if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(CNPJ) & string.IsNullOrEmpty(CPF))
- _idEstrangeiro = value;
- else
- {
+ if (!string.IsNullOrEmpty(CNPJ) || !string.IsNullOrEmpty(CPF))
throw new ArgumentException(ErroCpfCnpjIdEstrangeiroPreenchidos);
- }
+
+ _idEstrangeiro = value;
}
}
diff --git a/NFe.Classes/Servicos/Evento/infEventoEnv.cs b/NFe.Classes/Servicos/Evento/infEventoEnv.cs
index 1c4592c3f..9c0b79ac1 100644
--- a/NFe.Classes/Servicos/Evento/infEventoEnv.cs
+++ b/NFe.Classes/Servicos/Evento/infEventoEnv.cs
@@ -69,13 +69,12 @@ public string CNPJ
get { return cnpj; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(cpf))
- cnpj = value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(cpf))
throw new ArgumentException(ErroCpfCnpjPreenchidos);
- }
+
+ cnpj = value;
}
}
@@ -87,13 +86,12 @@ public string CPF
get { return cpf; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(cnpj))
- cpf = value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(cnpj))
throw new ArgumentException(ErroCpfCnpjPreenchidos);
- }
+
+ cpf = value;
}
}
diff --git a/NFe.Classes/Servicos/Evento/infEventoRet.cs b/NFe.Classes/Servicos/Evento/infEventoRet.cs
index 85b927e61..f33ee61f9 100644
--- a/NFe.Classes/Servicos/Evento/infEventoRet.cs
+++ b/NFe.Classes/Servicos/Evento/infEventoRet.cs
@@ -110,13 +110,12 @@ public string CNPJDest
get { return cnpj; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(cpf))
- cnpj = value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(cpf))
throw new ArgumentException(ErroCpfCnpjPreenchidos);
- }
+
+ cnpj = value;
}
}
@@ -128,13 +127,12 @@ public string CPFDest
get { return cpf; }
set
{
- if (string.IsNullOrEmpty(value)) return;
- if (string.IsNullOrEmpty(cnpj))
- cpf = value;
- else
- {
+ if (string.IsNullOrEmpty(value))
+ return;
+ if (!string.IsNullOrEmpty(cnpj))
throw new ArgumentException(ErroCpfCnpjPreenchidos);
- }
+
+ cpf = value;
}
}
diff --git a/NFe.Danfe.AppTeste.Fast/MainWindow.xaml b/NFe.Danfe.AppTeste.Fast/MainWindow.xaml
index cbd75fdf1..36f02701b 100644
--- a/NFe.Danfe.AppTeste.Fast/MainWindow.xaml
+++ b/NFe.Danfe.AppTeste.Fast/MainWindow.xaml
@@ -217,6 +217,8 @@
VerticalAlignment="Top" Width="120" Click="BtnNfceDanfe_Click" Margin="5,10,5,0" />
+
diff --git a/NFe.Danfe.AppTeste.Fast/MainWindow.xaml.cs b/NFe.Danfe.AppTeste.Fast/MainWindow.xaml.cs
index 0cf1de38c..877d993fe 100644
--- a/NFe.Danfe.AppTeste.Fast/MainWindow.xaml.cs
+++ b/NFe.Danfe.AppTeste.Fast/MainWindow.xaml.cs
@@ -102,7 +102,7 @@ private void CarregarConfiguracao()
LogoEmitente.Source = BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}
- #endregion
+ #endregion Carrega a logo no controle logoEmitente
}
catch (Exception ex)
{
@@ -163,13 +163,15 @@ private void BtnNfeDanfeA4_Click(object sender, RoutedEventArgs e)
throw new Exception("O XML informado não é um NFe!");
/*
- //Carregar atravez de um stream....
+ //Carregar atravez de um stream....
var stream = new StreamReader(arquivoXml, Encoding.GetEncoding("ISO-8859-1"));
- var proc = new nfeProc().CarregardeStream(stream);
+ var proc = new nfeProc().CarregardeStream(stream);
*/
- #endregion
+
+ #endregion Carrega um XML com nfeProc para a variável
#region Abre a visualização do relatório para impressão
+
var danfe = new DanfeFrNfe(proc: proc,
configuracaoDanfeNfe: new ConfiguracaoDanfeNfe()
{
@@ -195,8 +197,7 @@ private void BtnNfeDanfeA4_Click(object sender, RoutedEventArgs e)
//danfe.ExibirDesign();
//danfe.ExportarPdf(@"d:\teste.pdf");
- #endregion
-
+ #endregion Abre a visualização do relatório para impressão
}
catch (Exception ex)
{
@@ -218,26 +219,25 @@ private void btnEventoNFe_Click(object sender, RoutedEventArgs e)
if (proc.NFe.infNFe.ide.mod != ModeloDocumento.NFe)
throw new Exception("O XML informado não é um NFe!");
-
arquivoXml = Funcoes.BuscarArquivoXml();
if (string.IsNullOrEmpty(arquivoXml))
return;
var procEvento = FuncoesXml.ArquivoXmlParaClasse(arquivoXml);
- #endregion
+ #endregion Carrega um XML com nfeProc para a variável
#region Abre a visualização do relatório para impressão
+
var danfe = new DanfeFrEvento(proc, procEvento, new ConfiguracaoDanfeNfe(_configuracoes.ConfiguracaoDanfeNfce.Logomarca,
- RdbDuasLinhas.IsChecked == true || RdbCompleto.IsChecked == true,
- ChbCancelado.IsChecked ?? false),
+ RdbDuasLinhas.IsChecked == true || RdbCompleto.IsChecked == true,
+ ChbCancelado.IsChecked ?? false),
"NOME DA SOFTWARE HOUSE");
danfe.Visualizar();
//danfe.Imprimir();
//danfe.ExibirDesign();
//danfe.ExportarPdf(@"d:\teste.pdf");
- #endregion
-
+ #endregion Abre a visualização do relatório para impressão
}
catch (Exception ex)
{
@@ -271,7 +271,7 @@ private void ImprimirDanfeNfce(NfceLayoutQrCode layout)
if (nfeProc.NFe.infNFe.ide.mod != ModeloDocumento.NFCe)
throw new Exception("O XML informado não é um NFCe!");
- #endregion
+ #endregion Carrega um XML para a variável
#region Abre a visualização do relatório para impressão
@@ -281,8 +281,7 @@ private void ImprimirDanfeNfce(NfceLayoutQrCode layout)
//danfe.ExibirDesign();
//danfe.ExportarPdf(@"d:\teste.pdf");
- #endregion
-
+ #endregion Abre a visualização do relatório para impressão
}
catch (Exception ex)
{
@@ -316,13 +315,15 @@ private void BtnNFeSimplificado_Click(object sender, RoutedEventArgs e)
throw new Exception("O XML informado não é um NFe!");
/*
- //Carregar atravez de um stream....
+ //Carregar atravez de um stream....
var stream = new StreamReader(arquivoXml, Encoding.GetEncoding("ISO-8859-1"));
- var proc = new nfeProc().CarregardeStream(stream);
+ var proc = new nfeProc().CarregardeStream(stream);
*/
- #endregion
+
+ #endregion Carrega um XML com nfeProc para a variável
#region Abre a visualização do relatório para impressão
+
var danfe = new DanfeFrSimplificado(proc: proc,
configuracaoDanfeNfe: new ConfiguracaoDanfeNfe()
{
@@ -343,13 +344,86 @@ private void BtnNFeSimplificado_Click(object sender, RoutedEventArgs e)
desenvolvedor: "NOME DA SOFTWARE HOUSE",
arquivoRelatorio: string.Empty);
- //danfe.Visualizar();
+ danfe.Visualizar();
//danfe.Imprimir();
- danfe.ExibirDesign();
+ //danfe.ExibirDesign();
//danfe.ExportarPdf(@"d:\teste.pdf");
- #endregion
+ #endregion Abre a visualização do relatório para impressão
+ }
+ catch (Exception ex)
+ {
+ if (!string.IsNullOrEmpty(ex.Message))
+ Funcoes.Mensagem(ex.Message, "Erro", MessageBoxButton.OK);
+ }
+ }
+
+ private void BtnNFeSimplificadoTipo2_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ #region Carrega um XML com nfeProc para a variável
+
+ var arquivoXml = Funcoes.BuscarArquivoXml();
+ if (string.IsNullOrEmpty(arquivoXml))
+ return;
+
+ nfeProc proc = null;
+
+ try
+ {
+ proc = new nfeProc().CarregarDeArquivoXml(arquivoXml);
+ }
+ catch //Carregar NFe ainda não transmitida à sefaz, como uma pré-visualização.
+ {
+ proc = new nfeProc() { NFe = new Classes.NFe().CarregarDeArquivoXml(arquivoXml), protNFe = new Classes.Protocolo.protNFe() };
+ }
+
+ if (proc.NFe.infNFe.ide.mod != ModeloDocumento.NFe)
+ throw new Exception("O XML informado não é um NFe!");
+
+ #endregion Carrega um XML com nfeProc para a variável
+
+ #region Abre a visualização do relatório para impressão
+
+ var danfe = new DanfeFrSimplificadoTipo2(proc: proc,
+ configuracao: new ConfiguracaoDanfeNfeSimplificadoTipo2
+ {
+ Logomarca = _configuracoes.ConfiguracaoDanfeNfce.Logomarca,
+ DetalheVendaNormal = (NfeSimplificadoTipo2DetalheVendaNormal)(int)_configuracoes.ConfiguracaoDanfeNfce.DetalheVendaNormal,
+ DetalheVendaContigencia = (NfeSimplificadoTipo2DetalheVendaContigencia)(int)_configuracoes.ConfiguracaoDanfeNfce.DetalheVendaContigencia,
+ ImprimeDescontoItem = _configuracoes.ConfiguracaoDanfeNfce.ImprimeDescontoItem,
+ ImprimeFoneEmitente = _configuracoes.ConfiguracaoDanfeNfce.ImprimeFoneEmitente,
+ MargemEsquerda = _configuracoes.ConfiguracaoDanfeNfce.MargemEsquerda,
+ MargemDireita = _configuracoes.ConfiguracaoDanfeNfce.MargemDireita,
+ ModoImpressao = (NfeSimplificadoTipo2ModoImpressao)(int)_configuracoes.ConfiguracaoDanfeNfce.ModoImpressao,
+ LayoutQrCode = (NfeSimplificadoTipo2LayoutQrCode)(int)_configuracoes.ConfiguracaoDanfeNfce.NfceLayoutQrCode,
+ VersaoQrCode = _configuracoes.ConfiguracaoDanfeNfce.VersaoQrCode,
+ SegundaViaContingencia = _configuracoes.ConfiguracaoDanfeNfce.SegundaViaContingencia,
+ DuasLinhas = RdbDuasLinhas.IsChecked == true || RdbCompleto.IsChecked == true,
+ DocumentoCancelado = ChbCancelado.IsChecked ?? false,
+ QuebrarLinhasObservacao = _configuracoes.ConfiguracaoDanfeNfe.QuebrarLinhasObservacao,
+ ExibirResumoCanhoto = _configuracoes.ConfiguracaoDanfeNfe.ExibirResumoCanhoto,
+ ResumoCanhoto = _configuracoes.ConfiguracaoDanfeNfe.ResumoCanhoto,
+ ChaveContingencia = _configuracoes.ConfiguracaoDanfeNfe.ChaveContingencia,
+ ExibeCampoFatura = _configuracoes.ConfiguracaoDanfeNfe.ExibeCampoFatura,
+ ImprimirISSQN = _configuracoes.ConfiguracaoDanfeNfe.ImprimirISSQN,
+ ImprimirDescPorc = _configuracoes.ConfiguracaoDanfeNfe.ImprimirDescPorc,
+ ImprimirTotalLiquido = _configuracoes.ConfiguracaoDanfeNfe.ImprimirTotalLiquido,
+ ImprimirUnidQtdeValor = _configuracoes.ConfiguracaoDanfeNfe.ImprimirUnidQtdeValor,
+ ExibirTotalTributos = _configuracoes.ConfiguracaoDanfeNfe.ExibirTotalTributos
+ },
+ _configuracoes.CIdToken,
+ _configuracoes.Csc,
+ desenvolvedor: "NOME DA SOFTWARE HOUSE",
+ arquivoRelatorio: string.Empty);
+
+ danfe.Visualizar();
+ //danfe.Imprimir();
+ //danfe.ExibirDesign();
+ //danfe.ExportarPdf(@"d:\teste.pdf");
+ #endregion Abre a visualização do relatório para impressão
}
catch (Exception ex)
{
@@ -358,5 +432,4 @@ private void BtnNFeSimplificado_Click(object sender, RoutedEventArgs e)
}
}
}
-
}
diff --git a/NFe.Danfe.Base/Enumns.cs b/NFe.Danfe.Base/Enumns.cs
index 20181c203..cb37074c3 100644
--- a/NFe.Danfe.Base/Enumns.cs
+++ b/NFe.Danfe.Base/Enumns.cs
@@ -66,4 +66,38 @@ public enum NfceLayoutQrCode
Abaixo = 0,
Lateral = 1
}
+
+ public enum NfeSimplificadoTipo2DetalheVendaNormal
+ {
+ NaoImprimir = 0,
+ UmaLinha = 1,
+ DuasLinhas = 2,
+ Completo = 3
+ }
+
+ public enum NfeSimplificadoTipo2DetalheVendaContigencia
+ {
+ UmaLinha = 1,
+ DuasLinhas = 2,
+ Completo = 3
+ }
+
+ public enum NfeSimplificadoTipo2ModoImpressao
+ {
+ /// Imprime o conteúdo em múltiplas páginas
+ MultiplasPaginas = 0,
+
+ /// Imprime o conteúdo em uma única página, mesmo que o tamanho da página exceda o tamanho pré-definido
+ UnicaPagina = 1
+ }
+
+ ///
+ /// Layout de impressão do DANFE NF-e Simplificado Tipo 2:
+ /// Abaixo - QRCode abaixo dos dados; Lateral - QRCode ao lado dos dados (usa menos papel)
+ ///
+ public enum NfeSimplificadoTipo2LayoutQrCode
+ {
+ Abaixo = 0,
+ Lateral = 1
+ }
}
diff --git a/NFe.Danfe.Base/NFe.Danfe.Base.csproj b/NFe.Danfe.Base/NFe.Danfe.Base.csproj
index 42e09d508..b43dd0121 100644
--- a/NFe.Danfe.Base/NFe.Danfe.Base.csproj
+++ b/NFe.Danfe.Base/NFe.Danfe.Base.csproj
@@ -16,6 +16,7 @@
+
@@ -31,6 +32,9 @@
Always
+
+ Always
+
diff --git a/NFe.Danfe.Base/NFe/ConfiguracaoDanfeNfeSimplificadoTipo2.cs b/NFe.Danfe.Base/NFe/ConfiguracaoDanfeNfeSimplificadoTipo2.cs
new file mode 100644
index 000000000..dff922ca1
--- /dev/null
+++ b/NFe.Danfe.Base/NFe/ConfiguracaoDanfeNfeSimplificadoTipo2.cs
@@ -0,0 +1,156 @@
+using NFe.Utils;
+using System;
+
+namespace NFe.Danfe.Base.NFe
+{
+ public class ConfiguracaoDanfeNfeSimplificadoTipo2 : ConfiguracaoDanfe
+ {
+ public ConfiguracaoDanfeNfeSimplificadoTipo2(
+ NfeSimplificadoTipo2DetalheVendaNormal detalheVendaNormal,
+ NfeSimplificadoTipo2DetalheVendaContigencia detalheVendaContigencia,
+ byte[] logomarca = null,
+ bool imprimeDescontoItem = false,
+ float margemEsquerda = 4.5F,
+ float margemDireita = 4.5F,
+ NfeSimplificadoTipo2ModoImpressao modoImpressao = NfeSimplificadoTipo2ModoImpressao.MultiplasPaginas,
+ bool documentoCancelado = false,
+ NfeSimplificadoTipo2LayoutQrCode layoutQrCode = NfeSimplificadoTipo2LayoutQrCode.Abaixo,
+ VersaoQrCode versaoQrCode = VersaoQrCode.QrCodeVersao1,
+ bool duasLinhas = true,
+ bool quebrarLinhasObservacao = true,
+ bool exibirResumoCanhoto = true) : this()
+ {
+ DocumentoCancelado = documentoCancelado;
+ DetalheVendaNormal = detalheVendaNormal;
+ DetalheVendaContigencia = detalheVendaContigencia;
+ Logomarca = logomarca;
+ ImprimeDescontoItem = imprimeDescontoItem;
+ MargemEsquerda = margemEsquerda;
+ MargemDireita = margemDireita;
+ ModoImpressao = modoImpressao;
+ LayoutQrCode = layoutQrCode;
+ VersaoQrCode = versaoQrCode;
+ SegundaViaContingencia = true;
+ DuasLinhas = duasLinhas;
+ QuebrarLinhasObservacao = quebrarLinhasObservacao;
+ ExibirResumoCanhoto = exibirResumoCanhoto;
+ }
+
+ ///
+ /// Construtor sem parâmetros para serialização
+ ///
+ public ConfiguracaoDanfeNfeSimplificadoTipo2()
+ {
+ DocumentoCancelado = false;
+ DetalheVendaNormal = NfeSimplificadoTipo2DetalheVendaNormal.UmaLinha;
+ DetalheVendaContigencia = NfeSimplificadoTipo2DetalheVendaContigencia.UmaLinha;
+ ImprimeDescontoItem = false;
+ ImprimeFoneEmitente = false;
+ MargemEsquerda = 4.5F;
+ MargemDireita = 4.5F;
+ ModoImpressao = NfeSimplificadoTipo2ModoImpressao.MultiplasPaginas;
+ LayoutQrCode = NfeSimplificadoTipo2LayoutQrCode.Abaixo;
+ VersaoQrCode = VersaoQrCode.QrCodeVersao1;
+ SegundaViaContingencia = true;
+ DuasLinhas = true;
+ QuebrarLinhasObservacao = true;
+ ExibirResumoCanhoto = true;
+ ResumoCanhoto = string.Empty;
+ ChaveContingencia = string.Empty;
+ ExibeCampoFatura = false;
+ ExibeRetencoes = false;
+ ImprimirISSQN = true;
+ ImprimirDescPorc = false;
+ ImprimirTotalLiquido = false;
+ ImprimirUnidQtdeValor = ImprimirUnidQtdeValor.Comercial;
+ ExibirTotalTributos = false;
+ DecimaisValorUnitario = 2;
+ DecimaisQuantidadeItem = 2;
+ DataHoraImpressao = null;
+ }
+
+ // ── Parâmetros específicos do layout NF-e Simplificado Tipo 2 (QR Code) ──────────────
+
+ ///
+ /// Modo de impressão do detalhe (produtos) para NF-es em ambiente Normal
+ ///
+ public NfeSimplificadoTipo2DetalheVendaNormal DetalheVendaNormal { get; set; }
+
+ ///
+ /// Modo de impressão do detalhe (produtos) para NF-es em contingência/homologação
+ ///
+ public NfeSimplificadoTipo2DetalheVendaContigencia DetalheVendaContigencia { get; set; }
+
+ ///
+ /// Determina se o desconto do item será impresso no DANFE, quando houver
+ ///
+ public bool ImprimeDescontoItem { get; set; }
+
+ ///
+ /// Determina se o número de telefone do emitente será impresso no DANFE
+ ///
+ public bool ImprimeFoneEmitente { get; set; }
+
+ ///
+ /// Margem esquerda de impressão em milímetros
+ ///
+ public float MargemEsquerda { get; set; }
+
+ ///
+ /// Margem direita de impressão em milímetros
+ ///
+ public float MargemDireita { get; set; }
+
+ ///
+ /// Determina o modo de impressão do DANFE da NF-e Simplificado Tipo 2
+ ///
+ public NfeSimplificadoTipo2ModoImpressao ModoImpressao { get; set; }
+
+ ///
+ /// Determina se o QRCode será impresso ao lado ou abaixo dos dados
+ ///
+ public NfeSimplificadoTipo2LayoutQrCode LayoutQrCode { get; set; }
+
+ ///
+ /// Versão do QRCode. 1.0 ou 2.0
+ ///
+ public VersaoQrCode VersaoQrCode { get; set; }
+
+ ///
+ /// Envia segunda via de contingência para a impressora (apenas suportado no FastReport clássico)
+ ///
+ public bool SegundaViaContingencia { get; set; }
+
+ // ── Parâmetros herdados do layout NF-e padrão ────────────────────────────────────────
+
+ public bool DuasLinhas { get; set; }
+
+ public bool QuebrarLinhasObservacao { get; set; }
+
+ public bool ExibeCampoFatura { get; set; }
+
+ public bool ExibirResumoCanhoto { get; set; }
+
+ public bool ExibeRetencoes { get; set; }
+
+ public string ResumoCanhoto { get; set; }
+
+ public string ChaveContingencia { get; set; }
+
+ public bool ImprimirISSQN { get; set; }
+
+ public bool ImprimirDescPorc { get; set; }
+
+ public bool ImprimirTotalLiquido { get; set; }
+
+ public ImprimirUnidQtdeValor ImprimirUnidQtdeValor { get; set; }
+
+ public bool ExibirTotalTributos { get; set; }
+
+ public int DecimaisValorUnitario { get; set; }
+
+ public int DecimaisQuantidadeItem { get; set; }
+
+ public DateTime? DataHoraImpressao { get; set; }
+ }
+}
diff --git a/NFe.Danfe.Base/NFe/NFeRetrato.frx b/NFe.Danfe.Base/NFe/NFeRetrato.frx
index 19d2e8cca..38d27f740 100644
--- a/NFe.Danfe.Base/NFe/NFeRetrato.frx
+++ b/NFe.Danfe.Base/NFe/NFeRetrato.frx
@@ -73,38 +73,40 @@ namespace FastReport
}
var vol = Report.GetDataSource("NFe.NFe.infNFe.transp.vol");
- vol.Init();
- int qtdeVol = 0;
-
- int volumes = 0;
- decimal pesoL = 0;
- decimal pesoB = 0;
- while (vol.HasMoreRows)
- {
- Memo106.Text = ((String)Report.GetColumnValue("NFe.NFe.infNFe.transp.vol.esp"));
- Memo108.Text = ((String)Report.GetColumnValue("NFe.NFe.infNFe.transp.vol.marca"));
- Memo110.Text = ((String)Report.GetColumnValue("NFe.NFe.infNFe.transp.vol.nVol"));
-
- volumes += ((Nullable<int>)Report.GetColumnValue("NFe.NFe.infNFe.transp.vol.qVol")) ?? 0;
- pesoL += ((Nullable<decimal>)Report.GetColumnValue("NFe.NFe.infNFe.transp.vol.pesoL")) ?? 0M;
- pesoB += ((Nullable<decimal>)Report.GetColumnValue("NFe.NFe.infNFe.transp.vol.pesoB")) ?? 0M;
- qtdeVol++;
- vol.Next();
- }
-
- if (qtdeVol >= 1)
- {
- if (qtdeVol > 1)
+ if(vol != null){
+ vol.Init();
+ int qtdeVol = 0;
+
+ int volumes = 0;
+ decimal pesoL = 0;
+ decimal pesoB = 0;
+ while (vol.HasMoreRows)
{
- Memo106.Text = "VOLUMES";
- Memo108.Text = "";
- Memo110.Text = "";
+ Memo106.Text = ((String)Report.GetColumnValue("NFe.NFe.infNFe.transp.vol.esp"));
+ Memo108.Text = ((String)Report.GetColumnValue("NFe.NFe.infNFe.transp.vol.marca"));
+ Memo110.Text = ((String)Report.GetColumnValue("NFe.NFe.infNFe.transp.vol.nVol"));
+
+ volumes += ((Nullable<int>)Report.GetColumnValue("NFe.NFe.infNFe.transp.vol.qVol")) ?? 0;
+ pesoL += ((Nullable<decimal>)Report.GetColumnValue("NFe.NFe.infNFe.transp.vol.pesoL")) ?? 0M;
+ pesoB += ((Nullable<decimal>)Report.GetColumnValue("NFe.NFe.infNFe.transp.vol.pesoB")) ?? 0M;
+ qtdeVol++;
+ vol.Next();
}
-
- Memo104.Text = volumes.ToString();
- Memo112.Text = FormatNumber(pesoB,3) + " KG";
- Memo114.Text = FormatNumber(pesoL,3) + " KG";
- }
+
+ if (qtdeVol >= 1)
+ {
+ if (qtdeVol > 1)
+ {
+ Memo106.Text = "VOLUMES";
+ Memo108.Text = "";
+ Memo110.Text = "";
+ }
+
+ Memo104.Text = volumes.ToString();
+ Memo112.Text = FormatNumber(pesoB,3) + " KG";
+ Memo114.Text = FormatNumber(pesoL,3) + " KG";
+ }
+ }
if(Engine.FinalPass)
{
diff --git a/NFe.Danfe.Base/NFe/NFeSimplificadoTipo2.frx b/NFe.Danfe.Base/NFe/NFeSimplificadoTipo2.frx
new file mode 100644
index 000000000..09d644b99
--- /dev/null
+++ b/NFe.Danfe.Base/NFe/NFeSimplificadoTipo2.frx
@@ -0,0 +1,1234 @@
+
+
+ using System;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Windows.Forms;
+using System.Drawing;
+using System.Data;
+using System.Text.RegularExpressions;
+using FastReport;
+using FastReport.Data;
+using FastReport.Dialog;
+using FastReport.Barcode;
+using FastReport.Table;
+using FastReport.Utils;
+using NFe.Classes.Informacoes.Pagamento;
+using NFe.Utils;
+using DFe.Utils;
+using NFe.Classes.Informacoes.Destinatario;
+using NFe.Classes.Informacoes.Identificacao.Tipos;
+using DFe.Classes.Flags;
+using NFe.Danfe.Base;
+using DFe.Classes.Entidades;
+using NFe.Classes.Protocolo;
+
+namespace FastReport
+{
+ public class ReportScript
+ {
+ public Image ObterLogo()
+ {
+ byte[] logomarca = Report.GetParameterValue("Logo") as byte[];
+
+ if (logomarca == null) return null;
+
+ using(var ms = new MemoryStream(logomarca))
+ {
+ var image = Image.FromStream(ms);
+ return image;
+ }
+ }
+
+ private void txtDescPagto_BeforePrint(object sender, EventArgs e)
+ {
+ if(Report.GetColumnValue("NFe.NFe.infNFe.pag.tPag") != null)
+ txtDescPagto.Text = ((FormaPagamento)Report.GetColumnValue("NFe.NFe.infNFe.pag.tPag")).Descricao();
+ }
+
+ private void txtDescDetPagto_BeforePrint(object sender, EventArgs e)
+ {
+ if(Report.GetDataSource("NFe.NFe.infNFe.pag.detPag").RowCount != 0 && Report.GetColumnValue("NFe.NFe.infNFe.pag.detPag.tPag") != null)
+ txtDescDetPagto.Text = ((FormaPagamento)Report.GetColumnValue("NFe.NFe.infNFe.pag.detPag.tPag")).Descricao();
+
+ double tamanho1 = (4.2 / 2.54) * 96;
+ double tamanho2 = (1.2 / 2.54) * 96;
+ double tamanho3 = (3.2 / 2.54) * 96;
+ double tamanho4 = (0.2 / 2.54) * 96;
+ if(txtDescDetPagto.Text == "Outros")
+ {
+ txtDescDetPagto.Width = (float)tamanho2;
+ txtDescDetMeioPagto.Left = (float)tamanho2;
+ txtDescDetMeioPagto.Width = (float)tamanho3;
+ }
+ else
+ {
+ txtDescDetPagto.Width = (float)tamanho1;
+ txtDescDetMeioPagto.Left = (float)tamanho1;
+ txtDescDetMeioPagto.Width = (float)tamanho4;
+ }
+ }
+
+ private void txtEmitCnpj_BeforePrint(object sender, EventArgs e)
+ {
+ var cnpj = (string)Report.GetColumnValue("NFe.NFe.infNFe.emit.CNPJ");
+ if (!string.IsNullOrEmpty(cnpj))
+ txtEmitCnpj.Text = "CNPJ: " + String.Format(@"{0:00\.000\.000\/0000\-00}", long.Parse(cnpj));
+ /*
+ var ie = (string)Report.GetColumnValue("NFe.NFe.infNFe.emit.IE");
+ if (!string.IsNullOrEmpty(ie))
+ txtEmitCnpj.Text = txtEmitCnpj.Text + " - IE: " + ie;
+ */
+ }
+
+ private void memChaveNfe_BeforePrint(object sender, EventArgs e)
+ {
+ var chave = Substring( ((String)Report.GetColumnValue("NFe.NFe.infNFe.Id")), 3);
+ if (!string.IsNullOrEmpty(chave) & chave.Length == 44)
+ {
+ var chaveFormatada = "";
+ for (int i = 0; i < chave.Length; i += 4)
+ chaveFormatada = chaveFormatada + chave.Substring(i, 4) + " ";
+ memChaveNfe.Text = chaveFormatada;
+ }
+ }
+
+ private void Destinatario_BeforePrint(object sender, EventArgs e)
+ {
+ TrataCamposDestinatario();
+ dbDestinatario.Visible = ((NfeSimplificadoTipo2LayoutQrCode) Report.GetParameterValue("NfeSimplificadoTipo2LayoutQrCode") == NfeSimplificadoTipo2LayoutQrCode.Abaixo);
+ }
+
+ private void TrataCamposDestinatario(){
+ if ( ((dest)Report.GetColumnValue("NFe.NFe.infNFe.dest")) == null ) //Destinatário não informado
+ {
+ txtConsumidor.Text = "CONSUMIDOR NÃO IDENTIFICADO";
+ txtConsumidor2.Text = txtConsumidor.Text;
+ txtDestEndereco.Text = "";
+ txtDestEndereco2.Text = txtDestEndereco.Text;
+ txtDestNome.Text = "";
+ txtDestNome2.Text = txtDestNome.Text;
+ }
+ else
+ {
+ txtDestNome.Text = ObterDocumentoDest() + ((String)Report.GetColumnValue("NFe.NFe.infNFe.dest.xNome"));
+ txtDestNome2.Text = txtDestNome.Text;
+ }
+ //Endereço do destinatário é opcional para NFe
+ txtDestEndereco.Visible = ((enderDest)Report.GetColumnValue("NFe.NFe.infNFe.dest.enderDest")) != null;
+ txtDestEndereco2.Visible = txtDestEndereco.Visible;
+ }
+
+ private string ObterDocumentoDest(){
+ var documentoDest = "";
+ var cnpj = (String)Report.GetColumnValue("NFe.NFe.infNFe.dest.CNPJ");
+ var cpf = (String)Report.GetColumnValue("NFe.NFe.infNFe.dest.CPF");
+ var idEstrangeiro = (String)Report.GetColumnValue("NFe.NFe.infNFe.dest.idEstrangeiro");
+ if ( !String.IsNullOrEmpty(cnpj)) documentoDest = "CNPJ: " + String.Format(@"{0:00\.000\.000\/0000\-00}", long.Parse(cnpj)) + " ";
+ if ( !String.IsNullOrEmpty(cpf)) documentoDest = "CPF: " + String.Format(@"{0:000\.000\.000\-00}", long.Parse(cpf)) + " ";
+ if ( !String.IsNullOrEmpty(idEstrangeiro)) documentoDest = "Id. Estrangeiro: " + idEstrangeiro + " ";
+ return documentoDest;
+ }
+
+ private void dbProdutosUmaLinha_BeforePrint(object sender, EventArgs e)
+ {
+ //Conforme Manual de Padrões Padrões Técnicos do DANFE-NFC-e e QR Code, página 8. "No caso de emissão em contingência, é obrigatória a impressão do Detalhe da Venda e do DANFE NFC-e"
+ if ( ((TipoEmissao)Report.GetColumnValue("NFe.NFe.infNFe.ide.tpEmis")) == TipoEmissao.teNormal )
+ dbProdutosUmaLinha.Visible = ((NfeSimplificadoTipo2DetalheVendaNormal)((Int32)Report.GetParameterValue("NfeSimplificadoTipo2DetalheVendaNormal"))) == NfeSimplificadoTipo2DetalheVendaNormal.UmaLinha;
+ else
+ dbProdutosUmaLinha.Visible = ((NfeSimplificadoTipo2DetalheVendaContigencia)((Int32)Report.GetParameterValue("NfeSimplificadoTipo2DetalheVendaContigencia"))) == NfeSimplificadoTipo2DetalheVendaContigencia.UmaLinha;
+
+ //Mostrar/Ocultar desconto concedido no item
+ txtProdutoUmaLinhaValorUnit.Text = "[NFe.NFe.infNFe.det.prod.vUnCom]";
+ txtProdutoUmaLinhaValorTotal.Text = "[NFe.NFe.infNFe.det.prod.vProd]";
+ dbProdutosUmaLinha.Border.Lines = BorderLines.None; //BorderLines.Bottom;
+ var imprimeDesconto = dbProdutosUmaLinha.Visible & ((Boolean)Report.GetParameterValue("NfeSimplificadoTipo2ImprimeDescontoItem")) &
+ ((Nullable<Decimal>)Report.GetColumnValue("NFe.NFe.infNFe.det.prod.vDesc")) > 0;
+ cbDescontoItemUmaLinha.Visible = imprimeDesconto;
+ if (imprimeDesconto)
+ dbProdutosUmaLinha.Border.Lines = BorderLines.None;
+ }
+
+ private void ghbProdutosDuasLinhas_BeforePrint(object sender, EventArgs e)
+ {
+ //Conforme Manual de Padrões Padrões Técnicos do DANFE-NFC-e e QR Code, página 8. "No caso de emissão em contingência, é obrigatória a impressão do Detalhe da Venda e do DANFE NFC-e"
+ if ( ((TipoEmissao)Report.GetColumnValue("NFe.NFe.infNFe.ide.tpEmis")) == TipoEmissao.teNormal )
+ ghbProdutosDuasLinhas.Visible = ((NfeSimplificadoTipo2DetalheVendaNormal)((Int32)Report.GetParameterValue("NfeSimplificadoTipo2DetalheVendaNormal"))) == NfeSimplificadoTipo2DetalheVendaNormal.DuasLinhas;
+ else
+ ghbProdutosDuasLinhas.Visible = ((NfeSimplificadoTipo2DetalheVendaContigencia)((Int32)Report.GetParameterValue("NfeSimplificadoTipo2DetalheVendaContigencia"))) == NfeSimplificadoTipo2DetalheVendaContigencia.DuasLinhas;
+ }
+
+ private void dbProdutosDuasLinhas_BeforePrint(object sender, EventArgs e)
+ {
+ //Conforme Manual de Padrões Padrões Técnicos do DANFE-NFC-e e QR Code, página 8. "No caso de emissão em contingência, é obrigatória a impressão do Detalhe da Venda e do DANFE NFC-e"
+ if ( ((TipoEmissao)Report.GetColumnValue("NFe.NFe.infNFe.ide.tpEmis")) == TipoEmissao.teNormal )
+ dbProdutosDuasLinhas.Visible = ((NfeSimplificadoTipo2DetalheVendaNormal)((Int32)Report.GetParameterValue("NfeSimplificadoTipo2DetalheVendaNormal"))) == NfeSimplificadoTipo2DetalheVendaNormal.DuasLinhas;
+ else
+ dbProdutosDuasLinhas.Visible = ((NfeSimplificadoTipo2DetalheVendaContigencia)((Int32)Report.GetParameterValue("NfeSimplificadoTipo2DetalheVendaContigencia"))) == NfeSimplificadoTipo2DetalheVendaContigencia.DuasLinhas;
+
+ //Mostrar/Ocultar desconto concedido no item
+ txtProdutoDuasLinhasValorUnit.Text = "[NFe.NFe.infNFe.det.prod.vUnCom]";
+ txtProdutoDuasLinhasValorTotal.Text = "[NFe.NFe.infNFe.det.prod.vProd]";
+ dbProdutosDuasLinhas.Border.Lines = BorderLines.Bottom;
+ var imprimeDesconto = dbProdutosDuasLinhas.Visible & ((Boolean)Report.GetParameterValue("NfeSimplificadoTipo2ImprimeDescontoItem")) &
+ ((Nullable<Decimal>)Report.GetColumnValue("NFe.NFe.infNFe.det.prod.vDesc")) > 0;
+ cbDescontoItemDuasLinhas.Visible = imprimeDesconto;
+ if (imprimeDesconto)
+ dbProdutosDuasLinhas.Border.Lines = BorderLines.None;
+ //Se possuir desconto, e estiver configurado para não exibi-lo, exibe os valores líquidos nos campos abaixo:
+ if (((Nullable<Decimal>)Report.GetColumnValue("NFe.NFe.infNFe.det.prod.vDesc")) > 0 & !imprimeDesconto)
+ {
+ txtProdutoDuasLinhasValorUnit.Text = "[([NFe.NFe.infNFe.det.prod.vProd] - [NFe.NFe.infNFe.det.prod.vDesc]) / [NFe.NFe.infNFe.det.prod.qCom]]";
+ txtProdutoDuasLinhasValorTotal.Text = "[[NFe.NFe.infNFe.det.prod.vProd] - [NFe.NFe.infNFe.det.prod.vDesc]]";
+ }
+ }
+
+ private void ghbProdutosUmaLinha_BeforePrint(object sender, EventArgs e)
+ {
+ //Conforme Manual de Padrões Padrões Técnicos do DANFE-NFC-e e QR Code, página 8. "No caso de emissão em contingência, é obrigatória a impressão do Detalhe da Venda e do DANFE NFC-e"
+ if ( ((TipoEmissao)Report.GetColumnValue("NFe.NFe.infNFe.ide.tpEmis")) == TipoEmissao.teNormal )
+ ghbProdutosUmaLinha.Visible = ((NfeSimplificadoTipo2DetalheVendaNormal)((Int32)Report.GetParameterValue("NfeSimplificadoTipo2DetalheVendaNormal"))) == NfeSimplificadoTipo2DetalheVendaNormal.UmaLinha;
+ else
+ ghbProdutosUmaLinha.Visible = ((NfeSimplificadoTipo2DetalheVendaContigencia)((Int32)Report.GetParameterValue("NfeSimplificadoTipo2DetalheVendaContigencia"))) == NfeSimplificadoTipo2DetalheVendaContigencia.UmaLinha;
+ }
+
+ private void memMsgFiscal_BeforePrint(object sender, EventArgs e)
+ {
+ //Conforme Manual de Padrões Padrões Técnicos do DANFE-NFC-e e QR Code, página 8
+ string msgHomologacao = "";
+ string msgContigencia = "";
+ if ( ((TipoAmbiente)Report.GetColumnValue("NFe.NFe.infNFe.ide.tpAmb")) == TipoAmbiente.Homologacao )
+ msgHomologacao = "EMITIDA EM AMBIENTE DE HOMOLOGAÇÃO – SEM VALOR FISCAL" + Environment.NewLine;
+ if ( ((TipoEmissao)Report.GetColumnValue("NFe.NFe.infNFe.ide.tpEmis")) != TipoEmissao.teNormal )
+ msgContigencia = "EMITIDA EM CONTINGÊNCIA" + Environment.NewLine;
+
+ memMsgFiscal.Text = msgHomologacao + msgContigencia + memMsgFiscal.Text;
+ }
+
+ private void txtObs_BeforePrint(object sender, EventArgs e)
+ {
+ txtObs.Text = ((String)Report.GetColumnValue("NFe.NFe.infNFe.infAdic.infCpl")).Replace(";", Environment.NewLine);
+ }
+
+ private void PgNfeSimplificadoTipo2_StartPage(object sender, EventArgs e)
+ {
+ phbCancelado.Visible = ((Boolean)Report.GetParameterValue("NfeSimplificadoTipo2Cancelado"));
+
+ if (!Engine.FinalPass)
+ return;
+ if ( (NfeSimplificadoTipo2ModoImpressao) ((Int32)Report.GetParameterValue("NfeSimplificadoTipo2ModoImpressao")) != NfeSimplificadoTipo2ModoImpressao.UnicaPagina)
+ return;
+
+ PgNfeSimplificadoTipo2.PaperHeight =
+ (//rtbTituloHeight +
+ phbEmitenteHeight +
+ ((Boolean)Report.GetParameterValue("NfeSimplificadoTipo2Cancelado") ? phbCancelado.Height : 0)+
+ ghbProdutosUmaLinhaHeight +
+ dbProdutosUmaLinhaHeight +
+ ghbProdutosDuasLinhasHeight +
+ dbProdutosDuasLinhasHeight +
+ gfbProdutosHeight +
+ dbPagamentoHeight +
+ dbDetPagamentoHeight +
+ dbTributosHeight +
+ dbObservacaoHeight +
+ dbInfoFiscalHeight +
+ dbNumeroSerieDhHeight +
+ dbConsultaHeight +
+ dbDestinatarioHeight +
+ dbQrCodeNormalHeight +
+ dbQrCodeLateralHeight +
+ dbProtocoloHeigth
+ ) /
+ Units.Millimeters + PgNfeSimplificadoTipo2.TopMargin + PgNfeSimplificadoTipo2.BottomMargin;
+ }
+
+ float dbProdutosUmaLinhaHeight;
+ private void dbProdutosUmaLinha_AfterPrint(object sender, EventArgs e)
+ {
+ dbProdutosUmaLinhaHeight += (dbProdutosUmaLinha.Visible ? dbProdutosUmaLinha.Height : 0) + (cbDescontoItemUmaLinha.Visible ? cbDescontoItemUmaLinha.Height : 0);
+ }
+
+ float dbProdutosDuasLinhasHeight;
+ private void dbProdutosDuasLinhas_AfterPrint(object sender, EventArgs e)
+ {
+ dbProdutosDuasLinhasHeight += (dbProdutosDuasLinhas.Visible ?dbProdutosDuasLinhas.Height : 0) + (cbDescontoItemDuasLinhas.Visible ? cbDescontoItemDuasLinhas.Height : 0);
+ }
+
+ float dbInfoFiscalHeight;
+ private void dbInfoFiscal_AfterPrint(object sender, EventArgs e)
+ {
+ dbInfoFiscalHeight = (dbInfoFiscal.Visible ? dbInfoFiscal.Height : 0);
+ }
+
+ float dbNumeroSerieDhHeight;
+ private void dbNumeroSerieDh_AfterPrint(object sender, EventArgs e)
+ {
+ dbNumeroSerieDhHeight = (dbNumeroSerieDh.Visible ? dbNumeroSerieDh.Height : 0);
+ }
+
+ float dbConsultaHeight;
+ private void dbConsulta_AfterPrint(object sender, EventArgs e)
+ {
+ dbConsultaHeight = (dbConsulta.Visible ? dbConsulta.Height : 0);
+ }
+
+ float phbEmitenteHeight;
+ private void phbEmitente_AfterPrint(object sender, EventArgs e)
+ {
+ phbEmitenteHeight = (phbEmitente.Visible ? phbEmitente.Height : 0);
+ }
+
+ float ghbProdutosUmaLinhaHeight;
+ private void ghbProdutosUmaLinha_AfterPrint(object sender, EventArgs e)
+ {
+ ghbProdutosUmaLinhaHeight = (ghbProdutosUmaLinha.Visible ? ghbProdutosUmaLinha.Height : 0);
+ }
+
+ float ghbProdutosDuasLinhasHeight;
+ private void ghbProdutosDuasLinhas_AfterPrint(object sender, EventArgs e)
+ {
+ ghbProdutosDuasLinhasHeight = (ghbProdutosDuasLinhas.Visible ? ghbProdutosDuasLinhas.Height : 0);
+ }
+
+ float gfbProdutosHeight;
+ private void gfbProdutos_AfterPrint(object sender, EventArgs e)
+ {
+ gfbProdutosHeight = (gfbProdutos.Visible ? gfbProdutos.Height : 0);
+ }
+
+ float dbPagamentoHeight;
+ private void dbPagamento_AfterPrint(object sender, EventArgs e)
+ {
+ dbPagamentoHeight = (dbPagamento.Visible ? dbPagamento.Height : 0);
+ }
+
+ float dbDetPagamentoHeight;
+ private void dbDetPagamento_AfterPrint(object sender, EventArgs e)
+ {
+ dbDetPagamentoHeight = (dbDetPagamento.Visible ? dbDetPagamento.Height : 0);
+ }
+
+ float dbTributosHeight;
+ private void dbTributos_AfterPrint(object sender, EventArgs e)
+ {
+ dbTributosHeight = (dbTributos.Visible ? dbTributos.Height : 0);
+ }
+
+ float dbObservacaoHeight;
+ private void dbObservacao_AfterPrint(object sender, EventArgs e)
+ {
+ dbObservacaoHeight = (dbObservacao.Visible ? dbObservacao.Height : 0);
+ }
+
+ float dbDestinatarioHeight;
+ private void dbDestinatario_AfterPrint(object sender, EventArgs e)
+ {
+ dbDestinatarioHeight = (dbDestinatario.Visible ? dbDestinatario.Height : 0);
+ }
+
+ float dbQrCodeNormalHeight;
+ private void dbQrCode_AfterPrint(object sender, EventArgs e)
+ {
+ dbQrCodeNormalHeight = (dbQrCodeNormal.Visible ? dbQrCodeNormal.Height : 0);
+ }
+
+ private void cbDesconto_BeforePrint(object sender, EventArgs e)
+ {
+ cbDesconto.Visible = (((Decimal)Report.GetColumnValue("NFe.NFe.infNFe.total.ICMSTot.vDesc")) > 0) ||
+ (((Decimal)Report.GetColumnValue("NFe.NFe.infNFe.total.ICMSTot.vFrete")) > 0) ||
+ (((Decimal)Report.GetColumnValue("NFe.NFe.infNFe.total.IBSCBSTot.gCBS.vCBS")) > 0) ||
+ (((Decimal)Report.GetColumnValue("NFe.NFe.infNFe.total.IBSCBSTot.gIBS.vIBS")) > 0) ||
+ (((Decimal)Report.GetColumnValue("NFe.NFe.infNFe.total.ISTot.vIS")) > 0);
+
+ float vTop = 0;
+ if (((Decimal)Report.GetColumnValue("NFe.NFe.infNFe.total.ICMSTot.vDesc")) == 0)
+ {
+ Text43.Visible = false;
+ Text44.Visible = false;
+ }
+ else
+ vTop = vTop + Text44.Height;
+
+ if (((Decimal)Report.GetColumnValue("NFe.NFe.infNFe.total.ICMSTot.vFrete")) == 0)
+ {
+ Text52.Visible = false;
+ Text54.Visible = false;
+ }
+ else
+ vTop = vTop + Text54.Height;
+
+ if (Report.GetColumnValue("NFe.NFe.infNFe.total.IBSCBSTot.gCBS.vCBS") != null)
+ {
+ Text53.Top = vTop;
+ Text55.Top = vTop;
+ vTop = vTop + Text53.Height;
+ }
+ if (Report.GetColumnValue("NFe.NFe.infNFe.total.IBSCBSTot.gIBS.vIBS") != null)
+ {
+ Text57.Top = vTop;
+ Text58.Top = vTop;
+ vTop = vTop + Text58.Height;
+ }
+ if (((Nullable<Decimal>)Report.GetColumnValue("NFe.NFe.infNFe.total.ISTot.vIS") ?? 0m) > 0)
+ {
+ Text59.Top = vTop;
+ Text60.Top = vTop;
+ vTop = vTop + Text60.Height;
+ }
+ else
+ {
+ Text59.Visible = false;
+ Text60.Visible = false;
+ }
+ Text45.Top = vTop;
+ Text46.Top = vTop;
+ cbDesconto.Height = vTop + Text46.Height;
+ }
+
+ private void txtTotal_BeforePrint(object sender, EventArgs e)
+ {
+ var vServ = ((Nullable<Decimal>)Report.GetColumnValue("NFe.NFe.infNFe.total.ISSQNtot.vServ")) == null ? 0 : ((Nullable<Decimal>)Report.GetColumnValue("NFe.NFe.infNFe.total.ISSQNtot.vServ"));
+ txtTotal.Text = (((Decimal)Report.GetColumnValue("NFe.NFe.infNFe.total.ICMSTot.vProd")) + vServ).ToString();
+ }
+
+ private void dbPagamento_BeforePrint(object sender, EventArgs e)
+ {
+ dbPagamento.Visible = Report.GetColumnValue("NFe.NFe.infNFe.pag.tPag") != null;
+ }
+
+ private void dbDetPagamento_BeforePrint(object sender, EventArgs e)
+ {
+ dbDetPagamento.Visible = Report.GetDataSource("NFe.NFe.infNFe.pag.detPag").RowCount != 0 && Report.GetColumnValue("NFe.NFe.infNFe.pag.detPag.tPag") != null;
+ }
+
+ private void dbTroco_BeforePrint(object sender, EventArgs e)
+ {
+ dbTroco.Visible = Report.GetColumnValue("NFe.NFe.infNFe.pag.vTroco") != null;
+ }
+
+ private void dbQrCodeLateral_BeforePrint(object sender, EventArgs e)
+ {
+ TrataCamposDestinatario();
+ dbQrCodeLateral.Visible = ((NfeSimplificadoTipo2LayoutQrCode) Report.GetParameterValue("NfeSimplificadoTipo2LayoutQrCode") == NfeSimplificadoTipo2LayoutQrCode.Lateral);
+ }
+
+ float dbQrCodeLateralHeight;
+ private void dbQrCodeLateral_AfterPrint(object sender, EventArgs e)
+ {
+ dbQrCodeLateralHeight = (dbQrCodeLateral.Visible ? dbQrCodeLateral.Height : 0);
+ }
+
+ float dbProtocoloHeigth;
+ private void dbProtocolo_AfterPrint(object sender, EventArgs e)
+ {
+ dbProtocoloHeigth = (dbProtocolo.Visible ? dbProtocolo.Height : 0);
+ }
+
+ private void dbQrCodeNormal_BeforePrint(object sender, EventArgs e)
+ {
+ dbQrCodeNormal.Visible = ((NfeSimplificadoTipo2LayoutQrCode) Report.GetParameterValue("NfeSimplificadoTipo2LayoutQrCode") == NfeSimplificadoTipo2LayoutQrCode.Abaixo);
+ }
+
+ private void dbProtocolo_BeforePrint(object sender, EventArgs e)
+ {
+ dbProtocolo.Visible = ((protNFe)Report.GetColumnValue("NFe.protNFe")) != null;
+ }
+
+ private void dbNumeroSerieDh_BeforePrint(object sender, EventArgs e)
+ {
+ dbNumeroSerieDh.Visible = ((NfeSimplificadoTipo2LayoutQrCode) Report.GetParameterValue("NfeSimplificadoTipo2LayoutQrCode") == NfeSimplificadoTipo2LayoutQrCode.Abaixo);
+ }
+
+ private void phbEmitente_BeforePrint(object sender, EventArgs e)
+ {
+ poEmitLogo.Image = ObterLogo();
+ }
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NFe.Danfe.Fast.Skia/DanfeFastBase.cs b/NFe.Danfe.Fast.Skia/DanfeFastBase.cs
index 9c46c64b1..f71781017 100644
--- a/NFe.Danfe.Fast.Skia/DanfeFastBase.cs
+++ b/NFe.Danfe.Fast.Skia/DanfeFastBase.cs
@@ -19,6 +19,7 @@ public void ExportarPdf(string arquivo)
Relatorio.Prepare();
Relatorio.Export(new PDFExport(), arquivo);
}
+
///
/// Converte o DANFE para PDF e copia para o stream
///
@@ -37,6 +38,27 @@ public void ExportarPdf(Stream outputStream)
}
}
+ ///
+ /// Converte o DANFE para PDF retorna como byte[]
+ ///
+ public byte[] ExportarPdf()
+ {
+ using (MemoryStream stream = new MemoryStream()) // Create a stream for the report
+ {
+ try
+ {
+ Relatorio.Prepare();
+ Relatorio.Export(new PDFExport(), stream);
+ return stream.ToArray();
+ }
+ catch (System.Exception ex)
+ {
+ throw ex;
+ }
+ }
+ }
+
+
///
/// Converte o DANFE para PDF e salva-o no caminho/arquivo indicado
///
@@ -65,7 +87,28 @@ public void ExportarPdf(Stream outputStream, FastReport.Export.ExportBase export
Relatorio.Export(exportBase, outputStream);
outputStream.Position = 0;
}
-
+
+ ///
+ /// Converte o DANFE para PDF retorna como byte[]
+ ///
+ /// Instancia do tipo de exportacao do FastReport
+ public byte[] ExportarPdf(FastReport.Export.ExportBase exportBase)
+ {
+ using (MemoryStream stream = new MemoryStream()) // Create a stream for the report
+ {
+ try
+ {
+ Relatorio.Prepare();
+ Relatorio.Export(exportBase, stream);
+ return stream.ToArray();
+ }
+ catch (System.Exception ex)
+ {
+ throw ex;
+ }
+ }
+ }
+
public byte[] ExportarHtml()
{
using (MemoryStream stream = new MemoryStream()) // Create a stream for the report
diff --git a/NFe.Danfe.Fast/NFe/DanfeFrSimplificadoTipo2.cs b/NFe.Danfe.Fast/NFe/DanfeFrSimplificadoTipo2.cs
new file mode 100644
index 000000000..1c96ba956
--- /dev/null
+++ b/NFe.Danfe.Fast/NFe/DanfeFrSimplificadoTipo2.cs
@@ -0,0 +1,31 @@
+using DFe.Utils;
+using NFe.Classes;
+using NFe.Danfe.Base.NFe;
+using Shared.DFe.Danfe;
+
+namespace NFe.Danfe.Fast.NFe
+{
+ public class DanfeFrSimplificadoTipo2 : DanfeFastBase
+ {
+ ///
+ /// Construtor da classe responsável pela impressão do DANFE Simplificado Tipo 2 da NF-e em Fast Reports
+ ///
+ /// Objeto do tipo nfeProc
+ /// Objeto do tipo contendo as definições de impressão
+ /// Identificador do Token CSC
+ /// Token CSC para geração do QR Code
+ /// Texto do desenvolvedor a ser informado no DANFE
+ /// Caminho do arquivo frx
+ public DanfeFrSimplificadoTipo2(nfeProc proc, ConfiguracaoDanfeNfeSimplificadoTipo2 configuracao, string cIdToken, string csc, string desenvolvedor = "", string arquivoRelatorio = "")
+ {
+ byte[] frx = null;
+ if (string.IsNullOrWhiteSpace(arquivoRelatorio))
+ {
+ const string caminho = @"NFe\NFeSimplificadoTipo2.frx";
+ frx = FrxFileHelper.TryGetFrxFile(caminho);
+ }
+
+ Relatorio = DanfeSharedHelper.GenerateDanfeFrNfeSimplificadoTipo2Report(proc, configuracao, cIdToken, csc, frx, desenvolvedor, arquivoRelatorio);
+ }
+ }
+}
diff --git a/NFe.Danfe.OpenFast/DanfeOpenFastBase.cs b/NFe.Danfe.OpenFast/DanfeOpenFastBase.cs
index 8d2ce3d08..1eeaf0b27 100644
--- a/NFe.Danfe.OpenFast/DanfeOpenFastBase.cs
+++ b/NFe.Danfe.OpenFast/DanfeOpenFastBase.cs
@@ -39,6 +39,26 @@ public void ExportarPdf(Stream outputStream)
}
}
+ ///
+ /// Converte o DANFE para PDF retorna como byte[]
+ ///
+ public byte[] ExportarPdf()
+ {
+ using (MemoryStream stream = new MemoryStream()) // Create a stream for the report
+ {
+ try
+ {
+ Relatorio.Prepare();
+ Relatorio.Export(new PDFSimpleExport(), stream);
+ return stream.ToArray();
+ }
+ catch (System.Exception ex)
+ {
+ throw ex;
+ }
+ }
+ }
+
///
/// Converte o DANFE para PDF e salva-o no caminho/arquivo indicado
///
@@ -68,14 +88,18 @@ public void ExportarPdf(Stream outputStream, FastReport.Export.ExportBase export
outputStream.Position = 0;
}
- public byte[] ExportarPdf()
+ ///
+ /// Converte o DANFE para PDF retorna como byte[]
+ ///
+ /// Instancia do tipo de exportacao do FastReport
+ public byte[] ExportarPdf(FastReport.Export.ExportBase exportBase)
{
using (MemoryStream stream = new MemoryStream()) // Create a stream for the report
{
try
{
Relatorio.Prepare();
- Relatorio.Export(new PDFSimpleExport(), stream);
+ Relatorio.Export(exportBase, stream);
return stream.ToArray();
}
catch (System.Exception ex)
diff --git a/NFe.Danfe.PdfClown/Elementos/Barcode128C.cs b/NFe.Danfe.PdfClown/Elementos/Barcode128C.cs
index 524688bad..6ab3d5132 100644
--- a/NFe.Danfe.PdfClown/Elementos/Barcode128C.cs
+++ b/NFe.Danfe.PdfClown/Elementos/Barcode128C.cs
@@ -1,6 +1,7 @@
using System.Drawing;
using System.Text.RegularExpressions;
using NFe.Danfe.PdfClown.Graphics;
+using NFe.Danfe.PdfClown.Tools;
namespace NFe.Danfe.PdfClown.Elementos
{
@@ -144,12 +145,13 @@ public Barcode128C(string code, Estilo estilo, float largura = 75F) : base(estil
throw new ArgumentException("O código não pode ser vazio.", "code");
}
- if (!Regex.IsMatch(code, @"^\d+$"))
+ // NT Conjunta 2025.001: a chave de acesso pode conter letras maiúsculas nas posições do CNPJ
+ if (!Regex.IsMatch(code, "^[0-9A-Z]+$"))
{
- throw new ArgumentException("O código deve apenas conter digítos numéricos.", "code");
+ throw new ArgumentException("O código deve apenas conter digítos numéricos e letras maiúsculas.", "code");
}
- if (code.Length % 2 != 0)
+ if (Regex.IsMatch(code, @"^\d+$") && code.Length % 2 != 0)
{
Code = "0" + code;
}
@@ -163,35 +165,14 @@ public Barcode128C(string code, Estilo estilo, float largura = 75F) : base(estil
private void DrawBarcode(RectangleF rect, Gfx gfx)
{
+ byte[] codeBytes = Code128Hibrido.ObterSimbolos(this.Code);
- List codeBytes = new List();
-
- codeBytes.Add(105);
-
- for (int i = 0; i < this.Code.Length; i += 2)
- {
- byte b = byte.Parse(this.Code.Substring(i, 2));
- codeBytes.Add(b);
- }
-
- // Calcular dígito verificador
- int cd = 105;
-
- for (int i = 1; i < codeBytes.Count; i++)
- {
- cd += i * codeBytes[i];
- cd %= 103;
- }
-
- codeBytes.Add((byte)cd);
- codeBytes.Add(106);
-
- float n = codeBytes.Count * 11 + 2;
+ float n = codeBytes.Length * 11 + 2;
float w = rect.Width / n;
float x = 0;
- for (int i = 0; i < codeBytes.Count; i++)
+ for (int i = 0; i < codeBytes.Length; i++)
{
byte[] pt = Barcode128C.Dic[codeBytes[i]];
diff --git a/NFe.Danfe.PdfClown/Tools/Code128Hibrido.cs b/NFe.Danfe.PdfClown/Tools/Code128Hibrido.cs
new file mode 100644
index 000000000..e48f23d6f
--- /dev/null
+++ b/NFe.Danfe.PdfClown/Tools/Code128Hibrido.cs
@@ -0,0 +1,149 @@
+using System.Text.RegularExpressions;
+
+namespace NFe.Danfe.PdfClown.Tools
+{
+ ///
+ /// Codificador CODE-128 híbrido (subconjuntos C e A) conforme a seção 6 da NT Conjunta 2025.001,
+ /// para o código de barras da chave de acesso com CNPJ alfanumérico.
+ /// Regras: inicia com Start C (105); alterna para o Code A (código 101) nos caracteres não numéricos;
+ /// retorna ao Code C (código 99) em corridas de 4 ou mais dígitos ou em corrida final com quantidade
+ /// par de dígitos; dígito ímpar remanescente antes de uma letra fica no Code A.
+ /// Conteúdo 100% numérico produz exatamente a sequência do CODE-128 C puro.
+ ///
+ public static class Code128Hibrido
+ {
+ private const byte StartC = 105;
+ private const byte TrocaParaCodeA = 101;
+ private const byte TrocaParaCodeC = 99;
+ private const byte Stop = 106;
+
+ ///
+ /// Obtém a sequência completa de símbolos CODE-128 (Start C, dados com as trocas de subconjunto,
+ /// dígito verificador módulo 103 e Stop) para um conteúdo composto por dígitos e letras maiúsculas.
+ ///
+ /// Conteúdo a codificar ([0-9A-Z]+), ex.: chave de acesso de 44 posições
+ /// Símbolos CODE-128, um valor (0-106) por posição
+ public static byte[] ObterSimbolos(string codigo)
+ {
+ if (string.IsNullOrEmpty(codigo))
+ throw new ArgumentException("O código não pode ser vazio.", nameof(codigo));
+
+ if (!Regex.IsMatch(codigo, "^[0-9A-Z]+$"))
+ throw new ArgumentException("O código deve conter somente dígitos (0-9) e letras maiúsculas (A-Z).", nameof(codigo));
+
+ var simbolos = new List { StartC };
+ var emCodeC = true;
+ var i = 0;
+
+ while (i < codigo.Length)
+ {
+ var corrida = TamanhoCorridaDeDigitos(codigo, i);
+
+ if (corrida == 0)
+ {
+ //caractere não numérico: garante o Code A e codifica a letra
+ if (emCodeC)
+ {
+ simbolos.Add(TrocaParaCodeA);
+ emCodeC = false;
+ }
+
+ simbolos.Add(ValorCodeA(codigo[i]));
+ i++;
+ continue;
+ }
+
+ var corridaFinal = i + corrida == codigo.Length;
+
+ if (emCodeC)
+ {
+ //em Code C codifica os dígitos aos pares; o dígito ímpar remanescente fica no Code A
+ for (var p = 0; p < corrida / 2; p++)
+ {
+ simbolos.Add(ValorCodeC(codigo, i));
+ i += 2;
+ }
+
+ if (corrida % 2 == 1)
+ {
+ simbolos.Add(TrocaParaCodeA);
+ emCodeC = false;
+ simbolos.Add(ValorCodeA(codigo[i]));
+ i++;
+ }
+ }
+ else if (corrida >= 4 || (corridaFinal && corrida % 2 == 0))
+ {
+ //retorna ao Code C para a parte com quantidade par de dígitos
+ if (corrida % 2 == 1 && corridaFinal)
+ {
+ //corrida final ímpar de 4+ dígitos: o primeiro dígito fica no Code A para a parte restante ser par
+ simbolos.Add(ValorCodeA(codigo[i]));
+ i++;
+ corrida--;
+ }
+
+ simbolos.Add(TrocaParaCodeC);
+ emCodeC = true;
+
+ for (var p = 0; p < corrida / 2; p++)
+ {
+ simbolos.Add(ValorCodeC(codigo, i));
+ i += 2;
+ }
+
+ //corrida ímpar antes de letra: o dígito remanescente é codificado no Code A na próxima iteração
+ }
+ else
+ {
+ //corrida curta (1 a 3 dígitos) que não justifica a troca: codifica os dígitos no próprio Code A
+ for (var d = 0; d < corrida; d++)
+ {
+ simbolos.Add(ValorCodeA(codigo[i]));
+ i++;
+ }
+ }
+ }
+
+ simbolos.Add(ObterDigitoVerificador(simbolos));
+ simbolos.Add(Stop);
+
+ return simbolos.ToArray();
+ }
+
+ ///
+ /// Dígito verificador módulo 103: soma ponderada dos símbolos, com o start valendo peso 1
+ /// e cada símbolo de dados o peso da sua posição
+ ///
+ private static byte ObterDigitoVerificador(List simbolos)
+ {
+ var soma = (int)simbolos[0];
+
+ for (var i = 1; i < simbolos.Count; i++)
+ soma += i * simbolos[i];
+
+ return (byte)(soma % 103);
+ }
+
+ private static int TamanhoCorridaDeDigitos(string codigo, int inicio)
+ {
+ var fim = inicio;
+
+ while (fim < codigo.Length && codigo[fim] >= '0' && codigo[fim] <= '9')
+ fim++;
+
+ return fim - inicio;
+ }
+
+ private static byte ValorCodeC(string codigo, int posicao)
+ {
+ return (byte)((codigo[posicao] - '0') * 10 + (codigo[posicao + 1] - '0'));
+ }
+
+ private static byte ValorCodeA(char caractere)
+ {
+ //no Code A os caracteres ASCII 32-95 valem ASCII - 32 ('0'-'9' => 16-25; 'A'-'Z' => 33-58)
+ return (byte)(caractere - 32);
+ }
+ }
+}
diff --git a/NFe.Servicos/ServicosNFe.cs b/NFe.Servicos/ServicosNFe.cs
index 0aaafb209..13f0be433 100644
--- a/NFe.Servicos/ServicosNFe.cs
+++ b/NFe.Servicos/ServicosNFe.cs
@@ -855,6 +855,23 @@ public RetornoRecepcaoEvento RecepcaoEventoManifestacaoDestinatario(int idlote,
return retorno;
}
+ ///
+ /// Envia eventos do tipo "Manifestação do destinatário" já assinado.
+ ///
+ ///
+ ///
+ ///
+ /// false (padrão) para transmitir os eventos exatamente como vieram, já assinados; true para a biblioteca
+ /// calcular o Id e assinar cada evento com o certificado desta instância de ServicosNFe, sobrescrevendo o Id
+ /// que já estiver preenchido.
+ ///
+ ///
+ public RetornoRecepcaoEvento RecepcaoEventoManifestacaoDestinatario(int idlote, List eventos, bool assinar = false)
+ {
+ var retorno = RecepcaoEvento(idlote, eventos, ServicoNFe.RecepcaoEventoManifestacaoDestinatario, _cFgServico.VersaoRecepcaoEventoManifestacaoDestinatario, assinar);
+ return retorno;
+ }
+
///
/// Envia um evento do tipo "EPEC"
///
@@ -996,6 +1013,23 @@ public RetornoRecepcaoEvento RecepcaoEventoInsucessoEntrega(int idlote,
return retorno;
}
+ ///
+ /// Envia eventos do tipo "Insucesso na Entrega da NF-e" já assinado.
+ ///
+ ///
+ ///
+ ///
+ /// false (padrão) para transmitir os eventos exatamente como vieram, já assinados; true para a biblioteca
+ /// calcular o Id e assinar cada evento com o certificado desta instância de ServicosNFe, sobrescrevendo o Id
+ /// que já estiver preenchido.
+ ///
+ ///
+ public RetornoRecepcaoEvento RecepcaoEventoInsucessoEntrega(int idlote, List eventos, bool assinar = false)
+ {
+ var retorno = RecepcaoEvento(idlote, eventos, ServicoNFe.RecepcaoEventoInsucessoEntregaNFe, _cFgServico.VersaoRecepcaoEventoInsucessoEntrega, assinar);
+ return retorno;
+ }
+
///
/// Serviço para cancelamento insucesso na entrega
///
@@ -1048,6 +1082,23 @@ public RetornoRecepcaoEvento RecepcaoEventoCancInsucessoEntrega(int idlote,
return retorno;
}
+ ///
+ /// Envia eventos do tipo "Cancelamento do Insucesso na Entrega da NF-e" já assinado.
+ ///
+ ///
+ ///
+ ///
+ /// false (padrão) para transmitir os eventos exatamente como vieram, já assinados; true para a biblioteca
+ /// calcular o Id e assinar cada evento com o certificado desta instância de ServicosNFe, sobrescrevendo o Id
+ /// que já estiver preenchido.
+ ///
+ ///
+ public RetornoRecepcaoEvento RecepcaoEventoCancInsucessoEntrega(int idlote, List eventos, bool assinar = false)
+ {
+ var retorno = RecepcaoEvento(idlote, eventos, ServicoNFe.RecepcaoEventoCancInsucessoEntregaNFe, _cFgServico.VersaoRecepcaoEventoInsucessoEntrega, assinar);
+ return retorno;
+ }
+
///
/// Recepção do Evento de Comprovante de Entrega
///
@@ -1117,6 +1168,23 @@ public RetornoRecepcaoEvento RecepcaoEventoComprovanteEntrega(int idlote,
return retorno;
}
+ ///
+ /// Envia eventos do tipo "Comprovante de Entrega da NF-e" já assinado.
+ ///
+ ///
+ ///
+ ///
+ /// false (padrão) para transmitir os eventos exatamente como vieram, já assinados; true para a biblioteca
+ /// calcular o Id e assinar cada evento com o certificado desta instância de ServicosNFe, sobrescrevendo o Id
+ /// que já estiver preenchido.
+ ///
+ ///
+ public RetornoRecepcaoEvento RecepcaoEventoComprovanteEntrega(int idlote, List eventos, bool assinar = false)
+ {
+ var retorno = RecepcaoEvento(idlote, eventos, ServicoNFe.RecepcaoEventoComprovanteEntregaNFe, _cFgServico.VersaoRecepcaoEventoComprovanteEntrega, assinar);
+ return retorno;
+ }
+
///
/// Serviço para cancelamento comprovante de entrega
///
@@ -1170,6 +1238,23 @@ public RetornoRecepcaoEvento RecepcaoEventoCancComprovanteEntrega(int idlote,
return retorno;
}
+ ///
+ /// Envia eventos do tipo "Cancelamento do Comprovante de Entrega da NF-e" já assinado.
+ ///
+ ///
+ ///
+ ///
+ /// false (padrão) para transmitir os eventos exatamente como vieram, já assinados; true para a biblioteca
+ /// calcular o Id e assinar cada evento com o certificado desta instância de ServicosNFe, sobrescrevendo o Id
+ /// que já estiver preenchido.
+ ///
+ ///
+ public RetornoRecepcaoEvento RecepcaoEventoCancComprovanteEntrega(int idlote, List eventos, bool assinar = false)
+ {
+ var retorno = RecepcaoEvento(idlote, eventos, ServicoNFe.RecepcaoEventoCancComprovanteEntregaNFe, _cFgServico.VersaoRecepcaoEventoComprovanteEntrega, assinar);
+ return retorno;
+ }
+
///
/// Recepção do Evento de Conciliação Financeira
@@ -1221,6 +1306,23 @@ public RetornoRecepcaoEvento RecepcaoEventoConciliacaoFinanceira(int idlote,
return retorno;
}
+ ///
+ /// Envia eventos do tipo "Conciliação Financeira da NF-e" já assinado.
+ ///
+ ///
+ ///
+ ///
+ /// false (padrão) para transmitir os eventos exatamente como vieram, já assinados; true para a biblioteca
+ /// calcular o Id e assinar cada evento com o certificado desta instância de ServicosNFe, sobrescrevendo o Id
+ /// que já estiver preenchido.
+ ///
+ ///
+ public RetornoRecepcaoEvento RecepcaoEventoConciliacaoFinanceira(int idlote, List eventos, bool assinar = false)
+ {
+ var retorno = RecepcaoEvento(idlote, eventos, ServicoNFe.RecepcaoEventoConciliacaoFinanceiraNFe, _cFgServico.VersaoRecepcaoEventoConciliacaoFinanceira, assinar);
+ return retorno;
+ }
+
///
/// Serviço para cancelamento Conciliação Financeira
///
@@ -1348,6 +1450,23 @@ public RetornoRecepcaoEvento RecepcaoEventoSolicitacaoDeApropriacaoDeCreditoPres
return retornoRecepcaoEvento;
}
+ ///
+ /// Envia eventos do tipo "Cancelamento da Conciliação Financeira da NF-e" já assinado.
+ ///
+ ///
+ ///
+ ///
+ /// false (padrão) para transmitir os eventos exatamente como vieram, já assinados; true para a biblioteca
+ /// calcular o Id e assinar cada evento com o certificado desta instância de ServicosNFe, sobrescrevendo o Id
+ /// que já estiver preenchido.
+ ///
+ ///
+ public RetornoRecepcaoEvento RecepcaoEventoCancConciliacaoFinanceira(int idlote, List eventos, bool assinar = false)
+ {
+ var retorno = RecepcaoEvento(idlote, eventos, ServicoNFe.RecepcaoEventoCancConciliacaoFinanceiraNFe, _cFgServico.VersaoRecepcaoEventoConciliacaoFinanceira, assinar);
+ return retorno;
+ }
+
///
/// Serviço para evento destinação de item para consumo pessoal
///
diff --git a/NFe.Utils.Testes/ExtinfNFeSuplChaveAlfanumericaTestes.cs b/NFe.Utils.Testes/ExtinfNFeSuplChaveAlfanumericaTestes.cs
new file mode 100644
index 000000000..f4b3fda9e
--- /dev/null
+++ b/NFe.Utils.Testes/ExtinfNFeSuplChaveAlfanumericaTestes.cs
@@ -0,0 +1,82 @@
+using System;
+using DFe.Classes.Entidades;
+using DFe.Classes.Flags;
+using NFe.Classes;
+using NFe.Classes.Informacoes;
+using NFe.Classes.Informacoes.Identificacao;
+using NFe.Classes.Informacoes.Identificacao.Tipos;
+using NFe.Classes.Informacoes.Total;
+using NFe.Utils.InformacoesSuplementares;
+using Xunit;
+
+namespace NFe.Utils.Testes
+{
+ ///
+ /// Testes do QR-Code da NFC-e com chave de acesso contendo CNPJ alfanumérico (NT Conjunta 2025.001)
+ ///
+ public class ExtinfNFeSuplChaveAlfanumericaTestes
+ {
+ //NFC-e de GO com o CNPJ alfanumérico de teste da Receita (PC3D315K000193); DV da chave = 0
+ private const string ChaveAlfanumerica = "522507PC3D315K000193650010000000011000000010";
+
+ private static Classes.NFe CriarNfce(string chave)
+ {
+ return new Classes.NFe
+ {
+ infNFe = new infNFe
+ {
+ Id = "NFe" + chave,
+ versao = "4.00",
+ ide = new ide
+ {
+ tpAmb = TipoAmbiente.Homologacao,
+ cUF = Estado.GO,
+ tpEmis = TipoEmissao.teNormal,
+ dhEmi = new DateTimeOffset(2025, 7, 15, 10, 0, 0, TimeSpan.FromHours(-3))
+ },
+ total = new total
+ {
+ ICMSTot = new ICMSTot { vNF = 10.50m }
+ }
+ }
+ };
+ }
+
+ [Fact]
+ public void ObterUrlQrCode2_ComChaveAlfanumerica_MontaAUrlComAChaveSemConversaoNumerica()
+ {
+ // Arrange
+ var nfce = CriarNfce(ChaveAlfanumerica);
+
+ // Act
+ var url = new infNFeSupl().ObterUrlQrCode(nfce, VersaoQrCode.QrCodeVersao2, "000001", "CSC-DE-TESTE");
+
+ // Assert
+ Assert.Contains(ChaveAlfanumerica, url);
+
+ //formato dos parâmetros: chave|versão do QR-Code|ambiente|idCsc|hash SHA-1
+ var parametros = url.Substring(url.IndexOf("p=", StringComparison.Ordinal) + 2).Split('|');
+ Assert.Equal(5, parametros.Length);
+ Assert.Equal(ChaveAlfanumerica, parametros[0]);
+ Assert.Equal("2", parametros[1]);
+ Assert.Equal("2", parametros[2]);
+ Assert.Equal("1", parametros[3]);
+ Assert.Equal(40, parametros[4].Trim().Length);
+ }
+
+ [Fact]
+ public void ObterUrlQrCode2_ComChaveNumerica_MantemComportamentoAntigo()
+ {
+ // Arrange
+ var nfce = CriarNfce("23190811820016000167650010000000221100000227");
+
+ // Act
+ var url = new infNFeSupl().ObterUrlQrCode(nfce, VersaoQrCode.QrCodeVersao2, "000001", "CSC-DE-TESTE");
+
+ // Assert
+ var parametros = url.Substring(url.IndexOf("p=", StringComparison.Ordinal) + 2).Split('|');
+ Assert.Equal("23190811820016000167650010000000221100000227", parametros[0]);
+ Assert.Equal(40, parametros[4].Trim().Length);
+ }
+ }
+}
diff --git a/NFe.Utils/Evento/Extevento.cs b/NFe.Utils/Evento/Extevento.cs
index 95ad2764d..b5fa718ec 100644
--- a/NFe.Utils/Evento/Extevento.cs
+++ b/NFe.Utils/Evento/Extevento.cs
@@ -34,6 +34,7 @@
using System.Security.Cryptography.X509Certificates;
using DFe.Utils;
using NFe.Classes.Servicos.Evento;
+using NFe.Classes.Servicos.Tipos;
using NFe.Utils.Assinatura;
namespace NFe.Utils.Evento
@@ -50,6 +51,23 @@ public static string ObterXmlString(this evento pedEvento)
return FuncoesXml.ClasseParaXmlString(pedEvento);
}
+ ///
+ /// Obtém o Id de um evento (infEvento/@Id): literal "ID" + tpEvento + chNFe + nSeqEvento com 2 dígitos
+ ///
+ /// Uso opcional, para quando o evento for montado fora da biblioteca — por exemplo, para assinar com o
+ /// certificado numa máquina cliente e depois transmitir com a sobrecarga que recebe o evento já
+ /// assinado. Os métodos que assinam internamente continuam calculando o Id sozinhos.
+ ///
+ ///
+ /// Código do evento
+ /// Chave de acesso da NF-e vinculada ao evento
+ /// Sequencial do evento para o mesmo tipo de evento
+ /// Retorna o conteúdo do atributo infEvento/@Id
+ public static string ObterId(NFeTipoEvento tpEvento, string chNFe, int nSeqEvento)
+ {
+ return "ID" + ((int)tpEvento) + chNFe + nSeqEvento.ToString().PadLeft(2, '0');
+ }
+
///
/// Assina um objeto evento
///
diff --git a/NFe.Utils/InformacoesSuplementares/ExtinfNFeSupl.cs b/NFe.Utils/InformacoesSuplementares/ExtinfNFeSupl.cs
index df249a72b..28d21870e 100644
--- a/NFe.Utils/InformacoesSuplementares/ExtinfNFeSupl.cs
+++ b/NFe.Utils/InformacoesSuplementares/ExtinfNFeSupl.cs
@@ -264,7 +264,7 @@ private static List CarregarUrls()
{Estado.PR, versao3E4, "http://www.fazenda.pr.gov.br"},
{Estado.PI, versao3E4, "http://webas.sefaz.pi.gov.br/nfceweb-homologacao/consultarNFCe.jsf"},
{Estado.RJ, versao3E4, "http://nfce.fazenda.rj.gov.br/consulta"},
- {Estado.RN, versao3E4, "http://nfce.set.rn.gov.br/consultarNFCe.aspx"},
+ {Estado.RN, versao3E4, "http://hom.nfce.set.rn.gov.br/consultarNFCe.aspx"},
{Estado.RS, versao3E4, "https://www.sefaz.rs.gov.br/NFCE/NFCE-COM.aspx"},
{Estado.RO, versao3E4, "http://www.nfce.sefin.ro.gov.br"},
{Estado.RR, versao3E4, "http://200.174.88.103:8080/nfce/servlet/wp_consulta_nfce"},
@@ -302,7 +302,6 @@ private static List CarregarUrls()
{Estado.PE, versao3E4, "nfce.sefaz.pe.gov.br/nfce/consulta"},
{Estado.PI, versao3E4, "www.sefaz.pi.gov.br/nfce/consulta"},
{Estado.RJ, versao3E4, "www.fazenda.rj.gov.br/nfce/consulta"},
- {Estado.RN, versao3E4, "www.set.rn.gov.br/nfce/consulta"},
{Estado.RS, versao3E4, "www.sefaz.rs.gov.br/nfce/consulta"},
{Estado.RO, versao3E4, "www.sefin.ro.gov.br/nfce/consulta"},
{Estado.RR, versao3E4, "www.sefaz.rr.gov.br/nfce/consulta"}
@@ -320,6 +319,7 @@ private static List CarregarUrls()
{Estado.BA, versao3E4, "www.sefaz.ba.gov.br/nfce/consulta"},
{Estado.MT, versao3E4, "http://www.sefaz.mt.gov.br/nfce/consultanfce"},
{Estado.PB, versao3E4, "www.receita.pb.gov.br/nfce/consulta"},
+ {Estado.RN, versao3E4, "https://nfce.sefaz.rn.gov.br/portalDFE/NFCe/ConsultaNFCe.aspx"},
{Estado.SP, versao3E4, "https://www.nfce.fazenda.sp.gov.br/consulta"},
{Estado.SE, versao3E4, "http://www.nfce.se.gov.br/nfce/consulta"},
{Estado.GO, versao3E4, "www.sefaz.go.gov.br/nfce/consulta"},
@@ -339,6 +339,7 @@ private static List CarregarUrls()
{Estado.BA, versao3E4, "http://hinternet.sefaz.ba.gov.br/nfce/consulta"},
{Estado.MT, versao3E4, "http://homologacao.sefaz.mt.gov.br/nfce/consultanfce"},
{Estado.PB, versao3E4, "www.receita.pb.gov.br/nfcehom"},
+ {Estado.RN, versao3E4, "www.set.rn.gov.br/nfce/consulta"},
{Estado.SP, versao3E4, "https://www.homologacao.nfce.fazenda.sp.gov.br/consulta"},
{Estado.SE, versao3E4, "http://www.hom.nfe.se.gov.br/nfce/consulta"},
{Estado.GO, versao3E4, "https://nfewebhomolog.sefaz.go.gov.br/nfeweb/sites/nfce/danfeNFCe"},
diff --git a/NFe.Utils/Inutilizacao/ExtinutNFe.cs b/NFe.Utils/Inutilizacao/ExtinutNFe.cs
index 9b0dab15b..db0b09cf5 100644
--- a/NFe.Utils/Inutilizacao/ExtinutNFe.cs
+++ b/NFe.Utils/Inutilizacao/ExtinutNFe.cs
@@ -32,6 +32,8 @@
/********************************************************************************/
using System;
using System.Security.Cryptography.X509Certificates;
+using DFe.Classes.Entidades;
+using DFe.Classes.Flags;
using DFe.Utils;
using NFe.Classes.Servicos.Inutilizacao;
using NFe.Utils.Assinatura;
@@ -61,6 +63,36 @@ public static string ObterXmlString(this inutNFe pedInutilizacao)
return FuncoesXml.ClasseParaXmlString(pedInutilizacao);
}
+ ///
+ /// Obtém o Id de um pedido de inutilização (infInut/@Id): literal "ID" + cUF + ano com 2 dígitos + CNPJ +
+ /// modelo + série com 3 dígitos + número inicial e número final com 9 dígitos
+ ///
+ /// Uso opcional, para quando o pedido for montado fora da biblioteca — por exemplo, para assinar com o
+ /// certificado numa máquina cliente e depois transmitir com já feito, via a
+ /// sobrecarga que recebe o inutNFe pronto. O método que assina internamente continua calculando o Id
+ /// sozinho.
+ ///
+ ///
+ /// Código da UF do solicitante
+ /// Ano de inutilização da numeração
+ /// CNPJ do emitente
+ /// Modelo do documento
+ /// Série
+ /// Número inicial a ser inutilizado
+ /// Número final a ser inutilizado
+ /// Retorna o conteúdo do atributo infInut/@Id
+ public static string ObterId(Estado cUF, int ano, string cnpj, ModeloDocumento modelo, int serie,
+ int numeroInicial, int numeroFinal)
+ {
+ var numId = string.Concat((int)cUF, ano.ToString("D2"),
+ cnpj, (int)modelo,
+ serie.ToString().PadLeft(3, '0'),
+ numeroInicial.ToString().PadLeft(9, '0'),
+ numeroFinal.ToString().PadLeft(9, '0'));
+
+ return "ID" + numId;
+ }
+
///
/// Assina um objeto inutNFe
///
diff --git a/Shared.NFe.Danfe/DanfeSharedHelper.cs b/Shared.NFe.Danfe/DanfeSharedHelper.cs
index e17576fe4..64e05f02f 100644
--- a/Shared.NFe.Danfe/DanfeSharedHelper.cs
+++ b/Shared.NFe.Danfe/DanfeSharedHelper.cs
@@ -22,11 +22,11 @@ public static Report GenerateDanfeNfceReport(nfeProc proc, ConfiguracaoDanfeNfce
{
//Define as variáveis que serão usadas no relatório (dúvidas a respeito do fast reports consulte a documentação em https://www.fast-report.com/pt/product/fast-report-net/documentation/)
- Report relatorio = new Report();
+ Report relatorio = new Report();
if (!string.IsNullOrEmpty(arquivoRelatorio))
relatorio.Load(arquivoRelatorio);
- else if(frx != null && frx.Length > 0)
+ else if (frx != null && frx.Length > 0)
relatorio.Load(new MemoryStream(frx));
else
throw new Exception("Erro em DanfeSharedHelper.GenerateDanfeNfceReport no Zeus.DFe. Relatório não encontrado, passe os parametros 'frx' com bytes ou 'arquivoRelatorio' com o caminho do arquivo");
@@ -84,8 +84,8 @@ public static Report GenerateDanfeFrEventoReport(nfeProc proc, procEventoNFe pro
{
//Define as variáveis que serão usadas no relatório (dúvidas a respeito do fast reports consulte a documentação em https://www.fast-report.com/pt/product/fast-report-net/documentation/)
- Report relatorio = new Report();
-
+ Report relatorio = new Report();
+
if (!string.IsNullOrEmpty(arquivoRelatorio))
relatorio.Load(arquivoRelatorio);
else if (frx != null && frx.Length > 0)
@@ -292,5 +292,187 @@ public static void ConfigurarParametrosRelatorioNfe(Report relatorio, nfeProc pr
relatorio.SetParameterValue("DecimaisQuantidadeItem", configuracaoDanfeNfe.DecimaisQuantidadeItem);
relatorio.SetParameterValue("DataHoraImpressao", configuracaoDanfeNfe.DataHoraImpressao ?? DateTime.Now);
}
+
+ public static Report GenerateDanfeFrNfeSimplificadoTipo2Report(nfeProc proc, ConfiguracaoDanfeNfeSimplificadoTipo2 configuracao, string cIdToken, string csc, byte[] frx, string desenvolvedor, string arquivoRelatorio, string textoRodape = "")
+ {
+ Report relatorio = new Report();
+
+ if (!string.IsNullOrEmpty(arquivoRelatorio))
+ relatorio.Load(arquivoRelatorio);
+ else if (frx != null && frx.Length > 0)
+ relatorio.Load(new MemoryStream(frx));
+ else
+ throw new Exception("Erro em DanfeSharedHelper.GenerateDanfeFrNfeSimplificadoTipo2Report no Zeus.DFe. Relatório não encontrado, passe os parametros 'frx' com bytes ou 'arquivoRelatorio' com o caminho do arquivo");
+
+ relatorio.RegisterData(new[] { proc }, "NFe", 20);
+ relatorio.GetDataSource("NFe").Enabled = true;
+
+ relatorio.SetParameterValue("NfeSimplificadoTipo2DetalheVendaNormal", configuracao.DetalheVendaNormal);
+ relatorio.SetParameterValue("NfeSimplificadoTipo2DetalheVendaContigencia", configuracao.DetalheVendaContigencia);
+ relatorio.SetParameterValue("NfeSimplificadoTipo2ImprimeDescontoItem", configuracao.ImprimeDescontoItem);
+ relatorio.SetParameterValue("NfeSimplificadoTipo2ImprimeFoneEmitente", configuracao.ImprimeFoneEmitente);
+
+ string foneEmitente = null;
+
+ if (proc.NFe.infNFe.emit.enderEmit.fone != null)
+ foneEmitente = proc.NFe.infNFe.emit.enderEmit.fone.ToString();
+
+ if (foneEmitente != null && foneEmitente.Length == 10)
+ foneEmitente = string.Format("{0:(00)0000-0000}", Convert.ToInt64(foneEmitente));
+ else if (foneEmitente != null && foneEmitente.Length == 11)
+ foneEmitente = string.Format("{0:(00)00000-0000}", Convert.ToInt64(foneEmitente));
+
+ relatorio.SetParameterValue("NfeSimplificadoTipo2FoneEmitente", foneEmitente);
+ relatorio.SetParameterValue("NfeSimplificadoTipo2ModoImpressao", configuracao.ModoImpressao);
+ relatorio.SetParameterValue("NfeSimplificadoTipo2Cancelado", configuracao.DocumentoCancelado);
+ relatorio.SetParameterValue("NfeSimplificadoTipo2LayoutQrCode", configuracao.LayoutQrCode);
+ relatorio.SetParameterValue("TextoRodape", textoRodape);
+
+ ((ReportPage)relatorio.FindObject("PgNfeSimplificadoTipo2")).LeftMargin = configuracao.MargemEsquerda;
+ ((ReportPage)relatorio.FindObject("PgNfeSimplificadoTipo2")).RightMargin = configuracao.MargemDireita;
+
+ var logomarcaEmitDefinida = configuracao.Logomarca != null && configuracao.Logomarca.Length > 0;
+ var rtbEmitLogo = relatorio.FindObject("rtbEmitLogo") as ReportTitleBand;
+ if (rtbEmitLogo != null)
+ {
+ rtbEmitLogo.Visible = logomarcaEmitDefinida;
+ if (logomarcaEmitDefinida)
+ {
+ var poEmitLogo = relatorio.FindObject("poEmitLogo") as PictureObject;
+ poEmitLogo?.SetImageData(configuracao.Logomarca);
+ }
+ }
+
+ ((TextObject)relatorio.FindObject("txtUrl")).Text = string.IsNullOrEmpty(proc.NFe.infNFeSupl?.urlChave) ? proc.NFe.infNFeSupl.ObterUrlConsulta(proc.NFe, configuracao.VersaoQrCode) : proc.NFe.infNFeSupl.urlChave;
+ ((BarcodeObject)relatorio.FindObject("bcoQrCode")).Text = proc.NFe.infNFeSupl == null ? proc.NFe.infNFeSupl.ObterUrlQrCode(proc.NFe, configuracao.VersaoQrCode, cIdToken, csc) : proc.NFe.infNFeSupl.qrCode;
+ ((BarcodeObject)relatorio.FindObject("bcoQrCodeLateral")).Text = proc.NFe.infNFeSupl == null ? proc.NFe.infNFeSupl.ObterUrlQrCode(proc.NFe, configuracao.VersaoQrCode, cIdToken, csc) : proc.NFe.infNFeSupl.qrCode;
+
+ string mensagem = string.Empty;
+ string resumoCanhoto = string.Empty;
+ string contingenciaDescricao = string.Empty;
+ string contingenciaValor = string.Empty;
+ string consultaAutenticidade = "Consulta de autenticidade no portal nacional da NF-e" + Environment.NewLine +
+ "www.nfe.fazenda.gov.br/portal ou no site da Sefaz autorizadora";
+
+ if (configuracao.ExibirResumoCanhoto)
+ {
+ resumoCanhoto = string.IsNullOrEmpty(configuracao.ResumoCanhoto) ?
+ string.Format("Emissão: {0: dd/MM/yyyy} Dest/Reme: {1} Valor Total: {2:C}", proc.NFe.infNFe.ide.dhEmi,
+ proc.NFe.infNFe.dest.xNome, proc.NFe.infNFe.total.ICMSTot.vNF) :
+ configuracao.ResumoCanhoto;
+ }
+
+ if (proc.NFe.infNFe.ide.tpAmb == TipoAmbiente.Homologacao)
+ {
+ if (proc.NFe.infNFe.ide.tpEmis == TipoEmissao.teSCAN ||
+ proc.NFe.infNFe.ide.tpEmis == TipoEmissao.teEPEC ||
+ proc.NFe.infNFe.ide.tpEmis == TipoEmissao.teFSDA ||
+ proc.NFe.infNFe.ide.tpEmis == TipoEmissao.teFSIA)
+ {
+ if (proc.protNFe != null && proc.protNFe.infProt != null &&
+ (proc.protNFe.infProt.cStat == 101 ||
+ proc.protNFe.infProt.cStat == 135 ||
+ proc.protNFe.infProt.cStat == 151 ||
+ proc.protNFe.infProt.cStat == 155))
+ {
+ mensagem = "NFe sem Valor Fiscal - HOMOLOGAÇÃO" + Environment.NewLine +
+ "NFe em Contingência - CANCELADA";
+ }
+ else
+ {
+ mensagem = "NFe sem Valor Fiscal - HOMOLOGAÇÃO" + Environment.NewLine +
+ "NFe em Contingência";
+ }
+ }
+ else
+ {
+ mensagem = "NFe sem Valor Fiscal - HOMOLOGAÇÃO";
+ }
+ }
+ else
+ {
+ if (configuracao.DocumentoCancelado ||
+ (proc.protNFe != null && proc.protNFe.infProt != null &&
+ !string.IsNullOrEmpty(proc.protNFe.infProt.nProt) &&
+ (proc.protNFe.infProt.cStat == 101 ||
+ proc.protNFe.infProt.cStat == 135 ||
+ proc.protNFe.infProt.cStat == 151 ||
+ proc.protNFe.infProt.cStat == 155)))
+ {
+ mensagem = "NFe Cancelada";
+ }
+ else if (proc.protNFe != null && proc.protNFe.infProt != null &&
+ (proc.protNFe.infProt.cStat == 110 ||
+ proc.protNFe.infProt.cStat == 301 ||
+ proc.protNFe.infProt.cStat == 302 ||
+ proc.protNFe.infProt.cStat == 303))
+ {
+ mensagem = "NFe denegada pelo Fisco";
+ }
+ else if (proc.protNFe != null && proc.protNFe.infProt != null &&
+ string.IsNullOrEmpty(proc.protNFe.infProt.nProt))
+ {
+ mensagem = "NFe sem Autorização de Uso da SEFAZ";
+ }
+ }
+
+ switch (proc.NFe.infNFe.ide.tpEmis)
+ {
+ case TipoEmissao.teNormal:
+ case TipoEmissao.teSCAN:
+ case TipoEmissao.teSVCAN:
+ case TipoEmissao.teSVCRS:
+ contingenciaDescricao = "PROTOCOLO DE AUTORIZAÇÃO DE USO";
+ contingenciaValor = ((proc.protNFe == null || proc.protNFe.infProt == null || string.IsNullOrEmpty(proc.protNFe.infProt.nProt)) ? "NFe sem Autorização de Uso da SEFAZ" : string.Format("{0} - {1:dd/MM/yyyy HH:mm:ss}", proc.protNFe.infProt.nProt, proc.protNFe.infProt.dhRecbto));
+ if (configuracao.DocumentoCancelado || (proc.protNFe != null && proc.protNFe.infProt != null && (proc.protNFe.infProt.cStat == 101 || proc.protNFe.infProt.cStat == 151 || proc.protNFe.infProt.cStat == 155)))
+ {
+ contingenciaDescricao = "PROTOCOLO DE HOMOLOGAÇÃO DO CANCELAMENTO";
+ }
+ else if (proc.protNFe != null && proc.protNFe.infProt != null && (proc.protNFe.infProt.cStat == 110 || proc.protNFe.infProt.cStat == 301 || proc.protNFe.infProt.cStat == 302 || proc.protNFe.infProt.cStat == 303))
+ {
+ contingenciaDescricao = "PROTOCOLO DE DENEGAÇÃO DE USO";
+ }
+ break;
+
+ case TipoEmissao.teFSIA:
+ case TipoEmissao.teEPEC:
+ case TipoEmissao.teFSDA:
+ contingenciaDescricao = "DADOS DA NF-E";
+ contingenciaValor = Regex.Replace(configuracao.ChaveContingencia, ".{4}", "$0 ");
+ consultaAutenticidade = string.Empty;
+ break;
+
+ default:
+ contingenciaValor = string.Format("{0} - {1:dd/MM/yyyy HH:mm:ss}", proc.protNFe.infProt.nProt, proc.protNFe.infProt.dhRecbto);
+ break;
+ }
+
+ relatorio.SetParameterValue("ResumoCanhoto", resumoCanhoto);
+ relatorio.SetParameterValue("Mensagem", mensagem);
+ relatorio.SetParameterValue("ConsultaAutenticidade", consultaAutenticidade);
+ relatorio.SetParameterValue("ContingenciaDescricao", contingenciaDescricao);
+ relatorio.SetParameterValue("ContingenciaValor", contingenciaValor);
+ relatorio.SetParameterValue("ContingenciaID", configuracao.ChaveContingencia);
+ relatorio.SetParameterValue("DuasLinhas", configuracao.DuasLinhas);
+ relatorio.SetParameterValue("Desenvolvedor", desenvolvedor);
+ relatorio.SetParameterValue("QuebrarLinhasObservacao", configuracao.QuebrarLinhasObservacao);
+ relatorio.SetParameterValue("ImprimirISSQN", configuracao.ImprimirISSQN);
+ relatorio.SetParameterValue("ImprimirDescPorc", configuracao.ImprimirDescPorc);
+ relatorio.SetParameterValue("ImprimirTotalLiquido", configuracao.ImprimirTotalLiquido);
+ relatorio.SetParameterValue("ImprimirUnidQtdeValor", configuracao.ImprimirUnidQtdeValor);
+ relatorio.SetParameterValue("ExibeCampoFatura", configuracao.ExibeCampoFatura);
+ relatorio.SetParameterValue("Logo", configuracao.Logomarca);
+ relatorio.SetParameterValue("ExibirTotalTributos", configuracao.ExibirTotalTributos);
+ relatorio.SetParameterValue("DecimaisValorUnitario", configuracao.DecimaisValorUnitario);
+ relatorio.SetParameterValue("DecimaisQuantidadeItem", configuracao.DecimaisQuantidadeItem);
+ relatorio.SetParameterValue("DataHoraImpressao", configuracao.DataHoraImpressao ?? DateTime.Now);
+
+#if !openfastreport && !fastskia
+ if (configuracao.SegundaViaContingencia)
+ relatorio.PrintSettings.Copies = (proc.NFe.infNFe.ide.tpEmis == TipoEmissao.teNormal | (proc.protNFe != null && proc.protNFe.infProt != null && NfeSituacao.Autorizada(proc.protNFe.infProt.cStat))) ? 1 : 2;
+#endif
+
+ return relatorio;
+ }
}
-}
+}
\ No newline at end of file