spool.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. from datetime import datetime
  2. from pydantic import BaseModel, Field
  3. class SpoolBase(BaseModel):
  4. material: str = Field(..., min_length=1, max_length=50)
  5. subtype: str | None = None
  6. color_name: str | None = None
  7. rgba: str | None = Field(None, pattern=r"^[0-9A-Fa-f]{8}$")
  8. brand: str | None = None
  9. label_weight: int = 1000
  10. core_weight: int = 250
  11. core_weight_catalog_id: int | None = None
  12. weight_used: float = 0
  13. slicer_filament: str | None = None
  14. slicer_filament_name: str | None = None
  15. nozzle_temp_min: int | None = None
  16. nozzle_temp_max: int | None = None
  17. note: str | None = None
  18. tag_uid: str | None = None
  19. tray_uuid: str | None = None
  20. data_origin: str | None = None
  21. tag_type: str | None = None
  22. cost_per_kg: float | None = Field(default=None, ge=0)
  23. weight_locked: bool = False
  24. last_scale_weight: int | None = None
  25. last_weighed_at: datetime | None = None
  26. # User-defined category + per-spool low-stock threshold override (#729).
  27. category: str | None = Field(default=None, max_length=50)
  28. low_stock_threshold_pct: int | None = Field(default=None, ge=1, le=99)
  29. class SpoolCreate(SpoolBase):
  30. pass
  31. class SpoolBulkCreate(BaseModel):
  32. spool: SpoolCreate
  33. quantity: int = Field(default=1, ge=1, le=100)
  34. class SpoolUpdate(BaseModel):
  35. material: str | None = None
  36. subtype: str | None = None
  37. color_name: str | None = None
  38. rgba: str | None = Field(None, pattern=r"^[0-9A-Fa-f]{8}$")
  39. brand: str | None = None
  40. label_weight: int | None = None
  41. core_weight: int | None = None
  42. core_weight_catalog_id: int | None = None
  43. weight_used: float | None = None
  44. slicer_filament: str | None = None
  45. slicer_filament_name: str | None = None
  46. nozzle_temp_min: int | None = None
  47. nozzle_temp_max: int | None = None
  48. note: str | None = None
  49. tag_uid: str | None = None
  50. tray_uuid: str | None = None
  51. data_origin: str | None = None
  52. tag_type: str | None = None
  53. cost_per_kg: float | None = Field(default=None, ge=0)
  54. weight_locked: bool | None = None
  55. # User-defined category + per-spool low-stock threshold override (#729).
  56. category: str | None = Field(default=None, max_length=50)
  57. low_stock_threshold_pct: int | None = Field(default=None, ge=1, le=99)
  58. class SpoolKProfileBase(BaseModel):
  59. printer_id: int
  60. extruder: int = 0
  61. nozzle_diameter: str = "0.4"
  62. nozzle_type: str | None = None
  63. k_value: float
  64. name: str | None = None
  65. cali_idx: int | None = None
  66. setting_id: str | None = None
  67. class SpoolKProfileResponse(SpoolKProfileBase):
  68. id: int
  69. spool_id: int
  70. created_at: datetime
  71. class Config:
  72. from_attributes = True
  73. class SpoolResponse(SpoolBase):
  74. id: int
  75. # rgba is intentionally unconstrained on the response side: the write paths
  76. # (SpoolCreate, SpoolUpdate) enforce the 8-char hex pattern, but legacy rows
  77. # or data sourced from AMS firmware / backups may carry malformed values.
  78. # A single bad row must not 500 the entire inventory list endpoint (#1055).
  79. rgba: str | None = None
  80. added_full: bool | None = None
  81. last_used: datetime | None = None
  82. encode_time: datetime | None = None
  83. tag_uid: str | None = None
  84. tray_uuid: str | None = None
  85. data_origin: str | None = None
  86. tag_type: str | None = None
  87. archived_at: datetime | None = None
  88. created_at: datetime
  89. updated_at: datetime
  90. k_profiles: list[SpoolKProfileResponse] = []
  91. class Config:
  92. from_attributes = True
  93. class SpoolAssignmentCreate(BaseModel):
  94. spool_id: int
  95. printer_id: int
  96. ams_id: int
  97. tray_id: int
  98. class SpoolAssignmentResponse(BaseModel):
  99. id: int
  100. spool_id: int
  101. printer_id: int
  102. printer_name: str | None = None
  103. ams_id: int
  104. tray_id: int
  105. fingerprint_color: str | None = None
  106. fingerprint_type: str | None = None
  107. created_at: datetime
  108. spool: SpoolResponse | None = None
  109. configured: bool = False
  110. ams_label: str | None = None # User-defined friendly name for the AMS unit
  111. class Config:
  112. from_attributes = True