feat: Implement report generation service and add report route for investor profiles
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,121 @@
|
||||
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,
|
||||
"geographic_focus": investor.geographic_focus,
|
||||
"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
|
||||
],
|
||||
"check_size_lower": None,
|
||||
"check_size_upper": None,
|
||||
"investment_stages": [],
|
||||
}
|
||||
|
||||
# Get check sizes and stages from funds
|
||||
if investor.funds:
|
||||
# Use the first fund's data or aggregate
|
||||
fund = investor.funds[0]
|
||||
investor_data["check_size_lower"] = fund.check_size_lower
|
||||
investor_data["check_size_upper"] = fund.check_size_upper
|
||||
|
||||
# Aggregate all investment stages from all funds
|
||||
stages = set()
|
||||
for fund in investor.funds:
|
||||
for stage in fund.investment_stages:
|
||||
stages.add(stage.name)
|
||||
investor_data["investment_stages"] = list(stages)
|
||||
|
||||
# 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
|
||||
)
|
||||
|
||||
# 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}"'},
|
||||
)
|
||||
Reference in New Issue
Block a user