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 })