Phase 1: - Real-time signal alerts (Discord/Telegram webhook) - Trading journal with entry/exit tracking - Position sizing calculator (Fixed/Kelly/ATR) Phase 2: - Pension asset allocation (DC/IRP 70% risk limit) - Drawdown monitoring with SVG gauge - Benchmark dashboard (portfolio vs KOSPI vs deposit) Phase 3: - Tax benefit simulation (Korean pension tax rules) - Correlation matrix heatmap - Parameter optimizer with grid search + overfit detection
112 lines
3.1 KiB
Python
112 lines
3.1 KiB
Python
"""
|
|
Notification settings and history API endpoints.
|
|
"""
|
|
from typing import List
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.core.database import get_db
|
|
from app.api.deps import CurrentUser
|
|
from app.models.notification import NotificationSetting, NotificationHistory
|
|
from app.schemas.notification import (
|
|
NotificationSettingCreate,
|
|
NotificationSettingUpdate,
|
|
NotificationSettingResponse,
|
|
NotificationHistoryResponse,
|
|
)
|
|
|
|
router = APIRouter(prefix="/api/notifications", tags=["notifications"])
|
|
|
|
|
|
@router.get("/settings", response_model=List[NotificationSettingResponse])
|
|
async def get_notification_settings(
|
|
current_user: CurrentUser,
|
|
db: Session = Depends(get_db),
|
|
):
|
|
"""Get all notification settings for the current user."""
|
|
settings = (
|
|
db.query(NotificationSetting)
|
|
.filter(NotificationSetting.user_id == current_user.id)
|
|
.all()
|
|
)
|
|
return settings
|
|
|
|
|
|
@router.post("/settings", response_model=NotificationSettingResponse, status_code=201)
|
|
async def create_notification_setting(
|
|
data: NotificationSettingCreate,
|
|
current_user: CurrentUser,
|
|
db: Session = Depends(get_db),
|
|
):
|
|
"""Create a new notification setting."""
|
|
existing = (
|
|
db.query(NotificationSetting)
|
|
.filter(
|
|
NotificationSetting.user_id == current_user.id,
|
|
NotificationSetting.channel_type == data.channel_type,
|
|
)
|
|
.first()
|
|
)
|
|
if existing:
|
|
raise HTTPException(
|
|
status_code=400,
|
|
detail=f"Setting for {data.channel_type.value} already exists. Use PUT to update.",
|
|
)
|
|
|
|
setting = NotificationSetting(
|
|
user_id=current_user.id,
|
|
channel_type=data.channel_type,
|
|
webhook_url=data.webhook_url,
|
|
enabled=data.enabled,
|
|
)
|
|
db.add(setting)
|
|
db.commit()
|
|
db.refresh(setting)
|
|
return setting
|
|
|
|
|
|
@router.put("/settings/{setting_id}", response_model=NotificationSettingResponse)
|
|
async def update_notification_setting(
|
|
setting_id: int,
|
|
data: NotificationSettingUpdate,
|
|
current_user: CurrentUser,
|
|
db: Session = Depends(get_db),
|
|
):
|
|
"""Update an existing notification setting."""
|
|
setting = (
|
|
db.query(NotificationSetting)
|
|
.filter(
|
|
NotificationSetting.id == setting_id,
|
|
NotificationSetting.user_id == current_user.id,
|
|
)
|
|
.first()
|
|
)
|
|
if not setting:
|
|
raise HTTPException(status_code=404, detail="Notification setting not found")
|
|
|
|
if data.webhook_url is not None:
|
|
setting.webhook_url = data.webhook_url
|
|
if data.enabled is not None:
|
|
setting.enabled = data.enabled
|
|
|
|
db.commit()
|
|
db.refresh(setting)
|
|
return setting
|
|
|
|
|
|
@router.get("/history", response_model=List[NotificationHistoryResponse])
|
|
async def get_notification_history(
|
|
current_user: CurrentUser,
|
|
db: Session = Depends(get_db),
|
|
limit: int = Query(50, ge=1, le=200),
|
|
):
|
|
"""Get notification history."""
|
|
history = (
|
|
db.query(NotificationHistory)
|
|
.order_by(NotificationHistory.sent_at.desc())
|
|
.limit(limit)
|
|
.all()
|
|
)
|
|
return history
|