diff --git a/DFe.Utils/ExtXmlSerializerFactory.cs b/DFe.Utils/ExtXmlSerializerFactory.cs new file mode 100644 index 000000000..67ec93748 --- /dev/null +++ b/DFe.Utils/ExtXmlSerializerFactory.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Serialization; + +namespace DFe.Utils { + + public abstract class XmlOrderFreeSerializerFactory { + // Referência https://stackoverflow.com/a/33508815 + readonly static XmlAttributeOverrides overrides = new XmlAttributeOverrides(); + readonly static object locker = new object(); + readonly static Dictionary serializers = new Dictionary(); + static HashSet overridesAdded = new HashSet(); + + static void AddOverrideAttributes(Type type, XmlAttributeOverrides overrides) { + + if (type == null || type == typeof(object) || type.IsPrimitive || type == typeof(string) || type == typeof(DateTime)) { + return; + } + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) { + AddOverrideAttributes(type.GetGenericArguments()[0], overrides); + return; + } + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>)) { + AddOverrideAttributes(type.GetGenericArguments()[0], overrides); + return; + } + + var mask = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public; + foreach (var member in type.GetProperties(mask).Cast().Union(type.GetFields(mask))) { + var otTag = $"{type.Name}_{member.Name}"; + if (overridesAdded.Contains(otTag)) { + continue; + } + XmlAttributes overrideAttr = null; + foreach (var attr in member.GetCustomAttributes()) { + overrideAttr = overrideAttr ?? new XmlAttributes(); + var overrideElt = new XmlElementAttribute(attr.ElementName, attr.Type) { DataType = attr.DataType, ElementName = attr.ElementName, Form = attr.Form, Namespace = attr.Namespace, Type = attr.Type }; + if(attr.IsNullable) { + // Isso aqui deve ter uma logica personalizada no setter, colocar ali em cima causa erro + overrideElt.IsNullable = true; + } + overrideAttr.XmlElements.Add(overrideElt); + if(attr.Type != null) { + AddOverrideAttributes(attr.Type, overrides); + } + } + foreach (var attr in member.GetCustomAttributes()) { + overrideAttr = overrideAttr ?? new XmlAttributes(); + overrideAttr.XmlArray = new XmlArrayAttribute { ElementName = attr.ElementName, Form = attr.Form, IsNullable = attr.IsNullable, Namespace = attr.Namespace }; + } + foreach (var attr in member.GetCustomAttributes()) { + overrideAttr = overrideAttr ?? new XmlAttributes(); + overrideAttr.XmlArrayItems.Add(attr); + } + foreach (var attr in member.GetCustomAttributes()) { + overrideAttr = overrideAttr ?? new XmlAttributes(); + overrideAttr.XmlAnyElements.Add(new XmlAnyElementAttribute { Name = attr.Name, Namespace = attr.Namespace }); + } + if (overrideAttr != null) { + overridesAdded.Add(otTag); + overrides.Add(type, member.Name, overrideAttr); + } + var mType = (member is PropertyInfo pi ? pi.PropertyType : member is FieldInfo fi ? fi.FieldType : null); + AddOverrideAttributes(mType, overrides); + } + } + + public static XmlSerializer GetSerializer(Type type) { + if (type == null) + throw new ArgumentNullException("type"); + lock (locker) { + XmlSerializer serializer; + if (!serializers.TryGetValue(type, out serializer)) { + AddOverrideAttributes(type, overrides); + serializers[type] = serializer = new XmlSerializer(type, overrides); + } + return serializer; + } + } + + } + + public static class TypeExtensions { + public static IEnumerable BaseTypesAndSelf(this Type type) { + while (type != null) { + yield return type; + type = type.BaseType; + } + } + } +} diff --git a/DFe.Utils/FuncoesXml.cs b/DFe.Utils/FuncoesXml.cs index 1bd534d27..da5964da1 100644 --- a/DFe.Utils/FuncoesXml.cs +++ b/DFe.Utils/FuncoesXml.cs @@ -1,4 +1,4 @@ -/********************************************************************************/ +/********************************************************************************/ /* Projeto: Biblioteca ZeusDFe */ /* Biblioteca C# para auxiliar no desenvolvimento das demais bibliotecas DFe */ /* */ @@ -77,14 +77,21 @@ public static string ClasseParaXmlString(T objeto) /// /// /// + /// true caso o XML possa conter elementos fora de ordem /// - public static T XmlStringParaClasse(string input) where T : class + public static T XmlStringParaClasse(string input, bool ignorarOrdenacaoElementos = false) where T : class { var keyNomeClasseEmUso = typeof(T).FullName; - var ser = BuscarNoCache(keyNomeClasseEmUso, typeof(T)); + + XmlSerializer serializador; + if(ignorarOrdenacaoElementos) { + serializador = XmlOrderFreeSerializerFactory.GetSerializer(typeof(T)); + } else { + serializador = BuscarNoCache(keyNomeClasseEmUso, typeof(T)); + } using (var sr = new StringReader(input)) - return (T)ser.Deserialize(sr); + return (T)serializador.Deserialize(sr); } /// @@ -94,7 +101,7 @@ public static T XmlStringParaClasse(string input) where T : class /// Classe /// Arquivo XML /// Retorna a classe - public static T ArquivoXmlParaClasse(string arquivo) where T : class + public static T ArquivoXmlParaClasse(string arquivo, bool ignorarOrdenacaoElementos = false) where T : class { if (!File.Exists(arquivo)) { @@ -102,7 +109,14 @@ public static T ArquivoXmlParaClasse(string arquivo) where T : class } var keyNomeClasseEmUso = typeof(T).FullName; - var serializador = BuscarNoCache(keyNomeClasseEmUso, typeof(T)); + + XmlSerializer serializador; + if (ignorarOrdenacaoElementos) { + serializador = XmlOrderFreeSerializerFactory.GetSerializer(typeof(T)); + } else { + serializador = BuscarNoCache(keyNomeClasseEmUso, typeof(T)); + } + var stream = new FileStream(arquivo, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); try { diff --git a/NFe.AppTeste/Schemas/leiauteNFe_v4.00.xsd b/NFe.AppTeste/Schemas/leiauteNFe_v4.00.xsd index 1c59fa9cf..8f0ccd229 100644 --- a/NFe.AppTeste/Schemas/leiauteNFe_v4.00.xsd +++ b/NFe.AppTeste/Schemas/leiauteNFe_v4.00.xsd @@ -1,5 +1,5 @@ - + @@ -17,6 +17,7 @@ + @@ -6285,6 +6286,88 @@ tipo de ato concessório: + + + Produtos Agropecurários Animais, Vegetais e Florestais + + + + + + Defensivo Agrícola / Agrotóxico + + + + + + Número do Receituário ou Receita do Defensivo / Agrotóxico + + + + + + + + + + + CPF do Responsável Técnico pelo receituário + + + + + + + + Guias De Trânsito de produtos agropecurários animais, vegetais e de origem florestal. + + + + + + Tipo da Guia: 1 - GTA; 2 - TTA; 3 - DTA; 4 - ATV; 5 - PTV; 6 - GTV; 7 - Guia Florestal (DOF, SisFlora - PA e MT, SIAM - MG) + + + + + + + + + + + + + + + + + + Série da Guia + + + + + + + + + + + Número da Guia + + + + + + + + + + + + + diff --git a/NFe.Classes/Informacoes/Agropecuario/agroTipos.cs b/NFe.Classes/Informacoes/Agropecuario/agroTipos.cs new file mode 100644 index 000000000..afd67fca4 --- /dev/null +++ b/NFe.Classes/Informacoes/Agropecuario/agroTipos.cs @@ -0,0 +1,67 @@ +using System.ComponentModel; +using System.Xml.Serialization; + +namespace NFe.Classes.Informacoes.Agropecuario +{ + /// + /// Tipo da Guia + /// 1 - GTA - Guia de Trânsito Animal + /// 2 - TTA - Termo de Trânsito Animal + /// 3 - DTA - Documento de Transferência Animal + /// 4 - ATV - Autorização de Trânsito Vegetal + /// 5 - PTV - Permissão de Trânsito Vegetal + /// 6 - GTV - Guia de Trânsito Vegetal + /// 7 - Guia Florestal (DOF, SisFlora - PA e MT ou SIAM - MG) + /// + public enum TipoGuia + { + /// + /// 1 - GTA - Guia de Trânsito Animal + /// + [Description("GTA - Guia de Trânsito Animal")] + [XmlEnum("1")] + GTA = 1, + + /// + /// 2 - TTA - Termo de Trânsito Animal + /// + [Description("TTA - Termo de Trânsito Animal")] + [XmlEnum("2")] + TTA = 2, + + /// + /// 3 - DTA - Documento de Transferência Animal + /// + [Description("DTA - Documento de Transferência Animal")] + [XmlEnum("3")] + DTA = 3, + + /// + /// 4 - ATV - Autorização de Trânsito Vegetal + /// + [Description("ATV - Autorização de Trânsito Vegetal")] + [XmlEnum("4")] + ATV = 4, + + /// + /// 5 - PTV - Permissão de Trânsito Vegetal + /// + [Description("PTV - Permissão de Trânsito Vegetal")] + [XmlEnum("5")] + PTV = 5, + + /// + /// 6 - GTV - Guia de Trânsito Vegetal + /// + [Description("GTV - Guia de Trânsito Vegetal")] + [XmlEnum("6")] + GTV = 6, + + /// + /// 7 - Guia Florestal (DOF, SisFlora - PA e MT ou SIAM - MG) + /// + [Description("Guia Florestal (DOF, SisFlora - PA e MT ou SIAM - MG)")] + [XmlEnum("7")] + GuiaFlorestal = 7, + } +} diff --git a/NFe.Classes/Informacoes/Agropecuario/agropecuario.cs b/NFe.Classes/Informacoes/Agropecuario/agropecuario.cs new file mode 100644 index 000000000..5f42f59cb --- /dev/null +++ b/NFe.Classes/Informacoes/Agropecuario/agropecuario.cs @@ -0,0 +1,37 @@ +namespace NFe.Classes.Informacoes.Agropecuario +{ + public class agropecuario + { +#if NET5_0_OR_GREATER//o uso de tipos de referência anuláveis não é permitido até o C# 8.0. + + /// + /// ZF02 - serieGuia + /// + public defensivo? defensivo { get; set; } + + /// + /// ZF04 - Guia de Trânsito + /// + public guiaTransito? guiaTransito { get; set; } + + public bool ShouldSerializedefensivo() + { + return defensivo != null; + } + public bool ShouldSerializeguiaTransito() + { + return guiaTransito != null; + } +#else + /// + /// ZF02 - serieGuia + /// + public defensivo defensivo { get; set; } + + /// + /// ZF04 - Guia de Trânsito + /// + public guiaTransito guiaTransito { get; set; } +#endif + } +} diff --git a/NFe.Classes/Informacoes/Agropecuario/defensivo.cs b/NFe.Classes/Informacoes/Agropecuario/defensivo.cs new file mode 100644 index 000000000..eb6470293 --- /dev/null +++ b/NFe.Classes/Informacoes/Agropecuario/defensivo.cs @@ -0,0 +1,15 @@ +namespace NFe.Classes.Informacoes.Agropecuario +{ + public class defensivo + { + /// + /// ZF03 - Número da receita ou receituário do agrotóxico / defensivo agrícola + /// + public string nReceituario { get; set; } + + /// + /// ZP03a - CPF do Responsável Técnico, emitente do receituário + /// + public string CPFRespTec { get; set; } + } +} diff --git a/NFe.Classes/Informacoes/Agropecuario/guiaTransito.cs b/NFe.Classes/Informacoes/Agropecuario/guiaTransito.cs new file mode 100644 index 000000000..0f641e070 --- /dev/null +++ b/NFe.Classes/Informacoes/Agropecuario/guiaTransito.cs @@ -0,0 +1,56 @@ +namespace NFe.Classes.Informacoes.Agropecuario +{ + public class guiaTransito + { +#if NET5_0_OR_GREATER//o uso de tipos de referência anuláveis não é permitido até o C# 8.0. + /// + /// ZF05 - Tipo da Guia + /// + public TipoGuia tpGuia { get; set; } + + /// + /// ZF06 - UF de emissão + /// + public string? UFGuia { get; set; } + + /// + /// ZF07 - Série da Guia + /// + public string? serieGuia { get; set; } + + /// + /// ZF08 - Número da Guia + /// + public string nGuia { get; set; } + + public bool ShouldSerializeUFGuia() + { + return UFGuia != null; + } + public bool ShouldSerializeserieGuia() + { + return serieGuia != null; + } +#else + /// + /// ZF05 - Tipo da Guia + /// + public TipoGuia tpGuia { get; set; } + + /// + /// ZF06 - UF de emissão + /// + public string UFGuia { get; set; } + + /// + /// ZF07 - Série da Guia + /// + public string serieGuia { get; set; } + + /// + /// ZF08 - Número da Guia + /// + public string nGuia { get; set; } +#endif + } +} \ No newline at end of file diff --git a/NFe.Classes/Informacoes/infNFe.cs b/NFe.Classes/Informacoes/infNFe.cs index 5d3b269c0..3d3b8d699 100644 --- a/NFe.Classes/Informacoes/infNFe.cs +++ b/NFe.Classes/Informacoes/infNFe.cs @@ -32,6 +32,7 @@ /********************************************************************************/ using System.Collections.Generic; using System.Xml.Serialization; +using NFe.Classes.Informacoes.Agropecuario; using NFe.Classes.Informacoes.Cana; using NFe.Classes.Informacoes.Cobranca; using NFe.Classes.Informacoes.Destinatario; @@ -158,6 +159,14 @@ public infNFe() /// public cana cana { get; set; } + /// + /// ZD01 - Grupo do Responsável Técnico + /// public infRespTec infRespTec { get; set; } + + /// + /// ZF01 - Grupo de produtos da agricultura, pecuária e produção Florestal + /// + public agropecuario agropecuario { get; set; } } } \ No newline at end of file diff --git a/NFe.Utils/Enderecos/Enderecador.cs b/NFe.Utils/Enderecos/Enderecador.cs index 895fa7814..cbd3d2b45 100644 --- a/NFe.Utils/Enderecos/Enderecador.cs +++ b/NFe.Utils/Enderecos/Enderecador.cs @@ -1,4 +1,4 @@ -/********************************************************************************/ +/********************************************************************************/ /* Projeto: Biblioteca ZeusNFe */ /* Biblioteca C# para emissão de Nota Fiscal Eletrônica - NFe e Nota Fiscal de */ /* Consumidor Eletrônica - NFC-e (http://www.nfe.fazenda.gov.br) */ @@ -1490,11 +1490,11 @@ private static List CarregarEnderecosServicos() addServico(new[] { ServicoNFe.NFeAutorizacao }, versao3, hom, TipoEmissao.teSVCAN, estado, modelo, "https://hom.svc.fazenda.gov.br/NfeAutorizacao/NfeAutorizacao.asmx"); addServico(new[] { ServicoNFe.NFeRetAutorizacao }, versao3, hom, TipoEmissao.teSVCAN, estado, modelo, "https://hom.svc.fazenda.gov.br/NfeRetAutorizacao/NfeRetAutorizacao.asmx"); - addServico(new[] { ServicoNFe.NfeConsultaProtocolo }, versao4, hom, TipoEmissao.teSVCAN, estado, modelo, "https://hom.svc.fazenda.gov.br/NFeConsultaProtocolo4/NFeConsultaProtocolo4.asmx"); - addServico(new[] { ServicoNFe.NfeStatusServico }, versao4, hom, TipoEmissao.teSVCAN, estado, modelo, "https://hom.svc.fazenda.gov.br/NFeStatusServico4/NFeStatusServico4.asmx"); - addServico(eventoCceCanc, versao4, hom, TipoEmissao.teSVCAN, estado, modelo, "https://hom.svc.fazenda.gov.br/NFeRecepcaoEvento4/NFeRecepcaoEvento4.asmx"); - addServico(new[] { ServicoNFe.NFeAutorizacao }, versao4, hom, TipoEmissao.teSVCAN, estado, modelo, "https://hom.svc.fazenda.gov.br/NFeAutorizacao4/NFeAutorizacao4.asmx"); - addServico(new[] { ServicoNFe.NFeRetAutorizacao }, versao4, hom, TipoEmissao.teSVCAN, estado, modelo, "https://hom.svc.fazenda.gov.br/NFeRetAutorizacao4/NFeRetAutorizacao4.asmx"); + addServico(new[] { ServicoNFe.NfeConsultaProtocolo }, versao4, hom, TipoEmissao.teSVCAN, estado, modelo, "https://hom.sefazvirtual.fazenda.gov.br/NFeConsultaProtocolo4/NFeConsultaProtocolo4.asmx"); + addServico(new[] { ServicoNFe.NfeStatusServico }, versao4, hom, TipoEmissao.teSVCAN, estado, modelo, "https://hom.sefazvirtual.fazenda.gov.br/NFeStatusServico4/NFeStatusServico4.asmx"); + addServico(eventoCceCanc, versao4, hom, TipoEmissao.teSVCAN, estado, modelo, "https://hom.sefazvirtual.fazenda.gov.br/NFeRecepcaoEvento4/NFeRecepcaoEvento4.asmx"); + addServico(new[] { ServicoNFe.NFeAutorizacao }, versao4, hom, TipoEmissao.teSVCAN, estado, modelo, "https://hom.sefazvirtual.fazenda.gov.br/NFeAutorizacao4/NFeAutorizacao4.asmx"); + addServico(new[] { ServicoNFe.NFeRetAutorizacao }, versao4, hom, TipoEmissao.teSVCAN, estado, modelo, "https://hom.sefazvirtual.fazenda.gov.br/NFeRetAutorizacao4/NFeRetAutorizacao4.asmx"); } } @@ -1513,11 +1513,11 @@ private static List CarregarEnderecosServicos() addServico(new[] { ServicoNFe.NFeAutorizacao }, versao3, prod, TipoEmissao.teSVCAN, estado, modelo, "https://www.svc.fazenda.gov.br/NfeAutorizacao/NfeAutorizacao.asmx"); addServico(new[] { ServicoNFe.NFeRetAutorizacao }, versao3, prod, TipoEmissao.teSVCAN, estado, modelo, "https://www.svc.fazenda.gov.br/NfeRetAutorizacao/NfeRetAutorizacao.asmx"); - addServico(new[] { ServicoNFe.NfeConsultaProtocolo }, versao4, prod, TipoEmissao.teSVCAN, estado, modelo, "https://www.svc.fazenda.gov.br/NFeConsultaProtocolo4/NFeConsultaProtocolo4.asmx"); - addServico(new[] { ServicoNFe.NfeStatusServico }, versao4, prod, TipoEmissao.teSVCAN, estado, modelo, "https://www.svc.fazenda.gov.br/NFeStatusServico4/NFeStatusServico4.asmx"); - addServico(eventoCceCanc, versao4, prod, TipoEmissao.teSVCAN, estado, modelo, "https://www.svc.fazenda.gov.br/NFeRecepcaoEvento4/NFeRecepcaoEvento4.asmx"); - addServico(new[] { ServicoNFe.NFeAutorizacao }, versao4, prod, TipoEmissao.teSVCAN, estado, modelo, "https://www.svc.fazenda.gov.br/NFeAutorizacao4/NFeAutorizacao4.asmx"); - addServico(new[] { ServicoNFe.NFeRetAutorizacao }, versao4, prod, TipoEmissao.teSVCAN, estado, modelo, "https://www.svc.fazenda.gov.br/NFeRetAutorizacao4/NFeRetAutorizacao4.asmx"); + addServico(new[] { ServicoNFe.NfeConsultaProtocolo }, versao4, prod, TipoEmissao.teSVCAN, estado, modelo, "https://www.sefazvirtual.fazenda.gov.br/NFeConsultaProtocolo4/NFeConsultaProtocolo4.asmx"); + addServico(new[] { ServicoNFe.NfeStatusServico }, versao4, prod, TipoEmissao.teSVCAN, estado, modelo, "https://www.sefazvirtual.fazenda.gov.br/NFeStatusServico4/NFeStatusServico4.asmx"); + addServico(eventoCceCanc, versao4, prod, TipoEmissao.teSVCAN, estado, modelo, "https://www.sefazvirtual.fazenda.gov.br/NFeRecepcaoEvento4/NFeRecepcaoEvento4.asmx"); + addServico(new[] { ServicoNFe.NFeAutorizacao }, versao4, prod, TipoEmissao.teSVCAN, estado, modelo, "https://www.sefazvirtual.fazenda.gov.br/NFeAutorizacao4/NFeAutorizacao4.asmx"); + addServico(new[] { ServicoNFe.NFeRetAutorizacao }, versao4, prod, TipoEmissao.teSVCAN, estado, modelo, "https://www.sefazvirtual.fazenda.gov.br/NFeRetAutorizacao4/NFeRetAutorizacao4.asmx"); } } @@ -1823,4 +1823,4 @@ into g } } -} +} \ No newline at end of file