Files
leocrm/app/plugins/builtins/dms/models.py
T

77 lines
3.0 KiB
Python
Raw Normal View History

"""Folder and File models for the DMS plugin."""
from __future__ import annotations
import uuid
from datetime import datetime
from typing import Any
from pgvector.sqlalchemy import Vector
from sqlalchemy import DateTime, ForeignKey, Index, Integer, String, Text, UniqueConstraint
from sqlalchemy.dialects.postgresql import TSVECTOR
from sqlalchemy.dialects.postgresql import UUID as PGUUID
from sqlalchemy.orm import Mapped, mapped_column
from app.core.db import Base, TenantMixin
from app.models.owned_mixin import OwnedMixin
class Folder(Base, TenantMixin, OwnedMixin):
"""Folder entity — hierarchical, tenant-scoped, soft-deletable."""
__tablename__ = "folders"
__table_args__ = (
UniqueConstraint(
"tenant_id",
"name",
"parent_id",
name="uq_folders_tenant_name_parent",
# Partial uniqueness only for non-deleted folders is handled at app level
),
Index("ix_folders_parent", "parent_id"),
Index("ix_folders_tenant", "tenant_id"),
)
id: Mapped[uuid.UUID] = mapped_column(
PGUUID(as_uuid=True), primary_key=True, default=uuid.uuid4
)
name: Mapped[str] = mapped_column(String(255), nullable=False)
parent_id: Mapped[uuid.UUID | None] = mapped_column(
PGUUID(as_uuid=True),
ForeignKey("folders.id", ondelete="CASCADE"),
nullable=True,
)
created_by: Mapped[uuid.UUID] = mapped_column(PGUUID(as_uuid=True), nullable=False)
deleted_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
class File(Base, TenantMixin, OwnedMixin):
"""File entity — stored on disk, tenant-scoped, soft-deletable."""
__tablename__ = "files"
indexed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
content_tsv: Mapped[Any] = mapped_column(TSVECTOR, nullable=True)
content_text: Mapped[str | None] = mapped_column(Text, nullable=True)
embedding: Mapped[Any] = mapped_column(Vector(768), nullable=True)
__table_args__ = (
Index("ix_files_folder", "folder_id"),
Index("ix_files_tenant", "tenant_id"),
Index("ix_files_name", "name"),
)
id: Mapped[uuid.UUID] = mapped_column(
PGUUID(as_uuid=True), primary_key=True, default=uuid.uuid4
)
name: Mapped[str] = mapped_column(String(255), nullable=False)
folder_id: Mapped[uuid.UUID | None] = mapped_column(
PGUUID(as_uuid=True),
ForeignKey("folders.id", ondelete="SET NULL"),
nullable=True,
)
uploaded_by: Mapped[uuid.UUID] = mapped_column(PGUUID(as_uuid=True), nullable=False)
mime_type: Mapped[str] = mapped_column(String(255), nullable=False)
size_bytes: Mapped[int] = mapped_column(Integer, nullable=False)
storage_path: Mapped[str] = mapped_column(String(1024), nullable=False)
2026-07-25 21:03:46 +02:00
content_hash: Mapped[str | None] = mapped_column(String(64), nullable=True)
deleted_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)