Files
foodlinkk-command-center/documents.py
T

97 lines
3.0 KiB
Python
Raw Normal View History

from pathlib import Path
from fastapi import APIRouter, Request
from fastapi.templating import Jinja2Templates
from app.db import fetch_all, fetch_one
router = APIRouter(prefix="/documents", tags=["documents"])
BASE_DIR = Path(__file__).resolve().parent.parent.parent
templates = Jinja2Templates(directory=str(BASE_DIR / "templates"))
def _iso_rows(rows: list) -> list:
for row in rows:
for key, val in list(row.items()):
if hasattr(val, "isoformat"):
row[key] = val.isoformat()
return rows
@router.get("")
async def documents_page(request: Request):
summary = {
"documents": 0,
"total_words": 0,
"unique_words": 0,
"avg_sentiment": 0.0,
"positive": 0,
"neutral": 0,
"negative": 0,
}
try:
row = fetch_one(
"""
SELECT COUNT(*) AS docs,
COALESCE(SUM(word_count), 0) AS words,
COALESCE(AVG(sentiment_compound), 0) AS avg_sent
FROM document_analytics
"""
)
if row:
summary["documents"] = int(row["docs"] or 0)
summary["total_words"] = int(row["words"] or 0)
summary["avg_sentiment"] = round(float(row["avg_sent"] or 0), 3)
row = fetch_one("SELECT COUNT(DISTINCT lemma) AS c FROM document_word_counts WHERE NOT is_stopword")
summary["unique_words"] = int(row["c"] or 0) if row else 0
for label in ("positive", "neutral", "negative"):
row = fetch_one(
"SELECT COUNT(*) AS c FROM document_analytics WHERE sentiment_label = %s",
(label,),
)
summary[label] = int(row["c"] or 0) if row else 0
except Exception:
pass
top_words: list = []
documents: list = []
try:
top_words = fetch_all(
"""
SELECT lemma, MAX(token) AS token, SUM(count) AS total_count,
COUNT(DISTINCT storage_path) AS doc_count
FROM document_word_counts
WHERE NOT is_stopword
GROUP BY lemma
ORDER BY total_count DESC
LIMIT 30
"""
)
documents = _iso_rows(
fetch_all(
"""
SELECT filename, storage_path, doc_type, language, word_count,
unique_lemmas, sentiment_label, sentiment_compound,
sentiment_positive, sentiment_negative, sentiment_neutral,
extraction_method, analyzed_at,
COALESCE(user_labels, '{}') AS user_labels, label_notes, labeled_at
FROM document_analytics
ORDER BY analyzed_at DESC
LIMIT 50
"""
)
)
except Exception:
pass
return templates.TemplateResponse(
"documents.html",
{
"request": request,
"page_title": "Documents & Sentiment",
"summary": summary,
"top_words": top_words,
"documents": documents,
},
)