import uuid from datetime import datetime import enum from sqlalchemy import ( String, Numeric, Float, Boolean, DateTime, Text, ForeignKey, Enum as SAEnum, func, ) from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import Mapped, mapped_column, relationship from app.core.database import Base from app.models.evidence_image import SourceApp class Direction(str, enum.Enum): in_ = "in" out = "out" class TransactionRecord(Base): __tablename__ = "transaction_records" id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) case_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("cases.id"), index=True) evidence_image_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("evidence_images.id"), nullable=True) cluster_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("transaction_clusters.id"), nullable=True) source_app: Mapped[SourceApp] = mapped_column(SAEnum(SourceApp), default=SourceApp.other) trade_time: Mapped[datetime] = mapped_column(DateTime(timezone=True), index=True) amount: Mapped[float] = mapped_column(Numeric(14, 2), default=0) direction: Mapped[Direction] = mapped_column(SAEnum(Direction)) counterparty_name: Mapped[str] = mapped_column(String(256), default="") counterparty_account: Mapped[str] = mapped_column(String(256), default="") self_account_tail_no: Mapped[str] = mapped_column(String(32), default="") order_no: Mapped[str] = mapped_column(String(128), default="", index=True) remark: Mapped[str] = mapped_column(Text, default="") confidence: Mapped[float] = mapped_column(Float, default=0.0) is_duplicate: Mapped[bool] = mapped_column(Boolean, default=False) is_transit: Mapped[bool] = mapped_column(Boolean, default=False) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) case = relationship("Case", back_populates="transactions") cluster = relationship("TransactionCluster", back_populates="transactions", foreign_keys=[cluster_id])