import uuid from sqlalchemy import ( Boolean, ForeignKey, ForeignKeyConstraint, Integer, String, UniqueConstraint, Uuid, ) from sqlalchemy.orm import Mapped, mapped_column from app.db.base import Base, PkMixin, TimestampMixin class IncomeSource(Base, PkMixin, TimestampMixin): __tablename__ = "income_sources" __table_args__ = ( UniqueConstraint("space_id", "name", name="uq_income_sources_space_name"), UniqueConstraint("space_id", "id", name="uq_income_sources_space_id"), ) space_id: Mapped[uuid.UUID] = mapped_column( Uuid, ForeignKey("financial_spaces.id", ondelete="CASCADE"), nullable=False, index=True ) name: Mapped[str] = mapped_column(String(200), nullable=False) archived: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False) class Payee(Base, PkMixin, TimestampMixin): __tablename__ = "payees" __table_args__ = ( UniqueConstraint("space_id", "name", name="uq_payees_space_name"), UniqueConstraint("space_id", "id", name="uq_payees_space_id"), ) space_id: Mapped[uuid.UUID] = mapped_column( Uuid, ForeignKey("financial_spaces.id", ondelete="CASCADE"), nullable=False, index=True ) name: Mapped[str] = mapped_column(String(200), nullable=False) archived: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False) class PayeeAlias(Base, PkMixin, TimestampMixin): __tablename__ = "payee_aliases" __table_args__ = ( UniqueConstraint("space_id", "alias", name="uq_payee_aliases_space_alias"), ForeignKeyConstraint( ["space_id", "payee_id"], ["payees.space_id", "payees.id"], ondelete="CASCADE", name="fk_payee_aliases_payee_tenant", ), ) space_id: Mapped[uuid.UUID] = mapped_column( Uuid, ForeignKey("financial_spaces.id", ondelete="CASCADE"), nullable=False, index=True ) payee_id: Mapped[uuid.UUID] = mapped_column(Uuid, nullable=False, index=True) alias: Mapped[str] = mapped_column(String(300), nullable=False) class CategorizationRule(Base, PkMixin, TimestampMixin): """Confirmed payee rule: auto-applies category to matching future operations.""" __tablename__ = "categorization_rules" __table_args__ = ( UniqueConstraint("space_id", "payee_id", name="uq_rules_space_payee"), ForeignKeyConstraint( ["space_id", "payee_id"], ["payees.space_id", "payees.id"], ondelete="CASCADE", name="fk_rules_payee_tenant", ), ForeignKeyConstraint( ["space_id", "category_id"], ["categories.space_id", "categories.id"], name="fk_rules_category_tenant", ), ) space_id: Mapped[uuid.UUID] = mapped_column( Uuid, ForeignKey("financial_spaces.id", ondelete="CASCADE"), nullable=False, index=True ) payee_id: Mapped[uuid.UUID] = mapped_column(Uuid, nullable=False) category_id: Mapped[uuid.UUID] = mapped_column(Uuid, nullable=False) created_by_user_id: Mapped[uuid.UUID | None] = mapped_column( Uuid, ForeignKey("users.id", ondelete="SET NULL"), nullable=True ) class MccCode(Base): """Global versioned MCC dictionary (not space-scoped, outside RLS).""" __tablename__ = "mcc_codes" code: Mapped[int] = mapped_column(Integer, primary_key=True) title: Mapped[str] = mapped_column(String(300), nullable=False) dictionary_version: Mapped[int] = mapped_column(nullable=False, default=1) class BankCategoryMapping(Base, PkMixin): """Maps a bank's raw category string to an MCC for suggestion purposes.""" __tablename__ = "bank_category_mappings" __table_args__ = ( UniqueConstraint("bank_code", "bank_category", name="uq_bank_mappings_bank_category"), ) bank_code: Mapped[str] = mapped_column(String(32), nullable=False, index=True) bank_category: Mapped[str] = mapped_column(String(200), nullable=False) mcc_code: Mapped[int | None] = mapped_column(Integer, nullable=True)