DACTE: recorta textos longos que invadem campos vizinhos - #190
Merged
Conversation
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.
This was referenced Aug 14, 2026
Codecov Report✅ All modified and coverable lines are covered by tests. 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. 🚀 New features to boost your workflow:
|
CristianoMafraJunior
approved these changes
Aug 19, 2026
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.
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 sobreCNPJ: ... IE: ...:2. Nome de componente invade a coluna do valor. Na seção "COMPONENTES DO VALOR DA PRESTAÇÃO DO SERVIÇO" o
xNomeé escrito comcell(), que não recorta nem quebra. A coluna temcol_width/2= 23,75 mm, menos2 × c_margin= 21,75 mm úteis;"OUTROS VALORES"em Times 8 mede 25,01 mm:Não é caso de borda:
Comp/xNomeé texto livre de até 15 caracteres no XSD, eAGENDAMENTO— 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_fielddo componente passafont_size=8explí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/xNomemaxLength="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=27e 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_cnpjtest_nome_de_componente_longo_nao_invade_a_coluna_do_valorAmbos 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.