180 lines
4.5 KiB
Python
180 lines
4.5 KiB
Python
"""Portfolio API endpoints."""
|
|
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from sqlalchemy.orm import Session
|
|
from typing import Optional
|
|
from uuid import UUID
|
|
|
|
from app.database import get_db
|
|
from app.schemas.portfolio import (
|
|
PortfolioCreate,
|
|
PortfolioUpdate,
|
|
PortfolioResponse,
|
|
PortfolioListResponse
|
|
)
|
|
from app.services.rebalancing_service import PortfolioService
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.post("/", response_model=PortfolioResponse, status_code=status.HTTP_201_CREATED)
|
|
async def create_portfolio(
|
|
portfolio: PortfolioCreate,
|
|
user_id: Optional[str] = None,
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""
|
|
포트폴리오 생성.
|
|
|
|
Args:
|
|
portfolio: 포트폴리오 생성 요청
|
|
user_id: 사용자 ID (선택)
|
|
db: 데이터베이스 세션
|
|
|
|
Returns:
|
|
생성된 포트폴리오
|
|
"""
|
|
try:
|
|
assets_data = [
|
|
{'ticker': asset.ticker, 'target_ratio': asset.target_ratio}
|
|
for asset in portfolio.assets
|
|
]
|
|
|
|
created_portfolio = PortfolioService.create_portfolio(
|
|
name=portfolio.name,
|
|
description=portfolio.description,
|
|
assets=assets_data,
|
|
user_id=user_id,
|
|
db_session=db
|
|
)
|
|
|
|
return created_portfolio
|
|
|
|
except Exception as e:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"포트폴리오 생성 오류: {str(e)}"
|
|
)
|
|
|
|
|
|
@router.get("/{portfolio_id}", response_model=PortfolioResponse)
|
|
async def get_portfolio(
|
|
portfolio_id: UUID,
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""
|
|
포트폴리오 조회.
|
|
|
|
Args:
|
|
portfolio_id: 포트폴리오 ID
|
|
db: 데이터베이스 세션
|
|
|
|
Returns:
|
|
포트폴리오
|
|
"""
|
|
portfolio = PortfolioService.get_portfolio(portfolio_id, db)
|
|
|
|
if not portfolio:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="포트폴리오를 찾을 수 없습니다"
|
|
)
|
|
|
|
return portfolio
|
|
|
|
|
|
@router.get("/", response_model=PortfolioListResponse)
|
|
async def list_portfolios(
|
|
user_id: Optional[str] = None,
|
|
skip: int = 0,
|
|
limit: int = 100,
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""
|
|
포트폴리오 목록 조회.
|
|
|
|
Args:
|
|
user_id: 사용자 ID (필터)
|
|
skip: 건너뛸 레코드 수
|
|
limit: 최대 레코드 수
|
|
db: 데이터베이스 세션
|
|
|
|
Returns:
|
|
포트폴리오 목록
|
|
"""
|
|
result = PortfolioService.list_portfolios(db, user_id, skip, limit)
|
|
return result
|
|
|
|
|
|
@router.put("/{portfolio_id}", response_model=PortfolioResponse)
|
|
async def update_portfolio(
|
|
portfolio_id: UUID,
|
|
portfolio: PortfolioUpdate,
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""
|
|
포트폴리오 수정.
|
|
|
|
Args:
|
|
portfolio_id: 포트폴리오 ID
|
|
portfolio: 포트폴리오 수정 요청
|
|
db: 데이터베이스 세션
|
|
|
|
Returns:
|
|
수정된 포트폴리오
|
|
"""
|
|
try:
|
|
assets_data = None
|
|
if portfolio.assets:
|
|
assets_data = [
|
|
{'ticker': asset.ticker, 'target_ratio': asset.target_ratio}
|
|
for asset in portfolio.assets
|
|
]
|
|
|
|
updated_portfolio = PortfolioService.update_portfolio(
|
|
portfolio_id=portfolio_id,
|
|
name=portfolio.name,
|
|
description=portfolio.description,
|
|
assets=assets_data,
|
|
db_session=db
|
|
)
|
|
|
|
if not updated_portfolio:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="포트폴리오를 찾을 수 없습니다"
|
|
)
|
|
|
|
return updated_portfolio
|
|
|
|
except ValueError as e:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=str(e)
|
|
)
|
|
except Exception as e:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"포트폴리오 수정 오류: {str(e)}"
|
|
)
|
|
|
|
|
|
@router.delete("/{portfolio_id}", status_code=status.HTTP_204_NO_CONTENT)
|
|
async def delete_portfolio(
|
|
portfolio_id: UUID,
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""
|
|
포트폴리오 삭제.
|
|
|
|
Args:
|
|
portfolio_id: 포트폴리오 ID
|
|
db: 데이터베이스 세션
|
|
"""
|
|
success = PortfolioService.delete_portfolio(portfolio_id, db)
|
|
|
|
if not success:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="포트폴리오를 찾을 수 없습니다"
|
|
)
|