archive.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. from datetime import datetime
  2. from pydantic import BaseModel
  3. class ArchiveBase(BaseModel):
  4. print_name: str | None = None
  5. is_favorite: bool | None = None
  6. tags: str | None = None
  7. notes: str | None = None
  8. cost: float | None = None
  9. failure_reason: str | None = None
  10. class ArchiveUpdate(ArchiveBase):
  11. printer_id: int | None = None
  12. class ArchiveDuplicate(BaseModel):
  13. """Reference to a duplicate archive."""
  14. id: int
  15. print_name: str | None
  16. created_at: datetime
  17. match_type: str # "exact" (hash match) or "similar" (name match)
  18. class ArchiveResponse(BaseModel):
  19. id: int
  20. printer_id: int | None
  21. filename: str
  22. file_path: str
  23. file_size: int
  24. content_hash: str | None
  25. thumbnail_path: str | None
  26. timelapse_path: str | None
  27. # Duplicate detection
  28. duplicates: list[ArchiveDuplicate] | None = None
  29. duplicate_count: int = 0 # Quick count for list views
  30. print_name: str | None
  31. print_time_seconds: int | None # Estimated time from slicer
  32. actual_time_seconds: int | None = None # Computed from started_at/completed_at
  33. time_accuracy: float | None = None # Percentage: 100 = perfect, >100 = faster than estimated
  34. filament_used_grams: float | None
  35. filament_type: str | None
  36. filament_color: str | None
  37. layer_height: float | None
  38. nozzle_diameter: float | None
  39. bed_temperature: int | None
  40. nozzle_temperature: int | None
  41. status: str
  42. started_at: datetime | None
  43. completed_at: datetime | None
  44. extra_data: dict | None
  45. makerworld_url: str | None
  46. designer: str | None
  47. is_favorite: bool
  48. tags: str | None
  49. notes: str | None
  50. cost: float | None
  51. photos: list | None
  52. failure_reason: str | None
  53. created_at: datetime
  54. class Config:
  55. from_attributes = True
  56. class ArchiveStats(BaseModel):
  57. total_prints: int
  58. successful_prints: int
  59. failed_prints: int
  60. total_print_time_hours: float
  61. total_filament_grams: float
  62. total_cost: float
  63. prints_by_filament_type: dict
  64. prints_by_printer: dict
  65. # Time accuracy stats
  66. average_time_accuracy: float | None = None # Average across all prints with data
  67. time_accuracy_by_printer: dict | None = None # Per-printer accuracy
  68. class ProjectPageImage(BaseModel):
  69. """Image embedded in 3MF project page."""
  70. name: str
  71. path: str # Path within 3MF
  72. url: str # API URL to fetch image
  73. class ProjectPageResponse(BaseModel):
  74. """Project page data extracted from 3MF file."""
  75. # Model info
  76. title: str | None = None
  77. description: str | None = None # HTML content
  78. designer: str | None = None
  79. designer_user_id: str | None = None
  80. license: str | None = None
  81. copyright: str | None = None
  82. creation_date: str | None = None
  83. modification_date: str | None = None
  84. origin: str | None = None # "original" or "remix"
  85. # Profile info
  86. profile_title: str | None = None
  87. profile_description: str | None = None
  88. profile_cover: str | None = None
  89. profile_user_id: str | None = None
  90. profile_user_name: str | None = None
  91. # MakerWorld info
  92. design_model_id: str | None = None
  93. design_profile_id: str | None = None
  94. design_region: str | None = None
  95. # Images
  96. model_pictures: list[ProjectPageImage] = []
  97. profile_pictures: list[ProjectPageImage] = []
  98. thumbnails: list[ProjectPageImage] = []
  99. class ProjectPageUpdate(BaseModel):
  100. """Update project page data in 3MF file."""
  101. title: str | None = None
  102. description: str | None = None
  103. designer: str | None = None
  104. license: str | None = None
  105. copyright: str | None = None
  106. profile_title: str | None = None
  107. profile_description: str | None = None