feat: Implement pagination for companies, investors, and projects endpoints
This commit is contained in:
+73
-14
@@ -1,4 +1,4 @@
|
||||
from typing import List, Optional
|
||||
from typing import Optional
|
||||
|
||||
from db.db import get_db
|
||||
from db.models import InvestorTable, SectorTable
|
||||
@@ -8,6 +8,7 @@ from schemas.router_schemas import (
|
||||
InvestmentStage,
|
||||
InvestorData,
|
||||
InvestorFundData,
|
||||
PaginatedResponse,
|
||||
)
|
||||
from sqlalchemy.orm import Session, selectinload
|
||||
|
||||
@@ -39,13 +40,24 @@ class InvestorUpdate(BaseModel):
|
||||
number_of_investments: Optional[int] = None
|
||||
|
||||
|
||||
@router.get("/investors", response_model=List[InvestorFundData])
|
||||
def read_investors(db: Session = Depends(get_db)):
|
||||
"""Get all investors with their funds as separate entries
|
||||
@router.get("/investors", response_model=PaginatedResponse[InvestorFundData])
|
||||
def read_investors(
|
||||
page: int = Query(1, ge=1, description="Page number (starts at 1)"),
|
||||
page_size: int = Query(10, ge=1, le=100, description="Items per page (max 100)"),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""Get all investors with their funds as separate entries (paginated)
|
||||
|
||||
Each investor-fund combination is returned as a separate row.
|
||||
An investor with 3 funds will appear as 3 entries.
|
||||
"""
|
||||
# Calculate offset
|
||||
offset = (page - 1) * page_size
|
||||
|
||||
# Get total count
|
||||
total_count = db.query(InvestorTable).count()
|
||||
|
||||
# Get paginated results
|
||||
investors = (
|
||||
db.query(InvestorTable)
|
||||
.options(
|
||||
@@ -54,6 +66,8 @@ def read_investors(db: Session = Depends(get_db)):
|
||||
selectinload(InvestorTable.sectors),
|
||||
selectinload(InvestorTable.funds),
|
||||
)
|
||||
.offset(offset)
|
||||
.limit(page_size)
|
||||
.all()
|
||||
)
|
||||
|
||||
@@ -124,10 +138,19 @@ def read_investors(db: Session = Depends(get_db)):
|
||||
)
|
||||
investor_fund_list.append(investor_fund_data)
|
||||
|
||||
return investor_fund_list
|
||||
# Calculate total pages
|
||||
total_pages = (total_count + page_size - 1) // page_size
|
||||
|
||||
return PaginatedResponse(
|
||||
items=investor_fund_list,
|
||||
total=total_count,
|
||||
page=page,
|
||||
page_size=page_size,
|
||||
total_pages=total_pages,
|
||||
)
|
||||
|
||||
|
||||
@router.get("/investors/filter", response_model=List[InvestorFundData])
|
||||
@router.get("/investors/filter", response_model=PaginatedResponse[InvestorFundData])
|
||||
def filter_investors(
|
||||
stage: Optional[InvestmentStage] = Query(
|
||||
None, description="Filter by investment stage"
|
||||
@@ -140,9 +163,11 @@ def filter_investors(
|
||||
sector: Optional[str] = Query(None, description="Sector name (partial match)"),
|
||||
min_aum: Optional[int] = Query(None, description="Minimum AUM"),
|
||||
max_aum: Optional[int] = Query(None, description="Maximum AUM"),
|
||||
page: int = Query(1, ge=1, description="Page number (starts at 1)"),
|
||||
page_size: int = Query(10, ge=1, le=100, description="Items per page (max 100)"),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""Filter investors based on various criteria
|
||||
"""Filter investors based on various criteria (paginated)
|
||||
|
||||
Returns investor-fund combinations as separate rows.
|
||||
An investor with 3 funds will appear as 3 entries.
|
||||
@@ -182,7 +207,12 @@ def filter_investors(
|
||||
SectorTable.name.ilike(f"%{sector}%")
|
||||
)
|
||||
|
||||
investors = query.all()
|
||||
# Get total count before pagination
|
||||
total_count = query.count()
|
||||
|
||||
# Calculate offset and apply pagination
|
||||
offset = (page - 1) * page_size
|
||||
investors = query.offset(offset).limit(page_size).all()
|
||||
|
||||
# Transform to InvestorFundData format (one row per investor-fund combination)
|
||||
investor_fund_list = []
|
||||
@@ -251,7 +281,16 @@ def filter_investors(
|
||||
)
|
||||
investor_fund_list.append(investor_fund_data)
|
||||
|
||||
return investor_fund_list
|
||||
# Calculate total pages
|
||||
total_pages = (total_count + page_size - 1) // page_size
|
||||
|
||||
return PaginatedResponse(
|
||||
items=investor_fund_list,
|
||||
total=total_count,
|
||||
page=page,
|
||||
page_size=page_size,
|
||||
total_pages=total_pages,
|
||||
)
|
||||
|
||||
|
||||
@router.get("/investors/{investor_id}", response_model=InvestorData)
|
||||
@@ -368,13 +407,18 @@ def delete_investor(investor_id: int, db: Session = Depends(get_db)):
|
||||
return {"message": "Investor deleted successfully"}
|
||||
|
||||
|
||||
@router.get("/investors/{investor_id}/similar", response_model=List[InvestorFundData])
|
||||
@router.get(
|
||||
"/investors/{investor_id}/similar",
|
||||
response_model=PaginatedResponse[InvestorFundData],
|
||||
)
|
||||
def find_similar_investors(
|
||||
investor_id: int,
|
||||
limit: int = Query(10, description="Maximum number of similar investors to return"),
|
||||
page: int = Query(1, ge=1, description="Page number (starts at 1)"),
|
||||
page_size: int = Query(10, ge=1, le=100, description="Items per page (max 100)"),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""Find investors similar to a given investor based on characteristics
|
||||
"""Find investors similar to a given investor based on characteristics (paginated)
|
||||
|
||||
Returns investor-fund combinations as separate rows.
|
||||
"""
|
||||
@@ -475,9 +519,15 @@ def find_similar_investors(
|
||||
if score > 0: # Only include investors with some similarity
|
||||
scored_investors.append((score, candidate))
|
||||
|
||||
# Sort by score (descending) and take top N
|
||||
# Sort by score (descending) and take top N based on limit
|
||||
scored_investors.sort(key=lambda x: x[0], reverse=True)
|
||||
similar_investors = [inv for score, inv in scored_investors[:limit]]
|
||||
top_similar = scored_investors[:limit]
|
||||
|
||||
# Apply pagination to the top similar investors
|
||||
total_count = len(top_similar)
|
||||
offset = (page - 1) * page_size
|
||||
paginated_similar = top_similar[offset : offset + page_size]
|
||||
similar_investors = [inv for score, inv in paginated_similar]
|
||||
|
||||
# Transform to InvestorFundData format (one row per investor-fund combination)
|
||||
investor_fund_list = []
|
||||
@@ -546,4 +596,13 @@ def find_similar_investors(
|
||||
)
|
||||
investor_fund_list.append(investor_fund_data)
|
||||
|
||||
return investor_fund_list
|
||||
# Calculate total pages
|
||||
total_pages = (total_count + page_size - 1) // page_size
|
||||
|
||||
return PaginatedResponse(
|
||||
items=investor_fund_list,
|
||||
total=total_count,
|
||||
page=page,
|
||||
page_size=page_size,
|
||||
total_pages=total_pages,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user