File size: 5,283 Bytes
46d350b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import copy
import unittest

from docx import Document
from docx.opc.constants import RELATIONSHIP_TYPE as RT
from docx.oxml import parse_xml
from docx.oxml.ns import qn

from document.evolutivo import construction_bdi_notes, construction_groups
from test_evo_adjustments import body
from test_evolutivo_documento import fixture, resolved


LABELS = ['Administração central', 'Despesas financeiras', 'Seguros e garantias', 'Riscos', 'Tributos', 'Remuneração']


def composition(values):
    return [{'descricao': label, 'percentual': value} for label, value in zip(LABELS, values)]


def notes(doc):
    root = parse_xml(doc.part.part_related_by(RT.FOOTNOTES).blob)
    return ' '.join(''.join(n.itertext(qn('w:t'))) for n in root if int(n.get(qn('w:id'))) > 0)


class BdiSectionsTests(unittest.TestCase):
    def data(self):
        data = fixture((2021, 2022))
        for year in data['anos']:
            c = year['construcao']['construcoes'][0]
            c.update(bdiComposicaoAdotada=composition([4, 1, 1, 2, 7, 10]), bdiJustificativa='Composição aditiva sobre o custo direto.')
        return data

    def render(self, data):
        imported = resolved(data)
        before = copy.deepcopy(imported)
        doc = Document()
        construction_bdi_notes(doc, construction_groups(imported['avaliacoes']))
        self.assertEqual(imported, before)
        return doc

    def test_general_chapter_only_introduction_and_each_construction_has_total(self):
        data = self.data()
        for year in data['anos']:
            second = copy.deepcopy(year['construcao']['construcoes'][0])
            second.update(id='second', seq=2, nome='Galpão B', bdi=20,
                          bdiComposicaoAdotada=composition([3, 1, 1, 2, 6, 7]))
            year['construcao']['construcoes'].append(second)
        doc = body(resolved(data))
        paragraphs = [p.text for p in doc.paragraphs]
        start = paragraphs.index('3.4.1.3 BDI e justificativa')
        end = paragraphs.index('3.4.1.3.1 Construção 1 — Galpão A')
        self.assertEqual(len(paragraphs[start + 1:end]), 2)
        self.assertTrue(paragraphs[start + 1].startswith('BDI (%):'))
        self.assertTrue(paragraphs[start + 2].startswith('O BDI informado em percentual'))
        self.assertIn('3.4.1.3.2 Construção 2 — Galpão B', paragraphs)
        tables = [t for t in doc.tables if t.cell(0, 0).text == 'Componente de BDI adotado']
        self.assertEqual(len(tables), 2)
        for table, total in zip(tables, ['25,00%', '20,00%']):
            self.assertEqual([c.text for c in table.rows[-1].cells], ['Total do BDI', total])
            self.assertEqual(len(table.rows), 8)
            self.assertEqual(len(table.columns), 2)
            self.assertTrue(all(run.bold for c in table.rows[-1].cells for p in c.paragraphs for run in p.runs))
        self.assertFalse(any('Aplicável a Construção' in p for p in paragraphs[start:paragraphs.index('3.4.1.4 Depreciação e conservação')]))

    def test_year_changes_compare_components_and_totals_without_duplicate_subchapters(self):
        data = self.data()
        c = data['anos'][1]['construcao']['construcoes'][0]
        c.update(bdi=20, bdiComposicaoAdotada=composition([3, 1, 1, 2, 6, 7]), bdiJustificativa='Justificativa do segundo exercício.')
        doc = self.render(data)
        self.assertEqual(len(doc.tables), 1)
        table = doc.tables[0]
        self.assertEqual([c.text for c in table.rows[0].cells], ['Parâmetro / valor', 'IPTU 2022', 'IPTU 2023'])
        self.assertEqual([c.text for c in table.rows[1].cells], ['Administração central', '4,00%', '3,00%'])
        self.assertEqual([c.text for c in table.rows[-1].cells], ['Total do BDI', '25,00%', '20,00%'])
        text = '\n'.join(p.text for p in doc.paragraphs)
        self.assertIn('Justificativa do BDI (IPTU 2022): Composição aditiva', text)
        self.assertIn('Justificativa do BDI (IPTU 2023): Justificativa do segundo exercício.', text)

    def test_divergent_sum_does_not_replace_saved_bdi(self):
        data = self.data()
        for year in data['anos']:
            year['construcao']['construcoes'][0]['bdiComposicaoAdotada'][0]['percentual'] = 5
        doc = self.render(data)
        self.assertEqual([c.text for c in doc.tables[0].rows[-2].cells], ['Soma dos componentes', '26,00%'])
        self.assertEqual([c.text for c in doc.tables[0].rows[-1].cells], ['Total do BDI', '25,00%'])
        self.assertIn('difere do percentual global registrado', notes(doc))

    def test_missing_composition_and_private_reason_are_not_invented_or_exposed(self):
        data = self.data()
        for year in data['anos']:
            c = year['construcao']['construcoes'][0]
            c.pop('bdiComposicaoAdotada')
            c.update(bdi=0, bdiJustificativa='JUSTIFICATIVA INTERNA', bdiJustificativaInterna=True)
        doc = self.render(data)
        self.assertEqual(len(doc.tables[0].rows), 2)
        self.assertEqual([c.text for c in doc.tables[0].rows[-1].cells], ['Total do BDI', '0,00%'])
        self.assertNotIn('JUSTIFICATIVA INTERNA', '\n'.join(p.text for p in doc.paragraphs) + notes(doc))
        self.assertIn('sem discriminar sua composição', notes(doc))


if __name__ == '__main__':
    unittest.main()