from sqlmodel import Session, select from datetime import datetime, timedelta from collections import Counter from uuid import UUID import models def generate_parent_report(student_id: UUID, session: Session) -> dict: """ Aggregates granular performance data for a specific student into a clean, simple, parent-friendly schema. """ # 1. Fetch Student Baseline Info student = session.get(models.User, student_id) if not student: return {"error": "Student record not found."} # 2. Compile Last 7 Days Time & Attempts Data seven_days_ago = datetime.utcnow() - timedelta(days=7) attempts = session.exec( select(models.Attempt) .where(models.Attempt.user_id == student_id) .where(models.Attempt.submitted_at >= seven_days_ago) ).all() total_time_spent_seconds = sum((a.time_taken or 0) for a in attempts) total_time_spent_minutes = round(total_time_spent_seconds / 60, 1) # 3. Calculate 7-Day Accuracy Trend Line Data # Group accuracy by date strings for simple frontend parsing trend_data = [] for i in range(6, -1, -1): target_date = (datetime.utcnow() - timedelta(days=i)).date() daily_attempts = [a for a in attempts if a.submitted_at.date() == target_date] if daily_attempts: avg_accuracy = sum(a.accuracy for a in daily_attempts) / len(daily_attempts) trend_data.append({"date": target_date.strftime("%b %d"), "accuracy": round(avg_accuracy, 1)}) else: trend_data.append({"date": target_date.strftime("%b %d"), "accuracy": 0.0}) # 4. Extract Top "Areas of Concern" (Active un-mastered mistakes) active_mistakes = session.exec( select(models.Mistake) .where(models.Mistake.user_id == student_id) .where(models.Mistake.is_mastered == False) ).all() # Aggregate topic counts to find where they struggle most topic_counter = Counter([m.topic for m in active_mistakes]) top_concerns = [ {"topic": topic, "pending_errors": count} for topic, count in topic_counter.most_common(3) ] return { "student_name": student.name, "streak_count": student.streak_count, "weekly_minutes_spent": total_time_spent_minutes, "total_tests_attempted_this_week": len(attempts), "accuracy_trend": trend_data, "areas_of_concern": top_concerns, "last_active": student.last_active.strftime("%Y-%m-%d %H:%M:%S") }