"""Transaction model for WealthWise. This module defines the Transaction database model. Transactions represent individual financial entries (income, expenses, transfers) within a portfolio. """ import datetime as dt from decimal import Decimal from enum import Enum from typing import TYPE_CHECKING, Optional from uuid import UUID from sqlalchemy import Column, Date, DateTime, ForeignKey, Numeric, String, Text from sqlmodel import Field, Relationship, SQLModel from app.models.base import BaseModel if TYPE_CHECKING: from app.models.portfolio import Portfolio class TransactionType(str, Enum): """Transaction type enumeration. Defines the possible types of financial transactions: - INCOME: Money coming in (salary, dividends, etc.) - EXPENSE: Money going out (purchases, bills, etc.) - TRANSFER: Movement between accounts/portfolios """ INCOME = "income" EXPENSE = "expense" TRANSFER = "transfer" class TransactionBase(SQLModel): """Base Transaction model with common attributes. Attributes: amount: Transaction amount (Decimal for financial precision) transaction_type: Transaction type (income, expense, transfer) date: Transaction date description: Optional transaction description category: Optional transaction category/tag """ amount: Decimal = Field( sa_column=Column(Numeric(15, 2), nullable=False), description="Transaction amount", ) transaction_type: TransactionType = Field( sa_column=Column(String(20), nullable=False), description="Transaction type: income, expense, or transfer", ) transaction_date: dt.date = Field( sa_column=Column(Date, nullable=False), description="Transaction date", ) description: Optional[str] = Field( default=None, sa_column=Column(Text, nullable=True), description="Optional transaction description", ) category: Optional[str] = Field( default=None, sa_column=Column(String(100), nullable=True), description="Optional transaction category or tag", ) class Transaction(BaseModel, TransactionBase, table=True): """Transaction database model. Transactions represent individual financial entries within a portfolio. They track amounts, dates, types, and categorization for financial analysis. Attributes: id: UUID primary key (inherited from BaseModel) portfolio_id: Foreign key to portfolios table amount: Transaction amount with 2 decimal precision transaction_type: Transaction type enum date: Transaction date description: Optional description category: Optional category/tag portfolio: Relationship to parent portfolio created_at: Timestamp (inherited from BaseModel) updated_at: Not used (transactions are immutable after creation) """ __tablename__ = "transactions" portfolio_id: UUID = Field( sa_column=Column( ForeignKey("portfolios.id", ondelete="CASCADE"), nullable=False, ), description="Parent portfolio ID", ) # Relationships portfolio: "Portfolio" = Relationship(back_populates="transactions") class Config: """Pydantic configuration.""" arbitrary_types_allowed = True