library.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. """Library models for file manager functionality."""
  2. from datetime import datetime
  3. from sqlalchemy import JSON, Boolean, DateTime, ForeignKey, Integer, String, Text, func
  4. from sqlalchemy.orm import Mapped, mapped_column, relationship
  5. from backend.app.core.database import Base
  6. class LibraryFolder(Base):
  7. """Folder for organizing library files."""
  8. __tablename__ = "library_folders"
  9. id: Mapped[int] = mapped_column(primary_key=True)
  10. name: Mapped[str] = mapped_column(String(255))
  11. parent_id: Mapped[int | None] = mapped_column(ForeignKey("library_folders.id", ondelete="CASCADE"), nullable=True)
  12. # External folder flags (for folders that point to external paths)
  13. is_external: Mapped[bool] = mapped_column(Boolean, default=False)
  14. external_readonly: Mapped[bool] = mapped_column(Boolean, default=False)
  15. external_show_hidden: Mapped[bool] = mapped_column(Boolean, default=False)
  16. external_path: Mapped[str | None] = mapped_column(String(500), nullable=True)
  17. # Link to project or archive
  18. project_id: Mapped[int | None] = mapped_column(ForeignKey("projects.id", ondelete="SET NULL"), nullable=True)
  19. archive_id: Mapped[int | None] = mapped_column(ForeignKey("print_archives.id", ondelete="SET NULL"), nullable=True)
  20. # Timestamps
  21. created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())
  22. updated_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), onupdate=func.now())
  23. # Relationships
  24. parent: Mapped["LibraryFolder | None"] = relationship(
  25. "LibraryFolder",
  26. back_populates="children",
  27. remote_side="LibraryFolder.id",
  28. foreign_keys="LibraryFolder.parent_id",
  29. )
  30. children: Mapped[list["LibraryFolder"]] = relationship(
  31. "LibraryFolder",
  32. back_populates="parent",
  33. foreign_keys="LibraryFolder.parent_id",
  34. cascade="all, delete-orphan",
  35. )
  36. files: Mapped[list["LibraryFile"]] = relationship(
  37. back_populates="folder",
  38. cascade="all, delete-orphan",
  39. )
  40. project: Mapped["Project | None"] = relationship()
  41. archive: Mapped["PrintArchive | None"] = relationship()
  42. class LibraryFile(Base):
  43. """File stored in the library."""
  44. __tablename__ = "library_files"
  45. id: Mapped[int] = mapped_column(primary_key=True)
  46. folder_id: Mapped[int | None] = mapped_column(ForeignKey("library_folders.id", ondelete="CASCADE"), nullable=True)
  47. project_id: Mapped[int | None] = mapped_column(ForeignKey("projects.id", ondelete="SET NULL"), nullable=True)
  48. # External file flag
  49. is_external: Mapped[bool] = mapped_column(Boolean, default=False)
  50. # File info
  51. filename: Mapped[str] = mapped_column(String(255)) # Original filename
  52. file_path: Mapped[str] = mapped_column(String(500)) # Storage path
  53. file_type: Mapped[str] = mapped_column(String(10)) # "3mf" or "gcode"
  54. file_size: Mapped[int] = mapped_column(Integer)
  55. file_hash: Mapped[str | None] = mapped_column(String(64)) # SHA256 for duplicate detection
  56. thumbnail_path: Mapped[str | None] = mapped_column(String(500))
  57. # Extracted metadata (from 3MF parser)
  58. file_metadata: Mapped[dict | None] = mapped_column(JSON)
  59. # Usage tracking
  60. print_count: Mapped[int] = mapped_column(Integer, default=0)
  61. last_printed_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
  62. # User notes
  63. notes: Mapped[str | None] = mapped_column(Text, nullable=True)
  64. # User tracking (Issue #206)
  65. created_by_id: Mapped[int | None] = mapped_column(ForeignKey("users.id", ondelete="SET NULL"), nullable=True)
  66. # Timestamps
  67. created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())
  68. updated_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), onupdate=func.now())
  69. # Relationships
  70. folder: Mapped["LibraryFolder | None"] = relationship(back_populates="files")
  71. project: Mapped["Project | None"] = relationship()
  72. created_by: Mapped["User | None"] = relationship()
  73. from backend.app.models.archive import PrintArchive # noqa: E402, F811
  74. from backend.app.models.project import Project # noqa: E402, F811
  75. from backend.app.models.user import User # noqa: E402, F811