feat: praxis assignments

This commit is contained in:
Reto Aebersold 2023-12-06 10:56:08 +01:00
parent 278d659905
commit 669dfdd7c1
4 changed files with 207 additions and 27 deletions

View File

@ -1,4 +1,4 @@
# Generated by Django 3.2.20 on 2023-12-01 10:11
# Generated by Django 3.2.20 on 2023-12-06 09:32
import django.db.models.deletion
from django.conf import settings
@ -9,6 +9,7 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
("course", "0005_course_enable_circle_documents"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
@ -24,7 +25,7 @@ class Migration(migrations.Migration):
),
(
"mentor",
models.ForeignKey(
models.OneToOneField(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
@ -34,7 +35,7 @@ class Migration(migrations.Migration):
(
"students",
models.ManyToManyField(
related_name="students", to=settings.AUTH_USER_MODEL
related_name="students", to="course.CourseSessionUser"
),
),
],

View File

@ -1,13 +1,20 @@
from django.db import models
from vbv_lernwelt.core.models import User
from vbv_lernwelt.course.models import CourseSessionUser
class LearningMentor(models.Model):
mentor_email = models.EmailField(primary_key=True)
mentor = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
mentor = models.OneToOneField(
User, on_delete=models.SET_NULL, null=True, blank=True
)
students = models.ManyToManyField(User, related_name="students")
students = models.ManyToManyField(CourseSessionUser, related_name="students")
def __str__(self):
return self.mentor_email
@property
def course_sessions(self):
return self.students.values_list("course_session", flat=True).distinct()

View File

@ -0,0 +1,76 @@
from django.test import TestCase
from vbv_lernwelt.assignment.models import (
AssignmentCompletion,
AssignmentCompletionStatus,
AssignmentType,
)
from vbv_lernwelt.course.creators.test_utils import (
create_assignment,
create_circle,
create_course,
create_course_session,
create_user,
)
from vbv_lernwelt.learning_mentor.views import (
CompletionStatus,
get_assignment_completions,
)
class AttendanceServicesTestCase(TestCase):
def setUp(self):
self.user1 = create_user("Alpha")
self.user2 = create_user("Beta")
self.user3 = create_user("Kappa")
self.user4 = create_user("Gamma")
self.course, self.course_page = create_course("Test Course")
self.course_session = create_course_session(course=self.course, title=":)")
self.circle, _ = create_circle(title="Circle", course_page=self.course_page)
self.assignment = create_assignment(
course=self.course, assignment_type=AssignmentType.CASEWORK
)
AssignmentCompletion.objects.create(
assignment_user=self.user1,
course_session=self.course_session,
assignment=self.assignment,
completion_status=AssignmentCompletionStatus.EVALUATION_SUBMITTED.value,
)
AssignmentCompletion.objects.create(
assignment_user=self.user2,
course_session=self.course_session,
assignment=self.assignment,
completion_status=AssignmentCompletionStatus.SUBMITTED.value,
)
AssignmentCompletion.objects.create(
assignment_user=self.user3,
course_session=self.course_session,
assignment=self.assignment,
completion_status=AssignmentCompletionStatus.IN_PROGRESS.value,
)
def test_assignments(self):
# GIVEN
participants = [self.user1, self.user2, self.user3, self.user4]
# WHEN
results = get_assignment_completions(
self.course_session, self.assignment, participants
)
# THEN
expected_order = ["Beta", "Alpha", "Gamma", "Kappa"]
expected_statuses = {
"Alpha": CompletionStatus.EVALUATED, # user1
"Beta": CompletionStatus.SUBMITTED, # user2
"Gamma": CompletionStatus.PENDING, # user4 (no AssignmentCompletion)
"Kappa": CompletionStatus.PENDING, # user3 (IN_PROGRESS should be PENDING)
}
self.assertEqual(len(results), len(participants))
for i, result in enumerate(results):
self.assertEqual(result.last_name, expected_order[i])
self.assertEqual(result.status, expected_statuses[result.last_name])

View File

@ -1,38 +1,127 @@
from dataclasses import dataclass
from enum import Enum
from typing import List
from rest_framework.decorators import api_view
from rest_framework.response import Response
from vbv_lernwelt.assignment.models import (
Assignment,
AssignmentCompletion,
AssignmentCompletionStatus,
AssignmentType,
)
from vbv_lernwelt.core.models import User
from vbv_lernwelt.core.serializers import UserSerializer
from vbv_lernwelt.course.models import CourseSession
from vbv_lernwelt.feedback.models import FeedbackResponse
from vbv_lernwelt.feedback.utils import feedback_users
from vbv_lernwelt.learnpath.models import Circle
from vbv_lernwelt.course_session.models import CourseSessionAssignment
from vbv_lernwelt.learning_mentor.models import LearningMentor
def get_practical_assignment():
pass
class CompletionStatus(str, Enum):
PENDING = "PENDING"
SUBMITTED = "SUBMITTED"
EVALUATED = "EVALUATED"
def get_feedbacks(course_session: CourseSession):
circle_feedbacks = []
@dataclass
class PraxisAssignmentCompletion:
status: CompletionStatus
user_id: str
last_name: str
fbs = FeedbackResponse.objects.filter(
submitted=True,
@dataclass
class PraxisAssignmentStatus:
id: str
title: str
circle_id: str
completions: List[PraxisAssignmentCompletion]
def get_assignment_completions(
course_session: CourseSession, assignment: Assignment, participants: List[User]
) -> List[PraxisAssignmentCompletion]:
evaluation_results = AssignmentCompletion.objects.filter(
assignment_user__in=participants,
course_session=course_session,
feedback_user__in=feedback_users(course_session.id),
assignment=assignment,
).values("completion_status", "assignment_user__last_name", "assignment_user")
user_status_map = {}
for result in evaluation_results:
completion_status = result["completion_status"]
if completion_status == AssignmentCompletionStatus.EVALUATION_SUBMITTED.value:
status = CompletionStatus.EVALUATED
elif completion_status in [
AssignmentCompletionStatus.SUBMITTED.value,
AssignmentCompletionStatus.EVALUATION_IN_PROGRESS.value,
]:
status = CompletionStatus.SUBMITTED
else:
status = CompletionStatus.PENDING
user_status_map[result["assignment_user"]] = (
status,
result["assignment_user__last_name"],
)
status_priority = {
CompletionStatus.SUBMITTED: 1,
CompletionStatus.EVALUATED: 2,
CompletionStatus.PENDING: 3,
}
sorted_participants = sorted(
participants,
key=lambda u: (
status_priority.get(
user_status_map.get(u.id, (CompletionStatus.PENDING, ""))[0]
),
user_status_map.get(u.id, ("", u.last_name))[1],
),
)
return [
PraxisAssignmentCompletion(
status=user_status_map.get(
user.id, (CompletionStatus.PENDING, user.last_name)
)[0],
user_id=user.id,
last_name=user.last_name,
)
for user in sorted_participants
]
def get_all_feedbacks(course_session: CourseSession):
circle_feedbacks = []
circles = (
course_session.course.get_learning_path()
.get_descendants()
.live()
.specific()
.exact_type(Circle)
)
def get_praxis_assignments(
course_session: CourseSession, participants: List[User]
) -> List[PraxisAssignmentStatus]:
records = []
print(circles)
for course_session_assignment in CourseSessionAssignment.objects.filter(
course_session=course_session,
learning_content__content_assignment__assignment_type__in=[
# TODO: Switch to PRAXIS_ASSIGNMENT
AssignmentType.CASEWORK.value,
],
):
learning_content = course_session_assignment.learning_content
records.append(
PraxisAssignmentStatus(
id=course_session_assignment.id,
title=learning_content.content_assignment.title,
circle_id=learning_content.get_circle().id,
completions=get_assignment_completions(
course_session=course_session,
assignment=learning_content.content_assignment,
participants=participants,
),
)
)
return records
@api_view(["GET"])
@ -43,6 +132,13 @@ def mentor_summary(request, course_session_id: int):
if request.method == "GET":
course_session = CourseSession.objects.get(id=course_session_id)
get_all_feedbacks(course_session)
participants = LearningMentor.objects.filter(mentor=request.user)
return Response({})
return Response(
{
"participants": [UserSerializer(s).data for s in participants],
"praxis_assignments": get_praxis_assignments(
course_session, participants
),
}
)