experience.py 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. """Experience case API router (basic CRUD for Phase 2)."""
  2. import json
  3. from fastapi import APIRouter, Depends, HTTPException, Query
  4. from sqlalchemy.orm import Session
  5. from ..database import get_db
  6. from ..models.experience_case import ExperienceCase
  7. router = APIRouter(prefix="/api/experience", tags=["experience"])
  8. def _case_to_dict(case: ExperienceCase) -> dict:
  9. return {
  10. "id": case.id,
  11. "source_plan_id": case.source_plan_id or "",
  12. "topology": case.topology or "SSSR",
  13. "model_path": case.model_path or "",
  14. "params": case.get_params(),
  15. "metrics": case.get_metrics(),
  16. "conclusion": case.conclusion or "",
  17. "tags": [t.strip() for t in (case.tags or "").split(",") if t.strip()],
  18. "rating": case.rating or 0,
  19. "created_at": case.created_at,
  20. }
  21. @router.get("")
  22. def list_experience(
  23. topology: str | None = None,
  24. tag: str | None = None,
  25. skip: int = 0,
  26. limit: int = 50,
  27. db: Session = Depends(get_db),
  28. ):
  29. """List experience cases with filters."""
  30. query = db.query(ExperienceCase)
  31. if topology:
  32. query = query.filter(ExperienceCase.topology == topology)
  33. if tag:
  34. query = query.filter(ExperienceCase.tags.contains(tag))
  35. total = query.count()
  36. cases = query.order_by(ExperienceCase.created_at.desc()).offset(skip).limit(limit).all()
  37. return {"total": total, "items": [_case_to_dict(c) for c in cases]}
  38. @router.post("", status_code=201)
  39. def create_experience(
  40. data: dict,
  41. db: Session = Depends(get_db),
  42. ):
  43. """Create an experience case from a dict."""
  44. case = ExperienceCase(
  45. source_plan_id=data.get("source_plan_id", ""),
  46. topology=data.get("topology", "SSSR"),
  47. model_path=data.get("model_path", ""),
  48. conclusion=data.get("conclusion", ""),
  49. tags=",".join(data.get("tags", [])),
  50. rating=data.get("rating", 0),
  51. )
  52. case.params_json = json.dumps(data.get("params", {}), ensure_ascii=False)
  53. case.metrics_json = json.dumps(data.get("metrics", {}), ensure_ascii=False)
  54. db.add(case)
  55. db.commit()
  56. db.refresh(case)
  57. return _case_to_dict(case)
  58. @router.get("/{case_id}")
  59. def get_experience(case_id: int, db: Session = Depends(get_db)):
  60. """Get an experience case by ID."""
  61. case = db.query(ExperienceCase).filter(ExperienceCase.id == case_id).first()
  62. if not case:
  63. raise HTTPException(status_code=404, detail="Experience case not found")
  64. return _case_to_dict(case)
  65. @router.delete("/{case_id}", status_code=204)
  66. def delete_experience(case_id: int, db: Session = Depends(get_db)):
  67. """Delete an experience case."""
  68. case = db.query(ExperienceCase).filter(ExperienceCase.id == case_id).first()
  69. if not case:
  70. raise HTTPException(status_code=404, detail="Experience case not found")
  71. db.delete(case)
  72. db.commit()
  73. return None