import copy import io import unittest import zipfile from docx import Document from docx.oxml import parse_xml from docx.oxml.ns import qn from document.evolutivo import construction_cub_notes, construction_groups from document.footnotes import add_first_footnote from test_evolutivo_documento import fixture, resolved class CubNotesTests(unittest.TestCase): def notes(self, doc): stream=io.BytesIO();doc.save(stream) with zipfile.ZipFile(stream) as archive: root=parse_xml(archive.read('word/footnotes.xml')) return [''.join(t.text or '' for t in n.iter(qn('w:t'))).strip() for n in root if int(n.get(qn('w:id'))) > 0] def test_one_row_per_construction_saved_values_and_composition_in_footnotes(self): data=fixture((2021,2022,2023,2024,2025)) for year in data['anos']: simple=copy.deepcopy(year['construcao']['construcoes'][0]) simple.update(id='simples',seq=2,nome='Galpão simples',cubTipo='GI (Galpao Industrial)',cubCompostoAtivo=False,valorCub=1000) year['construcao']['construcoes'].append(simple) imported=resolved(data) doc=Document() intro=doc.add_paragraph('O custo unitário básico (CUB) é empregado no cálculo.') percent=doc.add_paragraph('CUNIT = CUB × (% CUB / 100)') doc.add_paragraph('CUB histórico, referência temporal e adequações') construction_cub_notes(doc,construction_groups(imported['avaliacoes'])) self.assertEqual(len(doc.tables),1) table=doc.tables[0] self.assertEqual(len(table.rows),3) self.assertEqual(len(table.columns),7) self.assertEqual(table.cell(1,1).text,'CUB composto') self.assertEqual(table.cell(2,1).text,'GI (100%)') self.assertEqual([c.text for c in table.rows[1].cells][2:],['R$ 1.400,00']*5) self.assertEqual([c.text for c in table.rows[2].cells][2:],['R$ 1.000,00']*5) notes=self.notes(doc) self.assertEqual(len(notes),6) self.assertIn('% do CUB',notes[1]) self.assertIn('valor do CUB por metro quadrado',notes[2]) self.assertIn('tipo ou composição de CUB',notes[3]) composite=next(n for n in notes if 'média ponderada' in n) self.assertIn('GI: 60,00%; R1-N: 40,00%',composite) self.assertIn('Todos os exercícios',composite) self.assertTrue(any('GI: Galpao industrial' in n for n in notes)) self.assertIsNotNone(intro._p.find('.//'+qn('w:footnoteReference'))) self.assertIsNotNone(percent._p.find('.//'+qn('w:footnoteReference'))) self.assertFalse(any('grupo dos dados' in p.text or 'média ponderada' in p.text for p in doc.paragraphs)) self.assertEqual(intro.text,'O custo unitário básico (CUB) é empregado no cálculo.') def test_first_occurrence_marker_preserves_text_and_formatting(self): doc=Document() first=doc.add_paragraph() first.add_run('Projeto ') first.add_run('CUB composto e CUB simples.').italic=True later=doc.add_paragraph('Outro CUB composto.') add_first_footnote(doc,r'CUB composto','Explicação técnica.') self.assertEqual(first.text,'Projeto CUB composto e CUB simples.') self.assertEqual(first.runs[1].text,'CUB composto') self.assertTrue(first.runs[1].italic) self.assertIsNotNone(first.runs[2]._r.find(qn('w:footnoteReference'))) self.assertTrue(first.runs[3].italic) self.assertIsNone(later._p.find('.//'+qn('w:footnoteReference'))) self.assertEqual(self.notes(doc),['Explicação técnica.']) if __name__=='__main__': unittest.main()