Spaces:
Sleeping
Sleeping
File size: 9,986 Bytes
55d9355 af24288 55d9355 af24288 55d9355 ca18aa5 55d9355 ca18aa5 4e531da 55d9355 4e531da 55d9355 ca18aa5 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | 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)
|