Skip to content

dacte: ICMS ST lê vICMSST em vez de repetir o vICMS - #185

Closed
andmit10 wants to merge 1 commit into
Engenere:mainfrom
andmit10:fix/dacte-icms-st
Closed

dacte: ICMS ST lê vICMSST em vez de repetir o vICMS#185
andmit10 wants to merge 1 commit into
Engenere:mainfrom
andmit10:fix/dacte-icms-st

Conversation

@andmit10

Copy link
Copy Markdown
Contributor

Problema

No DACTE, a coluna ICMS ST é preenchida com a tag vICMS — o ICMS próprio — em vez do ICMS ST:

https://github.com/Engenere/BrazilFiscalReport/blob/main/brazilfiscalreport/dacte/dacte.py#L1292-L1293

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, ambas em documento fiscal auxiliar:

  1. CT-e sem ST exibe um ST que não existe. Com CST 00 (tributação normal) o XML traz só vICMS; o DACTE imprime esse mesmo valor na coluna ICMS ST. Quem confere o documento lê uma substituição tributária inexistente.
  2. Quando o XML declara vICMSST, o valor declarado nunca aparece.

Como reproduzir

Com uma fixture que já existe no repositório — tests/fixtures/dacte/dacte_test_overload.xml declara vICMS=26.54 e vICMSST=20.00:

from brazilfiscalreport.dacte import Dacte

dacte = Dacte(xml=open("tests/fixtures/dacte/dacte_test_overload.xml", encoding="utf-8").read())
print(dacte.v_icms, dacte.v_icms_st)
# antes:  26,54 26,54   <- o 20,00 declarado no XML não aparece em lugar nenhum do PDF
# depois: 26,54 20,00

O que muda

v_icms_st passa a ler vICMSSTRet (ICMS ST retido anteriormente) e, na ausência dele, vICMSST — caindo para zero quando nenhum dos dois é declarado, que é o caso do CST 00.

A ordem vICMSSTRetvICMSST segue o leiaute do CT-e: em ICMSSN/ICMSOutraUF o ST retido vem em vICMSSTRet, enquanto vICMSST aparece nos grupos com ST próprio.

Testes

Dois testes novos em tests/test_dacte.py, ambos direto no atributo (sem depender de comparação de PDF):

  • test_dacte_icms_st_le_a_tag_correta — com dacte_test_overload.xml, garante v_icms == "26,54" e v_icms_st == "20,00".
  • test_dacte_icms_st_zero_quando_nao_declarado — com dacte_test_1.xml (sem vICMSST), garante v_icms_st == "0,00".

Verifiquei que ambos falham sem a correção (AssertionError: assert '26,54' == '20,00').

PDFs de referência

Os 15 PDFs de tests/generated/dacte/ foram regerados com BFR_GENERATE_EXPECTED=1, porque a coluna ICMS ST deles estava errada — os testes golden vinham confirmando o valor incorreto.

Suíte completa: 94 passed.

A coluna ICMS ST do DACTE vinha da tag vICMS, então imprimia o próprio
ICMS. Em CT-e sem ST (CST 00) o DACTE mostrava um ICMS ST que não existe;
quando o XML declarava vICMSST, o valor declarado nunca era exibido.

Passa a ler vICMSSTRet (ST retido anteriormente) e, na ausência, vICMSST,
caindo para zero quando nenhum dos dois é declarado.

Os PDFs de referência foram regerados: a coluna ICMS ST deles estava
errada.
@antoniospneto

Copy link
Copy Markdown
Contributor

@andmit10 boa, consegue só arrumar o pre-commit?

@antoniospneto

Copy link
Copy Markdown
Contributor

Obrigado, @andmit10 — o bug que você achou aqui é dos bons: um CT-e sem substituição tributária nenhuma exibindo o ICMS próprio na coluna ICMS ST, em documento fiscal auxiliar. Confirmei tudo e refiz em #193, com sua autoria preservada no commit.

O que mudou em relação a esta:

1. Tirei o fallback or extract_text(self.imp, "vICMSST"). Fui atrás no pacote oficial PL_CTe_400_NT2026.002: vICMSST não existe no documento CT-e — aparece só em evEPECCTe_v4.00.xsd, o evento EPEC. No CT-e o único campo de ST é o vICMSSTRet mesmo, no grupo ICMS60. O fallback era código morto.

2. Troquei a fixture do teste. O dacte_test_overload.xml declara <vICMSST> dentro de um ICMS00, e o xmllint rejeita explicitamente:

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

Ela é inválida de propósito (existe pra exercitar todo campo do layout), então não servia de prova. Criei a dacte_icms_st.xml, um CT-e CST 60 derivado do dacte_test_1.xml — validada contra o procCTe_v4.00.xsd com conjunto de erros idêntico ao da fixture de origem, ou seja, o bloco ICMS60 não introduz nenhum.

3. E501 + ruff-format — a linha do or tinha 93 caracteres e era o único CI vermelho aqui.

4. Teste golden pra fixture nova, travando a renderização completa de um CT-e com ST.

Sobre os goldens: mantive sua decisão de regerar (eles vinham confirmando o valor errado), mas conferi o escopo antes de aceitar — 15 dos 16 mudaram exatamente um trecho, do vICMS para 0,00, sem nenhuma mudança de posição. O dacte_multi_pages não mudou, porque é ICMS45/CST 40 e já exibia 0,00.

Um achado adjacente que virou item de backlog, não entrou na #193: num CT-e ICMS60 o resto do quadro sai zerado, porque vBC/pICMS/vICMS não existem nesse grupo (lá são vBCSTRet e pICMSSTRet). É omissão pré-existente, não valor incorreto — sua correção não piora nada, só não alcança isso.

Fechando em favor da #193. Valeu pela contribuição — essa e a #186 renderam quatro PRs.

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.

2 participants