99 lines
3.9 KiB
Python
Executable File
99 lines
3.9 KiB
Python
Executable File
"""
|
|
Модуль Метрика - числовые показатели эффективности
|
|
"""
|
|
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)}")
|
|
|