feat: course_progress assignment and competence
This commit is contained in:
parent
571b6b347b
commit
0f80fe5104
|
|
@ -2,14 +2,16 @@ from typing import Dict, List, Set, Tuple
|
|||
|
||||
import graphene
|
||||
|
||||
from vbv_lernwelt.assignment.models import AssignmentCompletion, AssignmentCompletionStatus
|
||||
from vbv_lernwelt.core.admin import User
|
||||
from vbv_lernwelt.course.models import Course, CourseSession, CourseSessionUser
|
||||
from vbv_lernwelt.course_session_group.models import CourseSessionGroup
|
||||
from vbv_lernwelt.dashboard.graphql.types.competence import competences
|
||||
from vbv_lernwelt.dashboard.graphql.types.dashboard import (
|
||||
CourseProgressType,
|
||||
CourseStatisticsType,
|
||||
DashboardConfigType,
|
||||
DashboardType,
|
||||
DashboardType, ProgressDashboardCompetenceType, ProgressDashboardAssignmentType,
|
||||
)
|
||||
from vbv_lernwelt.iam.permissions import (
|
||||
can_view_course_session,
|
||||
|
|
@ -87,12 +89,17 @@ class DashboardQuery(graphene.ObjectType):
|
|||
"""
|
||||
|
||||
user = info.context.user
|
||||
newest: CourseSession | None = None
|
||||
course = Course.objects.get(id=course_id)
|
||||
|
||||
newest: CourseSession | None = None
|
||||
course_session_for_user: List[str] = []
|
||||
|
||||
# generation
|
||||
for course_session in CourseSession.objects.filter(course_id=course_id):
|
||||
if can_view_course_session_progress(
|
||||
user=user, course_session=course_session
|
||||
):
|
||||
course_session_for_user.append(course_session)
|
||||
generation_newest = newest.generation if newest else None
|
||||
if (
|
||||
generation_newest is None
|
||||
|
|
@ -100,11 +107,36 @@ class DashboardQuery(graphene.ObjectType):
|
|||
):
|
||||
newest = course_session
|
||||
|
||||
if not newest:
|
||||
return None
|
||||
# competence
|
||||
_, success_total, fail_total = competences(
|
||||
course_slug=str(course.slug),
|
||||
course_session_selection_ids=course_session_for_user
|
||||
)
|
||||
|
||||
# assignment
|
||||
evaluation_results = AssignmentCompletion.objects.filter(
|
||||
completion_status=AssignmentCompletionStatus.EVALUATION_SUBMITTED.value,
|
||||
assignment_user=user,
|
||||
course_session__course=course,
|
||||
).values("evaluation_max_points", "evaluation_points")
|
||||
|
||||
evaluation_results = list(evaluation_results)
|
||||
points_max_count = sum([result.get("evaluation_max_points", 0) for result in evaluation_results])
|
||||
points_achieved_count = sum([result.get("evaluation_points", 0) for result in evaluation_results])
|
||||
|
||||
return CourseProgressType(
|
||||
id=course_id, session_to_continue_id=newest.id # noqa # noqa
|
||||
id=course_id, # noqa
|
||||
session_to_continue_id=newest.id if newest else None, # noqa
|
||||
competence=ProgressDashboardCompetenceType( # noqa
|
||||
total_count=success_total + fail_total, # noqa
|
||||
success_count=success_total, # noqa
|
||||
fail_count=fail_total, # noqa
|
||||
),
|
||||
assignment=ProgressDashboardAssignmentType( # noqa
|
||||
total_count=len(evaluation_results), # noqa
|
||||
points_max_count=points_max_count, # noqa
|
||||
points_achieved_count=points_achieved_count, # noqa
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
from typing import List, Tuple
|
||||
|
||||
import graphene
|
||||
|
||||
from vbv_lernwelt.course.models import CourseCompletion, CourseCompletionStatus
|
||||
|
|
@ -23,16 +25,22 @@ class Competences(graphene.ObjectType):
|
|||
|
||||
|
||||
def competences(
|
||||
course_session_selection_ids: graphene.List(graphene.ID),
|
||||
course_slug: graphene.String,
|
||||
) -> Competences:
|
||||
course_session_selection_ids: List[str],
|
||||
course_slug: str,
|
||||
user_selection_ids: List[str] | None = None,
|
||||
) -> Tuple[List[CompetencePerformance], int, int]:
|
||||
completions = CourseCompletion.objects.filter(
|
||||
course_session_id__in=course_session_selection_ids,
|
||||
page_type="competence.PerformanceCriteria",
|
||||
)
|
||||
|
||||
if user_selection_ids is not None:
|
||||
completions = completions.filter(user_id__in=user_selection_ids)
|
||||
|
||||
competence_performances = {}
|
||||
|
||||
# purely for performance reasons, since looking up
|
||||
# the circle for each completion is expensive :-/
|
||||
circle_cache = {}
|
||||
|
||||
for completion in completions:
|
||||
|
|
@ -58,14 +66,8 @@ def competences(
|
|||
elif completion.completion_status == CourseCompletionStatus.FAIL.value:
|
||||
competence_performances[circle.id].fail_count += 1
|
||||
|
||||
return Competences(
|
||||
performances=competence_performances.values(), # noqa
|
||||
summary=CompletionSummary( # noqa
|
||||
success_total=sum( # noqa
|
||||
[c.success_count for c in competence_performances.values()]
|
||||
),
|
||||
fail_total=sum( # noqa
|
||||
[c.fail_count for c in competence_performances.values()]
|
||||
),
|
||||
),
|
||||
)
|
||||
values = list(competence_performances.values())
|
||||
success_count = sum([c.success_count for c in values])
|
||||
fail_count = sum([c.fail_count for c in values])
|
||||
|
||||
return values, success_count, fail_count
|
||||
|
|
|
|||
|
|
@ -7,7 +7,11 @@ from vbv_lernwelt.dashboard.graphql.types.attendance import (
|
|||
attendance_day_presences,
|
||||
AttendanceDayPresences,
|
||||
)
|
||||
from vbv_lernwelt.dashboard.graphql.types.competence import competences, Competences
|
||||
from vbv_lernwelt.dashboard.graphql.types.competence import (
|
||||
competences,
|
||||
Competences,
|
||||
CompletionSummary,
|
||||
)
|
||||
from vbv_lernwelt.dashboard.graphql.types.feedback import (
|
||||
feedback_responses,
|
||||
FeedbackResponses,
|
||||
|
|
@ -51,9 +55,23 @@ class DashboardConfigType(graphene.ObjectType):
|
|||
dashboard_type = graphene.Field(DashboardType, required=True)
|
||||
|
||||
|
||||
class ProgressDashboardCompetenceType(graphene.ObjectType):
|
||||
total_count = graphene.Int(required=True)
|
||||
success_count = graphene.Int(required=True)
|
||||
fail_count = graphene.Int(required=True)
|
||||
|
||||
|
||||
class ProgressDashboardAssignmentType(graphene.ObjectType):
|
||||
total_count = graphene.Int(required=True)
|
||||
points_max_count = graphene.Int(required=True)
|
||||
points_achieved_count = graphene.Int(required=True)
|
||||
|
||||
|
||||
class CourseProgressType(graphene.ObjectType):
|
||||
id = graphene.ID(required=True) # course_id, named id for urql
|
||||
session_to_continue_id = graphene.ID(required=True)
|
||||
session_to_continue_id = graphene.ID(required=False)
|
||||
competence = graphene.Field(ProgressDashboardCompetenceType, required=True)
|
||||
assignment = graphene.Field(ProgressDashboardAssignmentType, required=True)
|
||||
|
||||
|
||||
class CourseStatisticsType(graphene.ObjectType):
|
||||
|
|
@ -82,9 +100,17 @@ class CourseStatisticsType(graphene.ObjectType):
|
|||
)
|
||||
|
||||
def resolve_competences(root, info) -> Competences:
|
||||
return competences(
|
||||
course_session_selection_ids=root.course_session_selection_ids,
|
||||
course_slug=root.course_slug,
|
||||
performances, success_total, fail_total = competences(
|
||||
course_slug=str(root.course_slug),
|
||||
course_session_selection_ids=[
|
||||
str(cs) for cs in root.course_session_selection_ids # noqa
|
||||
],
|
||||
)
|
||||
return Competences(
|
||||
performances=performances, # noqa
|
||||
summary=CompletionSummary( # noqa
|
||||
success_total=success_total, fail_total=fail_total # noqa
|
||||
),
|
||||
)
|
||||
|
||||
def resolve_assignments(root, info) -> Assignments:
|
||||
|
|
|
|||
|
|
@ -114,7 +114,8 @@ class DashboardAttendanceTestCase(GraphQLTestCase):
|
|||
self.assertEqual(record["participants_total"], 3)
|
||||
self.assertEqual(
|
||||
record["details_url"],
|
||||
f"/course/test-lehrgang/cockpit/attendance?id={attendance_course.learning_content.id}&courseSessionId={course_session.id}",
|
||||
f"/course/test-lehrgang/cockpit/attendance?id={attendance_course.learning_content.id}"
|
||||
f"&courseSessionId={course_session.id}",
|
||||
)
|
||||
|
||||
summary = attendance_day_presences["summary"]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
from graphene_django.utils import GraphQLTestCase
|
||||
|
||||
from vbv_lernwelt.assignment.models import AssignmentType
|
||||
from vbv_lernwelt.course.models import CourseSessionUser
|
||||
from vbv_lernwelt.dashboard.tests.graphql.utils import (
|
||||
add_course_session_group_supervisor,
|
||||
|
|
@ -8,6 +9,8 @@ from vbv_lernwelt.dashboard.tests.graphql.utils import (
|
|||
create_course_session,
|
||||
create_course_session_group,
|
||||
create_user,
|
||||
create_assignment_completion,
|
||||
create_assignment,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -40,12 +43,44 @@ class DashboardTestCase(GraphQLTestCase):
|
|||
course_session=cs_3, user=member, role=CourseSessionUser.Role.MEMBER
|
||||
)
|
||||
|
||||
create_assignment_completion(
|
||||
user=member,
|
||||
assignment=create_assignment(
|
||||
course=course, assignment_type=AssignmentType.CASEWORK
|
||||
),
|
||||
course_session=cs_1,
|
||||
has_passed=True,
|
||||
achieved_points=10,
|
||||
max_points=10,
|
||||
)
|
||||
|
||||
create_assignment_completion(
|
||||
user=member,
|
||||
assignment=create_assignment(
|
||||
course=course, assignment_type=AssignmentType.CASEWORK
|
||||
),
|
||||
course_session=cs_2,
|
||||
has_passed=False,
|
||||
achieved_points=10,
|
||||
max_points=40,
|
||||
)
|
||||
|
||||
self.client.force_login(member)
|
||||
|
||||
query = f"""query($course_id: ID!) {{
|
||||
course_progress(course_id: $course_id) {{
|
||||
id
|
||||
session_to_continue_id
|
||||
competence {{
|
||||
total_count
|
||||
success_count
|
||||
fail_count
|
||||
}}
|
||||
assignment {{
|
||||
total_count
|
||||
points_max_count
|
||||
points_achieved_count
|
||||
}}
|
||||
}}
|
||||
}}
|
||||
"""
|
||||
|
|
@ -63,6 +98,14 @@ class DashboardTestCase(GraphQLTestCase):
|
|||
self.assertEqual(course_progress["id"], str(course.id))
|
||||
self.assertEqual(course_progress["session_to_continue_id"], str(cs_2.id))
|
||||
|
||||
competence = course_progress["competence"]
|
||||
# TODO
|
||||
|
||||
assignment = course_progress["assignment"]
|
||||
self.assertEqual(assignment["total_count"], 2)
|
||||
self.assertEqual(assignment["points_max_count"], 50)
|
||||
self.assertEqual(assignment["points_achieved_count"], 20)
|
||||
|
||||
def test_dashboard_config(self):
|
||||
# GIVEN
|
||||
course_1, _ = create_course("Test Course 1")
|
||||
|
|
|
|||
|
|
@ -181,14 +181,19 @@ def create_assignment_completion(
|
|||
assignment: Assignment,
|
||||
course_session: CourseSession,
|
||||
has_passed: bool | None = None,
|
||||
max_points: int = 0,
|
||||
achieved_points: int = 0,
|
||||
status: AssignmentCompletionStatus = AssignmentCompletionStatus.EVALUATION_SUBMITTED,
|
||||
) -> AssignmentCompletion:
|
||||
return AssignmentCompletion.objects.create(
|
||||
completion_status=AssignmentCompletionStatus.EVALUATION_SUBMITTED.value,
|
||||
completion_status=status.value,
|
||||
assignment_user=user,
|
||||
assignment=assignment,
|
||||
evaluation_passed=has_passed,
|
||||
course_session=course_session,
|
||||
completion_data={},
|
||||
evaluation_max_points=max_points,
|
||||
evaluation_points=achieved_points,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue