Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 29 additions & 36 deletions python/valuecell/server/api/routers/watchlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
from ...services.assets.asset_service import get_asset_service
from ...db.repositories.watchlist_repository import get_watchlist_repository

# Global default user ID for open source API
DEFAULT_USER_ID = "default_user"


def create_watchlist_router() -> APIRouter:
"""Create watchlist related routes."""
Expand Down Expand Up @@ -165,15 +168,15 @@ async def get_asset_price(
raise HTTPException(status_code=500, detail=f"Price data error: {str(e)}")

@router.get(
"/{user_id}",
"/",
response_model=SuccessResponse[List[WatchlistData]],
summary="Get user watchlists",
description="Get all watchlists for a user",
summary="Get watchlists",
description="Get all watchlists for the default user",
)
async def get_user_watchlists(user_id: str = Path(..., description="User ID")):
"""Get all watchlists for a user."""
async def get_watchlists():
"""Get all watchlists for the default user."""
try:
watchlists = watchlist_repo.get_user_watchlists(user_id)
watchlists = watchlist_repo.get_user_watchlists(DEFAULT_USER_ID)

watchlist_data = []
for watchlist in watchlists:
Expand All @@ -200,13 +203,12 @@ async def get_user_watchlists(user_id: str = Path(..., description="User ID")):
)

@router.get(
"/{user_id}/{watchlist_name}",
"/{watchlist_name}",
response_model=SuccessResponse[WatchlistData],
summary="Get specific watchlist",
description="Get a specific watchlist by name with optional price data",
)
async def get_watchlist(
user_id: str = Path(..., description="User ID"),
watchlist_name: str = Path(..., description="Watchlist name"),
include_prices: bool = Query(True, description="Include current prices"),
language: Optional[str] = Query(
Expand All @@ -217,7 +219,7 @@ async def get_watchlist(
try:
# Use asset service to get watchlist with prices
result = asset_service.get_watchlist(
user_id=user_id,
user_id=DEFAULT_USER_ID,
watchlist_name=watchlist_name,
include_prices=include_prices,
language=language,
Expand All @@ -227,7 +229,7 @@ async def get_watchlist(
if "not found" in result.get("error", "").lower():
raise HTTPException(
status_code=404,
detail=f"Watchlist '{watchlist_name}' not found for user '{user_id}'",
detail=f"Watchlist '{watchlist_name}' not found",
)
raise HTTPException(
status_code=500,
Expand Down Expand Up @@ -281,19 +283,18 @@ async def get_watchlist(
)

@router.post(
"/{user_id}",
"/",
response_model=SuccessResponse[WatchlistData],
summary="Create watchlist",
description="Create a new watchlist for a user",
description="Create a new watchlist",
)
async def create_watchlist(
user_id: str = Path(..., description="User ID"),
request: CreateWatchlistRequest = None,
):
"""Create a new watchlist."""
try:
watchlist = watchlist_repo.create_watchlist(
user_id=user_id,
user_id=DEFAULT_USER_ID,
name=request.name,
description=request.description or "",
is_default=request.is_default,
Expand Down Expand Up @@ -323,18 +324,16 @@ async def create_watchlist(
)

@router.post(
"/{user_id}/stocks",
"/stocks",
response_model=SuccessResponse[dict],
summary="Add stock to watchlist",
description="Add a stock to a user's watchlist",
description="Add a stock to a watchlist",
)
async def add_stock_to_watchlist(
user_id: str = Path(..., description="User ID"), request: AddStockRequest = None
):
async def add_stock_to_watchlist(request: AddStockRequest = None):
"""Add a stock to a watchlist."""
try:
success = watchlist_repo.add_stock_to_watchlist(
user_id=user_id,
user_id=DEFAULT_USER_ID,
ticker=request.ticker,
watchlist_name=request.watchlist_name,
notes=request.notes or "",
Expand All @@ -349,7 +348,6 @@ async def add_stock_to_watchlist(
return SuccessResponse.create(
data={
"ticker": request.ticker,
"user_id": user_id,
"watchlist_name": request.watchlist_name,
"notes": request.notes,
},
Expand All @@ -364,13 +362,12 @@ async def add_stock_to_watchlist(
)

@router.delete(
"/{user_id}/stocks/{ticker}",
"/stocks/{ticker}",
response_model=SuccessResponse[dict],
summary="Remove stock from watchlist",
description="Remove a stock from a user's watchlist",
description="Remove a stock from a watchlist",
)
async def remove_stock_from_watchlist(
user_id: str = Path(..., description="User ID"),
ticker: str = Path(..., description="Stock ticker to remove"),
watchlist_name: Optional[str] = Query(
None, description="Watchlist name (uses default if not provided)"
Expand All @@ -379,7 +376,7 @@ async def remove_stock_from_watchlist(
"""Remove a stock from a watchlist."""
try:
success = watchlist_repo.remove_stock_from_watchlist(
user_id=user_id, ticker=ticker, watchlist_name=watchlist_name
user_id=DEFAULT_USER_ID, ticker=ticker, watchlist_name=watchlist_name
)

if not success:
Expand All @@ -391,7 +388,6 @@ async def remove_stock_from_watchlist(
return SuccessResponse.create(
data={
"ticker": ticker,
"user_id": user_id,
"watchlist_name": watchlist_name,
},
msg="Stock removed from watchlist successfully",
Expand All @@ -405,29 +401,28 @@ async def remove_stock_from_watchlist(
)

@router.delete(
"/{user_id}/{watchlist_name}",
"/{watchlist_name}",
response_model=SuccessResponse[dict],
summary="Delete watchlist",
description="Delete a user's watchlist",
description="Delete a watchlist",
)
async def delete_watchlist(
user_id: str = Path(..., description="User ID"),
watchlist_name: str = Path(..., description="Watchlist name to delete"),
):
"""Delete a watchlist."""
try:
success = watchlist_repo.delete_watchlist(
user_id=user_id, watchlist_name=watchlist_name
user_id=DEFAULT_USER_ID, watchlist_name=watchlist_name
)

if not success:
raise HTTPException(
status_code=404,
detail=f"Watchlist '{watchlist_name}' not found for user '{user_id}'",
detail=f"Watchlist '{watchlist_name}' not found",
)

return SuccessResponse.create(
data={"user_id": user_id, "watchlist_name": watchlist_name},
data={"watchlist_name": watchlist_name},
msg="Watchlist deleted successfully",
)

Expand All @@ -439,13 +434,12 @@ async def delete_watchlist(
)

@router.put(
"/{user_id}/stocks/{ticker}/notes",
"/stocks/{ticker}/notes",
response_model=SuccessResponse[dict],
summary="Update stock notes",
description="Update notes for a stock in a watchlist",
)
async def update_stock_notes(
user_id: str = Path(..., description="User ID"),
ticker: str = Path(..., description="Stock ticker"),
request: UpdateStockNotesRequest = None,
watchlist_name: Optional[str] = Query(
Expand All @@ -455,7 +449,7 @@ async def update_stock_notes(
"""Update notes for a stock in a watchlist."""
try:
success = watchlist_repo.update_stock_notes(
user_id=user_id,
user_id=DEFAULT_USER_ID,
ticker=ticker,
notes=request.notes,
watchlist_name=watchlist_name,
Expand All @@ -470,7 +464,6 @@ async def update_stock_notes(
return SuccessResponse.create(
data={
"ticker": ticker,
"user_id": user_id,
"notes": request.notes,
"watchlist_name": watchlist_name,
},
Expand Down