Add more validation to `update_assignment_completion`
This commit is contained in:
parent
19a7738457
commit
9580d79559
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 3.2.13 on 2023-04-24 14:54
|
# Generated by Django 3.2.13 on 2023-04-25 06:49
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
@ -24,11 +24,11 @@ class Migration(migrations.Migration):
|
||||||
('additional_json_data', models.JSONField(default=dict)),
|
('additional_json_data', models.JSONField(default=dict)),
|
||||||
('assignment_user_email', models.CharField(max_length=255)),
|
('assignment_user_email', models.CharField(max_length=255)),
|
||||||
('assignment_slug', models.CharField(max_length=255)),
|
('assignment_slug', models.CharField(max_length=255)),
|
||||||
('graded_expert_email', models.CharField(blank=True, default='', max_length=255)),
|
('grading_user_email', models.CharField(blank=True, default='', max_length=255)),
|
||||||
('assignment', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='assignment.assignment')),
|
('assignment', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='assignment.assignment')),
|
||||||
('assignment_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
|
('assignment_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
|
||||||
('course_session', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='course.coursesession')),
|
('course_session', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='course.coursesession')),
|
||||||
('graded_expert', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
|
('grading_user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
|
|
@ -45,7 +45,7 @@ class Migration(migrations.Migration):
|
||||||
('assignment', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assignment.assignment')),
|
('assignment', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assignment.assignment')),
|
||||||
('assignment_user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
('assignment_user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||||
('course_session', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='course.coursesession')),
|
('course_session', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='course.coursesession')),
|
||||||
('graded_expert', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to=settings.AUTH_USER_MODEL)),
|
('grading_user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to=settings.AUTH_USER_MODEL)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
migrations.AddConstraint(
|
migrations.AddConstraint(
|
||||||
|
|
@ -185,7 +185,7 @@ class AssignmentCompletion(models.Model):
|
||||||
|
|
||||||
submitted_at = models.DateTimeField(null=True, blank=True)
|
submitted_at = models.DateTimeField(null=True, blank=True)
|
||||||
graded_at = models.DateTimeField(null=True, blank=True)
|
graded_at = models.DateTimeField(null=True, blank=True)
|
||||||
graded_expert = models.ForeignKey(
|
grading_user = models.ForeignKey(
|
||||||
User,
|
User,
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
null=True,
|
null=True,
|
||||||
|
|
@ -222,7 +222,7 @@ class AssignmentCompletionAuditLog(models.Model):
|
||||||
|
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
graded_expert = models.ForeignKey(
|
grading_user = models.ForeignKey(
|
||||||
User, on_delete=models.SET_NULL, null=True, blank=True, related_name="+"
|
User, on_delete=models.SET_NULL, null=True, blank=True, related_name="+"
|
||||||
)
|
)
|
||||||
assignment_user = models.ForeignKey(
|
assignment_user = models.ForeignKey(
|
||||||
|
|
@ -246,4 +246,4 @@ class AssignmentCompletionAuditLog(models.Model):
|
||||||
|
|
||||||
assignment_user_email = models.CharField(max_length=255)
|
assignment_user_email = models.CharField(max_length=255)
|
||||||
assignment_slug = models.CharField(max_length=255)
|
assignment_slug = models.CharField(max_length=255)
|
||||||
graded_expert_email = models.CharField(max_length=255, blank=True, default="")
|
grading_user_email = models.CharField(max_length=255, blank=True, default="")
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,13 @@ class AssignmentCompletionSerializer(serializers.ModelSerializer):
|
||||||
"id",
|
"id",
|
||||||
"created_at",
|
"created_at",
|
||||||
"updated_at",
|
"updated_at",
|
||||||
"user",
|
"submitted_at",
|
||||||
|
"graded_at",
|
||||||
|
"assignment_user",
|
||||||
"assignment",
|
"assignment",
|
||||||
"course_session",
|
"course_session",
|
||||||
"completion_status",
|
"completion_status",
|
||||||
"completion_data",
|
"completion_data",
|
||||||
|
"grading_user",
|
||||||
"additional_json_data",
|
"additional_json_data",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,14 @@
|
||||||
|
from copy import deepcopy
|
||||||
from typing import Type
|
from typing import Type
|
||||||
|
|
||||||
|
from django.utils import timezone
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
from vbv_lernwelt.assignment.models import (
|
from vbv_lernwelt.assignment.models import (
|
||||||
Assignment,
|
Assignment,
|
||||||
AssignmentCompletion,
|
AssignmentCompletion,
|
||||||
AssignmentCompletionStatus,
|
AssignmentCompletionStatus,
|
||||||
|
AssignmentCompletionAuditLog,
|
||||||
)
|
)
|
||||||
from vbv_lernwelt.core.models import User
|
from vbv_lernwelt.core.models import User
|
||||||
from vbv_lernwelt.core.utils import find_first
|
from vbv_lernwelt.core.utils import find_first
|
||||||
|
|
@ -16,6 +21,8 @@ def update_assignment_completion(
|
||||||
course_session: CourseSession,
|
course_session: CourseSession,
|
||||||
completion_data=None,
|
completion_data=None,
|
||||||
completion_status: Type[AssignmentCompletionStatus] = "in_progress",
|
completion_status: Type[AssignmentCompletionStatus] = "in_progress",
|
||||||
|
grading_user: User | None = None,
|
||||||
|
validate_completion_status_change: bool = True,
|
||||||
copy_task_data: bool = False,
|
copy_task_data: bool = False,
|
||||||
) -> AssignmentCompletion:
|
) -> AssignmentCompletion:
|
||||||
"""
|
"""
|
||||||
|
|
@ -46,6 +53,35 @@ def update_assignment_completion(
|
||||||
course_session_id=course_session.id,
|
course_session_id=course_session.id,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if validate_completion_status_change:
|
||||||
|
# TODO: check time?
|
||||||
|
if completion_status == "submitted":
|
||||||
|
if ac.completion_status in ["submitted", "grading_in_progress", "graded"]:
|
||||||
|
raise serializers.ValidationError(
|
||||||
|
{
|
||||||
|
"completion_status": f"Cannot update completion status from {ac.completion_status} to submitted"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
elif completion_status == "graded":
|
||||||
|
if ac.completion_status == "graded":
|
||||||
|
raise serializers.ValidationError(
|
||||||
|
{
|
||||||
|
"completion_status": f"Cannot update completion status from {ac.completion_status} to graded"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if completion_status in ["graded", "grading_in_progress"]:
|
||||||
|
if grading_user is None:
|
||||||
|
raise serializers.ValidationError(
|
||||||
|
{"grading_user": "grading_user is required for graded status"}
|
||||||
|
)
|
||||||
|
ac.grading_user = grading_user
|
||||||
|
|
||||||
|
if completion_status == "submitted":
|
||||||
|
ac.submitted_at = timezone.now()
|
||||||
|
elif completion_status == "graded":
|
||||||
|
ac.graded_at = timezone.now()
|
||||||
|
|
||||||
ac.completion_status = completion_status
|
ac.completion_status = completion_status
|
||||||
|
|
||||||
# TODO: make more validation of the provided input -> maybe with graphql
|
# TODO: make more validation of the provided input -> maybe with graphql
|
||||||
|
|
@ -65,6 +101,27 @@ def update_assignment_completion(
|
||||||
|
|
||||||
ac.save()
|
ac.save()
|
||||||
|
|
||||||
|
if completion_status in ["graded", "submitted"]:
|
||||||
|
acl = AssignmentCompletionAuditLog.objects.create(
|
||||||
|
assignment_user=assignment_user,
|
||||||
|
assignment=assignment,
|
||||||
|
course_session=course_session,
|
||||||
|
grading_user=grading_user,
|
||||||
|
completion_status=completion_status,
|
||||||
|
assignment_user_email=assignment_user.email,
|
||||||
|
assignment_slug=assignment.slug,
|
||||||
|
completion_data=deepcopy(ac.completion_data),
|
||||||
|
)
|
||||||
|
if grading_user:
|
||||||
|
acl.grading_user_email = grading_user.email
|
||||||
|
|
||||||
|
# copy over the question data, so that we don't lose the context
|
||||||
|
substasks = assignment.filter_user_subtasks()
|
||||||
|
for key, value in acl.completion_data.items():
|
||||||
|
task_data = find_first(substasks, pred=lambda x: x["id"] == key)
|
||||||
|
acl.completion_data[key].update(task_data)
|
||||||
|
acl.save()
|
||||||
|
|
||||||
return ac
|
return ac
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,9 @@ class AssignmentApiStudentTestCase(APITestCase):
|
||||||
course_session=self.cs,
|
course_session=self.cs,
|
||||||
user=self.user,
|
user=self.user,
|
||||||
)
|
)
|
||||||
self.client.login(username="student", password="test")
|
|
||||||
|
|
||||||
def test_can_updateAssignmentCompletion_asStudent(self):
|
def test_can_updateAssignmentCompletion_asStudent(self):
|
||||||
|
self.client.login(username="student", password="test")
|
||||||
url = f"/api/assignment/update/"
|
url = f"/api/assignment/update/"
|
||||||
|
|
||||||
user_text_input = find_first(
|
user_text_input = find_first(
|
||||||
|
|
@ -53,7 +53,7 @@ class AssignmentApiStudentTestCase(APITestCase):
|
||||||
print(json.dumps(response.json(), indent=2))
|
print(json.dumps(response.json(), indent=2))
|
||||||
|
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(response_json["user"], self.user.id)
|
self.assertEqual(response_json["assignment_user"], self.user.id)
|
||||||
self.assertEqual(response_json["assignment"], self.assignment.id)
|
self.assertEqual(response_json["assignment"], self.assignment.id)
|
||||||
self.assertEqual(response_json["completion_status"], "in_progress")
|
self.assertEqual(response_json["completion_status"], "in_progress")
|
||||||
self.assertDictEqual(
|
self.assertDictEqual(
|
||||||
|
|
@ -64,7 +64,7 @@ class AssignmentApiStudentTestCase(APITestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
db_entry = AssignmentCompletion.objects.get(
|
db_entry = AssignmentCompletion.objects.get(
|
||||||
user=self.user,
|
assignment_user=self.user,
|
||||||
course_session_id=self.cs.id,
|
course_session_id=self.cs.id,
|
||||||
assignment_id=self.assignment.id,
|
assignment_id=self.assignment.id,
|
||||||
)
|
)
|
||||||
|
|
@ -89,3 +89,48 @@ class AssignmentApiStudentTestCase(APITestCase):
|
||||||
user_text_input["id"]: {"user_data": {"text": "Hallo via API"}},
|
user_text_input["id"]: {"user_data": {"text": "Hallo via API"}},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# submit the assignment
|
||||||
|
response = self.client.post(
|
||||||
|
url,
|
||||||
|
{
|
||||||
|
"assignment_id": self.assignment.id,
|
||||||
|
"course_session_id": self.cs.id,
|
||||||
|
"completion_status": "submitted",
|
||||||
|
"completion_data": {
|
||||||
|
user_text_input["id"]: {"user_data": {"text": "Hallo via API 2"}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
format="json",
|
||||||
|
)
|
||||||
|
response_json = response.json()
|
||||||
|
print(json.dumps(response.json(), indent=2))
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertEqual(response_json["assignment_user"], self.user.id)
|
||||||
|
self.assertEqual(response_json["assignment"], self.assignment.id)
|
||||||
|
self.assertEqual(response_json["completion_status"], "submitted")
|
||||||
|
self.assertDictEqual(
|
||||||
|
response_json["completion_data"],
|
||||||
|
{
|
||||||
|
user_text_input["id"]: {"user_data": {"text": "Hallo via API 2"}},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
# second submit will fail
|
||||||
|
response = self.client.post(
|
||||||
|
url,
|
||||||
|
{
|
||||||
|
"assignment_id": self.assignment.id,
|
||||||
|
"course_session_id": self.cs.id,
|
||||||
|
"completion_status": "submitted",
|
||||||
|
"completion_data": {
|
||||||
|
user_text_input["id"]: {"user_data": {"text": "Hallo via API 2"}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
format="json",
|
||||||
|
)
|
||||||
|
response_json = response.json()
|
||||||
|
print(json.dumps(response.json(), indent=2))
|
||||||
|
self.assertEqual(response.status_code, 404)
|
||||||
|
self.assertTrue("Cannot update completion status" in str(response_json))
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,14 @@
|
||||||
|
from datetime import date
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
from django.utils import timezone
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
from vbv_lernwelt.assignment.creators.create_assignments import create_test_assignment
|
from vbv_lernwelt.assignment.creators.create_assignments import create_test_assignment
|
||||||
from vbv_lernwelt.assignment.models import AssignmentCompletion
|
from vbv_lernwelt.assignment.models import (
|
||||||
|
AssignmentCompletion,
|
||||||
|
AssignmentCompletionAuditLog,
|
||||||
|
)
|
||||||
from vbv_lernwelt.assignment.services import update_assignment_completion
|
from vbv_lernwelt.assignment.services import update_assignment_completion
|
||||||
from vbv_lernwelt.core.create_default_users import create_default_users
|
from vbv_lernwelt.core.create_default_users import create_default_users
|
||||||
from vbv_lernwelt.core.models import User
|
from vbv_lernwelt.core.models import User
|
||||||
|
|
@ -26,6 +33,7 @@ class UpdateAssignmentCompletionTestCase(TestCase):
|
||||||
title="Bern 2022 a",
|
title="Bern 2022 a",
|
||||||
)
|
)
|
||||||
self.user = User.objects.get(username="student")
|
self.user = User.objects.get(username="student")
|
||||||
|
self.trainer = User.objects.get(username="admin")
|
||||||
|
|
||||||
def test_can_store_new_user_input(self):
|
def test_can_store_new_user_input(self):
|
||||||
subtasks = self.assignment.filter_user_subtasks()
|
subtasks = self.assignment.filter_user_subtasks()
|
||||||
|
|
@ -126,7 +134,7 @@ class UpdateAssignmentCompletionTestCase(TestCase):
|
||||||
)
|
)
|
||||||
self.assertEqual(ac.completion_data, {})
|
self.assertEqual(ac.completion_data, {})
|
||||||
|
|
||||||
def test_change_completion_status(self):
|
def test_completion_status_submitted(self):
|
||||||
subtasks = self.assignment.filter_user_subtasks(
|
subtasks = self.assignment.filter_user_subtasks(
|
||||||
subtask_types=["user_text_input"]
|
subtask_types=["user_text_input"]
|
||||||
)
|
)
|
||||||
|
|
@ -161,6 +169,84 @@ class UpdateAssignmentCompletionTestCase(TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(ac.completion_status, "submitted")
|
self.assertEqual(ac.completion_status, "submitted")
|
||||||
|
self.assertEqual(ac.submitted_at.date(), date.today())
|
||||||
|
|
||||||
|
# will create AssignmentCompletionAuditLog entry
|
||||||
|
acl = AssignmentCompletionAuditLog.objects.get(
|
||||||
|
assignment_user=self.user,
|
||||||
|
assignment=self.assignment,
|
||||||
|
course_session=self.course_session,
|
||||||
|
completion_status="submitted",
|
||||||
|
)
|
||||||
|
self.assertEqual(acl.created_at.date(), date.today())
|
||||||
|
self.assertEqual(acl.assignment_user_email, "student")
|
||||||
|
self.assertEqual(
|
||||||
|
acl.assignment_slug,
|
||||||
|
"versicherungsvermittler-in-assignment-überprüfen-einer-motorfahrzeugs-versicherungspolice",
|
||||||
|
)
|
||||||
|
|
||||||
|
# AssignmentCompletionAuditLog entry will remain event after deletion of foreign keys
|
||||||
|
ac.delete()
|
||||||
|
self.user.delete()
|
||||||
|
self.assignment.delete()
|
||||||
|
acl = AssignmentCompletionAuditLog.objects.get(id=acl.id)
|
||||||
|
self.assertEqual(acl.created_at.date(), date.today())
|
||||||
|
self.assertEqual(acl.assignment_user_email, "student")
|
||||||
|
self.assertEqual(
|
||||||
|
acl.assignment_slug,
|
||||||
|
"versicherungsvermittler-in-assignment-überprüfen-einer-motorfahrzeugs-versicherungspolice",
|
||||||
|
)
|
||||||
|
self.assertIsNone(acl.assignment_user)
|
||||||
|
self.assertIsNone(acl.assignment)
|
||||||
|
|
||||||
|
def test_completion_status_submitted_cannot_submit_twice(self):
|
||||||
|
subtasks = self.assignment.filter_user_subtasks(
|
||||||
|
subtask_types=["user_text_input"]
|
||||||
|
)
|
||||||
|
user_text_input0 = subtasks[0]
|
||||||
|
user_text_input1 = subtasks[1]
|
||||||
|
|
||||||
|
ac = AssignmentCompletion.objects.create(
|
||||||
|
assignment_user=self.user,
|
||||||
|
assignment=self.assignment,
|
||||||
|
course_session=self.course_session,
|
||||||
|
submitted_at=timezone.now(),
|
||||||
|
completion_status="submitted",
|
||||||
|
completion_data={
|
||||||
|
user_text_input0["id"]: {
|
||||||
|
"user_data": {"text": "Am Anfang war das Wort... 0"}
|
||||||
|
},
|
||||||
|
user_text_input1["id"]: {
|
||||||
|
"user_data": {"text": "Am Anfang war das Wort... 1"}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
with self.assertRaises(serializers.ValidationError) as error:
|
||||||
|
update_assignment_completion(
|
||||||
|
assignment_user=self.user,
|
||||||
|
assignment=self.assignment,
|
||||||
|
course_session=self.course_session,
|
||||||
|
completion_status="submitted",
|
||||||
|
)
|
||||||
|
|
||||||
|
# can submit twice with flag
|
||||||
|
update_assignment_completion(
|
||||||
|
assignment_user=self.user,
|
||||||
|
assignment=self.assignment,
|
||||||
|
course_session=self.course_session,
|
||||||
|
completion_status="submitted",
|
||||||
|
validate_completion_status_change=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
ac = AssignmentCompletion.objects.get(
|
||||||
|
assignment_user=self.user,
|
||||||
|
assignment=self.assignment,
|
||||||
|
course_session=self.course_session,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(ac.completion_status, "submitted")
|
||||||
|
self.assertEqual(ac.submitted_at.date(), date.today())
|
||||||
|
|
||||||
def test_copy_task_data(self):
|
def test_copy_task_data(self):
|
||||||
subtasks = self.assignment.filter_user_subtasks(
|
subtasks = self.assignment.filter_user_subtasks(
|
||||||
|
|
@ -210,7 +296,7 @@ class UpdateAssignmentCompletionTestCase(TestCase):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_can_add_trainer_data_without_loosing_user_input_data(self):
|
def test_can_add_grading_data_without_loosing_user_input_data(self):
|
||||||
subtasks = self.assignment.filter_user_subtasks(
|
subtasks = self.assignment.filter_user_subtasks(
|
||||||
subtask_types=["user_text_input"]
|
subtask_types=["user_text_input"]
|
||||||
)
|
)
|
||||||
|
|
@ -226,6 +312,7 @@ class UpdateAssignmentCompletionTestCase(TestCase):
|
||||||
assignment_user=self.user,
|
assignment_user=self.user,
|
||||||
assignment=self.assignment,
|
assignment=self.assignment,
|
||||||
course_session=self.course_session,
|
course_session=self.course_session,
|
||||||
|
completion_status="submitted",
|
||||||
completion_data={
|
completion_data={
|
||||||
user_text_input["id"]: {
|
user_text_input["id"]: {
|
||||||
"user_data": {"text": "Ich würde nichts weiteres empfehlen."}
|
"user_data": {"text": "Ich würde nichts weiteres empfehlen."}
|
||||||
|
|
@ -243,6 +330,7 @@ class UpdateAssignmentCompletionTestCase(TestCase):
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
completion_status="grading_in_progress",
|
completion_status="grading_in_progress",
|
||||||
|
grading_user=self.trainer,
|
||||||
)
|
)
|
||||||
|
|
||||||
ac = AssignmentCompletion.objects.get(
|
ac = AssignmentCompletion.objects.get(
|
||||||
|
|
@ -259,3 +347,44 @@ class UpdateAssignmentCompletionTestCase(TestCase):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
user_input["user_data"]["text"], "Ich würde nichts weiteres empfehlen."
|
user_input["user_data"]["text"], "Ich würde nichts weiteres empfehlen."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_cannot_grading_data_without_grading_user(self):
|
||||||
|
subtasks = self.assignment.filter_user_subtasks(
|
||||||
|
subtask_types=["user_text_input"]
|
||||||
|
)
|
||||||
|
user_text_input = find_first(
|
||||||
|
subtasks,
|
||||||
|
pred=lambda x: (value := x.get("value"))
|
||||||
|
and value.get("text", "").startswith(
|
||||||
|
"Gibt es zusätzliche Deckungen, die du der Person empfehlen würdest?"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
ac = AssignmentCompletion.objects.create(
|
||||||
|
assignment_user=self.user,
|
||||||
|
assignment=self.assignment,
|
||||||
|
course_session=self.course_session,
|
||||||
|
completion_status="in_progress",
|
||||||
|
completion_data={
|
||||||
|
user_text_input["id"]: {
|
||||||
|
"user_data": {"text": "Ich würde nichts weiteres empfehlen."}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
with self.assertRaises(serializers.ValidationError) as error:
|
||||||
|
update_assignment_completion(
|
||||||
|
assignment_user=self.user,
|
||||||
|
assignment=self.assignment,
|
||||||
|
course_session=self.course_session,
|
||||||
|
completion_status="grading_in_progress",
|
||||||
|
completion_data={
|
||||||
|
user_text_input["id"]: {
|
||||||
|
"trainer_data": {"points": 1, "comment": "Gut gemacht!"}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertTrue(
|
||||||
|
"grading_user" in error.exception.detail,
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,13 @@ from vbv_lernwelt.course.permissions import (
|
||||||
logger = structlog.get_logger(__name__)
|
logger = structlog.get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def _request_assignment_completion(assignment_id, course_session_id, user_id):
|
def _request_assignment_completion(
|
||||||
|
assignment_id, course_session_id, assignment_user_id
|
||||||
|
):
|
||||||
try:
|
try:
|
||||||
response_data = AssignmentCompletionSerializer(
|
response_data = AssignmentCompletionSerializer(
|
||||||
AssignmentCompletion.objects.get(
|
AssignmentCompletion.objects.get(
|
||||||
user_id=user_id,
|
assignment_user_id=assignment_user_id,
|
||||||
assignment_id=assignment_id,
|
assignment_id=assignment_id,
|
||||||
course_session_id=course_session_id,
|
course_session_id=course_session_id,
|
||||||
),
|
),
|
||||||
|
|
@ -41,7 +43,7 @@ def request_assignment_completion(request, assignment_id, course_session_id):
|
||||||
return _request_assignment_completion(
|
return _request_assignment_completion(
|
||||||
assignment_id=assignment_id,
|
assignment_id=assignment_id,
|
||||||
course_session_id=course_session_id,
|
course_session_id=course_session_id,
|
||||||
user_id=request.user.id,
|
assignment_user_id=request.user.id,
|
||||||
)
|
)
|
||||||
raise PermissionDenied()
|
raise PermissionDenied()
|
||||||
|
|
||||||
|
|
@ -56,7 +58,7 @@ def request_assignment_completion_for_user(
|
||||||
return _request_assignment_completion(
|
return _request_assignment_completion(
|
||||||
assignment_id=assignment_id,
|
assignment_id=assignment_id,
|
||||||
course_session_id=course_session_id,
|
course_session_id=course_session_id,
|
||||||
user_id=user_id,
|
assignment_user_id=user_id,
|
||||||
)
|
)
|
||||||
raise PermissionDenied()
|
raise PermissionDenied()
|
||||||
|
|
||||||
|
|
@ -77,7 +79,7 @@ def update_assignment_input(request):
|
||||||
assignment = assignment_page.specific
|
assignment = assignment_page.specific
|
||||||
|
|
||||||
ac = update_assignment_completion(
|
ac = update_assignment_completion(
|
||||||
user=request.user,
|
assignment_user=request.user,
|
||||||
assignment=assignment,
|
assignment=assignment,
|
||||||
course_session=CourseSession.objects.get(id=course_session_id),
|
course_session=CourseSession.objects.get(id=course_session_id),
|
||||||
completion_data=completion_data,
|
completion_data=completion_data,
|
||||||
|
|
|
||||||
|
|
@ -311,7 +311,7 @@ def create_course_uk_de_assignment_completion_data(assignment, course_session, u
|
||||||
user_text = f"Lorem ipsum dolor sit amet... {index}"
|
user_text = f"Lorem ipsum dolor sit amet... {index}"
|
||||||
|
|
||||||
update_assignment_completion(
|
update_assignment_completion(
|
||||||
user=user,
|
assignment_user=user,
|
||||||
assignment=assignment,
|
assignment=assignment,
|
||||||
course_session=course_session,
|
course_session=course_session,
|
||||||
completion_data={
|
completion_data={
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue