import os from fpdf import FPDF from googleapiclient.discovery import build from google.oauth2 import service_account from typing import List from dotenv import load_dotenv import json load_dotenv() class FelloUtils: @staticmethod def generate_pdf_report(data: dict) -> bytes: """Generates a professional PDF report with heavy debugging.""" try: pdf = FPDF() pdf.add_page() # Helper function to sanitize text for Latin-1 (FPDF default) def s(text): if text is None: return "" # Replace common problematic unicode characters that crash FPDF return str(text).encode('latin-1', 'replace').decode('latin-1') # 1. Title pdf.set_font("Arial", 'B', 20) pdf.set_text_color(37, 99, 235) pdf.cell(200, 15, txt="Fello IQ Account Intelligence", ln=True, align='C') pdf.ln(10) # 2. Company Identity pdf.set_font("Arial", 'B', 14) pdf.set_text_color(15, 23, 42) company = s(data.get('company_name', 'N/A')) domain = s(data.get('domain', 'N/A')) pdf.cell(0, 10, txt=f"Account: {company} ({domain})", ln=True) pdf.set_font("Arial", size=10) industry = s(data.get('industry', 'N/A')) revenue = s(data.get('annual_revenue', 'N/A')) pdf.cell(0, 7, txt=f"Industry: {industry} | Revenue: {revenue}", ln=True) pdf.ln(5) # 3. Strategic Intelligence pdf.set_font("Arial", 'B', 12) score = data.get('intent_score', 0) stage = s(data.get('intent_stage', 'Unknown')) pdf.cell(0, 10, txt=f"Intent Score: {score}/10 - {stage}", ln=True) pdf.set_font("Arial", 'I', 10) summary = s(data.get('ai_summary', 'No summary available.')) pdf.multi_cell(0, 7, txt=f"AI Summary: {summary}") pdf.ln(5) # 4. Recommended Actions pdf.set_font("Arial", 'B', 12) pdf.cell(0, 10, txt="Recommended Sales Actions:", ln=True) pdf.set_font("Arial", size=10) actions = data.get('recommended_sales_actions', []) if not actions: pdf.cell(0, 7, txt="- No specific actions recommended.", ln=True) else: for action in actions: pdf.multi_cell(0, 7, txt=s(f"- {action}")) pdf_output = pdf.output(dest='S') return pdf_output.encode('latin-1', 'replace') except Exception as e: print("!!! PDF GENERATION CRASHED !!!") print(traceback.format_exc()) raise e @staticmethod def sync_to_google_sheets(data: dict): """Appends research data to Google Sheets using your reference logic.""" SCOPES = ["https://www.googleapis.com/auth/spreadsheets"] SPREADSHEET_ID = os.getenv("SPREADSHEET_ID") try: creds_json = os.getenv("GOOGLE_CREDENTIALS_JSON") creds_info = json.loads(creds_json) creds = service_account.Credentials.from_service_account_info( creds_info, scopes=SCOPES ) service = build("sheets", "v4", credentials=creds) # Formatting the row based on the Pydantic model values = [ data['company_name'], data['domain'], data['intent_score'], data['intent_stage'], data['industry'], data['annual_revenue'], ", ".join(data['recommended_sales_actions'][:2]) ] body = {"values": [values]} service.spreadsheets().values().append( spreadsheetId=SPREADSHEET_ID, range="Sheet1", valueInputOption="USER_ENTERED", insertDataOption="INSERT_ROWS", body=body ).execute() return True except Exception as e: print(f"Google Sheets Sync Error: {e}") return False