Spaces:
Sleeping
Sleeping
Estiliza equações de depreciação e retira referências à ferramenta interna
Browse filesRoss, K e Kd são equações editáveis com fração, expoente, subscrito e legendas de 8 pt. Remove menções à ferramenta e à versão do catálogo do laudo, preservando as fontes técnicas internas e os dados de origem. Validado com 113 testes e conferência visual.
- document/equations.py +64 -0
- document/evolutivo.py +6 -15
- document/footnotes.py +2 -0
- document/formatters/paragraph.py +2 -1
- document/formatters/table.py +4 -3
- document/public_text.py +16 -0
- tests/test_equations.py +71 -0
- tests/test_evolutivo_documento.py +1 -1
document/equations.py
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Editable Word equations with compact legends for depreciation factors."""
|
| 2 |
+
from docx.oxml import OxmlElement
|
| 3 |
+
from docx.oxml.ns import qn
|
| 4 |
+
from docx.enum.text import WD_ALIGN_PARAGRAPH
|
| 5 |
+
from docx.shared import Pt, RGBColor
|
| 6 |
+
|
| 7 |
+
from .formatters.paragraph import criar_paragrafo_formatado
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
def _run(text, variable=False):
|
| 11 |
+
run = OxmlElement('m:r')
|
| 12 |
+
props = OxmlElement('m:rPr')
|
| 13 |
+
style = OxmlElement('m:sty'); style.set(qn('m:val'), 'i' if variable else 'p')
|
| 14 |
+
props.append(style); run.append(props)
|
| 15 |
+
font_props = OxmlElement('w:rPr')
|
| 16 |
+
font = OxmlElement('w:rFonts')
|
| 17 |
+
font.set(qn('w:ascii'), 'Cambria Math'); font.set(qn('w:hAnsi'), 'Cambria Math')
|
| 18 |
+
font_props.append(font)
|
| 19 |
+
size = OxmlElement('w:sz'); size.set(qn('w:val'), '28'); font_props.append(size)
|
| 20 |
+
run.append(font_props)
|
| 21 |
+
value = OxmlElement('m:t'); value.text = text
|
| 22 |
+
value.set(qn('xml:space'), 'preserve'); run.append(value)
|
| 23 |
+
return run
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
def _fraction(numerator, denominator):
|
| 27 |
+
fraction = OxmlElement('m:f')
|
| 28 |
+
for name, children in [('num', numerator), ('den', denominator)]:
|
| 29 |
+
node = OxmlElement('m:' + name)
|
| 30 |
+
for child in children: node.append(child)
|
| 31 |
+
fraction.append(node)
|
| 32 |
+
return fraction
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
def _script(kind, base, script):
|
| 36 |
+
node = OxmlElement('m:' + kind)
|
| 37 |
+
for name, child in [('e', base), ('sup' if kind=='sSup' else 'sub', script)]:
|
| 38 |
+
content = OxmlElement('m:' + name); content.append(child); node.append(content)
|
| 39 |
+
return node
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def depreciation_equations(doc):
|
| 43 |
+
formulas = [
|
| 44 |
+
([_run('Ross',True), _run(' = '), _fraction([_run('q',True), _run(' + '), _script('sSup',_run('q',True),_run('2'))],[_run('2')])],
|
| 45 |
+
'Ross: parcela de depreciação associada à idade; q: fração de vida útil consumida, obtida dividindo o percentual de vida útil consumida por 100.'),
|
| 46 |
+
([_run('K',True),_run(' = 1 − (1 − '),_run('Ross',True),_run(') × (1 − '),_run('H',True),_run(')')],
|
| 47 |
+
'K: coeficiente de depreciação de Ross-Heidecke; H: coeficiente correspondente ao estado de conservação adotado.'),
|
| 48 |
+
([_script('sSub',_run('K',True),_run('d',True)),_run(' = '),_run('R',True),_run(' + (1 − '),_run('K',True),_run(') × (1 − '),_run('R',True),_run(')')],
|
| 49 |
+
'Kd: fator remanescente aplicado ao custo de reedição, com consideração do valor residual; R: valor residual em forma decimal (percentual ÷ 100); K: coeficiente de depreciação.'),
|
| 50 |
+
]
|
| 51 |
+
for index,(elements, legend) in enumerate(formulas):
|
| 52 |
+
paragraph = doc.add_paragraph()
|
| 53 |
+
paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
| 54 |
+
paragraph.paragraph_format.space_before = Pt(10)
|
| 55 |
+
paragraph.paragraph_format.space_after = Pt(4)
|
| 56 |
+
paragraph.paragraph_format.keep_with_next = True
|
| 57 |
+
paragraph.paragraph_format.keep_together = True
|
| 58 |
+
math = OxmlElement('m:oMath')
|
| 59 |
+
for element in elements: math.append(element)
|
| 60 |
+
paragraph._p.append(math)
|
| 61 |
+
note = criar_paragrafo_formatado(doc,legend,tamanho=8,cor=RGBColor(70,70,70),
|
| 62 |
+
alinhamento=WD_ALIGN_PARAGRAPH.LEFT,espaco_depois=8)
|
| 63 |
+
note.paragraph_format.keep_together = True
|
| 64 |
+
note.paragraph_format.keep_with_next = index < len(formulas)-1
|
document/evolutivo.py
CHANGED
|
@@ -15,6 +15,7 @@ from .mesa_content import content_for
|
|
| 15 |
from .evo_adjustments import REDUCERS, applied_reducers
|
| 16 |
from .fundamentacao import number, global_foundation
|
| 17 |
from .footnotes import add_footnote, add_first_footnote, order_footnotes
|
|
|
|
| 18 |
from .formatters.table import set_table_font_size
|
| 19 |
from .formatters.table_fit import fit_table_to_page
|
| 20 |
from .anexos.metodologia import (_gerar_variaveis, _adicionar_pesquisa,
|
|
@@ -247,14 +248,12 @@ def gerar_corpo_evolutivo(doc, imported, num, caracteristicas_refs=None):
|
|
| 247 |
construction_cub_notes(doc,groups)
|
| 248 |
heading(doc,num,'BDI e justificativa',4)
|
| 249 |
definitions_for(doc,rows,['bdi'])
|
| 250 |
-
add_body_text(doc,'O BDI informado em percentual é convertido no multiplicador 1 + BDI/100.
|
| 251 |
construction_bdi_notes(doc,groups)
|
| 252 |
heading(doc,num,'Depreciação e conservação',4)
|
| 253 |
-
|
| 254 |
-
|
| 255 |
-
|
| 256 |
-
equation(doc,'K = 1 − (1 − Ross) × (1 − H); Kd = R + (1 − K) × (1 − R)')
|
| 257 |
-
add_body_text(doc,'A MESA registra a curva de Ross com seis casas decimais, K com quatro e Kd com três. Os resultados abaixo são transcritos dos registros salvos, sem recompor os valores a partir de coeficientes arredondados para exibição.')
|
| 258 |
construction_depreciation_notes(doc,groups)
|
| 259 |
heading(doc,num,'Cálculo por construção e exercício',4)
|
| 260 |
for entries in groups.values():
|
|
@@ -444,7 +443,7 @@ def construction_bdi_notes(doc, groups):
|
|
| 444 |
notes.setdefault('Justificativa do BDI: '+note,[]).append((row,c,i))
|
| 445 |
reference = next((item for item in content_for(source(row))['referencias'].get('bdiTiposConstrucao',[]) if item.get('tipo')==c.get('tipoConstrucao')),None)
|
| 446 |
if reference:
|
| 447 |
-
notes.setdefault(f"Referência
|
| 448 |
composition = c.get('bdiComposicaoAdotada')
|
| 449 |
if isinstance(composition,list) and composition:
|
| 450 |
details = [{key:item.get(key) for key in ('descricao','percentual')} for item in composition]
|
|
@@ -581,14 +580,6 @@ def gerar_especificacao_evolutivo(doc,imported,refs):
|
|
| 581 |
first = foundations[rows[0]['id']][key] if key else foundations[rows[0]['id']]
|
| 582 |
compared(doc,rows,[(item['label'],lambda row,i=index,k=key: (foundations[row['id']][k] if k else foundations[row['id']])['items'][i]['grade'] + ' / ' + str((foundations[row['id']][k] if k else foundations[row['id']])['items'][i]['points'] if (foundations[row['id']][k] if k else foundations[row['id']])['items'][i]['points'] is not None else '—') + ' ponto(s)') for index,item in enumerate(first['items'])])
|
| 583 |
grouped_notes(doc,rows,lambda row,k=key: ' '.join(f"{item['label']}: {item['detail']}" for item in (foundations[row['id']][k] if k else foundations[row['id']])['items']),'Evidências e critérios')
|
| 584 |
-
content_versions = OrderedDict()
|
| 585 |
for row in rows:
|
| 586 |
f = foundations[row['id']]['terrain']
|
| 587 |
if f.get('missingRequirements'): add_body_text(doc,f"{ref(row)} — o Grau III do terreno depende da declaração dos requisitos adicionais; enquadramento pendente.")
|
| 588 |
-
catalog = content_for(source(row))
|
| 589 |
-
saved = source(row).get('documentacaoTecnica')
|
| 590 |
-
note = f"Conteúdo técnico MESA, versão documental {catalog['versao']}, identificação {catalog['identificador']}. " + ('Pacote identificado na exportação; dados e referências históricas do cálculo preservados.' if saved and saved.get('origem') == 'catalogo_exportacao' else 'Pacote preservado na avaliação.' if saved else 'Arquivo sem pacote documental histórico identificado; utilizadas as explicações gerais do catálogo sincronizado, preservando os dados e as referências de cálculo salvos.')
|
| 591 |
-
content_versions.setdefault(note,[]).append(ref(row))
|
| 592 |
-
for note,references in content_versions.items():
|
| 593 |
-
paragraph = add_body_text(doc,note + (f" Aplicável a {', '.join(references)}." if len(content_versions)>1 else ''))
|
| 594 |
-
paragraph.paragraph_format.keep_together = True
|
|
|
|
| 15 |
from .evo_adjustments import REDUCERS, applied_reducers
|
| 16 |
from .fundamentacao import number, global_foundation
|
| 17 |
from .footnotes import add_footnote, add_first_footnote, order_footnotes
|
| 18 |
+
from .equations import depreciation_equations
|
| 19 |
from .formatters.table import set_table_font_size
|
| 20 |
from .formatters.table_fit import fit_table_to_page
|
| 21 |
from .anexos.metodologia import (_gerar_variaveis, _adicionar_pesquisa,
|
|
|
|
| 248 |
construction_cub_notes(doc,groups)
|
| 249 |
heading(doc,num,'BDI e justificativa',4)
|
| 250 |
definitions_for(doc,rows,['bdi'])
|
| 251 |
+
add_body_text(doc,'O BDI informado em percentual é convertido no multiplicador 1 + BDI/100. Os percentuais de referência orientam a análise; não constituem, por si, uma composição de BDI efetivamente adotada.')
|
| 252 |
construction_bdi_notes(doc,groups)
|
| 253 |
heading(doc,num,'Depreciação e conservação',4)
|
| 254 |
+
add_body_text(doc,'A depreciação física considera a vida útil consumida e o estado de conservação, pelo método de Ross-Heidecke. O valor residual integra o fator remanescente aplicado ao custo de reedição.').paragraph_format.keep_with_next = True
|
| 255 |
+
depreciation_equations(doc)
|
| 256 |
+
add_body_text(doc,'Os resultados apresentados são os registrados na avaliação, sem recomposição a partir dos coeficientes arredondados para exibição.')
|
|
|
|
|
|
|
| 257 |
construction_depreciation_notes(doc,groups)
|
| 258 |
heading(doc,num,'Cálculo por construção e exercício',4)
|
| 259 |
for entries in groups.values():
|
|
|
|
| 443 |
notes.setdefault('Justificativa do BDI: '+note,[]).append((row,c,i))
|
| 444 |
reference = next((item for item in content_for(source(row))['referencias'].get('bdiTiposConstrucao',[]) if item.get('tipo')==c.get('tipoConstrucao')),None)
|
| 445 |
if reference:
|
| 446 |
+
notes.setdefault(f"Referência técnica para {reference['tipo']}: BDI {reference['bdi']}. O percentual adotado consta no quadro de cálculo.",[]).append((row,c,i))
|
| 447 |
composition = c.get('bdiComposicaoAdotada')
|
| 448 |
if isinstance(composition,list) and composition:
|
| 449 |
details = [{key:item.get(key) for key in ('descricao','percentual')} for item in composition]
|
|
|
|
| 580 |
first = foundations[rows[0]['id']][key] if key else foundations[rows[0]['id']]
|
| 581 |
compared(doc,rows,[(item['label'],lambda row,i=index,k=key: (foundations[row['id']][k] if k else foundations[row['id']])['items'][i]['grade'] + ' / ' + str((foundations[row['id']][k] if k else foundations[row['id']])['items'][i]['points'] if (foundations[row['id']][k] if k else foundations[row['id']])['items'][i]['points'] is not None else '—') + ' ponto(s)') for index,item in enumerate(first['items'])])
|
| 582 |
grouped_notes(doc,rows,lambda row,k=key: ' '.join(f"{item['label']}: {item['detail']}" for item in (foundations[row['id']][k] if k else foundations[row['id']])['items']),'Evidências e critérios')
|
|
|
|
| 583 |
for row in rows:
|
| 584 |
f = foundations[row['id']]['terrain']
|
| 585 |
if f.get('missingRequirements'): add_body_text(doc,f"{ref(row)} — o Grau III do terreno depende da declaração dos requisitos adicionais; enquadramento pendente.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
document/footnotes.py
CHANGED
|
@@ -9,6 +9,7 @@ from docx.shared import Pt
|
|
| 9 |
from docx.text.paragraph import Paragraph
|
| 10 |
from copy import deepcopy
|
| 11 |
import re
|
|
|
|
| 12 |
|
| 13 |
|
| 14 |
def add_first_footnote(doc, pattern, text):
|
|
@@ -72,6 +73,7 @@ def order_footnotes(doc):
|
|
| 72 |
|
| 73 |
|
| 74 |
def add_footnote(doc, paragraph, text):
|
|
|
|
| 75 |
try:
|
| 76 |
part = doc.part.part_related_by(RT.FOOTNOTES)
|
| 77 |
root = parse_xml(part.blob)
|
|
|
|
| 9 |
from docx.text.paragraph import Paragraph
|
| 10 |
from copy import deepcopy
|
| 11 |
import re
|
| 12 |
+
from .public_text import public_text
|
| 13 |
|
| 14 |
|
| 15 |
def add_first_footnote(doc, pattern, text):
|
|
|
|
| 73 |
|
| 74 |
|
| 75 |
def add_footnote(doc, paragraph, text):
|
| 76 |
+
text = public_text(text)
|
| 77 |
try:
|
| 78 |
part = doc.part.part_related_by(RT.FOOTNOTES)
|
| 79 |
root = parse_xml(part.blob)
|
document/formatters/paragraph.py
CHANGED
|
@@ -5,6 +5,7 @@ from docx import Document
|
|
| 5 |
from docx.shared import Pt, Inches, Cm, RGBColor
|
| 6 |
from docx.enum.text import WD_ALIGN_PARAGRAPH
|
| 7 |
from typing import Optional, Tuple, Union
|
|
|
|
| 8 |
|
| 9 |
|
| 10 |
def aplicar_cor_run(run, cor: Optional[Union[Tuple[int, int, int], RGBColor]]) -> None:
|
|
@@ -56,7 +57,7 @@ def criar_paragrafo_formatado(
|
|
| 56 |
Parágrafo criado
|
| 57 |
"""
|
| 58 |
p = doc.add_paragraph()
|
| 59 |
-
run = p.add_run(texto)
|
| 60 |
|
| 61 |
run.bold = negrito
|
| 62 |
run.underline = sublinhado
|
|
|
|
| 5 |
from docx.shared import Pt, Inches, Cm, RGBColor
|
| 6 |
from docx.enum.text import WD_ALIGN_PARAGRAPH
|
| 7 |
from typing import Optional, Tuple, Union
|
| 8 |
+
from ..public_text import public_text
|
| 9 |
|
| 10 |
|
| 11 |
def aplicar_cor_run(run, cor: Optional[Union[Tuple[int, int, int], RGBColor]]) -> None:
|
|
|
|
| 57 |
Parágrafo criado
|
| 58 |
"""
|
| 59 |
p = doc.add_paragraph()
|
| 60 |
+
run = p.add_run(public_text(texto))
|
| 61 |
|
| 62 |
run.bold = negrito
|
| 63 |
run.underline = sublinhado
|
document/formatters/table.py
CHANGED
|
@@ -11,6 +11,7 @@ from collections.abc import Sequence as SequenceABC
|
|
| 11 |
from typing import List, Optional, Sequence, Union, Dict, Any
|
| 12 |
|
| 13 |
from .paragraph import aplicar_cor_run
|
|
|
|
| 14 |
|
| 15 |
WD_ALIGN_VERTICAL = WD_CELL_VERTICAL_ALIGNMENT
|
| 16 |
|
|
@@ -89,7 +90,7 @@ def formatar_celula_tabela(cell, texto: str, negrito: bool = False, cor=None,
|
|
| 89 |
|
| 90 |
cell.vertical_alignment = WD_ALIGN_VERTICAL.CENTER
|
| 91 |
|
| 92 |
-
run = p.add_run(texto)
|
| 93 |
run.font.size = Pt(9)
|
| 94 |
run.font.name = 'Arial'
|
| 95 |
run.bold = negrito
|
|
@@ -266,7 +267,7 @@ def criar_celula_cabecalho_tabela(cell, texto: str, recuo_primeira_linha_cm: flo
|
|
| 266 |
p.paragraph_format.first_line_indent = Cm(recuo_primeira_linha_cm)
|
| 267 |
p.alignment = WD_ALIGN_PARAGRAPH.LEFT
|
| 268 |
|
| 269 |
-
run = p.add_run(texto)
|
| 270 |
run.bold = True
|
| 271 |
run.underline = True
|
| 272 |
run.font.size = Pt(11)
|
|
@@ -292,7 +293,7 @@ def criar_celula_dados_tabela(cell, texto: str, is_label: bool = False) -> None:
|
|
| 292 |
p.paragraph_format.space_before = Pt(0)
|
| 293 |
p.paragraph_format.space_after = Pt(0)
|
| 294 |
|
| 295 |
-
run = p.add_run(texto)
|
| 296 |
run.bold = is_label
|
| 297 |
run.font.size = Pt(9)
|
| 298 |
run.font.name = 'Arial'
|
|
|
|
| 11 |
from typing import List, Optional, Sequence, Union, Dict, Any
|
| 12 |
|
| 13 |
from .paragraph import aplicar_cor_run
|
| 14 |
+
from ..public_text import public_text
|
| 15 |
|
| 16 |
WD_ALIGN_VERTICAL = WD_CELL_VERTICAL_ALIGNMENT
|
| 17 |
|
|
|
|
| 90 |
|
| 91 |
cell.vertical_alignment = WD_ALIGN_VERTICAL.CENTER
|
| 92 |
|
| 93 |
+
run = p.add_run(public_text(texto))
|
| 94 |
run.font.size = Pt(9)
|
| 95 |
run.font.name = 'Arial'
|
| 96 |
run.bold = negrito
|
|
|
|
| 267 |
p.paragraph_format.first_line_indent = Cm(recuo_primeira_linha_cm)
|
| 268 |
p.alignment = WD_ALIGN_PARAGRAPH.LEFT
|
| 269 |
|
| 270 |
+
run = p.add_run(public_text(texto))
|
| 271 |
run.bold = True
|
| 272 |
run.underline = True
|
| 273 |
run.font.size = Pt(11)
|
|
|
|
| 293 |
p.paragraph_format.space_before = Pt(0)
|
| 294 |
p.paragraph_format.space_after = Pt(0)
|
| 295 |
|
| 296 |
+
run = p.add_run(public_text(texto))
|
| 297 |
run.bold = is_label
|
| 298 |
run.font.size = Pt(9)
|
| 299 |
run.font.name = 'Arial'
|
document/public_text.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Public wording for report text; internal tool names stay out of the report."""
|
| 2 |
+
import re
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
def public_text(text):
|
| 6 |
+
text = str(text)
|
| 7 |
+
text = re.sub(r'\bmodelo MESA\b', 'modelo estatístico', text)
|
| 8 |
+
for original, replacement in [
|
| 9 |
+
('da MESA', 'de referência'), ('do MESA', 'da avaliação de origem'),
|
| 10 |
+
('no MESA', 'na avaliação de origem'), ('na MESA', 'na avaliação de origem'),
|
| 11 |
+
('pela MESA', 'pela avaliação de origem'), ('pelo MESA', 'pela avaliação de origem'),
|
| 12 |
+
('a MESA', 'a avaliação de origem'), ('A MESA', 'A avaliação de origem'),
|
| 13 |
+
('o MESA', 'a avaliação de origem'), ('O MESA', 'A avaliação de origem'),
|
| 14 |
+
]:
|
| 15 |
+
text = text.replace(original, replacement)
|
| 16 |
+
return re.sub(r'\bMESA\b', 'avaliação de origem', text)
|
tests/test_equations.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import copy
|
| 2 |
+
import io
|
| 3 |
+
import unittest
|
| 4 |
+
import zipfile
|
| 5 |
+
|
| 6 |
+
from docx import Document
|
| 7 |
+
from docx.oxml import parse_xml
|
| 8 |
+
from docx.oxml.ns import qn
|
| 9 |
+
from docx.enum.text import WD_ALIGN_PARAGRAPH
|
| 10 |
+
from unittest.mock import patch
|
| 11 |
+
|
| 12 |
+
from document.equations import depreciation_equations
|
| 13 |
+
from document.generator import LaudoGenerator
|
| 14 |
+
from document.public_text import public_text
|
| 15 |
+
from document.footnotes import add_footnote
|
| 16 |
+
from document.formatters import add_body_text
|
| 17 |
+
from test_evolutivo_documento import fixture,resolved
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
class DepreciationEquationTests(unittest.TestCase):
|
| 21 |
+
def test_editable_equations_keep_fraction_power_subscript_and_small_legends(self):
|
| 22 |
+
doc=Document();depreciation_equations(doc)
|
| 23 |
+
stream=io.BytesIO();doc.save(stream);stream.seek(0)
|
| 24 |
+
reopened=Document(stream)
|
| 25 |
+
math=list(reopened.element.body.iter(qn('m:oMath')))
|
| 26 |
+
self.assertEqual(len(math),3)
|
| 27 |
+
self.assertEqual(len(list(math[0].iter(qn('m:f')))),1)
|
| 28 |
+
self.assertEqual(len(list(math[0].iter(qn('m:sSup')))),1)
|
| 29 |
+
self.assertEqual(len(list(math[2].iter(qn('m:sSub')))),1)
|
| 30 |
+
texts=[''.join(t.text or '' for t in formula.iter(qn('m:t'))) for formula in math]
|
| 31 |
+
self.assertEqual(texts,['Ross = q + q22','K = 1 − (1 − Ross) × (1 − H)','Kd = R + (1 − K) × (1 − R)'])
|
| 32 |
+
self.assertEqual(len(reopened.paragraphs),6)
|
| 33 |
+
for index in (0,2,4):
|
| 34 |
+
self.assertEqual(reopened.paragraphs[index].alignment,WD_ALIGN_PARAGRAPH.CENTER)
|
| 35 |
+
self.assertTrue(reopened.paragraphs[index].paragraph_format.keep_with_next)
|
| 36 |
+
legend=reopened.paragraphs[index+1]
|
| 37 |
+
self.assertEqual({r.font.size.pt for r in legend.runs},{8})
|
| 38 |
+
self.assertIn('dividindo o percentual',reopened.paragraphs[1].text)
|
| 39 |
+
self.assertIn('estado de conservação',reopened.paragraphs[3].text)
|
| 40 |
+
self.assertIn('percentual ÷ 100',reopened.paragraphs[5].text)
|
| 41 |
+
|
| 42 |
+
def test_internal_references_stay_out_of_body_tables_and_footnotes(self):
|
| 43 |
+
imported=resolved(fixture((2021,)))
|
| 44 |
+
row=imported['avaliacoes'][0]
|
| 45 |
+
row['observacoes']='Resultados preservados no MESA.'
|
| 46 |
+
row['complementos']={'justificativa_fc':'Condição registrada no modelo MESA.'}
|
| 47 |
+
original=copy.deepcopy(imported)
|
| 48 |
+
doc=Document()
|
| 49 |
+
with patch('document.evolutivo.matching_local',return_value=(None,'')):
|
| 50 |
+
LaudoGenerator()._gerar_corpo(doc,{'avaliacoes_importadas':imported},{})
|
| 51 |
+
LaudoGenerator()._gerar_cabecalho(doc,{'modelo_avaliacao':'modelo MESA'})
|
| 52 |
+
add_footnote(doc,add_body_text(doc,'Referência técnica'),'Coeficientes da MESA preservados na avaliação.')
|
| 53 |
+
stream=io.BytesIO();doc.save(stream)
|
| 54 |
+
with zipfile.ZipFile(stream) as archive:
|
| 55 |
+
for name in ['word/document.xml','word/footnotes.xml']:
|
| 56 |
+
root=parse_xml(archive.read(name))
|
| 57 |
+
text=' '.join(t.text or '' for t in root.iter(qn('w:t')))
|
| 58 |
+
self.assertNotIn('MESA',text)
|
| 59 |
+
self.assertNotIn('versão documental',text)
|
| 60 |
+
self.assertNotIn('catálogo sincronizado',text)
|
| 61 |
+
self.assertEqual(imported,original)
|
| 62 |
+
|
| 63 |
+
def test_public_wording_preserves_technical_names_and_ordinary_words(self):
|
| 64 |
+
self.assertEqual(public_text('Método de Ross-Heidecke; ABNT NBR 14653-2; CUB.'),'Método de Ross-Heidecke; ABNT NBR 14653-2; CUB.')
|
| 65 |
+
self.assertEqual(public_text('modelo MESA'),'modelo estatístico')
|
| 66 |
+
self.assertEqual(public_text('salvo no MESA'),'salvo na avaliação de origem')
|
| 67 |
+
self.assertEqual(public_text('mesa de apoio'),'mesa de apoio')
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
if __name__=='__main__':
|
| 71 |
+
unittest.main()
|
tests/test_evolutivo_documento.py
CHANGED
|
@@ -242,7 +242,7 @@ class EvolutivoDocumentTests(unittest.TestCase):
|
|
| 242 |
conclusion_table(doc,imported)
|
| 243 |
text = all_text(doc)
|
| 244 |
for part in ['3.3 AVALIAÇÃO DO TERRENO','3.3.1.1 Variáveis','3.4 AVALIAÇÃO DAS CONSTRUÇÕES','3.4.1.3 BDI','3.5 AVALIAÇÃO DO IMÓVEL OBJETO',
|
| 245 |
-
'Ross-Heidecke','CUNIT = CUB','Kd
|
| 246 |
self.assertIn(part,text)
|
| 247 |
self.assertNotIn('SEGREDO INTERNO',text)
|
| 248 |
self.assertNotIn('11/2021',text)
|
|
|
|
| 242 |
conclusion_table(doc,imported)
|
| 243 |
text = all_text(doc)
|
| 244 |
for part in ['3.3 AVALIAÇÃO DO TERRENO','3.3.1.1 Variáveis','3.4 AVALIAÇÃO DAS CONSTRUÇÕES','3.4.1.3 BDI','3.5 AVALIAÇÃO DO IMÓVEL OBJETO',
|
| 245 |
+
'Ross-Heidecke','CUNIT = CUB','Kd: fator remanescente','Unidade autônoma da gleba','Composição justificada do caso','50.000,00','4.126,73','10/2021','R$ 427.500,00','R$ 420.000,00','quatrocentos e vinte mil reais','Critério da adoção','CUB composto','Caracterização salva']:
|
| 246 |
self.assertIn(part,text)
|
| 247 |
self.assertNotIn('SEGREDO INTERNO',text)
|
| 248 |
self.assertNotIn('11/2021',text)
|