diff --git a/src/tesla_ce/apps/api/v2/serializers/institution/alert.py b/src/tesla_ce/apps/api/v2/serializers/institution/alert.py new file mode 100644 index 0000000..c25b4e4 --- /dev/null +++ b/src/tesla_ce/apps/api/v2/serializers/institution/alert.py @@ -0,0 +1,50 @@ +# Copyright (c) 2020 Xavier Baró +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +""" Alert serializer module """ +import json + +from rest_framework import serializers +from tesla_ce.models import Alert, Message + + +class MessageSerializer(serializers.ModelSerializer): + """Message serialize model module.""" + class Meta: + model = Message + fields = "__all__" + + +class AlertSerializer(serializers.ModelSerializer): + """Alert serialize model module.""" + data = serializers.SerializerMethodField() + message = MessageSerializer(read_only=True, many=False, source='message_code', required=False) + + class Meta: + model = Alert + fields = "__all__" + + @staticmethod + def get_data(obj): + """ Get data """ + content = {} + + with obj.data.open() as f: + try: + content_json = f.read().decode('utf-8') + content = json.loads(content_json) + except Exception: + pass + + return content diff --git a/src/tesla_ce/lib/data/VERSION b/src/tesla_ce/lib/data/VERSION index b0f3d96..66c4c22 100644 --- a/src/tesla_ce/lib/data/VERSION +++ b/src/tesla_ce/lib/data/VERSION @@ -1 +1 @@ -1.0.8 +1.0.9 diff --git a/src/tesla_ce/models/report_activity_instrument.py b/src/tesla_ce/models/report_activity_instrument.py index 2ee4525..396bbc9 100644 --- a/src/tesla_ce/models/report_activity_instrument.py +++ b/src/tesla_ce/models/report_activity_instrument.py @@ -22,6 +22,7 @@ from django.dispatch import receiver from django.utils.translation import gettext_lazy as _ +from .alert import Alert from .base_model import BaseModel from .instrument import Instrument from .report_activity import REPORT_ALERT_LEVEL @@ -43,6 +44,7 @@ class ResultFacts(Enum): NEGATIVE_LEARNER_RESULT_BAD_ACTIVITY = -3 NEGATIVE_LEARNER_RESULT_NOT_FREQUENT = -4 NEGATIVE_CONFIDENCE_LOW = -5 + NEGATIVE_WITH_ALERTS = -6 class ReportActivityInstrument(BaseModel): @@ -222,6 +224,11 @@ def get_facts(self): if self.get_prob_learner() > 0.8: facts['positive'].append(ResultFacts.POSITIVE_LEARNER_RESULT_FREQUENT.name) + # check if there are any alerts + if Alert.objects.filter(session__activity=self.report.activity, + session__learner=self.report.learner).count() > 0: + facts['negative'].append(ResultFacts.NEGATIVE_WITH_ALERTS.name) + return facts def update_audit(self): diff --git a/src/tesla_ce/tasks/reports/results.py b/src/tesla_ce/tasks/reports/results.py index dd57bcc..38cfc44 100644 --- a/src/tesla_ce/tasks/reports/results.py +++ b/src/tesla_ce/tasks/reports/results.py @@ -1,4 +1,4 @@ -# Copyright (c) 2020 Xavier Baró +# Copyright (c) 2020 Xavier Baró # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -121,13 +121,15 @@ def update_learner_activity_session_report(self, learner_id, activity_id, sessio list(results_qs.values_list('created_at', 'result').order_by('created_at')), cls=DjangoJSONEncoder) + from tesla_ce.apps.api.v2.serializers.institution.alert import AlertSerializer session_data = { 'instruments': list(results_qs.values_list('instrument', flat=True).distinct()), - 'alerts': json.dumps( - list(models.Alert.objects.filter(session_id=session_id).order_by('created_at')), - cls=DjangoJSONEncoder), - 'data': data + 'alerts': list(AlertSerializer(models.Alert.objects.filter(session_id=session_id).order_by('created_at'), + many=True).data), + 'data': data, + 'session_id': session_id } + data_path = '{}/results/{}/{}/{}/session_{}.json'.format( session_report.session.activity.vle.institution_id, session_report.session.learner.learner_id, @@ -138,6 +140,31 @@ def update_learner_activity_session_report(self, learner_id, activity_id, sessio session_report.data.save(data_path, ContentFile(json.dumps(session_data, cls=DjangoJSONEncoder).encode('utf-8'))) + max_level = 2 # Ok + + # Update session_report levels with alerts information + if len(session_data['alerts']) > 0: + if models.Alert.objects.filter(session_id=session_id, level=2).count() > 0: + max_level = 4 # Alert + elif models.Alert.objects.filter(session_id=session_id, level__in=[1, 3]).count() > 0: + max_level = 3 # Warning + + # todo: Update session_report levels with provider results + session_report.identity_level = 1 + session_report.content_level = 1 + session_report.integrity_level = 1 + + for activity_instrument in session_report.session.activity.get_learner_instruments( + session_report.session.learner): + if activity_instrument.instrument.identity: + session_report.identity_level = max_level + + if activity_instrument.instrument.originality or activity_instrument.instrument.authorship: + session_report.content_level = max_level + + if activity_instrument.instrument.integrity: + session_report.integrity_level = max_level + session_report.save() @@ -310,6 +337,15 @@ def update_learner_activity_report(learner_id, activity_id, force_update=False): 'data': session_data }) + if session.identity_level > report.identity_level: + report.identity_level = session.identity_level + + if session.integrity_level > report.integrity_level: + report.integrity_level = session.integrity_level + + if session.content_level > report.content_level: + report.content_level = session.content_level + # Add results for attachments without session documents = models.Request.objects.filter(learner_id=learner_id, activity_id=activity_id, @@ -342,10 +378,14 @@ def update_learner_activity_report(learner_id, activity_id, force_update=False): @celery_app.task(ignore_result=True) -def update_activity_report(activity_id): - pass +def update_activity_report(activity_id, force_update=False): + activity = models.Activity.objects.get(id=activity_id) + + for learner in activity.course.learners.all(): + update_learner_activity_report(activity_id=activity_id, learner_id=learner.id, force_update=force_update) @celery_app.task(ignore_result=True) -def update_course_report(course_id): - pass +def update_course_report(course_id, force_update=False): + for activity in models.Activity.objects.filter(course_id=course_id): + update_activity_report(activity.id, force_update=False)