| from fastapi import APIRouter, Depends, HTTPException
|
| from sqlalchemy.ext.asyncio import AsyncSession
|
| from app.db.session import get_db
|
| from app.services.user_service import user_service
|
| from app.services.yahoo_finance import yahoo_finance_service
|
| from pydantic import BaseModel
|
| from typing import List, Optional
|
| from app.core.auth import get_current_user, get_authenticated_user, get_user_or_demo
|
| from app.models.database import User as DBUser
|
|
|
| router = APIRouter()
|
|
|
| class WatchlistItemSchema(BaseModel):
|
| symbol: str
|
| name: str
|
| exchange: str
|
|
|
| class WatchlistEnrichedSchema(WatchlistItemSchema):
|
| price: str
|
| change: str
|
| percentage: str
|
| isPositive: bool
|
|
|
| class UserProfileSchema(BaseModel):
|
| username: str
|
| full_name: str
|
| avatar_url: Optional[str]
|
| theme: Optional[str] = "dark"
|
|
|
| class ThemeUpdateSchema(BaseModel):
|
| theme: str
|
|
|
| class IndicatorsUpdateSchema(BaseModel):
|
| indicators: List[str]
|
|
|
| @router.get("/profile", response_model=UserProfileSchema)
|
| async def get_profile(user: DBUser = Depends(get_user_or_demo)):
|
| return {
|
| "username": user.username or user.email.split('@')[0],
|
| "full_name": user.full_name,
|
| "avatar_url": user.avatar_url,
|
| "theme": user.theme or "dark"
|
| }
|
|
|
| @router.put("/profile/theme")
|
| async def update_theme(data: ThemeUpdateSchema, db: AsyncSession = Depends(get_db), user: DBUser = Depends(get_authenticated_user)):
|
| user.theme = data.theme
|
| await db.commit()
|
| return {"status": "success", "theme": user.theme}
|
|
|
| @router.get("/watchlist", response_model=List[WatchlistEnrichedSchema])
|
| async def get_watchlist(db: AsyncSession = Depends(get_db), user: DBUser = Depends(get_user_or_demo)):
|
| items = await user_service.get_watchlist(db, user.id)
|
|
|
| if not items:
|
| return []
|
|
|
|
|
| symbols = [item.symbol for item in items]
|
| quotes = await yahoo_finance_service.get_quotes(symbols)
|
| quote_map = {q.symbol: q for q in quotes}
|
|
|
| results = []
|
| for item in items:
|
| quote = quote_map.get(item.symbol)
|
| results.append({
|
| "symbol": item.symbol,
|
| "name": item.name,
|
| "exchange": item.exchange,
|
| "price": quote.price if quote else "0.00",
|
| "change": quote.change if quote else "0.00",
|
| "percentage": quote.percentage if quote else "0.00%",
|
| "isPositive": quote.isPositive if quote else True
|
| })
|
| return results
|
|
|
| @router.post("/watchlist")
|
| async def add_to_watchlist(item: WatchlistItemSchema, db: AsyncSession = Depends(get_db), user: DBUser = Depends(get_authenticated_user)):
|
| await user_service.add_to_watchlist(
|
| db, user.id, item.symbol, item.name, item.exchange
|
| )
|
| return {"status": "success"}
|
|
|
| @router.delete("/watchlist/{symbol}")
|
| async def remove_from_watchlist(symbol: str, db: AsyncSession = Depends(get_db), user: DBUser = Depends(get_authenticated_user)):
|
| await user_service.remove_from_watchlist(db, user.id, symbol)
|
| return {"status": "success"}
|
|
|
| @router.get("/indicators", response_model=List[str])
|
| async def get_indicators(db: AsyncSession = Depends(get_db), user: DBUser = Depends(get_user_or_demo)):
|
| return await user_service.get_indicators(db, user.id)
|
|
|
| @router.post("/indicators")
|
| async def update_indicators(data: IndicatorsUpdateSchema, db: AsyncSession = Depends(get_db), user: DBUser = Depends(get_authenticated_user)):
|
| await user_service.update_indicators(db, user.id, data.indicators)
|
| return {"status": "success"}
|
|
|
| from app.models.database import UserAgenticScan
|
| from sqlalchemy import select, desc
|
|
|
| class AgenticScanSchema(BaseModel):
|
| id: int
|
| symbol: str
|
| decision: str
|
| confidence: float
|
| recommendation: str
|
| created_at: str
|
| risk_warning: Optional[str] = None
|
|
|
| entry_price: Optional[str] = None
|
|
|
| @router.get("/scans", response_model=List[AgenticScanSchema])
|
| async def get_scans(db: AsyncSession = Depends(get_db), user: DBUser = Depends(get_user_or_demo)):
|
| result = await db.execute(
|
| select(UserAgenticScan)
|
| .where(UserAgenticScan.user_id == user.id)
|
| .order_by(desc(UserAgenticScan.created_at))
|
| )
|
| scans = result.scalars().all()
|
|
|
| return [
|
| AgenticScanSchema(
|
| id=s.id,
|
| symbol=s.symbol,
|
| decision=s.decision,
|
| confidence=s.confidence,
|
| recommendation=s.recommendation,
|
| created_at=s.created_at.isoformat(),
|
| risk_warning=s.risk_warning,
|
| entry_price=s.entry_price
|
| )
|
| for s in scans
|
| ]
|
|
|