from datetime import datetime from typing import Any, Optional from pydantic import BaseModel class TopError(BaseModel): ts: Optional[datetime] event: str message: Optional[str] source: str user_id: Optional[str] run_id: Optional[str] class OverviewResponse(BaseModel): total_users: int users_logged_in_last_24h: int total_runs: int running_runs: int stopped_runs: int error_runs: int live_runs_count: int paper_runs_count: int orders_last_24h: int trades_last_24h: int sip_executed_last_24h: int top_errors: list[TopError] class UserSummary(BaseModel): user_id: str username: str role: str is_admin: bool created_at: Optional[datetime] last_login_at: Optional[datetime] active_run_id: Optional[str] active_run_status: Optional[str] runs_count: int broker_connected: bool class UsersResponse(BaseModel): page: int page_size: int total: int users: list[UserSummary] class RunSummary(BaseModel): run_id: str user_id: str status: str created_at: Optional[datetime] started_at: Optional[datetime] stopped_at: Optional[datetime] strategy: Optional[str] mode: Optional[str] broker: Optional[str] sip_amount: Optional[float] sip_frequency_value: Optional[int] sip_frequency_unit: Optional[str] last_event_time: Optional[datetime] last_sip_time: Optional[datetime] next_sip_time: Optional[datetime] order_count: int trade_count: int equity_latest: Optional[float] pnl_latest: Optional[float] class RunsResponse(BaseModel): page: int page_size: int total: int runs: list[RunSummary] class EventItem(BaseModel): ts: Optional[datetime] source: str event: str message: Optional[str] level: Optional[str] run_id: Optional[str] meta: Optional[dict[str, Any]] class CapitalSummary(BaseModel): cash: Optional[float] invested: Optional[float] mtm: Optional[float] equity: Optional[float] pnl: Optional[float] class UserDetailResponse(BaseModel): user: UserSummary runs: list[RunSummary] current_config: Optional[dict[str, Any]] events: list[EventItem] capital_summary: CapitalSummary class EngineStatusResponse(BaseModel): status: Optional[str] last_updated: Optional[datetime] class RunDetailResponse(BaseModel): run: RunSummary config: Optional[dict[str, Any]] engine_status: Optional[EngineStatusResponse] state_snapshot: Optional[dict[str, Any]] ledger_events: list[dict[str, Any]] orders: list[dict[str, Any]] trades: list[dict[str, Any]] invariants: dict[str, Any] class InvariantsResponse(BaseModel): running_runs_per_user_violations: int orphan_rows: int duplicate_logical_time: int negative_cash: int invalid_qty: int stale_running_runs: int class SupportTicketSummary(BaseModel): ticket_id: str name: str email: str subject: str message: str status: str created_at: Optional[datetime] updated_at: Optional[datetime] class SupportTicketsResponse(BaseModel): page: int page_size: int total: int tickets: list[SupportTicketSummary] class DeleteSupportTicketResponse(BaseModel): ticket_id: str deleted: bool class DeleteUserResponse(BaseModel): user_id: str deleted: dict[str, int] audit_id: int class HardResetResponse(BaseModel): user_id: str deleted: dict[str, int] audit_id: int