263 lines
6.5 KiB
Python
263 lines
6.5 KiB
Python
from datetime import datetime
|
|
from enum import Enum
|
|
from typing import Any, Generic, List, Optional, TypeVar
|
|
|
|
from pydantic import BaseModel
|
|
|
|
# Generic type for pagination
|
|
T = TypeVar("T")
|
|
|
|
|
|
class InvestmentStage(str, Enum):
|
|
SEED = "SEED"
|
|
SERIES_A = "SERIES_A"
|
|
SERIES_B = "SERIES_B"
|
|
SERIES_C = "SERIES_C"
|
|
GROWTH = "GROWTH"
|
|
LATE_STAGE = "LATE_STAGE"
|
|
|
|
|
|
class SectorSchema(BaseModel):
|
|
id: int
|
|
name: str
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class InvestmentStageSchema(BaseModel):
|
|
id: int
|
|
name: str
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class InvestorMemberSchema(BaseModel):
|
|
id: int
|
|
name: str
|
|
role: str | None
|
|
email: str | None
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class FundSchema(BaseModel):
|
|
id: int
|
|
fund_name: str | None
|
|
fund_size: int | None # Changed to int for numerical filtering
|
|
fund_size_source_url: str | None
|
|
check_size_lower: int | None # NEW: Lower bound of check size range
|
|
check_size_upper: int | None # NEW: Upper bound of check size range
|
|
source_url: str | None
|
|
source_provider: str | None
|
|
geographic_focus: str | None # Changed from List[str] to string
|
|
investment_stages: List[InvestmentStageSchema] | None # Changed to relationship
|
|
sectors: List[SectorSchema] | None # Changed to relationship
|
|
created_at: Optional[datetime] = None
|
|
updated_at: Optional[datetime] = None
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class CompanyMemberSchema(BaseModel):
|
|
id: int
|
|
name: Optional[str]
|
|
linkedin: Optional[str]
|
|
role: Optional[str]
|
|
company_id: int
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class CompanySchema(BaseModel):
|
|
id: int
|
|
name: str
|
|
industry: str | None
|
|
location: str | None
|
|
description: Optional[str]
|
|
founded_year: Optional[int]
|
|
website: Optional[str]
|
|
created_at: Optional[datetime] = None
|
|
updated_at: Optional[datetime] = None
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class InvestorSchema(BaseModel):
|
|
id: int
|
|
name: str
|
|
description: Optional[str]
|
|
website: Optional[str] = None
|
|
headquarters: Optional[str] = None
|
|
aum: int | None
|
|
aum_as_of_date: str | None = None
|
|
aum_source_url: str | None = None
|
|
check_size_lower: int | None
|
|
check_size_upper: int | None
|
|
geographic_focus: str | None
|
|
investment_thesis: Any = (
|
|
None # Flexible JSON field - can be list, dict, or list of dicts
|
|
)
|
|
portfolio_highlights: Any = (
|
|
None # Flexible JSON field - can be list, dict, or list of dicts
|
|
)
|
|
number_of_investments: int | None
|
|
created_at: Optional[datetime] = None
|
|
updated_at: Optional[datetime] = None
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class InvestorData(BaseModel):
|
|
"""Comprehensive investor data schema - used for individual investor requests"""
|
|
|
|
investor: InvestorSchema
|
|
portfolio_companies: List[CompanySchema]
|
|
team_members: List[InvestorMemberSchema]
|
|
sectors: List[SectorSchema]
|
|
funds: List[FundSchema]
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class InvestorFundData(BaseModel):
|
|
"""Investor-Fund combined data - used for list/filter requests
|
|
|
|
Each row represents one investor-fund combination.
|
|
An investor with 3 funds will appear as 3 separate entries.
|
|
"""
|
|
|
|
# Investor fields
|
|
investor_id: int
|
|
investor_name: str
|
|
investor_description: Optional[str]
|
|
investor_website: Optional[str]
|
|
investor_headquarters: Optional[str]
|
|
aum: int | None
|
|
aum_as_of_date: str | None
|
|
aum_source_url: str | None
|
|
investment_thesis: Any = None # Flexible JSON field
|
|
portfolio_highlights: Any = None # Flexible JSON field
|
|
number_of_investments: int | None
|
|
|
|
# Fund fields
|
|
fund_id: int | None
|
|
fund_name: str | None
|
|
fund_size: int | None # Changed to int for numerical filtering
|
|
fund_size_source_url: str | None
|
|
check_size_lower: int | None # NEW: Lower bound of check size range
|
|
check_size_upper: int | None # NEW: Upper bound of check size range
|
|
geographic_focus: str | None # Changed from List[str] to string
|
|
fund_investment_stages: (
|
|
List[InvestmentStageSchema] | None
|
|
) # Changed to relationship
|
|
fund_sectors: List[SectorSchema] | None # Changed to relationship
|
|
|
|
# Related data
|
|
portfolio_companies: List[CompanySchema]
|
|
team_members: List[InvestorMemberSchema]
|
|
sectors: List[SectorSchema]
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
class InvestorMinimal(BaseModel):
|
|
"""Minimal investor info with just id and name"""
|
|
|
|
id: int
|
|
name: str
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
class CompanySchemaMinimal(BaseModel):
|
|
id: int
|
|
name: str
|
|
industry: str | None
|
|
location: str | None
|
|
founded_year: Optional[int]
|
|
website: Optional[str]
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
class CompanyData(BaseModel): # Renamed from CompaniesData for consistency
|
|
company: CompanySchemaMinimal
|
|
investors: List[InvestorMinimal]
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class InvestorList(BaseModel):
|
|
investors: List[InvestorData]
|
|
|
|
|
|
class InvestorFundList(BaseModel):
|
|
"""List of investor-fund combinations"""
|
|
|
|
investor_funds: List[InvestorFundData]
|
|
|
|
|
|
class CompanyMinimal(BaseModel):
|
|
"""Minimal company info with just id and name"""
|
|
|
|
id: int
|
|
name: str
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class SectorMinimal(BaseModel):
|
|
"""Minimal sector info with just id and name"""
|
|
|
|
id: int
|
|
name: str
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class InvestmentResponse(BaseModel):
|
|
"""Simplified investment response schema
|
|
|
|
One row per investor-fund combination with streamlined data
|
|
"""
|
|
|
|
id: int # Investor ID
|
|
name: (
|
|
str # Combination of investor name and fund name (e.g., "Investor A - Fund A")
|
|
)
|
|
aum: int | None # From investor
|
|
check_size_lower: int | None # From fund
|
|
check_size_upper: int | None # From fund
|
|
geographic_focus: str | None # From fund
|
|
stage_focus: str | None # Comma-separated stages from fund
|
|
portfolio_companies: List[CompanyMinimal] # Top 3 companies from investor
|
|
sectors: List[SectorMinimal] # Top 3 sectors from fund
|
|
compatibility_score: float # 0 to 1 (default 1 for now)
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class PaginatedResponse(BaseModel, Generic[T]):
|
|
"""Generic paginated response schema"""
|
|
|
|
items: List[T]
|
|
total: int
|
|
page: int
|
|
page_size: int
|
|
total_pages: int
|
|
|
|
class Config:
|
|
from_attributes = True
|