import uuid from datetime import datetime import enum from sqlalchemy import String, Integer, DateTime, 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 class SourceApp(str, enum.Enum): wechat = "wechat" alipay = "alipay" bank = "bank" digital_wallet = "digital_wallet" other = "other" class PageType(str, enum.Enum): bill_list = "bill_list" bill_detail = "bill_detail" transfer_receipt = "transfer_receipt" sms_notice = "sms_notice" balance = "balance" unknown = "unknown" class OcrStatus(str, enum.Enum): pending = "pending" processing = "processing" done = "done" failed = "failed" class EvidenceImage(Base): __tablename__ = "evidence_images" 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) file_path: Mapped[str] = mapped_column(String(512)) thumb_path: Mapped[str] = mapped_column(String(512), default="") source_app: Mapped[SourceApp] = mapped_column(SAEnum(SourceApp), default=SourceApp.other) page_type: Mapped[PageType] = mapped_column(SAEnum(PageType), default=PageType.unknown) ocr_status: Mapped[OcrStatus] = mapped_column(SAEnum(OcrStatus), default=OcrStatus.pending) file_hash: Mapped[str] = mapped_column(String(128), unique=True, index=True) file_size: Mapped[int] = mapped_column(Integer, default=0) uploaded_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) case = relationship("Case", back_populates="images") ocr_blocks = relationship("OcrBlock", back_populates="image", lazy="selectin")