91 lines
2.9 KiB
Python
91 lines
2.9 KiB
Python
"""
|
|
CRUD for the lamp catalog. Each Aid references a lamp by id; the lamp's
|
|
voltage_min / voltage_max determine that aid's battery warning/alarm
|
|
thresholds (see compute_thresholds).
|
|
"""
|
|
from fastapi import APIRouter, Depends, HTTPException
|
|
from pydantic import BaseModel, Field
|
|
from sqlalchemy.orm import Session
|
|
from typing import Optional
|
|
import uuid
|
|
|
|
from database import get_db
|
|
from models.lamp import Lamp
|
|
from models.aid import Aid
|
|
|
|
router = APIRouter(prefix="/lamps", tags=["lamps"])
|
|
|
|
|
|
class LampIn(BaseModel):
|
|
manufacturer: str
|
|
model: str
|
|
lamp_count: int = 1
|
|
voltage_min: float = Field(..., gt=0)
|
|
voltage_max: float = Field(..., gt=0)
|
|
notes: Optional[str] = None
|
|
|
|
|
|
def compute_thresholds(vmin: float, vmax: float) -> dict:
|
|
rng = vmax - vmin
|
|
return {
|
|
"warn_v": round(vmin + rng * 0.20, 3),
|
|
"alarm_v": round(vmin + rng * 0.10, 3),
|
|
}
|
|
|
|
|
|
def _lamp_dict(l: Lamp) -> dict:
|
|
th = compute_thresholds(l.voltage_min, l.voltage_max)
|
|
return {
|
|
"id": l.id,
|
|
"manufacturer": l.manufacturer,
|
|
"model": l.model,
|
|
"lamp_count": l.lamp_count,
|
|
"voltage_min": l.voltage_min,
|
|
"voltage_max": l.voltage_max,
|
|
"notes": l.notes,
|
|
"warn_v": th["warn_v"],
|
|
"alarm_v": th["alarm_v"],
|
|
}
|
|
|
|
|
|
@router.get("/")
|
|
def list_lamps(db: Session = Depends(get_db)):
|
|
return [_lamp_dict(l) for l in db.query(Lamp).order_by(Lamp.manufacturer, Lamp.model).all()]
|
|
|
|
|
|
@router.post("/")
|
|
def create_lamp(data: LampIn, db: Session = Depends(get_db)):
|
|
if data.voltage_max <= data.voltage_min:
|
|
raise HTTPException(400, "voltage_max must be greater than voltage_min")
|
|
lamp = Lamp(id=str(uuid.uuid4()), **data.model_dump())
|
|
db.add(lamp)
|
|
db.commit(); db.refresh(lamp)
|
|
return _lamp_dict(lamp)
|
|
|
|
|
|
@router.put("/{lamp_id}")
|
|
def update_lamp(lamp_id: str, data: LampIn, db: Session = Depends(get_db)):
|
|
lamp = db.query(Lamp).filter(Lamp.id == lamp_id).first()
|
|
if not lamp:
|
|
raise HTTPException(404, "Lamp not found")
|
|
if data.voltage_max <= data.voltage_min:
|
|
raise HTTPException(400, "voltage_max must be greater than voltage_min")
|
|
for k, v in data.model_dump().items():
|
|
setattr(lamp, k, v)
|
|
db.commit(); db.refresh(lamp)
|
|
return _lamp_dict(lamp)
|
|
|
|
|
|
@router.delete("/{lamp_id}")
|
|
def delete_lamp(lamp_id: str, force: bool = False, db: Session = Depends(get_db)):
|
|
in_use = db.query(Aid).filter(Aid.lamp_id == lamp_id).count()
|
|
if in_use and not force:
|
|
# Frontend will retry with force=true after user confirms
|
|
raise HTTPException(409, f"Lamp is in use by {in_use} aid(s)")
|
|
if in_use and force:
|
|
# Unassign all aids that point at this lamp
|
|
db.query(Aid).filter(Aid.lamp_id == lamp_id).update({"lamp_id": None})
|
|
db.query(Lamp).filter(Lamp.id == lamp_id).delete()
|
|
db.commit()
|
|
return {"deleted": lamp_id, "unassigned_from": in_use}
|