routes.py 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. from __future__ import annotations
  2. from pathlib import Path
  3. from fastapi import APIRouter, Depends, File, Form, HTTPException, Request, UploadFile
  4. from fastapi.responses import HTMLResponse
  5. from fastapi.templating import Jinja2Templates
  6. from bom_assistant.api.store import SessionStore, get_store
  7. from bom_assistant.scouting.ingest import build_session
  8. from bom_assistant.scouting.orchestrator import apply_filter, confirm_category, confirm_pick, scout_row
  9. router = APIRouter()
  10. templates = Jinja2Templates(directory=str(Path(__file__).parent / "templates"))
  11. @router.get("/", response_class=HTMLResponse)
  12. def index(request: Request) -> HTMLResponse:
  13. return templates.TemplateResponse(request, "index.html", {})
  14. @router.post("/upload", response_class=HTMLResponse)
  15. def upload(
  16. request: Request,
  17. file: UploadFile = File(...),
  18. store: SessionStore = Depends(get_store),
  19. ) -> HTMLResponse:
  20. content = file.file.read()
  21. try:
  22. session = build_session(content, file.filename or "upload")
  23. except Exception as exc:
  24. raise HTTPException(status_code=400, detail=f"failed to parse BOM: {exc}") from exc
  25. store.create(session)
  26. return templates.TemplateResponse(request, "_rows.html", {"session": session})
  27. @router.get("/session/{session_id}/row/{row_id}/scout", response_class=HTMLResponse)
  28. def scout(
  29. request: Request,
  30. session_id: str,
  31. row_id: str,
  32. store: SessionStore = Depends(get_store),
  33. ) -> HTMLResponse:
  34. session = store.get(session_id)
  35. row = scout_row(session, row_id)
  36. store.save(session)
  37. return templates.TemplateResponse(request, "_scout_result.html", {"session_id": session_id, "row": row})
  38. @router.post("/session/{session_id}/row/{row_id}/confirm-category", response_class=HTMLResponse)
  39. def confirm_category_route(
  40. request: Request,
  41. session_id: str,
  42. row_id: str,
  43. category_id: int = Form(...),
  44. category_name: str = Form(...),
  45. store: SessionStore = Depends(get_store),
  46. ) -> HTMLResponse:
  47. session = store.get(session_id)
  48. row = confirm_category(session, row_id, category_id, category_name)
  49. store.save(session)
  50. return templates.TemplateResponse(request, "_filtering.html", {"session_id": session_id, "row": row})
  51. @router.post("/session/{session_id}/row/{row_id}/apply-filter", response_class=HTMLResponse)
  52. def apply_filter_route(
  53. request: Request,
  54. session_id: str,
  55. row_id: str,
  56. group: str = Form(...),
  57. value: str = Form(...),
  58. store: SessionStore = Depends(get_store),
  59. ) -> HTMLResponse:
  60. session = store.get(session_id)
  61. row = apply_filter(session, row_id, group, value)
  62. store.save(session)
  63. return templates.TemplateResponse(request, "_filtering.html", {"session_id": session_id, "row": row})
  64. @router.post("/session/{session_id}/row/{row_id}/confirm", response_class=HTMLResponse)
  65. def confirm_route(
  66. request: Request,
  67. session_id: str,
  68. row_id: str,
  69. product_code: str = Form(...),
  70. store: SessionStore = Depends(get_store),
  71. ) -> HTMLResponse:
  72. session = store.get(session_id)
  73. row = confirm_pick(session, row_id, product_code)
  74. store.save(session)
  75. return templates.TemplateResponse(request, "_confirmed.html", {"row": row})