Skip to content

DACTE: recorta textos longos que invadem campos vizinhos - #190

Merged
CristianoMafraJunior merged 1 commit into
mainfrom
fix/dacte-text-clip
Aug 19, 2026
Merged

DACTE: recorta textos longos que invadem campos vizinhos#190
CristianoMafraJunior merged 1 commit into
mainfrom
fix/dacte-text-clip

Conversation

@antoniospneto

@antoniospneto antoniospneto commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Primeira metade da #186, de @andmit10 — os dois recortes de texto, que não dependem de nenhuma decisão de layout. A agregação de componentes excedentes foi separada na #191.

Problema

O layout do DACTE desenha em posição absoluta e alguns campos não recortam o texto. Quando o conteúdo é mais largo que a coluna, ele é escrito por cima do campo vizinho.

1. Razão social longa do emitente cobre a linha do CNPJ. O nome é desenhado com multi_cell(h=5), que quebra linha, mas o endereço logo abaixo é ancorado num Y fixo (y_text + 6) — só há uma linha de 5 mm reservada. A segunda linha do nome cai exatamente sobre CNPJ: ... IE: ...:

RODONAVES TRANSPORTES E
CNPJ: ENCOMENDAS LTDA82533118      <- nome e CNPJ sobrepostos

2. Nome de componente invade a coluna do valor. Na seção "COMPONENTES DO VALOR DA PRESTAÇÃO DO SERVIÇO" o xNome é escrito com cell(), que não recorta nem quebra. A coluna tem col_width/2 = 23,75 mm, menos 2 × c_margin = 21,75 mm úteis; "OUTROS VALORES" em Times 8 mede 25,01 mm:

OUTROS VALORES331.77      <- nome e valor colados

Não é caso de borda: Comp/xNome é texto livre de até 15 caracteres no XSD, e AGENDAMENTO — um dos exemplos citados na documentação do próprio schema — já mede 21,95 mm.

O que muda

Os dois passam a usar long_field, o mesmo recorte por largura medida já usado no DANFE e nos demais nomes do próprio DACTE (rem_nome, dest_nome, receb_nome, exped_nome, tomador_nome). Nenhum helper novo, nenhuma mudança de geometria.

Único ajuste em relação à #186: o long_field do componente passa font_size=8 explícito. A fonte ambiente ali já era Times 8, então o resultado é idêntico — mas deixa de depender de estado implícito, como o call site do emitente já fazia.

Vale saber

A caixa do nome do emitente tem 63 mm e comporta ~30 caracteres em Times-Bold 9, de um domínio de 60 (emit/xNome maxLength="60"). Ou seja, razão social acima de ~30 caracteres passa a sair truncada com "…". É a troca certa — "nome cortado + CNPJ legível" é melhor que "nome inteiro + CNPJ ilegível", e é o que a lib já faz em todo o resto — mas não é de graça, e vai aparecer em bastante CT-e real.

Alargar a caixa não resolve: o retângulo do emitente vai de x=5 a x=72 e o bloco DACTE/MODAL começa em 72. Verticalmente também não sobra: h_rect=27 e o endereço termina 1 mm antes do fim. As saídas seriam reduzir a fonte quando não couber (a 7pt cabem ~34) ou compactar o bloco de endereço — as duas mudam geometria e ficam para depois.

Testes

Os testes renderizam o PDF e leem de volta as posições do texto do content stream, em vez de checar a chamada de um helper — medem o resultado e continuam válidos se a implementação mudar.

  • test_razao_social_longa_nao_escreve_por_cima_do_cnpj
  • test_nome_de_componente_longo_nao_invade_a_coluna_do_valor

Ambos verificados falhando sem a correção. PDFs de referência inalterados — nenhuma fixture tem razão social maior que 28 caracteres nem componente com nome largo, que é justamente por que os testes golden nunca pegaram isto.

O layout do DACTE desenha em posição absoluta e alguns campos não recortavam
o texto, então conteúdo mais largo que a coluna era escrito por cima do campo
vizinho.

Razão social do emitente: o nome é desenhado com multi_cell(h=5), que quebra
linha, mas o endereço logo abaixo é ancorado em Y fixo (y_text + 6) — só há uma
linha de 5 mm reservada. Um xNome longo fazia a segunda linha cair exatamente
sobre a linha "CNPJ: ... IE: ...".

Nome de componente: escrito com cell() numa coluna de col_width/2, que não
recorta nem quebra. "OUTROS VALORES" mede 25,01 mm numa coluna de 21,75 mm
úteis, sobrando por cima do primeiro dígito do valor.

Os dois passam a usar long_field, o mesmo recorte por largura medida já usado
no DANFE e nos demais nomes do próprio DACTE (rem_nome, dest_nome, receb_nome,
exped_nome, tomador_nome). Nenhum helper novo.

Os testes renderizam o PDF e leem de volta as posições do texto do content
stream, em vez de checar a chamada de um helper — medem o resultado e
continuam válidos se a implementação mudar.

Nenhuma fixture de DACTE tem razão social maior que 28 caracteres nem
componente com nome largo, que é por que os testes golden nunca pegaram isto:
os PDFs de referência seguem inalterados.
@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.43%. Comparing base (c6fcedc) to head (f9264bd).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #190   +/-   ##
=======================================
  Coverage   96.43%   96.43%           
=======================================
  Files          32       32           
  Lines        4375     4375           
  Branches      348      348           
=======================================
  Hits         4219     4219           
  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.

@CristianoMafraJunior
CristianoMafraJunior merged commit a067c9d into main Aug 19, 2026
10 checks passed
@CristianoMafraJunior
CristianoMafraJunior deleted the fix/dacte-text-clip branch August 19, 2026 19:41
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