dacte: recorta textos longos e agrega componentes excedentes - #186
dacte: recorta textos longos e agrega componentes excedentes#186andmit10 wants to merge 1 commit into
Conversation
O layout do DACTE desenha em posição absoluta, então texto mais largo que a
coluna era escrito por cima do vizinho:
- Razão social longa do emitente quebrava em duas linhas e a segunda saía
sobre a linha "CNPJ: ... IE: ..." (só há uma linha de 5 mm reservada,
porque o endereço é ancorado em Y fixo).
- Nome de componente do valor da prestação invadia a coluna do valor
("OUTROS VALORES" mede 25,01 mm numa coluna de 21,75 mm).
Ambos passam a usar long_field, o mesmo recorte por largura já usado no
DANFE e nos demais nomes do próprio DACTE.
Além disso, o bloco de componentes comporta 9 linhas e do 10º em diante o
valor era descartado sem aviso; o excedente agora é agregado em OUTROS.
|
@andmit10 Bem vindo ao projeto, sua contribuição é bem vinda. apenas veja que o pre-commit falhou, consegue ajeitar? |
|
Obrigado pelo trabalho aqui, @andmit10 — diagnóstico certo nos três casos, e os testes que leem a posição do texto de volta do content stream são a técnica certa pro problema. Confirmei que os quatro falham no Estou dividindo em duas para poder mergear a parte segura já:
Seus commits foram preservados com sua autoria nas duas. Ajustes que fiz em cima:
Sobre o item 3, que você mesmo marcou como o mais opinativo: fui atrás do que as outras implementações fazem e nenhuma resolve. O ACBr ( Um detalhe adjacente que saiu da revisão e vai virar issue à parte: o Fechando esta em favor das duas. Valeu mesmo pela contribuição. |
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 — o PDF fica ilegível naquele ponto.
Três situações, todas em CT-e válido (nenhuma depende de XML fora do leiaute):
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) — ou seja, só há uma linha de 5 mm reservada:https://github.com/Engenere/BrazilFiscalReport/blob/main/brazilfiscalreport/dacte/dacte.py#L358-L363
Com um
xNomede 39 caracteres, a segunda linha do nome cai exatamente sobre a linhaCNPJ: ... IE: ...:Vale notar que todos os outros nomes do próprio DACTE já são recortados —
rem_nome(limit_text(..., 48)),dest_nome,receb_nome,exped_nome,tomador_nome(38) — e o DANFE faz o mesmo emdanfe.pycomlong_field(limit=60). O emitente ficou de fora.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()numa coluna decol_width / 2. Ocell()não recorta nem quebra:Medindo:
col_width/2= 23,75 mm, menos2 × c_margindo fpdf2 = 21,75 mm úteis;"OUTROS VALORES"em Times 8 mede 25,01 mm. Sobra 1,26 mm por cima do primeiro dígito do valor.xNomedeCompé texto livre preenchido pelo emitente, então nomes largos são comuns na prática.3. Do 10º componente em diante, o valor some do PDF
A distribuição é fixa em 3 colunas × 3 linhas (
comp_list[:3],[3:6],[6:9]). O que passa disso não é desenhado — sem aviso, e sem que a soma exibida corresponda ao que o XML declara.O que muda
long_field— o mesmo recorte por largura medida já usado no DANFE e nos demais nomes do DACTE. Nenhum helper novo.OUTROS, preservando a soma. Um helper localto_floattolera valor ausente/malformado.Nada disso muta
self.emit_namenemself.comp_list— só o texto renderizado.O item (3) é a parte mais opinativa deste PR. Agregar em "OUTROS" me pareceu melhor que descartar em silêncio, mas se vocês preferirem outra saída (reduzir a fonte, paginar o bloco, ou simplesmente documentar o limite), fico à vontade para ajustar.
Testes
Novo arquivo
tests/test_dacte_overflow.py. 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 — assim medem o resultado e continuam válidos se a implementação mudar:test_razao_social_longa_nao_escreve_por_cima_do_cnpj— nenhum texto pode partilhar a baseline da linha do CNPJ.test_nome_de_componente_longo_nao_invade_a_coluna_do_valor— a largura renderizada do nome tem de caber na coluna.test_componentes_alem_do_nono_aparecem_agregados— com 12 componentes, "OUTROS" aparece no PDF.test_to_float_tolera_valor_ausente_ou_invalido.Verifiquei que eles falham sem a correção. O primeiro aponta o texto exato que sobrepõe:
PDFs de referência
Inalterados. Nenhuma das 13 fixtures de DACTE tem razão social maior que 28 caracteres nem componente com nome largo — que é justamente por que os testes golden nunca pegaram isto. Suíte completa: 96 passed.