From 4485311df4b6efefa63217cbbd5fac9038d5db33 Mon Sep 17 00:00:00 2001 From: Calebe Barbosa Sousa Date: Sat, 30 May 2026 13:45:59 -0300 Subject: [PATCH] Implementa NT 2022.002 v1.30a --- DFe.Testes/Impostos/ICMSGeral_Teste.cs | 98 ++++++++++++ NFe.AppTeste/Schemas/leiauteNFe_v4.00.xsd | 110 +++++++++++-- .../Detalhe/Tributacao/Estadual/ICMS90.cs | 145 +++++++++++++++--- .../Detalhe/Tributacao/Estadual/ICMSPart.cs | 41 ++++- .../Tributacao/Estadual/Tipos/ICMSTipos.cs | 7 + NFe.Utils/Conversao.cs | 1 + NFe.Utils/Tributacao/Estadual/ICMSGeral.cs | 23 ++- 7 files changed, 394 insertions(+), 31 deletions(-) diff --git a/DFe.Testes/Impostos/ICMSGeral_Teste.cs b/DFe.Testes/Impostos/ICMSGeral_Teste.cs index ba8a06ba7..6ec8792d2 100644 --- a/DFe.Testes/Impostos/ICMSGeral_Teste.cs +++ b/DFe.Testes/Impostos/ICMSGeral_Teste.cs @@ -1,5 +1,7 @@ using System; using System.ComponentModel; +using System.IO; +using System.Xml.Serialization; using DFe.Testes.Impostos.DadosDeTeste; using Microsoft.VisualStudio.TestTools.UnitTesting; using NFe.Classes.Informacoes.Detalhe.Tributacao.Estadual; @@ -115,6 +117,102 @@ public void ObterICMSBasico_ICMS10_Teste(CRT crt, OrigemMercadoria origem, Deter Assert.AreEqual(Convert.ToDecimal(vFCPST), tagICMSGerada.vFCPST); } + [TestMethod] + public void ObterICMSBasico_ICMS90ComDiferimento_Teste() + { + var icmsGeral = new ICMSGeral() + { + orig = OrigemMercadoria.OmNacional, + CST = Csticms.Cst90, + modBC = DeterminacaoBaseIcms.DbiValorOperacao, + vBC = 1000, + pRedBC = 10, + cBenefRBC = "ABC12345", + pICMS = 18, + vICMSOp = 180, + pDif = 50, + vICMSDif = 90, + vICMS = 90, + vBCFCP = 1000, + pFCP = 2, + vFCP = 20, + pFCPDif = 50, + vFCPDif = 10, + vFCPEfet = 10 + }; + + var tagGerada = icmsGeral.ObterICMSBasico(CRT.RegimeNormal); + + Assert.IsInstanceOfType(tagGerada, typeof(ICMS90)); + var tagICMSGerada = tagGerada as ICMS90; + Assert.AreEqual(Csticms.Cst90, tagICMSGerada.CST); + Assert.AreEqual("ABC12345", tagICMSGerada.cBenefRBC); + Assert.AreEqual(180m, tagICMSGerada.vICMSOp); + Assert.AreEqual(50m, tagICMSGerada.pDif); + Assert.AreEqual(90m, tagICMSGerada.vICMSDif); + Assert.AreEqual(50m, tagICMSGerada.pFCPDif); + Assert.AreEqual(10m, tagICMSGerada.vFCPDif); + Assert.AreEqual(10m, tagICMSGerada.vFCPEfet); + + var xml = Serializar(tagICMSGerada, "ICMS90"); + StringAssert.Contains(xml, "ABC12345"); + StringAssert.Contains(xml, "180.00"); + StringAssert.Contains(xml, "50.0000"); + StringAssert.Contains(xml, "90.00"); + StringAssert.Contains(xml, "50.0000"); + StringAssert.Contains(xml, "10.00"); + StringAssert.Contains(xml, "10.00"); + } + + [TestMethod] + public void ObterICMSBasico_ICMSPartCst20ComDesoneracao_Teste() + { + var icmsGeral = new ICMSGeral() + { + orig = OrigemMercadoria.OmNacional, + CST = Csticms.CstPart20, + modBC = DeterminacaoBaseIcms.DbiValorOperacao, + vBC = 1000, + pRedBC = 10, + pICMS = 18, + vICMS = 90, + modBCST = DeterminacaoBaseIcmsSt.DbisValordaOperacao, + vBCST = 1000, + pICMSST = 18, + vICMSST = 180, + pBCOp = 100, + UFST = "SP", + vICMSDeson = 10, + motDesICMS = MotivoDesoneracaoIcms.MdiDeficienteCondutor, + indDeduzDeson = DeduzDesoneracaoNoProduto.Deduz + }; + + var tagGerada = icmsGeral.ObterICMSBasico(CRT.RegimeNormal); + + Assert.IsInstanceOfType(tagGerada, typeof(ICMSPart)); + var tagICMSGerada = tagGerada as ICMSPart; + Assert.AreEqual(Csticms.CstPart20, tagICMSGerada.CST); + Assert.AreEqual(10m, tagICMSGerada.vICMSDeson); + Assert.AreEqual(MotivoDesoneracaoIcms.MdiDeficienteCondutor, tagICMSGerada.motDesICMS); + Assert.AreEqual(DeduzDesoneracaoNoProduto.Deduz, tagICMSGerada.indDeduzDeson); + + var xml = Serializar(tagICMSGerada, "ICMSPart"); + StringAssert.Contains(xml, "20"); + StringAssert.Contains(xml, "10.00"); + StringAssert.Contains(xml, "10"); + StringAssert.Contains(xml, "1"); + } + + private static string Serializar(T objeto, string raiz) + { + var serializer = new XmlSerializer(typeof(T), new XmlRootAttribute(raiz)); + using (var writer = new StringWriter()) + { + serializer.Serialize(writer, objeto); + return writer.ToString(); + } + } + //TODO: Falta criar os métodos de testes dos demais CSTs do ICMS (CTR = Normal) #endregion diff --git a/NFe.AppTeste/Schemas/leiauteNFe_v4.00.xsd b/NFe.AppTeste/Schemas/leiauteNFe_v4.00.xsd index 7d6fb69ef..671a8ab44 100644 --- a/NFe.AppTeste/Schemas/leiauteNFe_v4.00.xsd +++ b/NFe.AppTeste/Schemas/leiauteNFe_v4.00.xsd @@ -209,7 +209,13 @@ Campo preenchido somente quando “indPres = 5 (Operação presencial, fora do e - Tipo de Nota de Débito + 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. + @@ -501,7 +507,7 @@ Preencher com "2B", quando se tratar de Cupom Fiscal emitido por máqu - + Chave de acesso da NF-e de antecipação de pagamento @@ -2555,13 +2561,15 @@ ambiente. - Motivo da desoneração do ICMS:3-Uso na agropecuária;9-Outros;12-Fomento agropecuário + Motivo da desoneração do ICMS:3-Uso na agropecuária;9-Outros; 10=Deficiente Condutor (Convênio ICMS 38/12); 11=Deficiente Não Condutor (Convênio ICMS 38/12); 12-Fomento agropecuário + + @@ -3395,11 +3403,39 @@ Informar o motivo da desoneração: Percentual de redução da BC + + + Código de Benefício Fiscal na UF aplicado ao item quando houver RBC. + + + + + + + + Alíquota do ICMS + + + + Valor do ICMS da Operação + + + + + Percentual do diferemento + + + + + Valor do ICMS da diferido + + + Valor do ICMS @@ -3422,6 +3458,23 @@ Informar o motivo da desoneração: + + + + Percentual do diferimento do ICMS relativo ao Fundo de Combate à Pobreza (FCP). + + + + + Valor do ICMS relativo ao Fundo de Combate à Pobreza (FCP) diferido. + + + + + Valor efetivo do ICMS relativo ao Fundo de Combate à Pobreza (FCP). + + + @@ -3569,12 +3622,14 @@ Operação interestadual para consumidor final com partilha do ICMS devido na o Tributação pelo ICMS 10 - Tributada e com cobrança do ICMS por substituição tributária; +20 – Redução de base de cálculo 90 – Outros. + @@ -3693,6 +3748,43 @@ Operação interestadual para consumidor final com partilha do ICMS devido na o Sigla da UF para qual é devido o ICMS ST da operação. + + + Grupo desoneração + + + + Valor do ICMS de desoneração + + + + + Motivo da desoneração do ICMS:9-Outros;10=Deficiente Condutor (Convênio ICMS 38/12) 11=Deficiente Não Condutor (Convênio ICMS 38/12) + + + + + + + + + + + + + Indica se o valor do ICMS desonerado (vICMSDeson) deduz do valor do item (vProd): +0=Valor do ICMS desonerado (vICMSDeson) não deduz do valor do item (vProd) / total da NF-e; +1=Valor do ICMS desonerado (vICMSDeson) deduz do valor do item (vProd) / total da NF-e. + + + + + + + + + + @@ -6518,16 +6610,16 @@ tipo de ato concessório: - - - - - + + + + + @@ -7576,4 +7668,4 @@ alterado para tamanho variavel 1-4. (NT2011/004) - \ No newline at end of file + diff --git a/NFe.Classes/Informacoes/Detalhe/Tributacao/Estadual/ICMS90.cs b/NFe.Classes/Informacoes/Detalhe/Tributacao/Estadual/ICMS90.cs index a3bd586c8..b721dabdd 100644 --- a/NFe.Classes/Informacoes/Detalhe/Tributacao/Estadual/ICMS90.cs +++ b/NFe.Classes/Informacoes/Detalhe/Tributacao/Estadual/ICMS90.cs @@ -40,6 +40,9 @@ public class ICMS90 : ICMSBasico private decimal? _vBc; private decimal? _pRedBc; private decimal? _pIcms; + private decimal? _vIcmsOp; + private decimal? _pDif; + private decimal? _vIcmsDif; private decimal? _vIcms; private decimal? _pMvast; private decimal? _pRedBcst; @@ -50,6 +53,9 @@ public class ICMS90 : ICMSBasico private decimal? _vBcfcp; private decimal? _pFcp; private decimal? _vFcp; + private decimal? _pFCPDif; + private decimal? _vFCPDif; + private decimal? _vFCPEfet; private decimal? _vBcfcpst; private decimal? _pFcpst; private decimal? _vFcpst; @@ -94,19 +100,55 @@ public decimal? pRedBC } /// - /// N16 - Alíquota do imposto + /// N14a - Código de Benefício Fiscal na UF aplicado ao item quando houver RBC. /// [XmlElement(Order = 6)] + public string cBenefRBC { get; set; } + + /// + /// N16 - Alíquota do imposto + /// + [XmlElement(Order = 7)] public decimal? pICMS { get { return _pIcms.Arredondar(4); } set { _pIcms = value.Arredondar(4); } } + /// + /// N16b - Valor do ICMS da Operação + /// + [XmlElement(Order = 8)] + public decimal? vICMSOp + { + get { return _vIcmsOp.Arredondar(2); } + set { _vIcmsOp = value.Arredondar(2); } + } + + /// + /// N16c - Percentual do diferimento + /// + [XmlElement(Order = 9)] + public decimal? pDif + { + get { return _pDif.Arredondar(4); } + set { _pDif = value.Arredondar(4); } + } + + /// + /// N16d - Valor do ICMS diferido + /// + [XmlElement(Order = 10)] + public decimal? vICMSDif + { + get { return _vIcmsDif.Arredondar(2); } + set { _vIcmsDif = value.Arredondar(2); } + } + /// /// N17 - Valor do ICMS /// - [XmlElement(Order = 7)] + [XmlElement(Order = 11)] public decimal? vICMS { get { return _vIcms.Arredondar(2); } @@ -117,7 +159,7 @@ public decimal? vICMS /// N17a - Valor da Base de Cálculo do FCP /// Versão 4.00 /// - [XmlElement(Order = 8)] + [XmlElement(Order = 12)] public decimal? vBCFCP { get { return _vBcfcp.Arredondar(2); } @@ -133,7 +175,7 @@ public bool vBCFCPSpecified /// N17b - Percentual do Fundo de Combate à Pobreza (FCP) /// Versão 4.00 /// - [XmlElement(Order = 9)] + [XmlElement(Order = 13)] public decimal? pFCP { get { return _pFcp.Arredondar(4); } @@ -149,7 +191,7 @@ public bool pFCPSpecified /// N17c - Valor do Fundo de Combate à Pobreza (FCP) /// Versão 4.00 /// - [XmlElement(Order = 10)] + [XmlElement(Order = 14)] public decimal? vFCP { get { return _vFcp.Arredondar(2); } @@ -161,16 +203,49 @@ public bool vFCPSpecified get { return vFCP.HasValue; } } + /// + /// N17d - Percentual do diferimento do ICMS relativo ao Fundo de Combate à Pobreza (FCP) + /// Versão 4.00 + /// + [XmlElement(Order = 15)] + public decimal? pFCPDif + { + get { return _pFCPDif.Arredondar(4); } + set { _pFCPDif = value.Arredondar(4); } + } + + /// + /// N17e - Valor do ICMS relativo ao Fundo de Combate à Pobreza (FCP) diferido + /// Versão 4.00 + /// + [XmlElement(Order = 16)] + public decimal? vFCPDif + { + get { return _vFCPDif.Arredondar(2); } + set { _vFCPDif = value.Arredondar(2); } + } + + /// + /// N17f - Valor efetivo do ICMS relativo ao Fundo de Combate à Pobreza (FCP) + /// Versão 4.00 + /// + [XmlElement(Order = 17)] + public decimal? vFCPEfet + { + get { return _vFCPEfet.Arredondar(2); } + set { _vFCPEfet = value.Arredondar(2); } + } + /// /// N18 - Modalidade de determinação da BC do ICMS ST /// - [XmlElement(Order = 11)] + [XmlElement(Order = 18)] public DeterminacaoBaseIcmsSt? modBCST { get; set; } /// /// N19 - Percentual da margem de valor Adicionado do ICMS ST /// - [XmlElement(Order = 12)] + [XmlElement(Order = 19)] public decimal? pMVAST { get { return _pMvast.Arredondar(4); } @@ -180,7 +255,7 @@ public decimal? pMVAST /// /// N20 - Percentual da Redução de BC do ICMS ST /// - [XmlElement(Order = 13)] + [XmlElement(Order = 20)] public decimal? pRedBCST { get { return _pRedBcst.Arredondar(4); } @@ -190,7 +265,7 @@ public decimal? pRedBCST /// /// N21 - Valor da BC do ICMS ST /// - [XmlElement(Order = 14)] + [XmlElement(Order = 21)] public decimal? vBCST { get { return _vBcst.Arredondar(2); } @@ -200,7 +275,7 @@ public decimal? vBCST /// /// N22 - Alíquota do imposto do ICMS ST /// - [XmlElement(Order = 15)] + [XmlElement(Order = 22)] public decimal? pICMSST { get { return _pIcmsst.Arredondar(4); } @@ -210,7 +285,7 @@ public decimal? pICMSST /// /// N23 - Valor do ICMS ST /// - [XmlElement(Order = 16)] + [XmlElement(Order = 23)] public decimal? vICMSST { get { return _vIcmsst.Arredondar(2); } @@ -221,7 +296,7 @@ public decimal? vICMSST /// N23a - Valor da Base de Cálculo do FCP retido por Substituição Tributária /// Versão 4.00 /// - [XmlElement(Order = 17)] + [XmlElement(Order = 24)] public decimal? vBCFCPST { get { return _vBcfcpst.Arredondar(2); } @@ -237,7 +312,7 @@ public bool vBCFCPSTSpecified /// N23b - Percentual do FCP retido por Substituição Tributária /// Versão 4.00 /// - [XmlElement(Order = 18)] + [XmlElement(Order = 25)] public decimal? pFCPST { get { return _pFcpst.Arredondar(4); } @@ -253,7 +328,7 @@ public bool pFCPSTSpecified /// N23d - Valor do FCP retido por Substituição Tributária /// Versão 4.00 /// - [XmlElement(Order = 19)] + [XmlElement(Order = 26)] public decimal? vFCPST { get { return _vFcpst.Arredondar(2); } @@ -268,7 +343,7 @@ public bool vFCPSTSpecified /// /// N27a - Valor do ICMS desonerado /// - [XmlElement(Order = 20)] + [XmlElement(Order = 27)] public decimal? vICMSDeson { get { return _vIcmsDeson.Arredondar(2); } @@ -278,21 +353,21 @@ public decimal? vICMSDeson /// /// N28 - Motivo da desoneração do ICMS /// - [XmlElement(Order = 21)] + [XmlElement(Order = 28)] public MotivoDesoneracaoIcms? motDesICMS { get; set; } /// /// N28b - Indica se o valor do ICMS desonerado (vICMSDeson) deduz /// do valor do item (vProd). (NT 2023.004) /// - [XmlElement(Order = 22)] + [XmlElement(Order = 29)] public DeduzDesoneracaoNoProduto? indDeduzDeson { get; set; } /// /// N33a - Valor do ICMS- ST desonerado /// Versão 4.00 /// - [XmlElement(Order = 23)] + [XmlElement(Order = 30)] public decimal? vICMSSTDeson { get { return _vICMSSTDeson.Arredondar(2); } @@ -308,7 +383,7 @@ public bool ShouldSerializevICMSSTDeson() /// N33b - Motivo da desoneração do ICMS- ST /// Versão 4.00 /// - [XmlElement(Order = 24)] + [XmlElement(Order = 31)] public MotivoDesoneracaoIcmsSt? motDesICMSST { get; set; } public bool ShouldSerializemotDesICMSST() @@ -336,11 +411,41 @@ public bool ShouldSerializepICMS() return pICMS.HasValue; } + public bool ShouldSerializevICMSOp() + { + return vICMSOp.HasValue; + } + + public bool ShouldSerializepDif() + { + return pDif.HasValue; + } + + public bool ShouldSerializevICMSDif() + { + return vICMSDif.HasValue; + } + public bool ShouldSerializevICMS() { return vICMS.HasValue; } + public bool ShouldSerializepFCPDif() + { + return pFCPDif.HasValue; + } + + public bool ShouldSerializevFCPDif() + { + return vFCPDif.HasValue; + } + + public bool ShouldSerializevFCPEfet() + { + return vFCPEfet.HasValue; + } + public bool ShouldSerializemodBCST() { return modBCST.HasValue; @@ -386,4 +491,4 @@ public bool ShouldSerializeindDeduzDeson() return indDeduzDeson.HasValue; } } -} \ No newline at end of file +} diff --git a/NFe.Classes/Informacoes/Detalhe/Tributacao/Estadual/ICMSPart.cs b/NFe.Classes/Informacoes/Detalhe/Tributacao/Estadual/ICMSPart.cs index 754e6a20d..39c73c8be 100644 --- a/NFe.Classes/Informacoes/Detalhe/Tributacao/Estadual/ICMSPart.cs +++ b/NFe.Classes/Informacoes/Detalhe/Tributacao/Estadual/ICMSPart.cs @@ -50,6 +50,7 @@ public class ICMSPart : ICMSBasico private decimal? _pFCPST; private decimal? _vFCPST; private decimal _pBcOp; + private decimal? _vIcmsDeson; /// /// N11 - Origem da Mercadoria @@ -211,6 +212,29 @@ public decimal pBCOp [XmlElement(Order = 18)] public string UFST { get; set; } + /// + /// N28a - Valor do ICMS desonerado + /// + [XmlElement(Order = 19)] + public decimal? vICMSDeson + { + get { return _vIcmsDeson.Arredondar(2); } + set { _vIcmsDeson = value.Arredondar(2); } + } + + /// + /// N28 - Motivo da desoneração do ICMS + /// + [XmlElement(Order = 20)] + public MotivoDesoneracaoIcms? motDesICMS { get; set; } + + /// + /// N28b - Indica se o valor do ICMS desonerado (vICMSDeson) deduz + /// do valor do item (vProd). (NT 2023.004) + /// + [XmlElement(Order = 21)] + public DeduzDesoneracaoNoProduto? indDeduzDeson { get; set; } + public bool ShouldSerializepRedBC() { return pRedBC.HasValue; @@ -241,5 +265,20 @@ public bool ShouldSerializevFCPST() return vFCPST.HasValue; } + public bool ShouldSerializevICMSDeson() + { + return vICMSDeson.HasValue; + } + + public bool ShouldSerializemotDesICMS() + { + return motDesICMS.HasValue; + } + + public bool ShouldSerializeindDeduzDeson() + { + return indDeduzDeson.HasValue; + } + } -} \ No newline at end of file +} diff --git a/NFe.Classes/Informacoes/Detalhe/Tributacao/Estadual/Tipos/ICMSTipos.cs b/NFe.Classes/Informacoes/Detalhe/Tributacao/Estadual/Tipos/ICMSTipos.cs index afc2b80bc..9b01c2c7d 100644 --- a/NFe.Classes/Informacoes/Detalhe/Tributacao/Estadual/Tipos/ICMSTipos.cs +++ b/NFe.Classes/Informacoes/Detalhe/Tributacao/Estadual/Tipos/ICMSTipos.cs @@ -180,6 +180,13 @@ public enum Csticms [XmlEnum("20")] Cst20, + /// + /// 20 - Com redução de base de cálculo + /// + [Description("Com redução de base de cálculo")] + [XmlEnum("20")] + CstPart20, + /// /// 30 - Isenta ou não tributada e com cobrança do ICMS por substituição tributária /// diff --git a/NFe.Utils/Conversao.cs b/NFe.Utils/Conversao.cs index 5adaad42b..4222a7f66 100644 --- a/NFe.Utils/Conversao.cs +++ b/NFe.Utils/Conversao.cs @@ -200,6 +200,7 @@ public static string CsticmsParaString(this Csticms csticms) case Csticms.CstPart10: return "10"; case Csticms.Cst20: + case Csticms.CstPart20: return "20"; case Csticms.Cst15: return "15"; diff --git a/NFe.Utils/Tributacao/Estadual/ICMSGeral.cs b/NFe.Utils/Tributacao/Estadual/ICMSGeral.cs index 35fbadffc..c29a7eb64 100644 --- a/NFe.Utils/Tributacao/Estadual/ICMSGeral.cs +++ b/NFe.Utils/Tributacao/Estadual/ICMSGeral.cs @@ -129,6 +129,7 @@ public ICMSBasico ObterICMSBasico(CRT crt) icmsBasico = new ICMS15(); break; case Csticms.CstPart10: + case Csticms.CstPart20: case Csticms.CstPart90: icmsBasico = new ICMSPart(); break; @@ -242,6 +243,11 @@ public ICMSBasico ObterICMSBasico(CRT crt) /// public decimal pRedBC { get; set; } + /// + /// Código de Benefício Fiscal na UF aplicado ao item quando houver RBC. + /// + public string cBenefRBC { get; set; } + /// /// Valor do ICMS desonerado /// @@ -367,6 +373,21 @@ public ICMSBasico ObterICMSBasico(CRT crt) /// public decimal? vFCPST { get; set; } + /// + /// Percentual do diferimento do ICMS relativo ao Fundo de Combate à Pobreza (FCP) + /// + public decimal? pFCPDif { get; set; } + + /// + /// Valor do ICMS relativo ao Fundo de Combate à Pobreza (FCP) diferido + /// + public decimal? vFCPDif { get; set; } + + /// + /// Valor efetivo do ICMS relativo ao Fundo de Combate à Pobreza (FCP) + /// + public decimal? vFCPEfet { get; set; } + #endregion /// @@ -432,4 +453,4 @@ public ICMSBasico ObterICMSBasico(CRT crt) public decimal? vICMSMonoRet { get; set; } } -} \ No newline at end of file +}