from typing import Optional from db.db import get_db from db.models import FundTable, InvestorTable, ProjectTable from fastapi import APIRouter, Depends, HTTPException, Query from fastapi.responses import Response from services.report_gen import ReportGenerator from sqlalchemy.orm import Session, selectinload router = APIRouter(tags=["Report Generation"]) @router.get("/report/investor/{investor_id}") async def generate_investor_report( investor_id: int, project_id: Optional[int] = Query( None, description="Optional project ID for compatibility analysis" ), db: Session = Depends(get_db), ): """ Generate a PDF report for an investor profile. Args: investor_id: The ID of the investor to generate a report for project_id: Optional project ID to include mandate match analysis Returns: PDF file as a downloadable response """ # Fetch investor data with all relationships investor = ( db.query(InvestorTable) .options( selectinload(InvestorTable.portfolio_companies), selectinload(InvestorTable.team_members), selectinload(InvestorTable.sectors), selectinload(InvestorTable.funds).selectinload(FundTable.investment_stages), selectinload(InvestorTable.funds).selectinload(FundTable.sectors), ) .filter(InvestorTable.id == investor_id) .first() ) if not investor: raise HTTPException(status_code=404, detail="Investor not found") # Prepare investor data dictionary investor_data = { "name": investor.name, "description": investor.description, "website": investor.website, "headquarters": investor.headquarters, "aum": investor.aum, "portfolio_highlights": investor.portfolio_highlights or [], "investment_thesis": investor.investment_thesis or [], "sectors": [sector.name for sector in investor.sectors], "team_members": [ { "name": member.name, "role": member.role, "title": member.title, "email": member.email, } for member in investor.team_members ], "funds": [], } # Get all funds with their data if investor.funds: for fund in investor.funds: fund_data = { "fund_name": fund.fund_name, "fund_size": fund.fund_size, "check_size_lower": fund.check_size_lower, "check_size_upper": fund.check_size_upper, "geographic_focus": fund.geographic_focus, "investment_stages": [stage.name for stage in fund.investment_stages], "sectors": [sector.name for sector in fund.sectors], } investor_data["funds"].append(fund_data) # Fetch project data if project_id is provided project_data = None if project_id: project = ( db.query(ProjectTable) .options(selectinload(ProjectTable.sector)) .filter(ProjectTable.id == project_id) .first() ) if not project: raise HTTPException(status_code=404, detail="Project not found") project_data = { "name": project.name, "description": project.description, "location": project.location, "valuation": project.valuation, "stage": project.stage.name if project.stage else None, "sectors": [sector.name for sector in project.sector], } # Generate PDF report report_generator = ReportGenerator() pdf_bytes = await report_generator.generate_investor_report( investor_data, project_data, investor_model=investor, project_model=project ) # Return PDF as downloadable file filename = f"{investor.name.replace(' ', '_')}_Report.pdf" return Response( content=pdf_bytes, media_type="application/pdf", headers={"Content-Disposition": f'attachment; filename="{filename}"'}, )