filaments.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. from fastapi import APIRouter, Depends, HTTPException
  2. from sqlalchemy import select
  3. from sqlalchemy.ext.asyncio import AsyncSession
  4. from backend.app.core.database import get_db
  5. from backend.app.models.filament import Filament
  6. from backend.app.schemas.filament import (
  7. FilamentCostCalculation,
  8. FilamentCreate,
  9. FilamentResponse,
  10. FilamentUpdate,
  11. )
  12. router = APIRouter(prefix="/filaments", tags=["filaments"])
  13. @router.get("/", response_model=list[FilamentResponse])
  14. async def list_filaments(db: AsyncSession = Depends(get_db)):
  15. """List all filaments."""
  16. result = await db.execute(select(Filament).order_by(Filament.type, Filament.name))
  17. return list(result.scalars().all())
  18. @router.post("/", response_model=FilamentResponse)
  19. async def create_filament(
  20. filament_data: FilamentCreate,
  21. db: AsyncSession = Depends(get_db),
  22. ):
  23. """Create a new filament entry."""
  24. filament = Filament(**filament_data.model_dump())
  25. db.add(filament)
  26. await db.commit()
  27. await db.refresh(filament)
  28. return filament
  29. @router.get("/{filament_id}", response_model=FilamentResponse)
  30. async def get_filament(filament_id: int, db: AsyncSession = Depends(get_db)):
  31. """Get a specific filament."""
  32. result = await db.execute(select(Filament).where(Filament.id == filament_id))
  33. filament = result.scalar_one_or_none()
  34. if not filament:
  35. raise HTTPException(404, "Filament not found")
  36. return filament
  37. @router.patch("/{filament_id}", response_model=FilamentResponse)
  38. async def update_filament(
  39. filament_id: int,
  40. filament_data: FilamentUpdate,
  41. db: AsyncSession = Depends(get_db),
  42. ):
  43. """Update a filament."""
  44. result = await db.execute(select(Filament).where(Filament.id == filament_id))
  45. filament = result.scalar_one_or_none()
  46. if not filament:
  47. raise HTTPException(404, "Filament not found")
  48. for field, value in filament_data.model_dump(exclude_unset=True).items():
  49. setattr(filament, field, value)
  50. await db.commit()
  51. await db.refresh(filament)
  52. return filament
  53. @router.delete("/{filament_id}")
  54. async def delete_filament(filament_id: int, db: AsyncSession = Depends(get_db)):
  55. """Delete a filament."""
  56. result = await db.execute(select(Filament).where(Filament.id == filament_id))
  57. filament = result.scalar_one_or_none()
  58. if not filament:
  59. raise HTTPException(404, "Filament not found")
  60. await db.delete(filament)
  61. await db.commit()
  62. return {"status": "deleted"}
  63. @router.post("/calculate-cost", response_model=FilamentCostCalculation)
  64. async def calculate_cost(
  65. filament_id: int,
  66. weight_grams: float,
  67. db: AsyncSession = Depends(get_db),
  68. ):
  69. """Calculate the cost for a given weight of filament."""
  70. result = await db.execute(select(Filament).where(Filament.id == filament_id))
  71. filament = result.scalar_one_or_none()
  72. if not filament:
  73. raise HTTPException(404, "Filament not found")
  74. cost = (weight_grams / 1000) * filament.cost_per_kg
  75. return FilamentCostCalculation(
  76. filament_id=filament.id,
  77. filament_name=filament.name,
  78. weight_grams=weight_grams,
  79. cost=round(cost, 2),
  80. currency=filament.currency,
  81. )
  82. @router.get("/by-type/{filament_type}", response_model=list[FilamentResponse])
  83. async def get_filaments_by_type(
  84. filament_type: str,
  85. db: AsyncSession = Depends(get_db),
  86. ):
  87. """Get all filaments of a specific type."""
  88. result = await db.execute(select(Filament).where(Filament.type.ilike(f"%{filament_type}%")).order_by(Filament.name))
  89. return list(result.scalars().all())
  90. @router.post("/seed-defaults")
  91. async def seed_default_filaments(db: AsyncSession = Depends(get_db)):
  92. """Seed the database with common filament types."""
  93. defaults = [
  94. {
  95. "name": "Generic PLA",
  96. "type": "PLA",
  97. "cost_per_kg": 20.0,
  98. "print_temp_min": 190,
  99. "print_temp_max": 220,
  100. "bed_temp_min": 50,
  101. "bed_temp_max": 60,
  102. "density": 1.24,
  103. },
  104. {
  105. "name": "Generic PETG",
  106. "type": "PETG",
  107. "cost_per_kg": 25.0,
  108. "print_temp_min": 230,
  109. "print_temp_max": 250,
  110. "bed_temp_min": 70,
  111. "bed_temp_max": 80,
  112. "density": 1.27,
  113. },
  114. {
  115. "name": "Generic ABS",
  116. "type": "ABS",
  117. "cost_per_kg": 22.0,
  118. "print_temp_min": 230,
  119. "print_temp_max": 260,
  120. "bed_temp_min": 90,
  121. "bed_temp_max": 110,
  122. "density": 1.04,
  123. },
  124. {
  125. "name": "Generic TPU",
  126. "type": "TPU",
  127. "cost_per_kg": 35.0,
  128. "print_temp_min": 220,
  129. "print_temp_max": 250,
  130. "bed_temp_min": 40,
  131. "bed_temp_max": 60,
  132. "density": 1.21,
  133. },
  134. {
  135. "name": "Generic ASA",
  136. "type": "ASA",
  137. "cost_per_kg": 28.0,
  138. "print_temp_min": 240,
  139. "print_temp_max": 260,
  140. "bed_temp_min": 90,
  141. "bed_temp_max": 110,
  142. "density": 1.07,
  143. },
  144. {
  145. "name": "Bambu PLA Basic",
  146. "type": "PLA",
  147. "brand": "Bambu Lab",
  148. "cost_per_kg": 20.0,
  149. "print_temp_min": 190,
  150. "print_temp_max": 220,
  151. "bed_temp_min": 35,
  152. "bed_temp_max": 55,
  153. "density": 1.24,
  154. },
  155. {
  156. "name": "Bambu PLA Matte",
  157. "type": "PLA",
  158. "brand": "Bambu Lab",
  159. "cost_per_kg": 25.0,
  160. "print_temp_min": 190,
  161. "print_temp_max": 220,
  162. "bed_temp_min": 35,
  163. "bed_temp_max": 55,
  164. "density": 1.24,
  165. },
  166. {
  167. "name": "Bambu PETG Basic",
  168. "type": "PETG",
  169. "brand": "Bambu Lab",
  170. "cost_per_kg": 25.0,
  171. "print_temp_min": 250,
  172. "print_temp_max": 270,
  173. "bed_temp_min": 70,
  174. "bed_temp_max": 80,
  175. "density": 1.27,
  176. },
  177. {
  178. "name": "Bambu ABS",
  179. "type": "ABS",
  180. "brand": "Bambu Lab",
  181. "cost_per_kg": 30.0,
  182. "print_temp_min": 260,
  183. "print_temp_max": 280,
  184. "bed_temp_min": 90,
  185. "bed_temp_max": 100,
  186. "density": 1.04,
  187. },
  188. ]
  189. created = 0
  190. for filament_data in defaults:
  191. # Check if already exists
  192. result = await db.execute(
  193. select(Filament).where(
  194. Filament.name == filament_data["name"],
  195. Filament.type == filament_data["type"],
  196. )
  197. )
  198. if result.scalar_one_or_none():
  199. continue
  200. filament = Filament(**filament_data)
  201. db.add(filament)
  202. created += 1
  203. await db.commit()
  204. return {"created": created, "message": f"Created {created} default filaments"}