Propagate "deducted" fields via API
This commit is contained in:
parent
7c4300f40c
commit
f71e2e6ff3
|
|
@ -19,6 +19,7 @@ class AssignmentCompletionObjectType(DjangoObjectType):
|
|||
|
||||
# rounded to sensible representation
|
||||
evaluation_points = graphene.Float()
|
||||
evaluation_points_final = graphene.Float()
|
||||
evaluation_max_points = graphene.Float()
|
||||
|
||||
class Meta:
|
||||
|
|
@ -38,6 +39,9 @@ class AssignmentCompletionObjectType(DjangoObjectType):
|
|||
"evaluation_user",
|
||||
"additional_json_data",
|
||||
"edoniq_extended_time_flag",
|
||||
"evaluation_points_deducted",
|
||||
"evaluation_points_deducted_reason",
|
||||
"evaluation_points_deducted_user",
|
||||
"evaluation_passed",
|
||||
"task_completion_data",
|
||||
)
|
||||
|
|
@ -47,6 +51,11 @@ class AssignmentCompletionObjectType(DjangoObjectType):
|
|||
return round(self.evaluation_points, 1) # noqa
|
||||
return None
|
||||
|
||||
def resolve_evaluation_points_final(self, info):
|
||||
if self.evaluation_points:
|
||||
return round(self.evaluation_points_final, 1) # noqa
|
||||
return None
|
||||
|
||||
def resolve_evaluation_max_points(self, info):
|
||||
if self.evaluation_max_points:
|
||||
return round(self.evaluation_max_points, 1) # noqa
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
# Generated by Django 3.2.20 on 2024-05-21 13:43
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assignment', '0013_assignment_competence_certificate_weight'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='assignmentcompletion',
|
||||
name='evaluation_points_deducted',
|
||||
field=models.FloatField(default=0.0, verbose_name='Punkteabzug'),
|
||||
),
|
||||
]
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
# Generated by Django 3.2.20 on 2024-05-21 14:52
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('assignment', '0013_assignment_competence_certificate_weight'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='assignmentcompletion',
|
||||
name='evaluation_points_deducted',
|
||||
field=models.FloatField(default=0.0, verbose_name='Punkteabzug'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='assignmentcompletion',
|
||||
name='evaluation_points_deducted_reason',
|
||||
field=models.TextField(blank=True, default='', verbose_name='Punkteabzug Begründung'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='assignmentcompletion',
|
||||
name='evaluation_points_deducted_user',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
||||
|
|
@ -343,14 +343,26 @@ class AssignmentCompletion(models.Model):
|
|||
evaluation_points_deducted = models.FloatField(
|
||||
default=0.0, verbose_name="Punkteabzug"
|
||||
)
|
||||
evaluation_points_deducted_reason = models.TextField(
|
||||
default="", blank=True, verbose_name="Punkteabzug Begründung"
|
||||
)
|
||||
evaluation_points_deducted_user = models.ForeignKey(
|
||||
User,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name="+",
|
||||
)
|
||||
|
||||
evaluation_max_points = models.FloatField(null=True, blank=True)
|
||||
evaluation_passed = models.BooleanField(null=True, blank=True)
|
||||
edoniq_extended_time_flag = models.BooleanField(default=False)
|
||||
|
||||
@property
|
||||
def evaluation_points_final(self):
|
||||
# with Django>=5 it can be replaced with a `GeneratedField`
|
||||
return (self.evaluation_points or 0.0) - self.evaluation_points_deducted
|
||||
if self.evaluation_points is None:
|
||||
return None
|
||||
return self.evaluation_points - self.evaluation_points_deducted
|
||||
|
||||
assignment_user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
assignment = models.ForeignKey(Assignment, on_delete=models.CASCADE)
|
||||
|
|
@ -399,6 +411,14 @@ class AssignmentCompletion(models.Model):
|
|||
data[task.id] = get_task_data(task, self.completion_data)
|
||||
return data
|
||||
|
||||
def save(
|
||||
self,
|
||||
**kwargs,
|
||||
):
|
||||
if self.evaluation_points_deducted > 0:
|
||||
recalculate_assignment_passed(self)
|
||||
super().save(**kwargs)
|
||||
|
||||
|
||||
def get_file_info(file_id):
|
||||
file_info = UploadFile.objects.filter(id=file_id).first()
|
||||
|
|
@ -456,3 +476,13 @@ class AssignmentCompletionAuditLog(models.Model):
|
|||
evaluation_points = models.FloatField(null=True, blank=True)
|
||||
evaluation_max_points = models.FloatField(null=True, blank=True)
|
||||
evaluation_passed = models.BooleanField(null=True, blank=True)
|
||||
|
||||
|
||||
def recalculate_assignment_passed(ac: AssignmentCompletion):
|
||||
if ac.evaluation_points_final is not None and ac.evaluation_max_points is not None:
|
||||
# if more or equal than 55% of the points are reached, the assignment is passed
|
||||
ac.evaluation_passed = (
|
||||
ac.evaluation_points_final / ac.evaluation_max_points
|
||||
) >= 0.55
|
||||
|
||||
return ac
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ class AssignmentCompletionSerializer(serializers.ModelSerializer):
|
|||
"evaluation_user",
|
||||
"additional_json_data",
|
||||
"evaluation_points",
|
||||
"evaluation_points_deducted",
|
||||
"evaluation_points_deducted_reason",
|
||||
"evaluation_max_points",
|
||||
"evaluation_passed",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ from vbv_lernwelt.assignment.models import (
|
|||
AssignmentCompletionAuditLog,
|
||||
AssignmentCompletionStatus,
|
||||
AssignmentType,
|
||||
is_valid_assignment_completion_status,
|
||||
is_valid_assignment_completion_status, recalculate_assignment_passed,
|
||||
)
|
||||
from vbv_lernwelt.core.models import User
|
||||
from vbv_lernwelt.core.utils import find_first
|
||||
|
|
@ -146,11 +146,7 @@ def update_assignment_completion(
|
|||
|
||||
# if no evaluation_passed is provided, we calculate it from the points
|
||||
if evaluation_passed is None and ac.evaluation_max_points > 0:
|
||||
if evaluation_points is not None and ac.evaluation_max_points is not None:
|
||||
# if more or equal than 60% of the points are reached, the assignment is passed
|
||||
ac.evaluation_passed = (
|
||||
evaluation_points / ac.evaluation_max_points
|
||||
) >= 0.55
|
||||
recalculate_assignment_passed(ac)
|
||||
else:
|
||||
ac.evaluation_passed = evaluation_passed
|
||||
|
||||
|
|
|
|||
|
|
@ -403,6 +403,7 @@ def create_test_assignment_evaluation_data(
|
|||
# take the last input score as deduction if there is one left...
|
||||
if points_deducted > 0:
|
||||
ac.evaluation_points_deducted = points_deducted
|
||||
ac.evaluation_points_deducted_reason = "Assignment Punkteabug Test"
|
||||
ac.save()
|
||||
|
||||
|
||||
|
|
@ -433,6 +434,7 @@ def create_edoniq_test_result_data(
|
|||
|
||||
if evaluation_points_deducted > 0:
|
||||
ac.evaluation_points_deducted = evaluation_points_deducted
|
||||
ac.evaluation_points_deducted_reason = "Edoniq Punkteabug Test"
|
||||
ac.save()
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue