| |
|
|
| import pandas as pd |
| import re |
| import os |
| import requests |
| import matplotlib.font_manager as fm |
| from pydantic import BaseModel, Field, ConfigDict |
| from typing import List, Tuple, Optional |
| from fpdf import FPDF |
| from datetime import datetime |
|
|
| |
| class Historico(BaseModel): |
| entradas: List[Tuple[str, str]] = [] |
|
|
| def adicionar(self, pergunta: str, resposta: str): |
| if pergunta and resposta: |
| self.entradas.append((pergunta, resposta)) |
|
|
| |
| def descricao_colunas(df: pd.DataFrame) -> str: |
| descricao = "\n".join([f"`{col}`: {str(df[col].dtype)}" for col in df.columns]) |
| return "Colunas do DataFrame:\n" + descricao |
|
|
| def limpar_codigo_pandas(codigo: str) -> str: |
| codigo = re.sub(r'```(?:python)?\n?', '', codigo) |
| codigo = re.sub(r'```', '', codigo) |
| linhas = [linha.strip() for linha in codigo.split('\n') if linha.strip()] |
| codigo_filtrado = [l for l in linhas if not (l.startswith('#') or 'resposta:' in l.lower())] |
| return codigo_filtrado[-1] if codigo_filtrado else "" |
|
|
| |
| FONT_PATH = "" |
| def setup_font(): |
| global FONT_PATH |
| FONT_NAME_TO_FIND = "DejaVu Sans" |
| try: |
| FONT_PATH = fm.findfont(FONT_NAME_TO_FIND, fallback_to_default=True) |
| if not os.path.exists(FONT_PATH): raise FileNotFoundError |
| print(f"✅ Fonte encontrada localmente: {FONT_PATH}") |
| except Exception: |
| print(f"⚠️ Fonte '{FONT_NAME_TO_FIND}' não encontrada. Baixando alternativa (Roboto)...") |
| FONT_FILE_NAME = "Roboto-Regular.ttf" |
| FONT_URL = "https://github.com/google/fonts/raw/main/ofl/roboto/Roboto-Regular.ttf" |
| if not os.path.exists(FONT_FILE_NAME): |
| try: |
| response = requests.get(FONT_URL) |
| response.raise_for_status() |
| with open(FONT_FILE_NAME, "wb") as f: f.write(response.content) |
| FONT_PATH = FONT_FILE_NAME |
| print(f"✅ Fonte alternativa baixada!") |
| except Exception as e: |
| print(f"❌ FALHA CRÍTICA ao baixar fonte: {e}") |
| FONT_PATH = "" |
| else: |
| FONT_PATH = FONT_FILE_NAME |
| print(f"✅ Fonte alternativa já existe.") |
| return FONT_PATH |
|
|
| |
| def gerar_pdf_report(historico: Historico, font_path: str): |
| if not historico or not historico.entradas: |
| print("⚠️ Tentativa de gerar PDF com histórico vazio.") |
| return None |
| if not font_path or not os.path.exists(font_path): |
| print(f"❌ Erro ao gerar PDF: Arquivo da fonte não encontrado em '{font_path}'.") |
| return None |
|
|
| try: |
| timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") |
| caminho_pdf = f"relatorio_consultas_{timestamp}.pdf" |
| pdf = FPDF() |
| pdf.add_page() |
| pdf.add_font('CustomFont', '', font_path, uni=True) |
| pdf.set_font('CustomFont', '', 16) |
| pdf.cell(0, 10, "Relatório de Consultas ao CSV", ln=True, align="C") |
| pdf.ln(10) |
|
|
| for i, (pergunta, resposta) in enumerate(historico.entradas, 1): |
| pdf.set_font('CustomFont', '', 12) |
| pdf.multi_cell(0, 8, f"Pergunta {i}: {pergunta}") |
| pdf.ln(2) |
| pdf.set_font('CustomFont', '', 10) |
| pdf.multi_cell(0, 6, f"Resposta: {resposta}") |
| pdf.ln(8) |
| pdf.cell(0, 0, '', 'T'); pdf.ln(8) |
|
|
| pdf.output(caminho_pdf) |
| print(f"✅ PDF gerado: {caminho_pdf}") |
| return caminho_pdf |
| except Exception as e: |
| print(f"❌ Erro crítico ao gerar PDF: {e}") |
| return None |