Recode the analytic part

This commit is contained in:
sosokker 2023-11-20 22:36:19 +07:00
parent 298d7c2d10
commit 6c31fb059f
3 changed files with 331 additions and 203 deletions

View File

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

View File

@ -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

View File

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