96 lines
4.0 KiB
Python
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
|
|
})
|