feat(REQ-001): add portfolio comment history API, CLI, repository, migration, and tests
Agent-Logs-Url: https://github.com/genichin/portfolio-hub/sessions/64fc2cec-78f5-41d1-99a4-45f868781edd Co-authored-by: genichin <4282227+genichin@users.noreply.github.com>
This commit is contained in:
co-authored by
genichin
parent
4684597353
commit
e8f782bec6
+88
-1
@@ -1,12 +1,15 @@
|
||||
"""Portfolio API routes."""
|
||||
|
||||
from fastapi import APIRouter, Depends, Request, Response, status
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request, Response, status
|
||||
|
||||
from app.core.auth import Permission, authorize_request
|
||||
from app.core.config import Settings, get_settings
|
||||
from app.repositories.factory import get_portfolio_repository_from_settings
|
||||
from app.schemas.portfolio import (
|
||||
BuyRequest,
|
||||
CommentCreateRequest,
|
||||
CommentResponse,
|
||||
CommentUpdateRequest,
|
||||
CreatePortfolioRequest,
|
||||
InvestRequest,
|
||||
PortfolioDetailResponse,
|
||||
@@ -21,6 +24,13 @@ from app.services.portfolio_service import PortfolioService
|
||||
router = APIRouter(prefix="/portfolios", tags=["portfolios"])
|
||||
|
||||
|
||||
def _raise_portfolio_error(exc: ValueError) -> None:
|
||||
detail = str(exc)
|
||||
if "찾을 수 없습니다" in detail:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=detail) from exc
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=detail) from exc
|
||||
|
||||
|
||||
def _get_service(settings: Settings) -> tuple[PortfolioService, object]:
|
||||
repository = get_portfolio_repository_from_settings(settings)
|
||||
return PortfolioService(repository), repository
|
||||
@@ -192,3 +202,80 @@ def delete_portfolio(
|
||||
finally:
|
||||
_close_repository(repository)
|
||||
return Response(status_code=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
||||
@router.post(
|
||||
"/{portfolio_id}/comments",
|
||||
response_model=CommentResponse,
|
||||
status_code=status.HTTP_201_CREATED,
|
||||
)
|
||||
def create_comment(
|
||||
portfolio_id: str,
|
||||
payload: CommentCreateRequest,
|
||||
request: Request,
|
||||
*,
|
||||
settings: Settings = Depends(get_settings),
|
||||
) -> CommentResponse:
|
||||
authorize_request(Permission.TRADE_WRITE, request, settings)
|
||||
service, repository = _get_service(settings)
|
||||
try:
|
||||
return service.create_comment(portfolio_id, payload)
|
||||
except ValueError as exc:
|
||||
_raise_portfolio_error(exc)
|
||||
finally:
|
||||
_close_repository(repository)
|
||||
|
||||
|
||||
@router.get("/{portfolio_id}/comments", response_model=list[CommentResponse])
|
||||
def list_comments(
|
||||
portfolio_id: str,
|
||||
request: Request,
|
||||
*,
|
||||
settings: Settings = Depends(get_settings),
|
||||
) -> list[CommentResponse]:
|
||||
authorize_request(Permission.READ, request, settings)
|
||||
service, repository = _get_service(settings)
|
||||
try:
|
||||
return service.list_comments(portfolio_id)
|
||||
except ValueError as exc:
|
||||
_raise_portfolio_error(exc)
|
||||
finally:
|
||||
_close_repository(repository)
|
||||
|
||||
|
||||
@router.patch("/{portfolio_id}/comments/{comment_id}", response_model=CommentResponse)
|
||||
def update_comment(
|
||||
portfolio_id: str,
|
||||
comment_id: str,
|
||||
payload: CommentUpdateRequest,
|
||||
request: Request,
|
||||
*,
|
||||
settings: Settings = Depends(get_settings),
|
||||
) -> CommentResponse:
|
||||
authorize_request(Permission.TRADE_WRITE, request, settings)
|
||||
service, repository = _get_service(settings)
|
||||
try:
|
||||
return service.update_comment(portfolio_id, comment_id, payload)
|
||||
except ValueError as exc:
|
||||
_raise_portfolio_error(exc)
|
||||
finally:
|
||||
_close_repository(repository)
|
||||
|
||||
|
||||
@router.delete("/{portfolio_id}/comments/{comment_id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||
def delete_comment(
|
||||
portfolio_id: str,
|
||||
comment_id: str,
|
||||
request: Request,
|
||||
*,
|
||||
settings: Settings = Depends(get_settings),
|
||||
) -> Response:
|
||||
authorize_request(Permission.TRADE_WRITE, request, settings)
|
||||
service, repository = _get_service(settings)
|
||||
try:
|
||||
service.delete_comment(portfolio_id, comment_id)
|
||||
except ValueError as exc:
|
||||
_raise_portfolio_error(exc)
|
||||
finally:
|
||||
_close_repository(repository)
|
||||
return Response(status_code=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
Reference in New Issue
Block a user