feat: praxis assignments
This commit is contained in:
parent
278d659905
commit
669dfdd7c1
|
|
@ -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"
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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])
|
||||
|
|
@ -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
|
||||
),
|
||||
}
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in New Issue