from __future__ import annotations from datetime import datetime from sqlalchemy import DateTime, ForeignKey, Index, Integer, String, Text, text from sqlalchemy.orm import Mapped, mapped_column from app.enums.private_portrait import PrivatePortraitLibraryType, PrivatePortraitProjectStatus from app.models.base import Base, SoftDeleteMixin, TimestampMixin class PrivatePortraitProject(Base, TimestampMixin, SoftDeleteMixin): """用户本地私域人像素材项目组。remote_project_name 是火山 ProjectName 快照。""" __tablename__ = "private_portrait_projects" __table_args__ = ( Index("idx_private_portrait_projects_user_library_status_created", "user_id", "library_type", "status", "created_at"), Index("idx_private_portrait_projects_user_status_created", "user_id", "status", "created_at"), Index( "idx_private_portrait_projects_user_deleted", "user_id", "deleted_at", postgresql_where=text("deleted_at IS NULL"), ), Index("idx_private_portrait_projects_remote_project_name", "remote_project_name"), Index("idx_private_portrait_projects_library_type", "library_type"), ) id: Mapped[str] = mapped_column(String(32), primary_key=True) user_id: Mapped[str] = mapped_column(String(32), ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True) library_type: Mapped[str] = mapped_column( String(32), nullable=False, default=PrivatePortraitLibraryType.REAL_PERSON.value, server_default=PrivatePortraitLibraryType.REAL_PERSON.value, index=True, comment="素材库类型:real_person 真人认证;aigc_virtual 虚拟人像", ) name: Mapped[str] = mapped_column(String(128), nullable=False, index=True, comment="用户展示项目名") name_slug: Mapped[str] = mapped_column(String(128), nullable=False, index=True, comment="项目名安全 slug") remote_project_name: Mapped[str] = mapped_column(String(256), nullable=False, index=True, comment="火山 ProjectName 快照") description: Mapped[str | None] = mapped_column(Text, nullable=True) status: Mapped[str] = mapped_column( String(32), nullable=False, default=PrivatePortraitProjectStatus.ACTIVE.value, server_default=PrivatePortraitProjectStatus.ACTIVE.value, index=True, ) asset_group_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0, server_default="0") asset_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0, server_default="0") image_asset_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0, server_default="0") video_asset_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0, server_default="0") active_asset_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0, server_default="0") active_image_asset_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0, server_default="0") active_video_asset_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0, server_default="0") last_used_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)