Files
portfolio-hub/app/api/strategy_sets.py
T

88 lines
3.1 KiB
Python

"""Strategy Set API routes."""
from fastapi import APIRouter, Depends, Response, status
from app.core.auth import require_read, require_trade_write
from app.schemas.portfolio import CreateStrategySetRequest, StrategySetResponse, UpdateStrategySetRequest
from app.services.strategy_set_service import StrategySetService, get_strategy_set_repository
def get_strategy_set_service(repository=Depends(get_strategy_set_repository)) -> StrategySetService:
return StrategySetService(repository)
router = APIRouter(prefix="/strategy-sets", tags=["strategy-sets"])
@router.get("", response_model=list[StrategySetResponse], dependencies=[Depends(require_read)])
def list_strategy_sets(
service: StrategySetService = Depends(get_strategy_set_service),
) -> list[StrategySetResponse]:
"""List all strategy sets."""
strategy_sets = service.list()
return [
StrategySetResponse(
id=ss.id,
name=ss.name,
config=ss.config,
nick=ss.nick,
created_at=ss.created_at,
)
for ss in strategy_sets
]
@router.post("", response_model=StrategySetResponse, status_code=status.HTTP_201_CREATED, dependencies=[Depends(require_trade_write)])
def create_strategy_set(
payload: CreateStrategySetRequest,
service: StrategySetService = Depends(get_strategy_set_service),
) -> StrategySetResponse:
"""Create a new strategy set (or return existing if (name, config) pair already exists)."""
strategy_set = service.create(payload)
return StrategySetResponse(
id=strategy_set.id,
name=strategy_set.name,
config=strategy_set.config,
nick=strategy_set.nick,
created_at=strategy_set.created_at,
)
@router.patch("/{strategy_set_id}", response_model=StrategySetResponse, dependencies=[Depends(require_trade_write)])
def update_strategy_set(
strategy_set_id: str,
payload: UpdateStrategySetRequest,
service: StrategySetService = Depends(get_strategy_set_service),
) -> StrategySetResponse:
"""Update a strategy set's name and/or config.
Note: Since strategy sets are identified by (name, config) uniqueness,
updating may result in a new strategy set ID if name or config changes.
"""
strategy_set = service.update(strategy_set_id, payload)
return StrategySetResponse(
id=strategy_set.id,
name=strategy_set.name,
config=strategy_set.config,
nick=strategy_set.nick,
created_at=strategy_set.created_at,
)
@router.delete("/{strategy_set_id}", status_code=status.HTTP_204_NO_CONTENT, dependencies=[Depends(require_trade_write)])
def delete_strategy_set(
strategy_set_id: str,
service: StrategySetService = Depends(get_strategy_set_service),
) -> Response:
"""Delete a strategy set.
Returns 204 No Content on success.
Returns 409 Conflict if the strategy set is in use by any portfolio.
"""
try:
service.delete(strategy_set_id)
except ValueError as e:
# If strategy set is in use, return 409 Conflict
raise ValueError(str(e)) from e
return Response(status_code=status.HTTP_204_NO_CONTENT)