Files
MTCBD/backend/analytics/views.py
2026-02-23 20:31:53 +05:30

96 lines
4.0 KiB
Python

from rest_framework import generics, permissions, status
from rest_framework.response import Response
from rest_framework.views import APIView
from django.db.models import Count
from django.db.models.functions import TruncDate
from django.utils.dateparse import parse_date
from .models import ActivityLog, AuditLog
from .serializers import ActivityLogSerializer, AuditLogSerializer
from accounts.permissions import IsTenantUser, IsAdmin
from projects.models import Project, Task
class ActivityLogListView(generics.ListAPIView):
serializer_class = ActivityLogSerializer
permission_classes = [permissions.IsAuthenticated, IsTenantUser]
def get_queryset(self):
return ActivityLog.objects.filter(tenant=self.request.tenant)
class ReportView(APIView):
"""
Returns aggregated stats for a date range with daily breakdown
Query params: start_date (YYYY-MM-DD), end_date (YYYY-MM-DD)
"""
permission_classes = [permissions.IsAuthenticated, IsTenantUser, IsAdmin] # Only admins can see reports usually
def get(self, request):
tenant = request.tenant
start_date_str = request.query_params.get('start_date')
end_date_str = request.query_params.get('end_date')
project_qs = Project.objects.filter(tenant=tenant)
task_qs = Task.objects.filter(tenant=tenant)
if start_date_str:
start_date = parse_date(start_date_str)
if start_date:
project_qs = project_qs.filter(created_at__date__gte=start_date)
task_qs = task_qs.filter(created_at__date__gte=start_date)
if end_date_str:
end_date = parse_date(end_date_str)
if end_date:
project_qs = project_qs.filter(created_at__date__lte=end_date)
task_qs = task_qs.filter(created_at__date__lte=end_date)
# Total counts
projects_created = project_qs.count()
tasks_created = task_qs.count()
tasks_completed = task_qs.filter(status='done').count()
# Daily metrics: group by date
from django.db.models.functions import TruncDate
daily_projects = project_qs.annotate(day=TruncDate('created_at')).values('day').annotate(count=Count('id')).order_by('day')
daily_tasks_completed = task_qs.filter(status='done').annotate(day=TruncDate('created_at')).values('day').annotate(count=Count('id')).order_by('day')
daily_tasks_created = task_qs.annotate(day=TruncDate('created_at')).values('day').annotate(count=Count('id')).order_by('day')
# Build daily metrics array
daily_metrics = []
# Collect all unique dates from both projects and tasks
all_dates = set()
for item in daily_projects:
all_dates.add(item['day'])
for item in daily_tasks_completed:
all_dates.add(item['day'])
for item in daily_tasks_created:
all_dates.add(item['day'])
# Sort dates
sorted_dates = sorted(all_dates)
for date_obj in sorted_dates:
date_str = date_obj.strftime('%Y-%m-%d')
# Find counts for this date
proj_count = next((item['count'] for item in daily_projects if item['day'] == date_obj), 0)
tasks_comp = next((item['count'] for item in daily_tasks_completed if item['day'] == date_obj), 0)
tasks_created_count = next((item['count'] for item in daily_tasks_created if item['day'] == date_obj), 0)
daily_metrics.append({
'date': date_str,
'projects_created': proj_count,
'tasks_completed': tasks_comp,
'tasks_created': tasks_created_count,
})
return Response({
'period': {
'start': start_date_str,
'end': end_date_str
},
'total_projects': projects_created,
'total_tasks': tasks_created,
'tasks_completed': tasks_completed,
'daily_metrics': daily_metrics
})