init
This commit is contained in:
121 files changed
+17641
No files matched your search
@@ -0,0 +1,100 @@
|
||||
"""Report and statistics endpoints."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import date, timedelta
|
||||
|
||||
from fastapi import APIRouter, Query
|
||||
|
||||
from app.api.deps import DbSession, Settings
|
||||
from app.api.schemas import SendReportRequest, TestNotificationRequest
|
||||
from app.services import notify as notify_service
|
||||
from app.services import report, scheduler, stats
|
||||
from app.timeutil import ensure_utc, local_date
|
||||
|
||||
router = APIRouter(prefix="/api", tags=["reports"])
|
||||
|
||||
|
||||
@router.get("/reports/daily")
|
||||
def daily(
|
||||
session: DbSession,
|
||||
settings: Settings,
|
||||
day: date | None = Query(default=None),
|
||||
rebuild: bool = Query(default=True),
|
||||
) -> dict:
|
||||
target = day or local_date(settings.timezone)
|
||||
row, payload = report.get_or_build_daily(session, settings, target, rebuild=rebuild)
|
||||
return {
|
||||
"report": payload,
|
||||
"sent_at": ensure_utc(row.sent_at).isoformat() if row.sent_at else None,
|
||||
"telegram_preview": report.render_daily_telegram(payload, settings),
|
||||
}
|
||||
|
||||
|
||||
@router.post("/reports/daily/send")
|
||||
def send_daily(body: SendReportRequest, session: DbSession, settings: Settings) -> dict:
|
||||
target = body.report_date or local_date(settings.timezone)
|
||||
return report.send_daily(session, settings, target, force=body.force)
|
||||
|
||||
|
||||
@router.get("/reports/weekly")
|
||||
def weekly(
|
||||
session: DbSession,
|
||||
settings: Settings,
|
||||
end: date | None = Query(default=None),
|
||||
) -> dict:
|
||||
target = end or local_date(settings.timezone)
|
||||
payload = report.build_weekly(session, settings, target)
|
||||
return {"report": payload, "telegram_preview": report.render_weekly_telegram(payload, settings)}
|
||||
|
||||
|
||||
@router.post("/reports/weekly/send")
|
||||
def send_weekly(session: DbSession, settings: Settings) -> dict:
|
||||
payload = report.build_weekly(session, settings, local_date(settings.timezone))
|
||||
text = report.render_weekly_telegram(payload, settings)
|
||||
deliveries = notify_service.notify(settings, text, urgent=True)
|
||||
return {"sent": any(d.ok for d in deliveries), "deliveries": [d.as_dict() for d in deliveries]}
|
||||
|
||||
|
||||
@router.post("/reports/briefing/send")
|
||||
def send_briefing(session: DbSession, settings: Settings) -> dict:
|
||||
text = report.render_morning_briefing(session, settings)
|
||||
deliveries = notify_service.notify(settings, text, urgent=True)
|
||||
return {
|
||||
"sent": any(d.ok for d in deliveries),
|
||||
"deliveries": [d.as_dict() for d in deliveries],
|
||||
"text": text,
|
||||
}
|
||||
|
||||
|
||||
@router.get("/stats/summary")
|
||||
def summary(session: DbSession, settings: Settings, days: int = Query(default=30, ge=1, le=365)) -> dict:
|
||||
today = local_date(settings.timezone)
|
||||
return {
|
||||
"today": stats.day_metrics(session, settings, today),
|
||||
"streak": stats.streak(session, settings),
|
||||
"lifetime": stats.lifetime(session, settings),
|
||||
"average_7d": stats.averages(session, settings, 7, until=today),
|
||||
"range": stats.range_metrics(session, settings, today - timedelta(days=days - 1), today),
|
||||
"heatmap": stats.heatmap(session, settings, weeks=12),
|
||||
}
|
||||
|
||||
|
||||
@router.get("/stats/day")
|
||||
def day_stats(session: DbSession, settings: Settings, day: date | None = Query(default=None)) -> dict:
|
||||
return stats.day_metrics(session, settings, day or local_date(settings.timezone))
|
||||
|
||||
|
||||
@router.post("/notifications/test")
|
||||
def test_notification(body: TestNotificationRequest, settings: Settings) -> dict:
|
||||
text = body.text or (
|
||||
"🍅 <b>Kadence</b>\nNotifications are wired up correctly."
|
||||
)
|
||||
deliveries = notify_service.notify(settings, text, urgent=True)
|
||||
return {"deliveries": [d.as_dict() for d in deliveries]}
|
||||
|
||||
|
||||
@router.get("/scheduler/jobs")
|
||||
def scheduler_jobs() -> dict:
|
||||
"""What the background jobs are, and when they next fire."""
|
||||
return {"jobs": scheduler.describe()}
|
||||
Reference in new issue
Block a user