DACTE: coluna ICMS ST lê vICMSSTRet em vez de repetir o vICMS - #193
Merged
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #193 +/- ##
=======================================
Coverage 96.44% 96.44%
=======================================
Files 32 32
Lines 4385 4385
Branches 349 349
=======================================
Hits 4229 4229
Misses 92 92
Partials 64 64 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
CristianoMafraJunior
approved these changes
Aug 14, 2026
antoniospneto
force-pushed
the
fix/dacte-icms-st-ret
branch
from
August 20, 2026 00:54
7f50f75 to
e5f2a72
Compare
A coluna ICMS ST do quadro "INFORMAÇÕES RELATIVAS AO IMPOSTO" era preenchida
com a tag vICMS — o ICMS próprio:
self.v_icms = format_number(extract_text(self.imp, "vICMS"), ...)
self.v_icms_st = format_number(extract_text(self.imp, "vICMS"), ...)
Num CT-e com CST 00 (tributação normal, sem substituição tributária alguma) o
DACTE imprimia o ICMS próprio na coluna ICMS ST, ou seja, exibia uma ST que não
existe. E quando o CT-e realmente tinha ST, o valor declarado não aparecia.
A tag correta é vICMSSTRet. Verificado no pacote oficial PL_CTe_400_NT2026.002:
vICMSSTRet é o único campo de ST do documento CT-e e vive no grupo ICMS60
(CST, vBCSTRet, vICMSSTRet, pICMSSTRet, vCred, vICMSDeson, cBenef). Ausente nos
demais grupos, format_number devolve "0,00", que é o correto.
Não há fallback para vICMSST: essa tag não existe no documento CT-e, só no
evento EPEC (evEPECCTe_v4.00.xsd). Lê-la aqui seria código morto.
Fixture nova dacte_icms_st.xml, um CT-e CST 60 derivado do dacte_test_1.xml.
Validada com xmllint contra procCTe_v4.00.xsd: o conjunto de erros é idêntico
ao da fixture de origem, isto é, o bloco ICMS60 não introduz nenhum.
Os PDFs golden foram regerados porque a coluna ICMS ST deles estava errada — os
testes vinham confirmando o valor incorreto. Conferido que a diferença é só
essa: 15 dos 16 mudaram exatamente um trecho de texto, do valor do vICMS para
"0,00", sem nenhuma mudança de posição. O dacte_multi_pages não mudou (é
ICMS45/CST 40, sem vICMS, já exibia 0,00).
Nota: dacte_test_overload.xml declara <vICMSST> dentro de um ICMS00, o que o
xmllint rejeita ("This element is not expected") — a fixture é inválida de
propósito, para exercitar campos de layout. Com esta mudança essa tag deixa de
ser lida por qualquer código.
antoniospneto
force-pushed
the
fix/dacte-icms-st-ret
branch
from
August 20, 2026 01:13
e5f2a72 to
897871b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refaz a #185, de @andmit10. O bug que ela identificou é real e grave; a implementação estava lendo uma tag que não existe no leiaute do CT-e.
Problema
A coluna ICMS ST do quadro "INFORMAÇÕES RELATIVAS AO IMPOSTO" era preenchida com
vICMS— o ICMS próprio:Duas consequências, em documento fiscal auxiliar:
vICMS, e o DACTE imprimia esse mesmo valor na coluna ICMS ST. Quem confere o documento lia uma substituição tributária inexistente.O que muda em relação à #185
A #185 lia
vICMSSTRetcom fallback paravICMSST.vICMSSTnão existe no documento CT-e. Verifiquei no pacote oficialPL_CTe_400_NT2026.002: a tag aparece apenas emevEPECCTe_v4.00.xsd, o evento EPEC — outro documento. No CT-e o único campo de ST évICMSSTRet, no grupoICMS60:O fallback foi removido — era código morto. Ausente a tag,
format_numberdevolve"0,00", que é o correto para CST 00/20/45/90.A #185 também provava o comportamento com
dacte_test_overload.xml, que declara<vICMSST>dentro de umICMS00. Oxmllintrejeita explicitamente:Essa fixture é inválida de propósito (existe para exercitar todo campo do layout), então não serve como prova aqui. Trocada por uma fixture de CT-e com ST de verdade.
Fixture nova
tests/fixtures/dacte/dacte_icms_st.xml— um CT-e CST 60 derivado dodacte_test_1.xml, trocando o blocoICMS00porICMS60.Validada com
xmllintcontraprocCTe_v4.00.xsd: o conjunto de erros é idêntico ao da fixture de origem (7 erros, todos artefatos pré-existentes das fixtures —cUFfictício,cCTcom 7 dígitos, espaço à direita emproPred, quebra de linha noqrCodCTe). Ou seja, o bloco ICMS60 não introduz nenhum erro novo.Testes
test_dacte_icms_st_le_vicmsstret— CT-e CST 60 →v_icms_st == "20,00"test_dacte_icms_st_zero_quando_nao_declarado— CT-e CST 00 →v_icms == "26,54"ev_icms_st == "0,00"test_dacte_icms_st— golden PDF da fixture nova, que trava a renderização completa de um CT-e com STOs dois primeiros verificados falhando sem a correção.
PDFs golden — regenerados
Regenerados porque a coluna ICMS ST deles estava errada: os testes vinham confirmando o valor incorreto. Conferi a diferença comparando os content streams antes/depois trecho a trecho:
vICMSpara0,00(26,54 -> 0,00nos retrato,8,46 -> 0,00nos de modal)dacte_multi_pagesnão mudou — éICMS45/CST 40, não temvICMS, já exibia0,00. Bom sinal de sanidade.dacte_overloadpassa de26,54para0,00(e não para20,00), que é a consequência esperada de remover o fallbackNotas
mainatual (28bade4, depois de DACTE: recorta textos longos que invadem campos vizinhos #190, DACTE: agrega componentes do valor além do 9º em vez de descartá-los #191, DACTE: formata o valor dos componentes em pt-BR #192 e DACTE: acerta os testes de componentes com a formatação pt-BR #194). O conflito de binários com a DACTE: formata o valor dos componentes em pt-BR #192 foi resolvido regerando os goldens em cima dela: odacte_icms_st.pdfagora sai com os componentes em pt-BR (117.78 -> 117,78), que é a formatação que a DACTE: formata o valor dos componentes em pt-BR #192 introduziu.test_dacte_components.pyque apareciam aqui foram resolvidas pela DACTE: acerta os testes de componentes com a formatação pt-BR #194, já mergeada. Eram herança do cruzamento DACTE: agrega componentes do valor além do 9º em vez de descartá-los #191 × DACTE: formata o valor dos componentes em pt-BR #192 e nada tinham a ver com esta PR. Com a DACTE: acerta os testes de componentes com a formatação pt-BR #194 namain, a suíte fecha em 104 passando.ICMS60o resto do quadro sai zerado, porquevBC/pICMS/vICMSnão existem nesse grupo (sãovBCSTRetepICMSSTRet). É omissão pré-existente, não valor incorreto, e mexer nisso exige decidir o mapeamento das 6 colunas para os 7 grupos ICMS. Fica para uma issue separada.