Skip to content

DACTE: coluna ICMS ST lê vICMSSTRet em vez de repetir o vICMS - #193

Merged
antoniospneto merged 1 commit into
mainfrom
fix/dacte-icms-st-ret
Aug 20, 2026
Merged

DACTE: coluna ICMS ST lê vICMSSTRet em vez de repetir o vICMS#193
antoniospneto merged 1 commit into
mainfrom
fix/dacte-icms-st-ret

Conversation

@antoniospneto

@antoniospneto antoniospneto commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

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:

self.v_icms    = format_number(extract_text(self.imp, "vICMS"), precision=2)
self.v_icms_st = format_number(extract_text(self.imp, "vICMS"), precision=2)  # <-- vICMS

Duas consequências, em documento fiscal auxiliar:

  1. CT-e sem ST exibia uma ST que não existe. Com CST 00 (tributação normal) o XML traz só vICMS, e o DACTE imprimia esse mesmo valor na coluna ICMS ST. Quem confere o documento lia uma substituição tributária inexistente.
  2. Quando o CT-e realmente tinha ST, o valor declarado nunca aparecia.

O que muda em relação à #185

A #185 lia vICMSSTRet com fallback para vICMSST. vICMSST não existe no documento CT-e. Verifiquei no pacote oficial PL_CTe_400_NT2026.002: a tag aparece apenas em evEPECCTe_v4.00.xsd, o evento EPEC — outro documento. No CT-e o único campo de ST é vICMSSTRet, no grupo ICMS60:

ICMS00  ->  CST, vBC, pICMS, vICMS
ICMS60  ->  CST, vBCSTRet, vICMSSTRet, pICMSSTRet, vCred, vICMSDeson, cBenef

O fallback foi removido — era código morto. Ausente a tag, format_number devolve "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 um ICMS00. O xmllint rejeita explicitamente:

element vICMSST: Schemas validity error :
  Element '{...}vICMSST': This element is not expected.

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 do dacte_test_1.xml, trocando o bloco ICMS00 por ICMS60.

Validada com xmllint contra procCTe_v4.00.xsd: o conjunto de erros é idêntico ao da fixture de origem (7 erros, todos artefatos pré-existentes das fixtures — cUF fictício, cCT com 7 dígitos, espaço à direita em proPred, quebra de linha no qrCodCTe). 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" e v_icms_st == "0,00"
  • test_dacte_icms_st — golden PDF da fixture nova, que trava a renderização completa de um CT-e com ST

Os 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:

  • 15 dos 16 mudaram exatamente um trecho de texto, do valor do vICMS para 0,00 (26,54 -> 0,00 nos retrato, 8,46 -> 0,00 nos de modal)
  • nenhuma mudança de posição
  • dacte_multi_pages não mudou — é ICMS45/CST 40, não tem vICMS, já exibia 0,00. Bom sinal de sanidade.
  • dacte_overload passa de 26,54 para 0,00 (e não para 20,00), que é a consequência esperada de remover o fallback

Notas

@codecov

codecov Bot commented Aug 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.44%. Comparing base (28bade4) to head (897871b).

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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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
antoniospneto force-pushed the fix/dacte-icms-st-ret branch from e5f2a72 to 897871b Compare August 20, 2026 01:13
@antoniospneto
antoniospneto merged commit 2798b3a into main Aug 20, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants