from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy import text from sqlalchemy.orm import Session from typing import Any from app.database import get_session from app.auth import get_current_user router = APIRouter() def _row(r) -> dict: return dict(r._mapping) @router.get("") def list_inspections( colony_id: int = Query(...), session: Session = Depends(get_session), _: str = Depends(get_current_user), ) -> list[dict]: rows = session.execute(text(""" SELECT * FROM inspections WHERE colony_id = :colony_id ORDER BY date::DATE DESC, id DESC """), {"colony_id": colony_id}).fetchall() return [_row(r) for r in rows] @router.get("/last") def last_inspection( colony_id: int = Query(...), session: Session = Depends(get_session), _: str = Depends(get_current_user), ): row = session.execute(text(""" SELECT * FROM inspections WHERE colony_id = :colony_id ORDER BY date::DATE DESC, id DESC LIMIT 1 """), {"colony_id": colony_id}).fetchone() if row is None: return None return _row(row) @router.get("/{id}/traits") def inspection_traits( id: int, session: Session = Depends(get_session), _: str = Depends(get_current_user), ) -> list[dict]: rows = session.execute(text(""" SELECT * FROM inspection_traits WHERE inspection_id = :id """), {"id": id}).fetchall() return [_row(r) for r in rows] @router.get("/{id}") def get_inspection( id: int, session: Session = Depends(get_session), _: str = Depends(get_current_user), ) -> dict: row = session.execute( text("SELECT * FROM inspections WHERE id = :id"), {"id": id} ).fetchone() if row is None: raise HTTPException(status_code=404, detail="Not found") return _row(row) @router.post("", status_code=201) def create_inspection( body: dict[str, Any], session: Session = Depends(get_session), _: str = Depends(get_current_user), ) -> dict: row = session.execute(text(""" INSERT INTO inspections (colony_id, date, inspector, brood_frames, honey_frames, food_stores_kg, colony_strength, queen_seen, eggs_seen, queen_cells_count, notes) VALUES (:colony_id, :date, :inspector, :brood_frames, :honey_frames, :food_stores_kg, :colony_strength, :queen_seen, :eggs_seen, :queen_cells_count, :notes) RETURNING * """), { "colony_id": body.get("colony_id"), "date": body.get("date"), "inspector": body.get("inspector"), "brood_frames": body.get("brood_frames"), "honey_frames": body.get("honey_frames"), "food_stores_kg": body.get("food_stores_kg"), "colony_strength": body.get("colony_strength"), "queen_seen": int(body.get("queen_seen", 0)), "eggs_seen": int(body.get("eggs_seen", 0)), "queen_cells_count": int(body.get("queen_cells_count", 0)), "notes": body.get("notes"), }).fetchone() inspection_id = row._mapping["id"] traits = body.get("traits", {}) for trait, score in (traits or {}).items(): if score is not None: session.execute(text(""" INSERT INTO inspection_traits (inspection_id, trait, score) VALUES (:inspection_id, :trait, :score) """), {"inspection_id": inspection_id, "trait": trait, "score": int(score)}) session.commit() return _row(row) @router.put("/{id}") def update_inspection( id: int, body: dict[str, Any], session: Session = Depends(get_session), _: str = Depends(get_current_user), ) -> dict: result = session.execute(text(""" UPDATE inspections SET date = :date, inspector = :inspector, brood_frames = :brood_frames, honey_frames = :honey_frames, food_stores_kg = :food_stores_kg, colony_strength = :colony_strength, queen_seen = :queen_seen, eggs_seen = :eggs_seen, queen_cells_count = :queen_cells_count, notes = :notes WHERE id = :id RETURNING * """), { "id": id, "date": body.get("date"), "inspector": body.get("inspector"), "brood_frames": body.get("brood_frames"), "honey_frames": body.get("honey_frames"), "food_stores_kg": body.get("food_stores_kg"), "colony_strength": body.get("colony_strength"), "queen_seen": int(body.get("queen_seen", 0)), "eggs_seen": int(body.get("eggs_seen", 0)), "queen_cells_count": int(body.get("queen_cells_count", 0)), "notes": body.get("notes"), }).fetchone() if result is None: raise HTTPException(status_code=404, detail="Not found") session.execute( text("DELETE FROM inspection_traits WHERE inspection_id = :id"), {"id": id} ) traits = body.get("traits", {}) for trait, score in (traits or {}).items(): if score is not None: session.execute(text(""" INSERT INTO inspection_traits (inspection_id, trait, score) VALUES (:inspection_id, :trait, :score) """), {"inspection_id": id, "trait": trait, "score": int(score)}) session.commit() return _row(result) @router.delete("/{id}", status_code=204) def delete_inspection( id: int, session: Session = Depends(get_session), _: str = Depends(get_current_user), ): session.execute(text("DELETE FROM inspections WHERE id = :id"), {"id": id}) session.commit()