3fefc550fe
- Django backend with DRF (clubs, wrestlers, trainers, exercises, templates, trainings, homework, locations, leistungstest) - Next.js 16 frontend with React, Shadcn UI, Tailwind - JWT authentication - Full CRUD for all entities - Calendar view for trainings - Homework management system - Leistungstest tracking
93 lines
3.6 KiB
Python
93 lines
3.6 KiB
Python
from rest_framework.decorators import api_view, permission_classes
|
|
from rest_framework.permissions import IsAuthenticated
|
|
from rest_framework.response import Response
|
|
from django.db.models import Count
|
|
from datetime import datetime, timedelta
|
|
from wrestlers.models import Wrestler
|
|
from trainers.models import Trainer
|
|
from trainings.models import Training, Attendance
|
|
from homework.models import TrainingHomeworkAssignment
|
|
|
|
|
|
@api_view(['GET'])
|
|
@permission_classes([IsAuthenticated])
|
|
def dashboard_stats(request):
|
|
today = datetime.now().date()
|
|
week_start = today - timedelta(days=today.weekday())
|
|
two_weeks_ago = today - timedelta(days=14)
|
|
|
|
# Wrestlers stats
|
|
total_wrestlers = Wrestler.objects.count()
|
|
wrestlers_this_week = Wrestler.objects.filter(
|
|
created_at__date__gte=week_start
|
|
).count()
|
|
|
|
# Trainers stats
|
|
total_trainers = Trainer.objects.count()
|
|
active_trainers = Trainer.objects.filter(is_active=True).count()
|
|
|
|
# Trainings stats
|
|
total_trainings = Training.objects.count()
|
|
trainings_this_week = Training.objects.filter(
|
|
date__gte=week_start
|
|
).count()
|
|
|
|
# Homework stats
|
|
open_homework = TrainingHomeworkAssignment.objects.filter(is_completed=False).count()
|
|
completed_homework = TrainingHomeworkAssignment.objects.filter(is_completed=True).count()
|
|
|
|
# Attendance by group this week
|
|
trainings_this_week_qs = Training.objects.filter(date__gte=week_start)
|
|
attendance_data = {}
|
|
for group, label in [('kids', 'Kinder'), ('youth', 'Jugend'), ('adults', 'Erwachsene')]:
|
|
group_wrestlers = Wrestler.objects.filter(group=group)
|
|
attended = Attendance.objects.filter(
|
|
training__in=trainings_this_week_qs,
|
|
wrestler__in=group_wrestlers
|
|
).values('wrestler').distinct().count()
|
|
total = group_wrestlers.count()
|
|
attendance_data[group] = {
|
|
'attended': attended,
|
|
'total': total,
|
|
'percent': int((attended / total * 100) if total > 0 else 0)
|
|
}
|
|
|
|
# Activity (last 14 days)
|
|
activity = []
|
|
for i in range(14):
|
|
day = today - timedelta(days=13 - i)
|
|
count = Attendance.objects.filter(training__date=day).count()
|
|
activity.append({'date': day.isoformat(), 'count': count})
|
|
|
|
# Wrestlers by group
|
|
wrestlers_by_group = {
|
|
'kids': Wrestler.objects.filter(group='kids', is_active=True).count(),
|
|
'youth': Wrestler.objects.filter(group='youth', is_active=True).count(),
|
|
'adults': Wrestler.objects.filter(group='adults', is_active=True).count(),
|
|
'inactive': Wrestler.objects.filter(is_active=False).count(),
|
|
}
|
|
|
|
# Top trainers (by training count)
|
|
trainer_stats = Trainer.objects.annotate(
|
|
training_count=Count('trainings')
|
|
).order_by('-training_count')[:5]
|
|
top_trainers = [
|
|
{'name': t.first_name + ' ' + t.last_name[0] + '.', 'training_count': t.training_count}
|
|
for t in trainer_stats
|
|
]
|
|
|
|
return Response({
|
|
'wrestlers': {'total': total_wrestlers, 'this_week': wrestlers_this_week},
|
|
'trainers': {'total': total_trainers, 'active': active_trainers},
|
|
'trainings': {'total': total_trainings, 'this_week': trainings_this_week},
|
|
'homework': {'open': open_homework, 'completed': completed_homework},
|
|
'attendance': {
|
|
'this_week': attendance_data,
|
|
'average': Attendance.objects.filter(training__date__gte=week_start).values('training').distinct().count(),
|
|
'expected': total_wrestlers
|
|
},
|
|
'activity': activity,
|
|
'wrestlers_by_group': wrestlers_by_group,
|
|
'top_trainers': top_trainers,
|
|
})
|