109 lines
3.6 KiB
Python
109 lines
3.6 KiB
Python
"""Market alert and market data APIs."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import date
|
|
|
|
from fastapi import APIRouter, Depends, Query, Request
|
|
|
|
from app.api.deps import get_auth_context, require_permission
|
|
from app.model.schemas import (
|
|
AuthContext,
|
|
MarketAlertFeedbackRequest,
|
|
MarketAlertGenerationRequest,
|
|
MarketAlertList,
|
|
MarketAlertScanRequest,
|
|
MarketAlertView,
|
|
)
|
|
from app.repository.market_alert_repository import MarketAlertRepository
|
|
from app.service.market_alert_feedback_service import MarketAlertFeedbackService
|
|
from app.service.market_alert_generation_service import MarketAlertGenerationService
|
|
from app.service.market_data_service import MarketDataService
|
|
from app.service.market_scan_service import MarketScanService
|
|
from app.utils.response import success_response
|
|
|
|
router = APIRouter()
|
|
fund_router = APIRouter()
|
|
AUTH_CONTEXT_DEP = Depends(get_auth_context)
|
|
MARKET_READ_DEP = Depends(require_permission("market_alert:read"))
|
|
MARKET_GENERATE_DEP = Depends(require_permission("market_alert:generate"))
|
|
MARKET_FEEDBACK_DEP = Depends(require_permission("market_alert:feedback"))
|
|
market_data_service = MarketDataService()
|
|
market_alert_repository = MarketAlertRepository()
|
|
market_scan_service = MarketScanService(repository=market_alert_repository)
|
|
market_alert_generation_service = MarketAlertGenerationService(repository=market_alert_repository)
|
|
market_alert_feedback_service = MarketAlertFeedbackService(repository=market_alert_repository)
|
|
|
|
|
|
@router.get("/ping")
|
|
def ping(request: Request, auth: AuthContext = AUTH_CONTEXT_DEP):
|
|
return success_response(request, {"module": "market", "status": "ready"})
|
|
|
|
|
|
@router.get("")
|
|
def list_market_alerts(
|
|
request: Request,
|
|
auth: AuthContext = MARKET_READ_DEP,
|
|
date: date | None = None,
|
|
status: str | None = None,
|
|
alert_type: str | None = None,
|
|
):
|
|
rows = market_alert_repository.list_alerts(nav_date=date, status=status, alert_type=alert_type)
|
|
result = MarketAlertList(items=[MarketAlertView.model_validate(row) for row in rows])
|
|
return success_response(request, result.model_dump(mode="json"))
|
|
|
|
|
|
@router.post("/scan")
|
|
def scan_market_alerts(
|
|
request: Request,
|
|
payload: MarketAlertScanRequest,
|
|
auth: AuthContext = MARKET_GENERATE_DEP,
|
|
):
|
|
result = market_scan_service.scan(
|
|
nav_date=payload.nav_date,
|
|
threshold_pct=payload.threshold_pct,
|
|
trace_id=request.state.trace_id,
|
|
)
|
|
return success_response(request, result.model_dump(mode="json"))
|
|
|
|
|
|
@router.post("/generate")
|
|
def generate_market_alert(
|
|
request: Request,
|
|
payload: MarketAlertGenerationRequest,
|
|
auth: AuthContext = MARKET_GENERATE_DEP,
|
|
):
|
|
result = market_alert_generation_service.generate(
|
|
fund_code=payload.fund_code,
|
|
trace_id=request.state.trace_id,
|
|
advisor_id=auth.advisor_id or auth.user_id,
|
|
)
|
|
return success_response(request, result.model_dump(mode="json"))
|
|
|
|
|
|
@router.put("/{alert_id}/feedback")
|
|
def feedback_market_alert(
|
|
alert_id: str,
|
|
request: Request,
|
|
payload: MarketAlertFeedbackRequest,
|
|
auth: AuthContext = MARKET_FEEDBACK_DEP,
|
|
):
|
|
result = market_alert_feedback_service.feedback(
|
|
alert_id=alert_id,
|
|
payload=payload,
|
|
auth=auth,
|
|
trace_id=request.state.trace_id,
|
|
)
|
|
return success_response(request, result.model_dump(mode="json"))
|
|
|
|
|
|
@fund_router.get("/fund/{fund_code}")
|
|
def get_fund_quote(
|
|
fund_code: str,
|
|
request: Request,
|
|
auth: AuthContext = MARKET_READ_DEP,
|
|
history_limit: int = Query(default=30, ge=1, le=365),
|
|
):
|
|
result = market_data_service.get_fund_quote(fund_code, history_limit=history_limit)
|
|
return success_response(request, result.model_dump(mode="json"))
|