from __future__ import annotations from datetime import date from decimal import Decimal from sqlalchemy import BigInteger, Boolean, Date, ForeignKey, Integer, String, true from sqlalchemy.orm import Mapped, mapped_column from app.core.config import settings from app.db.base import Base from app.db.types import AuditMixin, IdMixin, Percent, Price, qualified class Security(IdMixin, AuditMixin, Base): """Облигация. isin — идентификатор для пользователя, secid — для запросов к ISS. У корпоративных бумаг secid обычно совпадает с ISIN, у ОФЗ — нет (например, SU26238RMFS4), поэтому храним оба. """ __tablename__ = "security" __table_args__ = ( {"schema": settings.DATABASE_SCHEMA} if settings.DATABASE_SCHEMA else {} ) isin: Mapped[str] = mapped_column(String(12), unique=True, nullable=False) secid: Mapped[str] = mapped_column(String(51), nullable=False) name: Mapped[str] = mapped_column(String(255), nullable=False) initial_face_value: Mapped[Decimal | None] = mapped_column(Price) currency_id: Mapped[int] = mapped_column( BigInteger, ForeignKey(qualified("currency.id")), nullable=False ) placement_date: Mapped[date | None] = mapped_column(Date) maturity_date: Mapped[date | None] = mapped_column(Date) coupon_rate: Mapped[Decimal | None] = mapped_column(Percent) coupon_frequency: Mapped[int | None] = mapped_column(Integer) # TODO(BIQ-38115): заменится признаком «есть позиция в портфеле». is_active: Mapped[bool] = mapped_column( Boolean, nullable=False, default=True, server_default=true() )