teste_docs / tests /test_evo_adjustments.py
gui-sparim's picture
Simplifica o quadro de CUB e move explicações para notas de rodapé
ca18aa5 verified
Raw History Blame Contribute Delete
9.99 kB
import copy
import unittest
from decimal import Decimal
from unittest.mock import patch
from docx import Document
from document.evo_adjustments import applied_reducers, visible_memory
from document.evolutivo import gerar_corpo_evolutivo, condition_description, construction_characteristics, construction_groups
from document.avaliacoes_importadas import calculation_sections
from document.numbering import NumeradorSecoes
from test_evolutivo_documento import fixture, resolved, all_text
def body(imported):
doc=Document(); n=NumeradorSecoes(3); n.subsecao(); n.subsecao()
with patch('document.evolutivo.matching_local',return_value=(None,'')):
gerar_corpo_evolutivo(doc,imported,n)
return doc
class AppliedAdjustmentsTests(unittest.TestCase):
def test_area_compositions_share_one_table_with_construction_names(self):
data=fixture((2021,2022))
for year in data['anos']:
first=year['construcao']['construcoes'][0]
first.update(nome='Casa principal',areaTotal=90,areaCalculada=87.5,
areasEquivalentes=[{'descricao':'área privativa','area':80,'coeficiente':1},
{'descricao':'varandas','area':10,'coeficiente':.75}])
second=copy.deepcopy(first)
second.update(id='segundo',seq=2,nome='Edícula de apoio',areaTotal=50,areaCalculada=45,
areasEquivalentes=[{'descricao':'área privativa','area':40,'coeficiente':1},
{'descricao':'área de serviço','area':10,'coeficiente':.5}])
year['construcao']['construcoes'].append(second)
doc=Document()
construction_characteristics(doc,construction_groups(resolved(data)['avaliacoes']))
tables=[t for t in doc.tables if t.rows[0].cells[1].text=='Tipo de área']
self.assertEqual(len(tables),1)
rows=[[c.text for c in row.cells] for row in tables[0].rows]
self.assertEqual(rows[1:], [
['Construção 1 — Casa principal','área privativa','80,00','1,0000','80,00'],
['Construção 1 — Casa principal','varandas','10,00','0,7500','7,50'],
['Construção 2 — Edícula de apoio','área privativa','40,00','1,0000','40,00'],
['Construção 2 — Edícula de apoio','área de serviço','10,00','0,5000','5,00']])
self.assertEqual([p.text for p in doc.paragraphs if p.text.startswith('Composição das áreas')],['Composição das áreas'])
def test_area_changes_preserve_exercise_scope_in_the_unified_table(self):
data=fixture((2021,2022))
data['anos'][1]['construcao']['construcoes'][0]['areasEquivalentes'][0]['coeficiente']=.8
doc=Document()
construction_characteristics(doc,construction_groups(resolved(data)['avaliacoes']))
table=next(t for t in doc.tables if t.rows[0].cells[1].text=='Tipo de área')
self.assertEqual(len(table.rows),3)
self.assertIn('IPTU 2022',table.cell(1,0).text)
self.assertIn('IPTU 2023',table.cell(2,0).text)
self.assertEqual(table.cell(1,4).text,'75,00')
self.assertEqual(table.cell(2,4).text,'80,00')
def test_neutral_execution_overrides_selected_conditions_and_reference_rates(self):
row=resolved(fixture((2021,)))['avaliacoes'][0]
row['evolutivo']['resultadoComposicao']['redutor88I']=.7
self.assertEqual(applied_reducers(row,True),[])
self.assertNotIn('redutores_terreno',[s['codigo'] for s in visible_memory(row)])
self.assertIn('redutores_imovel',[s['codigo'] for s in visible_memory(row)])
def test_legacy_unknown_effect_remains_visible_without_inventing_rate(self):
row={'evolutivo':{'resultadoComposicao':{'memoria':[{'codigo':'redutores_terreno','resultado':10}]}}}
self.assertEqual(applied_reducers(row,True),[('redutorTerreno','Redução territorial registrada',None)])
self.assertEqual(len(visible_memory(row)),1)
def test_component_fallback_uses_effective_saved_memory(self):
row={'evolutivo':{'resultadoComposicao':{'memoria':[{'codigo':'redutores_terreno','fator':.895,'componentes':[
{'rotulo':'Art. 88, inciso I','reducao':.105},{'rotulo':'Topografia','reducao':0}]}]}}}
self.assertEqual(applied_reducers(row,True),[('redutor88I','Art. 88, inciso I',Decimal('.105'))])
def test_only_effective_reducers_and_years_appear_in_body_and_annex(self):
data=fixture((2021,2022))
for year in data['anos']:
r=year['resultadoComposicao']; r['memoria'][4]['fator']=1
r.update(redutor88I=0,redutor6061=0,redutorTopografia=0,redutorAgua=0,redutor88II=0,redutorImovel=0,redutorApan=0,limiteArt88Aplicado=False)
r=data['anos'][0]['resultadoComposicao'];r['redutor88I']=.105;r['memoria'][0].update(fator=.895,componentes=[{'rotulo':'Art. 88, inciso I','reducao':.105},{'rotulo':'Topografia','reducao':0}])
imported=resolved(data); before=copy.deepcopy(imported)
doc=body(imported);text=all_text(doc)
for absent in ['Topografia:','Inundação — aplicado','Arts. 60 e 61:','Limite do art. 88','Art. 88, inciso II','APAN considerada no campo','Componentes de referência da MESA:']:
self.assertNotIn(absent,text)
t=next(t for t in doc.tables if any(c.text=='Art. 88, inciso I — redução efetiva' for r in t.rows for c in r.cells))
reduction=next(r for r in t.rows if r.cells[0].text=='Art. 88, inciso I — redução efetiva')
self.assertEqual([c.text for c in reduction.cells[1:]],['10,50%','—'])
ann=Document();calculation_sections(ann,imported)
self.assertNotIn('Redução do imóvel',all_text(ann));self.assertEqual(imported,before)
def test_inciso_i_excludes_areas_at_or_below_historical_threshold(self):
row=resolved(fixture((2021,)))['avaliacoes'][0]
row['evolutivo']['resultadoComposicao']['memoria'][0]['fator']=.895
row['evolutivo']['resultadoComposicao']['redutor88I']=.105
row['evolutivo']['catalogoAjustes']={'art_88_i':{'limite_minimo_area':.1,'condicoes':[
{'codigo':'app','rotulo':'APP aplicada','redutor':.7},{'codigo':'outra','rotulo':'Área não participante','redutor':.85}]}}
row['evolutivo']['terreno']['avaliacao']['ajuste_territorial']['configuracao']['art_88_i']={'condicoes':{'app':{'percentual_area':.15},'outra':{'percentual_area':.1}}}
text=condition_description(row,True)
self.assertIn('APP aplicada',text);self.assertIn('10,50%',text);self.assertNotIn('Área não participante',text)
def test_6061_describes_only_maximum_selected_condition(self):
row={'evolutivo':{'resultadoComposicao':{'redutor6061':.6},'catalogoAjustes':{'art_60_61':{'condicoes':[
{'codigo':'vila','rotulo':'Vila menor','redutor':.3},{'codigo':'encravado','rotulo':'Encravado aplicado','redutor':.6}]}},
'terreno':{'avaliacao':{'ajuste_territorial':{'configuracao':{'art_60_61':{'selecionados':['vila','encravado']}}}}}}}
text=condition_description(row,True)
self.assertIn('Encravado aplicado',text);self.assertNotIn('Vila menor',text)
def test_applied_cap_is_documented_with_effective_not_gross_percentage(self):
imported=resolved(fixture((2021,)));r=imported['avaliacoes'][0]['evolutivo']['resultadoComposicao']
r.update(redutor88II=.2,redutor88IIBruto=.6,limiteArt88Aplicado=True,valorReferenciaArt88=1000,valorAposIncisoIArt88=187.5,valorAposArt88Bruto=75,valorAposArt88Aplicado=150)
r['memoria'][4]['fator']=.8
imported['avaliacoes'][0]['evolutivo']['catalogoAjustes']={'limite_reducao_art_88':.85}
text=all_text(body(imported))
self.assertIn('limite conjunto dos incisos I e II do art. 88, previsto em seu § 3º, foi efetivamente acionado',text)
self.assertIn('20,00%',text);self.assertNotIn('60,00%',text);self.assertIn('R$ 150,00',text)
self.assertIn('85,00%',text);self.assertIn('15,00%',text)
def test_composite_cub_and_bdi_tables_deduplicate_across_constructions(self):
data=fixture((2021,2022));
for y in data['anos']:
c=copy.deepcopy(y['construcao']['construcoes'][0]);c.update(id='segundo',seq=2,nome='Galpão B')
y['construcao']['construcoes'].append(c)
doc=body(resolved(data))
weighted=[t for t in doc.tables if t.rows[0].cells[1].text=='Projeto CUB']
self.assertEqual(len(weighted),1);self.assertEqual(len(weighted[0].rows),3)
self.assertEqual(weighted[0].cell(1,1).text,'CUB composto')
self.assertEqual([c.text for c in weighted[0].rows[0].cells][2:],['IPTU 2022','IPTU 2023'])
calculations=[t for t in doc.tables if any(r.cells[0].text=='Valor da construção (R$)' for r in t.rows)]
self.assertEqual(len(calculations),2)
for t in calculations:
for label in ['Projeto CUB','CUB (R$/m²)','BDI (%)','Fator BDI','Depreciação K','Kd']:
self.assertTrue(any(r.cells[0].text==label for r in t.rows))
def test_changes_in_characteristics_and_compositions_keep_applicability(self):
data=fixture((2021,2022));data['anos'][1]['construcao']['construcoes'][0].update(areaCalculada=80,valorResidual=.2)
data['anos'][1]['construcao']['construcoes'][0]['cubComposicaoCalculada'][0]['peso']=50
doc=body(resolved(data))
t=next(t for t in doc.tables if t.rows[0].cells[1].text=='Tipo / ano')
self.assertEqual(len(t.rows),3)
self.assertIn('IPTU 2023',t.rows[2].cells[0].text)
t=next(t for t in doc.tables if t.rows[0].cells[1].text=='Projeto CUB')
self.assertEqual(len(t.rows),2)
from docx.opc.constants import RELATIONSHIP_TYPE as RT
from docx.oxml import parse_xml
text=' '.join(parse_xml(doc.part.part_related_by(RT.FOOTNOTES).blob).itertext())
for expected in ['IPTU 2022','IPTU 2023','60,00%','50,00%']:
self.assertIn(expected,text)