"""Persistence models for the advisory investment-goal workflow.""" from datetime import date, datetime from decimal import Decimal from typing import Any from sqlalchemy import JSON, BigInteger, Date, DateTime, Integer, Numeric, String, Text from sqlalchemy.orm import Mapped, mapped_column from app.model.base import Base class ClientFacingContent(Base): """Existing baseline content-review resource used for goal-book drafts.""" __tablename__ = "client_facing_content" id: Mapped[int] = mapped_column(BigInteger, primary_key=True) customer_id: Mapped[int] = mapped_column(BigInteger, nullable=False) content_type: Mapped[str] = mapped_column(String(32), nullable=False) draft_content: Mapped[dict[str, Any]] = mapped_column(JSON, nullable=False) generated_by_portal: Mapped[str] = mapped_column(String(32), nullable=False) review_status: Mapped[str] = mapped_column(String(16), nullable=False) reviewer_user_id: Mapped[int | None] = mapped_column(BigInteger) reviewed_at: Mapped[datetime | None] = mapped_column(DateTime) published_at: Mapped[datetime | None] = mapped_column(DateTime) created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) class AdvisorInvestmentGoal(Base): """An immutable collected goal version; confirmation activates it for later planning.""" __tablename__ = "advisor_investment_goal" id: Mapped[int] = mapped_column(BigInteger, primary_key=True) goal_no: Mapped[str] = mapped_column(String(36), unique=True, nullable=False) customer_id: Mapped[int] = mapped_column(BigInteger, nullable=False) status: Mapped[str] = mapped_column(String(24), nullable=False) annualized_return_lower_pct: Mapped[Decimal] = mapped_column(Numeric(7, 4), nullable=False) annualized_return_upper_pct: Mapped[Decimal] = mapped_column(Numeric(7, 4), nullable=False) max_drawdown_pct: Mapped[Decimal] = mapped_column(Numeric(7, 4), nullable=False) liquidity_requirement: Mapped[str] = mapped_column(String(32), nullable=False) investment_horizon_months: Mapped[int] = mapped_column(Integer, nullable=False) benchmark_name: Mapped[str] = mapped_column(String(128), nullable=False) notes: Mapped[str | None] = mapped_column(Text) source: Mapped[str] = mapped_column(String(16), nullable=False) goal_book_content_id: Mapped[int] = mapped_column(BigInteger, nullable=False, unique=True) created_by: Mapped[int] = mapped_column(BigInteger, nullable=False) confirmed_by: Mapped[int | None] = mapped_column(BigInteger) confirmed_at: Mapped[datetime | None] = mapped_column(DateTime) created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) class AllocationBacktestRun(Base): """Stored, analysis-only evidence for a dynamic allocation strategy run.""" __tablename__ = "advisor_allocation_backtest_run" id: Mapped[int] = mapped_column(BigInteger, primary_key=True) backtest_no: Mapped[str] = mapped_column(String(36), unique=True, nullable=False) started_on: Mapped[date] = mapped_column(Date, nullable=False) ended_on: Mapped[date] = mapped_column(Date, nullable=False) profile_risk_level: Mapped[str] = mapped_column(String(8), nullable=False) return_target_lower_pct: Mapped[Decimal] = mapped_column(Numeric(7, 4), nullable=False) max_drawdown_pct: Mapped[Decimal] = mapped_column(Numeric(7, 4), nullable=False) liquidity_requirement: Mapped[str] = mapped_column(String(32), nullable=False) status: Mapped[str] = mapped_column(String(32), nullable=False) observation_count: Mapped[int] = mapped_column(BigInteger, nullable=False) static_total_return_pct: Mapped[Decimal | None] = mapped_column(Numeric(12, 4)) dynamic_total_return_pct: Mapped[Decimal | None] = mapped_column(Numeric(12, 4)) static_max_drawdown_pct: Mapped[Decimal | None] = mapped_column(Numeric(12, 4)) dynamic_max_drawdown_pct: Mapped[Decimal | None] = mapped_column(Numeric(12, 4)) dynamic_rebalance_count: Mapped[int] = mapped_column(BigInteger, nullable=False) liquidity_history_coverage_pct: Mapped[Decimal] = mapped_column(Numeric(7, 4), nullable=False) limitations: Mapped[list[str]] = mapped_column(JSON, nullable=False) strategy_version: Mapped[str] = mapped_column(String(32), nullable=False) created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)