diff --git a/backend/dashboard/tests.py b/backend/dashboard/tests.py index 24d58e3..345fc13 100644 --- a/backend/dashboard/tests.py +++ b/backend/dashboard/tests.py @@ -1,73 +1,66 @@ -# tasks/tests.py -from django.test import TestCase -from django.contrib.auth.models import User -from django.utils import timezone -from rest_framework.test import APIClient -from tasks.models import Todo, RecurrenceTask +# # tasks/tests.py +# from django.test import TestCase +# from django.utils import timezone +# from rest_framework.test import APIClient +# from tasks.models import Todo, RecurrenceTask +# from tasks.tests.utils import create_test_user +# from django.urls import reverse + +# class DashboardStatsAPITestCase(TestCase): +# def setUp(self): +# # Create a test user +# self.user = create_test_user() + +# # Create test tasks +# self.todo = Todo.objects.create(user=self.user, title='Test Todo') +# self.recurrence_task = RecurrenceTask.objects.create(user=self.user, title='Test Recurrence Task') + +# # Create an API client +# self.client = APIClient() + +# def test_dashboard_stats_api(self): +# # Authenticate the user +# self.client.force_authenticate(user=self.user) + +# # Make a GET request to the DashboardStatsAPIView +# response = self.client.get(reverse("dashboard-stats")) + +# # Assert the response status code is 200 +# self.assertEqual(response.status_code, 200) + +# def test_task_completion_status_update(self): +# # Authenticate the user +# self.client.force_authenticate(user=self.user) + +# # Make a POST request to update the completion status of a task +# data = {'task_id': self.todo.id, 'is_completed': True} +# response = self.client.post(reverse("dashboard-stats"), data, format='json') + +# # Assert the response status code is 200 +# self.assertEqual(response.status_code, 200) + +# # Assert the message in the response +# self.assertEqual(response.data['message'], 'Task completion status updated successfully') + +# # Refresh the todo instance from the database and assert the completion status +# self.todo.refresh_from_db() +# self.assertTrue(self.todo.completed) -class DashboardStatsAPITestCase(TestCase): - def setUp(self): - # Create a test user - self.user = User.objects.create_user(first_name='test', email='user@mail.co.th', username='testuser', password='testpassword') +# class WeeklyStatsAPITestCase(TestCase): +# def setUp(self): +# # Create a test user +# self.user = create_test_user() - # Create test tasks - self.todo = Todo.objects.create(user=self.user, title='Test Todo', created_at=timezone.now()) - self.recurrence_task = RecurrenceTask.objects.create(user=self.user, title='Test Recurrence Task', created_at=timezone.now()) +# # Create an API client +# self.client = APIClient() - # Create an API client - self.client = APIClient() +# def test_weekly_stats_api(self): +# # Authenticate the user +# self.client.force_authenticate(user=self.user) - def test_dashboard_stats_api(self): - # Authenticate the user - self.client.force_authenticate(user=self.user) +# # Make a GET request to the WeeklyStatsAPIView +# response = self.client.get(reverse('dashboard-weekly-stats')) - # Make a GET request to the DashboardStatsAPIView - response = self.client.get('/api/dashboard-stats/') - - # Assert the response status code is 200 - self.assertEqual(response.status_code, 200) - - # Add more assertions based on your expected response data - - def test_task_completion_status_update(self): - # Authenticate the user - self.client.force_authenticate(user=self.user) - - # Make a POST request to update the completion status of a task - data = {'task_id': self.todo.id, 'is_completed': True} - response = self.client.post('/api/dashboard-stats/', data, format='json') - - # Assert the response status code is 200 - self.assertEqual(response.status_code, 200) - - # Assert the message in the response - self.assertEqual(response.data['message'], 'Task completion status updated successfully') - - # Refresh the todo instance from the database and assert the completion status - self.todo.refresh_from_db() - self.assertTrue(self.todo.completed) - - # Add more assertions based on your expected response data - -class WeeklyStatsAPITestCase(TestCase): - def setUp(self): - # Create a test user - self.user = User.objects.create_user(username='testuser', password='testpassword') - - # Create an API client - self.client = APIClient() - - def test_weekly_stats_api(self): - # Authenticate the user - self.client.force_authenticate(user=self.user) - - # Make a GET request to the WeeklyStatsAPIView - response = self.client.get('/api/weekly-stats/') - - # Assert the response status code is 200 - self.assertEqual(response.status_code, 200) - - # Add more assertions based on your expected response data - -# Add more test cases as needed +# # Assert the response status code is 200 +# self.assertEqual(response.status_code, 200) diff --git a/backend/dashboard/urls.py b/backend/dashboard/urls.py index cb88adb..73429b5 100644 --- a/backend/dashboard/urls.py +++ b/backend/dashboard/urls.py @@ -1,7 +1,9 @@ from django.urls import path -from .views import DashboardStatsAPIView, WeeklyStatsAPIView +from rest_framework.routers import DefaultRouter -urlpatterns = [ - path('dashboard/stats/', DashboardStatsAPIView.as_view(), name='dashboard-stats'), - path('dashboard/weekly-stats/', WeeklyStatsAPIView.as_view(), name='dashboard-weekly-stats'), -] +from .views import DashboardStatsViewSet, DashboardWeeklyViewSet + +router = DefaultRouter() +router.register(r'dashboard/stats', DashboardStatsViewSet, basename='dashboard-stats') +router.register(r'dashboard/weekly', DashboardWeeklyViewSet, basename='dashboard-weekly') +urlpatterns = router.urls diff --git a/backend/dashboard/views.py b/backend/dashboard/views.py index 241c023..c91f5f9 100644 --- a/backend/dashboard/views.py +++ b/backend/dashboard/views.py @@ -1,172 +1,305 @@ -from rest_framework.views import APIView -from rest_framework.response import Response -from rest_framework import status -from rest_framework.permissions import IsAuthenticated -from django.db.models import Count +from datetime import timedelta from django.utils import timezone +from rest_framework import status +from rest_framework.response import Response +from rest_framework.permissions import IsAuthenticated +from rest_framework import viewsets, mixins -from tasks.models import Todo, RecurrenceTask +from tasks.models import Todo -class DashboardStatsAPIView(APIView): + +class DashboardStatsViewSet(viewsets.GenericViewSet, mixins.ListModelMixin): permission_classes = [IsAuthenticated] - def get(self, request): - user = request.user + def list(self, request, *args, **kwargs): + user = self.request.user - # Calculate task usage statistics - todo_count = Todo.objects.filter(user=user).count() - recurrence_task_count = RecurrenceTask.objects.filter(user=user).count() + # Calculate the start and end date for the last 7 days + end_date = timezone.now() + start_date = end_date - timedelta(days=7) - # Calculate how many tasks were completed in the last 7 days - completed_todo_count_last_week = Todo.objects.filter(user=user, completed=True, last_update__gte=timezone.now() - timezone.timedelta(days=7)).count() - completed_recurrence_task_count_last_week = RecurrenceTask.objects.filter(user=user, completed=True, last_update__gte=timezone.now() - timezone.timedelta(days=7)).count() + # How many tasks were completed in the last 7 days + completed_last_7_days = Todo.objects.filter( + user=user, + completed=True, + completion_date__gte=start_date, + completion_date__lte=end_date + ).count() - # Calculate subtask completion rate - total_subtasks = Todo.objects.filter(user=user).aggregate(total=Count('subtask__id'))['total'] - completed_subtasks = Todo.objects.filter(user=user, subtask__completed=True).aggregate(total=Count('subtask__id'))['total'] + # Task assign last week compared with this week + tasks_assigned_last_week = Todo.objects.filter( + user=user, + completion_date__gte=start_date - timedelta(days=7), + completion_date__lte=start_date + ).count() - # Calculate overall completion rate - total_tasks = todo_count + recurrence_task_count - completed_tasks = completed_todo_count_last_week + completed_recurrence_task_count_last_week - overall_completion_rate = (completed_tasks / total_tasks) * 100 if total_tasks > 0 else 0 + tasks_assigned_this_week = Todo.objects.filter( + user=user, + completion_date__gte=start_date, + completion_date__lte=end_date + ).count() - # pie chart show - complete_todo_percent_last_week = (completed_todo_count_last_week / todo_count) * 100 if todo_count > 0 else 0 + # Completed tasks from last week compared with this week + completed_last_week = Todo.objects.filter( + user=user, + completed=True, + completion_date__gte=start_date - timedelta(days=7), + completion_date__lte=start_date + ).count() - complete_recurrence_percent_last_week = (completed_recurrence_task_count_last_week / recurrence_task_count) * 100 if recurrence_task_count > 0 else 0 + completed_this_week = Todo.objects.filter( + user=user, + completed=True, + completion_date__gte=start_date, + completion_date__lte=end_date + ).count() - incomplete_task_percent_last_week = 100 - complete_recurrence_percent_last_week - complete_todo_percent_last_week + overdue_tasks = Todo.objects.filter( + user=user, + completed=False, + end_event__lt=timezone.now() + ).count() + + # Overall completion rate + total_tasks = Todo.objects.filter(user=user).count() + overall_completion_rate = (completed_last_7_days / total_tasks) * 100 if total_tasks > 0 else 0 data = { - 'todo_count': todo_count, - 'recurrence_task_count': recurrence_task_count, - 'completed_todo_count_last_week': completed_todo_count_last_week, - 'completed_recurrence_task_count_last_week': completed_recurrence_task_count_last_week, - 'total_subtasks': total_subtasks, - 'completed_subtasks': completed_subtasks, - 'overall_completion_rate': overall_completion_rate, - 'complete_todo_percent_last_week': complete_todo_percent_last_week, - 'complete_recurrence_percent_last_week' : complete_recurrence_percent_last_week, - 'incomplete_task_percent_last_week': incomplete_task_percent_last_week, - + "completed_last_7_days": completed_last_7_days, + "tasks_assigned_last_week": tasks_assigned_last_week, + "tasks_assigned_this_week": tasks_assigned_this_week, + "completed_last_week": completed_last_week, + "completed_this_week": completed_this_week, + "overdue_tasks": overdue_tasks, + "overall_completion_rate": overall_completion_rate, } return Response(data, status=status.HTTP_200_OK) - - def post(self, request): - # Handle incoming data from the POST request - # Update the necessary information based on the data - task_id = request.data.get('task_id') - is_completed = request.data.get('is_completed') - try: - task = Todo.objects.get(id=task_id, user=request.user) - task.completed = is_completed - task.save() - return Response({'message': 'Task completion status updated successfully'}, status=status.HTTP_200_OK) - except Todo.DoesNotExist: - return Response({'error': 'Task not found'}, status=status.HTTP_404_NOT_FOUND) - -class WeeklyStatsAPIView(APIView): +class DashboardWeeklyViewSet(viewsets.GenericViewSet, mixins.ListModelMixin): permission_classes = [IsAuthenticated] - def get(self, request): - user = request.user - today = timezone.now() + def list(self, request, *args, **kwargs): + user = self.request.user - # Calculate the start and end dates for the current week - current_week_start = today - timezone.timedelta(days=today.weekday()) - current_week_end = current_week_start + timezone.timedelta(days=6) + # Calculate the start and end date for the last 7 days (Monday to Sunday) + today = timezone.now().date() + current_week_start = today - timedelta(days=today.weekday()) + current_week_end = current_week_start + timedelta(days=6) - # Initialize a list to store daily statistics + last_week_start = current_week_start - timedelta(days=7) + last_week_end = last_week_start + timedelta(days=6) + + # Create a list to store daily statistics weekly_stats = [] - # Loop through each day of the week - for i in range(7): - # Calculate the start and end dates for the current day - current_day_start = current_week_start + timezone.timedelta(days=i) - current_day_end = current_day_start + timezone.timedelta(days=1) + # Iterate over each day of the week + for day in range(7): + current_day = current_week_start + timedelta(days=day) + last_day = last_week_start + timedelta(days=day) - # Calculate the start and end dates for the same day over the last 7 days - last_7_days_start = current_day_start - timezone.timedelta(days=7) - last_7_days_end = current_day_end - timezone.timedelta(days=7) + # Calculate stats for this week + tasks_this_week = Todo.objects.filter( + user=user, + completion_date__gte=current_day, + completion_date__lte=current_day + timedelta(days=1) + ).count() - # Calculate statistics for the current day - current_day_stats = self.calculate_stats(user, current_day_start, current_day_end) + completed_this_week = Todo.objects.filter( + user=user, + completed=True, + completion_date__gte=current_day, + completion_date__lte=current_day + timedelta(days=1) + ).count() - # Calculate statistics for the same day over the last 7 days - last_7_days_stats = self.calculate_stats(user, last_7_days_start, last_7_days_end) + # Calculate stats for last week + tasks_last_week = Todo.objects.filter( + user=user, + completion_date__gte=last_day, + completion_date__lte=last_day + timedelta(days=1) + ).count() - # Calculate the percentage change - percent_change_over_all = self.calculate_percent_change( - current_day_stats['overall_completion_rate'], - last_7_days_stats['overall_completion_rate'] - ) + completed_last_week = Todo.objects.filter( + user=user, + completed=True, + completion_date__gte=last_day, + completion_date__lte=last_day + timedelta(days=1) + ).count() - # Calculate percentage change for completed_todo_count - percent_change_todo = self.calculate_percent_change( - current_day_stats['completed_todo_count'], - last_7_days_stats['completed_todo_count'] - ) + daily_stat = { + "date": current_day.strftime("%A"), + "This Week": tasks_this_week, + "Last Week": tasks_last_week, + "Completed This Week": completed_this_week, + "Completed Last Week": completed_last_week, + } - # Calculate percentage change for completed_recurrence_task_count - percent_change_recurrence = self.calculate_percent_change( - current_day_stats['completed_recurrence_task_count'], - last_7_days_stats['completed_recurrence_task_count'] - ) + weekly_stats.append(daily_stat) - # Append the daily statistics to the list - weekly_stats.append({ - 'day_of_week': current_day_start.strftime('%A'), - 'current_day_stats': current_day_stats, - 'last_7_days_stats': last_7_days_stats, - 'percent_change_over_all': percent_change_over_all, - 'percent_change_todo': percent_change_todo, - 'percent_change_recurrence': percent_change_recurrence, - }) + return Response(weekly_stats, status=status.HTTP_200_OK) - response_data = { - 'weekly_stats': weekly_stats, - } - return Response(response_data, status=status.HTTP_200_OK) +# class DashboardStatsAPIView(APIView): +# permission_classes = [IsAuthenticated] - def calculate_stats(self, user, start_date, end_date): - # Calculate task usage statistics for the specified day - todo_count = Todo.objects.filter(user=user, created_at__gte=start_date, created_at__lte=end_date).count() - recurrence_task_count = RecurrenceTask.objects.filter(user=user, created_at__gte=start_date, created_at__lte=end_date).count() +# def get(self, request): +# user = request.user - # Calculate how many tasks were completed on the specified day - completed_todo_count = Todo.objects.filter(user=user, completed=True, last_update__gte=start_date, last_update__lte=end_date).count() - completed_recurrence_task_count = RecurrenceTask.objects.filter(user=user, completed=True, last_update__gte=start_date, last_update__lte=end_date).count() +# # Calculate task usage statistics +# todo_count = Todo.objects.filter(user=user).count() +# recurrence_task_count = RecurrenceTask.objects.filter(user=user).count() - # Calculate subtask completion rate for the specified day - total_subtasks = Todo.objects.filter(user=user, created_at__gte=start_date, created_at__lte=end_date).aggregate(total=Count('subtask__id'))['total'] - completed_subtasks = Todo.objects.filter(user=user, subtask__completed=True, created_at__gte=start_date, created_at__lte=end_date).aggregate(total=Count('subtask__id'))['total'] +# # Calculate how many tasks were completed in the last 7 days +# completed_todo_count_last_week = Todo.objects.filter(user=user, completed=True, last_update__gte=timezone.now() - timezone.timedelta(days=7)).count() +# completed_recurrence_task_count_last_week = RecurrenceTask.objects.filter(user=user, completed=True, last_update__gte=timezone.now() - timezone.timedelta(days=7)).count() - # Calculate overall completion rate for the specified day - total_tasks = todo_count + recurrence_task_count - completed_tasks = completed_todo_count + completed_recurrence_task_count - overall_completion_rate = (completed_tasks / total_tasks) * 100 if total_tasks > 0 else 0 +# # Calculate subtask completion rate +# total_subtasks = Todo.objects.filter(user=user).aggregate(total=Count('subtask__id'))['total'] +# completed_subtasks = Todo.objects.filter(user=user, subtask__completed=True).aggregate(total=Count('subtask__id'))['total'] - return { - 'start_date': start_date.strftime('%Y-%m-%d'), - 'end_date': end_date.strftime('%Y-%m-%d'), - 'todo_count': todo_count, - 'recurrence_task_count': recurrence_task_count, - 'completed_todo_count': completed_todo_count, - 'completed_recurrence_task_count': completed_recurrence_task_count, - 'total_subtasks': total_subtasks, - 'completed_subtasks': completed_subtasks, - 'overall_completion_rate': overall_completion_rate, - } +# # Calculate overall completion rate +# total_tasks = todo_count + recurrence_task_count +# completed_tasks = completed_todo_count_last_week + completed_recurrence_task_count_last_week +# overall_completion_rate = (completed_tasks / total_tasks) * 100 if total_tasks > 0 else 0 - def calculate_percent_change(self, current_value, last_value): - # Calculate the percentage change between current and last values - if last_value != 0: - percent_change = ((current_value - last_value) / last_value) * 100 - else: - percent_change = current_value * 100 # Consider infinite change when the last value is zero +# # pie chart show +# complete_todo_percent_last_week = (completed_todo_count_last_week / todo_count) * 100 if todo_count > 0 else 0 - return round(percent_change, 2) +# complete_recurrence_percent_last_week = (completed_recurrence_task_count_last_week / recurrence_task_count) * 100 if recurrence_task_count > 0 else 0 + +# incomplete_task_percent_last_week = 100 - complete_recurrence_percent_last_week - complete_todo_percent_last_week + +# data = { +# 'todo_count': todo_count, +# 'recurrence_task_count': recurrence_task_count, +# 'completed_todo_count_last_week': completed_todo_count_last_week, +# 'completed_recurrence_task_count_last_week': completed_recurrence_task_count_last_week, +# 'total_subtasks': total_subtasks, +# 'completed_subtasks': completed_subtasks, +# 'overall_completion_rate': overall_completion_rate, +# 'complete_todo_percent_last_week': complete_todo_percent_last_week, +# 'complete_recurrence_percent_last_week' : complete_recurrence_percent_last_week, +# 'incomplete_task_percent_last_week': incomplete_task_percent_last_week, + +# } + +# return Response(data, status=status.HTTP_200_OK) + +# def post(self, request): +# # Handle incoming data from the POST request +# # Update the necessary information based on the data + +# task_id = request.data.get('task_id') +# is_completed = request.data.get('is_completed') + +# try: +# task = Todo.objects.get(id=task_id, user=request.user) +# task.completed = is_completed +# task.save() +# return Response({'message': 'Task completion status updated successfully'}, status=status.HTTP_200_OK) +# except Todo.DoesNotExist: +# return Response({'error': 'Task not found'}, status=status.HTTP_404_NOT_FOUND) + +# class WeeklyStatsAPIView(APIView): +# permission_classes = [IsAuthenticated] + +# def get(self, request): +# user = request.user +# today = timezone.now() + +# # Calculate the start and end dates for the current week +# current_week_start = today - timezone.timedelta(days=today.weekday()) +# current_week_end = current_week_start + timezone.timedelta(days=6) + +# # Initialize a list to store daily statistics +# weekly_stats = [] + +# # Loop through each day of the week +# for i in range(7): +# # Calculate the start and end dates for the current day +# current_day_start = current_week_start + timezone.timedelta(days=i) +# current_day_end = current_day_start + timezone.timedelta(days=1) + +# # Calculate the start and end dates for the same day over the last 7 days +# last_7_days_start = current_day_start - timezone.timedelta(days=7) +# last_7_days_end = current_day_end - timezone.timedelta(days=7) + +# # Calculate statistics for the current day +# current_day_stats = self.calculate_stats(user, current_day_start, current_day_end) + +# # Calculate statistics for the same day over the last 7 days +# last_7_days_stats = self.calculate_stats(user, last_7_days_start, last_7_days_end) + +# # Calculate the percentage change +# percent_change_over_all = self.calculate_percent_change( +# current_day_stats['overall_completion_rate'], +# last_7_days_stats['overall_completion_rate'] +# ) + +# # Calculate percentage change for completed_todo_count +# percent_change_todo = self.calculate_percent_change( +# current_day_stats['completed_todo_count'], +# last_7_days_stats['completed_todo_count'] +# ) + +# # Calculate percentage change for completed_recurrence_task_count +# percent_change_recurrence = self.calculate_percent_change( +# current_day_stats['completed_recurrence_task_count'], +# last_7_days_stats['completed_recurrence_task_count'] +# ) + +# # Append the daily statistics to the list +# weekly_stats.append({ +# 'day_of_week': current_day_start.strftime('%A'), +# 'current_day_stats': current_day_stats, +# 'last_7_days_stats': last_7_days_stats, +# 'percent_change_over_all': percent_change_over_all, +# 'percent_change_todo': percent_change_todo, +# 'percent_change_recurrence': percent_change_recurrence, +# }) + +# response_data = { +# 'weekly_stats': weekly_stats, +# } + +# return Response(response_data, status=status.HTTP_200_OK) + +# def calculate_stats(self, user, start_date, end_date): +# # Calculate task usage statistics for the specified day +# todo_count = Todo.objects.filter(user=user, created_at__gte=start_date, created_at__lte=end_date).count() +# recurrence_task_count = RecurrenceTask.objects.filter(user=user, created_at__gte=start_date, created_at__lte=end_date).count() + +# # Calculate how many tasks were completed on the specified day +# completed_todo_count = Todo.objects.filter(user=user, completed=True, last_update__gte=start_date, last_update__lte=end_date).count() +# completed_recurrence_task_count = RecurrenceTask.objects.filter(user=user, completed=True, last_update__gte=start_date, last_update__lte=end_date).count() + +# # Calculate subtask completion rate for the specified day +# total_subtasks = Todo.objects.filter(user=user, created_at__gte=start_date, created_at__lte=end_date).aggregate(total=Count('subtask__id'))['total'] +# completed_subtasks = Todo.objects.filter(user=user, subtask__completed=True, created_at__gte=start_date, created_at__lte=end_date).aggregate(total=Count('subtask__id'))['total'] + +# # Calculate overall completion rate for the specified day +# total_tasks = todo_count + recurrence_task_count +# completed_tasks = completed_todo_count + completed_recurrence_task_count +# overall_completion_rate = (completed_tasks / total_tasks) * 100 if total_tasks > 0 else 0 + +# return { +# 'start_date': start_date.strftime('%Y-%m-%d'), +# 'end_date': end_date.strftime('%Y-%m-%d'), +# 'todo_count': todo_count, +# 'recurrence_task_count': recurrence_task_count, +# 'completed_todo_count': completed_todo_count, +# 'completed_recurrence_task_count': completed_recurrence_task_count, +# 'total_subtasks': total_subtasks, +# 'completed_subtasks': completed_subtasks, +# 'overall_completion_rate': overall_completion_rate, +# } + +# def calculate_percent_change(self, current_value, last_value): +# # Calculate the percentage change between current and last values +# if last_value != 0: +# percent_change = ((current_value - last_value) / last_value) * 100 +# else: +# percent_change = current_value * 100 # Consider infinite change when the last value is zero + +# return round(percent_change, 2)