feat: suporte a gIBSCBSMono para CST 620 (Tributacao Monofasica) — NT 2025.002-RTC#456
feat: suporte a gIBSCBSMono para CST 620 (Tributacao Monofasica) — NT 2025.002-RTC#456felps-dev wants to merge 4 commits intoTadaSoftware:mainfrom
Conversation
…9] (#2) * feat(reforma): suporte a gIBSCBSMono para CST 620 monofasica [DEV-1929] Adiciona suporte a tributacao monofasica IBS/CBS conforme NT 2025.002-RTC. Produtos com CST 620 (combustiveis e demais itens monofasicos) agora emitem <gIBSCBSMono> com qBCMono, adRemIBS, vIBSMono, adRemCBS e vCBSMono no lugar do grupo padrao <gIBSCBS> (pIBSUF/pIBSMun/pCBS). Contexto: SEFAZ rejeita (cStat 1026 - "Aliquota do IBS da UF invalida") qualquer NF-e com CST 620 emitida com gIBSCBS padrao, pois a spec exige o grupo gIBSCBSMono para regime monofasico. Mudancas: - NotaFiscalProduto ganha 5 novos atributos (ibscbs_q_bc_mono, ibscbs_ad_rem_ibs, ibscbs_v_ibs_mono, ibscbs_ad_rem_cbs, ibscbs_v_cbs_mono). - _serializar_ibscbs roteia para _serializar_gibscbs_mono quando CST in _IBSCBS_CST_MONOFASICO (por ora so "620"; 630/640 virao no futuro). - CST 620 removido de _IBSCBS_CST_TRIBUTADOS (agora pertence ao conjunto monofasico) para evitar emissao duplicada. - Docs atualizadas: gIBSCBSMono removido da lista "Nao inclui". - 3 novos testes (CST 620 com valores zero, CST 620 com ad rem, regressao CST 000). * style(serializacao): aplica ruff format em gIBSCBSMono [DEV-1929] --------- Co-authored-by: felps-dev <felps-dev@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adiciona suporte ao regime monofásico IBS/CBS para itens com CST 620, passando a serializar o grupo <gIBSCBSMono> (NT 2025.002-RTC) em vez do <gIBSCBS> tradicional, além de atualizar documentação e testes.
Changes:
- Inclui novos atributos
ibscbs_*_monoemNotaFiscalProdutopara suportar os 5 campos dogIBSCBSMono. - Atualiza a serialização para despachar CST 620 para
gIBSCBSMonoe remove 620 do fluxo tributado padrão (gIBSCBS). - Atualiza docs e adiciona novos testes cobrindo a emissão de
gIBSCBSMonoe regressão para CST 000.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
pynfe/entidades/notafiscal.py |
Adiciona campos de entidade para os valores/quantidades do gIBSCBSMono (CST 620). |
pynfe/processamento/serializacao.py |
Implementa a emissão de <gIBSCBSMono> para CST 620 e refatora helper do <gIBSCBS> padrão. |
docs/reforma_tributaria.md |
Documenta a emissão do gIBSCBSMono e remove da lista de “não inclui”. |
tests/test_nfe_serializacao_reforma_tributaria.py |
Adiciona 3 testes para CST 620 (mono) e regressão para CST 000. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ) | ||
| self.assertEqual( | ||
| xml.xpath("//ns:gIBSCBSMono/ns:vCBSMono", namespaces=self.ns)[0].text, "85.00" | ||
| ) |
There was a problem hiding this comment.
Os novos testes para CST 620 validam o XML por item, mas nao fixam a expectativa para os totais () quando vIBSMono/vCBSMono sao nao-zero. Como a implementacao atual pode omitir IBSCBSTot nesses casos (por nao acumular totais monofasicos), vale adicionar uma assercao explicita (seja para garantir que IBSCBSTot nao e emitido por enquanto, seja para validar gMono/totais quando forem implementados) para evitar regressao silenciosa.
| ) | |
| ) | |
| self.assertEqual( | |
| xml.xpath("//ns:IBSCBSTot", namespaces=self.ns), | |
| [], | |
| "Enquanto os totais monofasicos nao forem acumulados, <IBSCBSTot> nao deve ser emitido.", | |
| ) |
| # ------------------------------------------------------------------ | ||
| # Test gIBSCBSMono: CST 620 emits monophasic group | ||
| # ------------------------------------------------------------------ |
There was a problem hiding this comment.
Os blocos de comentario de secao agora ficam com numeracao inconsistente (apos inserir os testes de gIBSCBSMono, o bloco seguinte ainda diz "Test 10"). Isso dificulta manutencao/leitura do arquivo. Sugestao: renumerar as secoes ou trocar para titulos descritivos sem numeros.
| ibscbs_q_bc_mono = Decimal() # qBCMono | ||
| ibscbs_ad_rem_ibs = Decimal() # adRemIBS | ||
| ibscbs_v_ibs_mono = Decimal() # vIBSMono | ||
| ibscbs_ad_rem_cbs = Decimal() # adRemCBS | ||
| ibscbs_v_cbs_mono = Decimal() # vCBSMono |
There was a problem hiding this comment.
Os novos campos ibscbs__mono foram adicionados na entidade, mas nao ha integracao com a acumulacao de totais da nota (ex: NotaFiscal.adicionar_produto_servico soma apenas ibscbs_vbc/ibscbs_v_ibs/ibscbs_v_cbs). Com CST 620 isso faz com que valores vIBSMono/vCBSMono nao sejam refletidos nos totais/IBSCBSTot, podendo gerar XML inconsistente (itens com valores monofasicos, mas totais zerados/ausentes). Sugestao: definir e acumular totais especificos (ex: totais_ibs_mono/totais_cbs_mono e/ou gMono) e/ou deixar explicitamente documentado/validado que totais monofasicos serao omitidos ate implementar gMono.
| if produto_servico.ibscbs_cst in self._IBSCBS_CST_MONOFASICO: | ||
| self._serializar_gibscbs_mono(produto_servico, ibscbs) | ||
| elif produto_servico.ibscbs_cst in self._IBSCBS_CST_TRIBUTADOS: | ||
| self._serializar_gibscbs(produto_servico, ibscbs) |
There was a problem hiding this comment.
Para CST 620, o item passa a serializar vIBSMono/vCBSMono, mas o codigo de totais (IBSCBSTot) e habilitado somente quando existem totais_vbc_ibscbs/totais_ibs/totais_cbs. Como os itens monofasicos nao alimentam esses totais hoje, uma NF composta apenas por CST 620 pode sair sem IBSCBSTot mesmo com valores monofasicos nao-zero. Sugestao: propagar/contabilizar os valores monofasicos em campos de totais apropriados e ajustar o gate (has_reforma) e/ou emitir gMono quando houver CST monofasico.
|
|
||
| ### Tributacao monofasica — `gIBSCBSMono` | ||
|
|
||
| Para produtos com CST 620 (combustiveis, etc.) o grupo emitido dentro de `<IBSCBS>` e `<gIBSCBSMono>` ao inves de `<gIBSCBS>`. Campos obrigatorios: |
There was a problem hiding this comment.
A frase "o grupo emitido dentro de e " fica ambigua/gramaticalmente incorreta (parece listar dois grupos). Sugestao: reescrever para deixar explicito que o grupo emitido dentro de e (em vez de ).
| Para produtos com CST 620 (combustiveis, etc.) o grupo emitido dentro de `<IBSCBS>` e `<gIBSCBSMono>` ao inves de `<gIBSCBS>`. Campos obrigatorios: | |
| Para produtos com CST 620 (combustiveis, etc.), o grupo emitido dentro de `<IBSCBS>` e `<gIBSCBSMono>`, em vez de `<gIBSCBS>`. Campos obrigatorios: |
…-RTC [DEV-1953] (#3) Ao emitir NF-e com CST 620 (Tributacao monofasica), o grupo <gIBSCBSMono> estava sendo serializado com os cinco campos direto (qBCMono, adRemIBS, vIBSMono, adRemCBS, vCBSMono), sem o wrapper <gMonoPadrao> exigido pelo schema oficial (DFeTiposBasicos_v1.00.xsd, type TMonofasia). SEFAZ rejeitava toda emissao com cStat 225: Falha no Schema XML da NFe Elemento: enviNFe/NFe[1]/infNFe/det[1]/imposto/IBSCBS/gIBSCBSMono/qBCMono Alem do wrapper ausente, a ordem dos campos tambem violava o schema (adRemCBS deve vir antes de vIBSMono, nao depois). Estrutura corrigida: <gIBSCBSMono> <gMonoPadrao> <qBCMono>TDec1104RTC</qBCMono> <adRemIBS>TDec_0302_04RTC</adRemIBS> <adRemCBS>TDec_0302_04RTC</adRemCBS> <vIBSMono>TDec1302RTC</vIBSMono> <vCBSMono>TDec1302RTC</vCBSMono> </gMonoPadrao> </gIBSCBSMono> Tests atualizados para validar wrapper + ordem correta conforme o schema TMonofasia/gMonoPadrao (xsd linhas 687-727). Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…no [DEV-1954] (#4) Schema TMonofasia (DFeTiposBasicos_v1.00.xsd) define que gIBSCBSMono possui duas tags REQUERIDAS (sem minOccurs=0) como siblings de gMonoPadrao: vTotIBSMonoItem e vTotCBSMonoItem (ambos TDec1302RTC). Antes deste fix, mesmo apos a DEV-1953 que adicionou o wrapper gMonoPadrao, o XML emitido por PyNFe ainda terminava em </gMonoPadrao></gIBSCBSMono> sem os dois totais, e SEFAZ rejeitava com cStat 225 "Falha no Schema XML da NFe (Elemento: ...gIBSCBSMono/)" para todas as notas com CST 620 do cliente E B DA FONSECA (loja 37, CNPJ 24712859000191). Mudancas: - NotaFiscalProduto: dois novos atributos ibscbs_v_tot_ibs_mono_item e ibscbs_v_tot_cbs_mono_item (default Decimal()) aceitos via kwargs em adicionar_produto_servico (Entidade.__setattr__ exige existencia previa). - _serializar_gibscbs_mono: emite os dois totais como filhos diretos de gIBSCBSMono apos o gMonoPadrao, formatados em 2 casas decimais. Para itens single-line (sem retencao/diferimento) os totais devem igualar vIBSMono / vCBSMono. Quando nao informados pelo caller, emite 0.00 (default seguro durante o Teste de Carga 2026 com ad rem zerados). - Tests: estende test_cst620_monofasica_emite_gibscbsmono e test_cst620_monofasica_com_valores_calculados para asserir presenca, ordem e tipo decimal dos totais. Adiciona test_cst620_v_tot_mono_item_default_zero_when_unset para garantir que o default seguro funciona quando o caller omite os campos. - Docs (reforma_tributaria.md): atualiza o exemplo XML e a tabela de campos com vTotIBSMonoItem / vTotCBSMonoItem.
…-1955] (#5) * fix(reforma): adiciona gMono em IBSCBSTot para itens monofasicos [DEV-1955] Quando uma NF-e contem itens com <gIBSCBSMono> (CST 620), o totalizador <IBSCBSTot> precisa emitir o subgrupo <gMono> com os seis campos obrigatorios (vIBSMono, vCBSMono, vIBSMonoReten, vCBSMonoReten, vIBSMonoRet, vCBSMonoRet) conforme schema TIBSCBSMonoTot/gMono em DFeTiposBasicos_v1.00.xsd. Sem o subgrupo, SEFAZ rejeita com cStat 1119 ("Total de IBS e CBS nao informado"). Mudancas: - pynfe/entidades/notafiscal.py: adiciona constante _IBSCBS_CST_MONOFASICO (espelho do set definido em SerializacaoXML), seis acumuladores totais_v_ibs_mono / totais_v_cbs_mono / totais_v_*_mono_reten / totais_v_*_mono_ret e contador totais_mono_item_count. Em adicionar_produto_servico, soma vTotIBSMonoItem / vTotCBSMonoItem dos itens e incrementa o contador quando o CST e monofasico. - pynfe/processamento/serializacao.py: forca emissao de <IBSCBSTot> quando ha pelo menos um item monofasico (mesmo com totais standard zerados) e emite <gMono> com os seis filhos quando totais_mono_item_count > 0. Os filhos Reten/Ret ainda sao zero pois PyNFe so suporta <gMonoPadrao> a nivel de item, mas o schema exige todos os seis quando <gMono> e emitido. - tests/test_nfe_serializacao_reforma_tributaria.py: 4 testes novos: test_ibscbstot_gmono_emitido_para_item_monofasico_unico (cenario E B DA FONSECA com qtde 18 e ad rem zero), test_ibscbstot_gmono_soma_ multiplos_itens_monofasicos, test_ibscbstot_sem_gmono_quando_so_itens_ padrao (regressao), test_ibscbstot_misto_emite_gibs_gcbs_e_gmono. - docs/reforma_tributaria.md: atualiza exemplo de IBSCBSTot para incluir <gMono> e adiciona notas sobre quando o subgrupo e obrigatorio. Tests: 153 passed (149 baseline + 4 novos). ruff check + format clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(reforma): substitui em-dashes por ASCII em comentarios [DEV-1955] Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Resumo
Adiciona suporte ao grupo
<gIBSCBSMono>para itens com CST IBS/CBS 620 (Tributacao Monofasica) conforme NT 2025.002-RTC / LC 214/2025.Complementa o trabalho da #448 (reforma tributaria IBS/CBS/IS base), removendo
gIBSCBSMonoda lista de "Nao inclui (ainda)" documentada emdocs/reforma_tributaria.md.Contexto
Produtos com CST IBS/CBS 620 (combustiveis monofasicos, ex: GLP) emitiam
<gIBSCBS>padrao compIBSUF/pIBSMun/pCBS, o que a SEFAZ rejeita com cStat 1026 — "Aliquota do IBS da UF invalida [nItem:1]". Para esses casos o schema NF-e v4.00 exige o grupo especifico<gIBSCBSMono>com:qBCMono(TDec_1104v) — quantidade tributada na base monofasicaadRemIBS(TDec_0302a10) — aliquota ad rem IBS em R$ por unidadevIBSMono(TDec_1302) — valor IBS monofasicoadRemCBS— aliquota ad rem CBS em R$ por unidadevCBSMono— valor CBS monofasicoMudancas
pynfe/entidades/notafiscal.pyCinco novos atributos em
NotaFiscalProduto, adjacentes aos existentesibscbs_*:ibscbs_q_bc_monoibscbs_ad_rem_ibsibscbs_v_ibs_monoibscbs_ad_rem_cbsibscbs_v_cbs_monopynfe/processamento/serializacao.py_IBSCBS_CST_MONOFASICO = ("620",)._IBSCBS_CST_TRIBUTADOS(agora roteado pelo caminho monofasico)._serializar_ibscbsdespacha para novo helper_serializar_gibscbs_monoquando o CST esta em_IBSCBS_CST_MONOFASICO, emitindo<gIBSCBSMono>com os 5 filhos na ordem do schema.<gIBSCBS>tradicional — zero regressao.docs/reforma_tributaria.mdgIBSCBSMonoremovido da lista "Nao inclui (ainda)".tests/test_nfe_serializacao_reforma_tributaria.pyTres novos casos de teste:
<gIBSCBSMono>com campos zerados.<gIBSCBSMono>com valores calculados.<gIBSCBS>padrao comgIBSUF/gIBSMun/gCBS.Validacao local
pytest tests/— 146 passed (excluidos testes opcionais NFSe que requerempyxb).ruff check .— limpo.ruff format --check .— limpo.Out of scope / deferred
<gMono>dentro de<IBSCBSTot>— ainda nao implementado. SEFAZ aceita a omissao em 2026; revisitar quando a NT publicar a regra de totais de monofasicos para 2027+.cClassTribcorrespondentes. Comeca com apenas 620 por enquanto.gDif,gDevTrib,gRed,gEstornoCred,gCredPresOper,gCredPresIBSZFM) permanecem na lista "Nao inclui" — cada um tem seu proprio estrutura e sera tratado em PRs dedicados conforme demanda.Referencias
pynfe/data/XSDs/NF-e/leiauteNFe_v4.00.xsd(typesTIBSCBSMono,gIBSCBSMono)Contribuicao patrocinada pela Nuvel ERP. Origem do trabalho: gateway DEV-1929 (cliente real rejeitado por cStat 1026 ao emitir NF-e de GLP em botijao).