Spaces:
Running
Running
| """Gerador de documento contendo apenas anexos do modelo selecionado.""" | |
| from __future__ import annotations | |
| import re | |
| from datetime import datetime | |
| from io import BytesIO | |
| from pathlib import Path | |
| from docx import Document | |
| from docx.enum.text import WD_ALIGN_PARAGRAPH | |
| from docx.shared import Cm | |
| from .banco_dados import anexo_banco_dados_cabe_na_largura, gerar_anexo_banco_dados | |
| from .calculo_valor import gerar_anexo_calculo | |
| from .graficos import gerar_anexo_graficos | |
| from .planilha_calculo import gerar_anexo_planilha | |
| from .formatters import ( | |
| criar_paragrafo_formatado, | |
| iniciar_secao_paisagem, | |
| iniciar_secao_retrato, | |
| ) | |
| from .model_data import ModelData | |
| class AnexosGenerator: | |
| """Gera um DOCX com os anexos técnicos de um modelo .dai.""" | |
| def __init__(self, output_dir: Path) -> None: | |
| self.output_dir = output_dir | |
| def gerar( | |
| self, | |
| modelo: ModelData, | |
| banco_dados_colunas: list[str] | None = None, | |
| avaliacao: dict | None = None, | |
| ) -> Path: | |
| doc = Document() | |
| self._configurar_margens(doc) | |
| self._gerar_anexos( | |
| doc, | |
| modelo, | |
| banco_dados_colunas=banco_dados_colunas, | |
| avaliacao=avaliacao, | |
| ) | |
| self.output_dir.mkdir(parents=True, exist_ok=True) | |
| output_path = self._gerar_nome_arquivo(modelo.nome) | |
| doc.save(str(output_path)) | |
| return output_path | |
| def gerar_em_memoria( | |
| self, | |
| modelo: ModelData, | |
| banco_dados_colunas: list[str] | None = None, | |
| avaliacao: dict | None = None, | |
| ) -> tuple[bytes, str]: | |
| """Gera o DOCX sem persistir o anexo no filesystem.""" | |
| doc = Document() | |
| self._configurar_margens(doc) | |
| self._gerar_anexos( | |
| doc, | |
| modelo, | |
| banco_dados_colunas=banco_dados_colunas, | |
| avaliacao=avaliacao, | |
| ) | |
| buffer = BytesIO() | |
| doc.save(buffer) | |
| return buffer.getvalue(), self._gerar_nome_arquivo(modelo.nome).name | |
| def _configurar_margens(self, doc: Document) -> None: | |
| for section in doc.sections: | |
| section.top_margin = Cm(2.5) | |
| section.bottom_margin = Cm(2.5) | |
| section.left_margin = Cm(3) | |
| section.right_margin = Cm(2) | |
| def _criar_titulo_anexo(self, doc: Document, titulo: str) -> None: | |
| criar_paragrafo_formatado( | |
| doc, | |
| titulo, | |
| negrito=True, | |
| sublinhado=True, | |
| tamanho=10, | |
| espaco_antes=18, | |
| espaco_depois=12, | |
| alinhamento=WD_ALIGN_PARAGRAPH.CENTER, | |
| ) | |
| def _largura_util_secao_atual(self, doc: Document) -> int: | |
| section = doc.sections[-1] | |
| return int(section.page_width - section.left_margin - section.right_margin) | |
| def _gerar_anexos( | |
| self, | |
| doc: Document, | |
| modelo: ModelData, | |
| banco_dados_colunas: list[str] | None = None, | |
| avaliacao: dict | None = None, | |
| ) -> None: | |
| banco_cabe_em_retrato = anexo_banco_dados_cabe_na_largura( | |
| modelo, | |
| banco_dados_colunas, | |
| self._largura_util_secao_atual(doc), | |
| ) | |
| if not banco_cabe_em_retrato: | |
| iniciar_secao_paisagem(doc) | |
| self._criar_titulo_anexo(doc, "ANEXO I - BANCO DE DADOS") | |
| gerar_anexo_banco_dados(doc, modelo, colunas=banco_dados_colunas) | |
| iniciar_secao_retrato(doc) | |
| self._criar_titulo_anexo( | |
| doc, | |
| "ANEXO II - PLANILHA DE CÁLCULO E RESULTADOS ESTATÍSTICOS", | |
| ) | |
| gerar_anexo_planilha(doc, modelo) | |
| doc.add_page_break() | |
| self._criar_titulo_anexo(doc, "ANEXO III - GRÁFICOS") | |
| gerar_anexo_graficos(doc, modelo) | |
| doc.add_page_break() | |
| self._criar_titulo_anexo(doc, "ANEXO IV - CÁLCULO DO VALOR") | |
| gerar_anexo_calculo(doc, modelo, avaliacao=avaliacao) | |
| def _gerar_nome_arquivo(self, modelo_nome: str) -> Path: | |
| timestamp = datetime.now().strftime("%Y%m%d_%H%M%S_%f") | |
| modelo_safe = re.sub(r"[^\w\-]", "_", modelo_nome) | |
| return self.output_dir / f"Anexos_{modelo_safe}_{timestamp}.docx" | |