119 lines
4.0 KiB
Python
119 lines
4.0 KiB
Python
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}"'},
|
|
)
|