Files
dash/backend/app/api/v1/metrics.py

99 lines
3.9 KiB
Python
Raw Normal View History

"""
Модуль Метрика - числовые показатели эффективности
"""
from fastapi import APIRouter, Depends, Query, HTTPException
from sqlalchemy.orm import Session
from sqlalchemy import text
from typing import Literal
from app.core.database import get_manictime_db
from app.core.security import get_current_user
from app.models.service_db import AppUser
from app.schemas.metrics import MetricsAggregateResponse, MetricsRow
router = APIRouter()
@router.get("/aggregate", response_model=MetricsAggregateResponse)
async def get_metrics_aggregate(
period: Literal["week", "month", "quarter", "year"] = Query(..., description="Период агрегации"),
year: int = Query(..., description="Год"),
current_user: AppUser = Depends(get_current_user),
manictime_db: Session = Depends(get_manictime_db)
):
"""
Получение агрегированных метрик за указанный период
"""
try:
if year < 2000 or year > 2100:
raise HTTPException(status_code=400, detail="Неверный год")
# Определение функции агрегации в зависимости от периода
date_trunc_func = {
"week": "week",
"month": "month",
"quarter": "quarter",
"year": "year"
}.get(period, "quarter")
# SQL запрос для агрегации активного времени
query = text(f"""
SELECT
u."DisplayName" AS user_name,
DATE_TRUNC('{date_trunc_func}', a."StartLocalTime") AS period_start,
SUM(EXTRACT(EPOCH FROM (a."EndLocalTime" - a."StartLocalTime"))) AS total_seconds
FROM "Ar_Activity" a
JOIN "Ar_Timeline" t ON a."ReportId" = t."ReportId"
JOIN "Ar_User" u ON t."OwnerId" = u."UserId"
WHERE
t."SchemaName" = 'ManicTime/Computer usage'
AND a."Name" = 'Active'
AND EXTRACT(YEAR FROM a."StartLocalTime") = :year
GROUP BY
u."DisplayName",
DATE_TRUNC('{date_trunc_func}', a."StartLocalTime")
ORDER BY
u."DisplayName",
period_start
""")
result = manictime_db.execute(query, {"year": year})
rows = result.fetchall()
# Группировка данных по пользователям
user_data = {}
for row in rows:
user_name = row.user_name
if user_name not in user_data:
user_data[user_name] = {}
# Формирование ключа периода
period_start = row.period_start
if period == "week":
period_key = f"W{period_start.isocalendar()[1]}"
elif period == "month":
period_key = f"M{period_start.month}"
elif period == "quarter":
quarter = (period_start.month - 1) // 3 + 1
period_key = f"Q{quarter}"
else: # year
period_key = "Y1"
# Конвертация секунд в часы
hours = float(row.total_seconds) / 3600
user_data[user_name][period_key] = round(hours, 2)
# Формирование ответа
metrics_rows = []
for user_name, periods in user_data.items():
metrics_rows.append(MetricsRow(user=user_name, data=periods))
return MetricsAggregateResponse(
period_type=period,
year=year,
data=metrics_rows
)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Ошибка при получении данных: {str(e)}")