Files
miem_workers/app/api.py

114 lines
3.6 KiB
Python

from fastapi import APIRouter, BackgroundTasks, Depends, Request
from sqlalchemy import desc, or_, select
from sqlalchemy.orm import Session
from app.config import Settings, get_settings
from app.db import SessionLocal, get_db
from app.models import CrawlRun, Employee
from app.security import require_admin
from app.services.crawler import run_crawl
from app.version import BACKEND_VERSION, FRONTEND_VERSION
router = APIRouter(prefix="/api")
@router.get("/health")
def health() -> dict:
return {"status": "ok", "backend_version": BACKEND_VERSION, "frontend_version": FRONTEND_VERSION}
@router.get("/employees")
def list_employees(
request: Request,
status: str | None = None,
q: str | None = None,
limit: int = 50,
offset: int = 0,
db: Session = Depends(get_db),
settings: Settings = Depends(get_settings),
) -> dict:
require_admin(request, settings)
stmt = select(Employee)
if status:
stmt = stmt.where(Employee.status == status)
if q:
pattern = f"%{q}%"
stmt = stmt.where(or_(Employee.full_name.ilike(pattern), Employee.canonical_url.ilike(pattern)))
employees = db.scalars(stmt.order_by(Employee.full_name).limit(limit).offset(offset)).all()
return {"items": [_employee_summary(item) for item in employees], "limit": limit, "offset": offset}
@router.get("/employees/{employee_id}")
def get_employee(
employee_id: int,
request: Request,
db: Session = Depends(get_db),
settings: Settings = Depends(get_settings),
) -> dict:
require_admin(request, settings)
employee = db.get(Employee, employee_id)
if not employee:
return {"error": "not_found"}
return _employee_detail(employee)
@router.get("/crawl-runs")
def list_crawl_runs(
request: Request,
limit: int = 20,
db: Session = Depends(get_db),
settings: Settings = Depends(get_settings),
) -> dict:
require_admin(request, settings)
runs = db.scalars(select(CrawlRun).order_by(desc(CrawlRun.started_at)).limit(limit)).all()
return {"items": [_run_summary(run) for run in runs]}
@router.post("/crawl-runs")
def trigger_crawl(
request: Request,
background_tasks: BackgroundTasks,
settings: Settings = Depends(get_settings),
) -> dict:
require_admin(request, settings)
def _crawl() -> None:
with SessionLocal() as db:
run_crawl(db, settings)
background_tasks.add_task(_crawl)
return {"status": "scheduled"}
def _employee_summary(employee: Employee) -> dict:
return {
"id": employee.id,
"full_name": employee.full_name,
"status": employee.status,
"canonical_url": employee.canonical_url,
"last_seen_at": employee.last_seen_at.isoformat() if employee.last_seen_at else None,
"dismissed_at": employee.dismissed_at.isoformat() if employee.dismissed_at else None,
}
def _employee_detail(employee: Employee) -> dict:
data = _employee_summary(employee)
data["current_data"] = employee.current_data
data["tabs"] = [{"title": tab.title, "href": tab.href, "data_index": tab.data_index} for tab in employee.tabs]
return data
def _run_summary(run: CrawlRun) -> dict:
return {
"id": run.id,
"source_url": run.source_url,
"status": run.status,
"started_at": run.started_at.isoformat() if run.started_at else None,
"finished_at": run.finished_at.isoformat() if run.finished_at else None,
"found_count": run.found_count,
"parsed_count": run.parsed_count,
"error_count": run.error_count,
"dismissed_count": run.dismissed_count,
"message": run.message,
}