-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create onplatform training with json
Added a serializer which will be used to allow admins to create a new training or update the existing training. To track the updates to training(manage versions), we are using semantic versioning. If the updated training has a major update eg: from 1.9 to 2.0, then all the users who did complete the previous versions will be sent an email asking them to complete the new version of training within x days.
- Loading branch information
1 parent
83c59f7
commit 1a22c45
Showing
3 changed files
with
189 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
import datetime | ||
from rest_framework import serializers | ||
from django.db import transaction | ||
from django.utils import timezone | ||
|
||
from training.models import OnPlatformTraining, Module, Quiz, QuizChoice, ContentBlock | ||
from user.models import Training, TrainingType | ||
from notification.utility import notify_users_of_training_expiry | ||
|
||
|
||
NUMBER_OF_DAYS_SET_TO_EXPIRE = 30 | ||
|
||
|
||
class QuizChoiceSerializer(serializers.ModelSerializer): | ||
|
||
class Meta: | ||
model = QuizChoice | ||
fields = "__all__" | ||
read_only_fields = ['id', 'quiz'] | ||
|
||
|
||
class QuizSerializer(serializers.ModelSerializer): | ||
choices = QuizChoiceSerializer(many=True) | ||
|
||
class Meta: | ||
model = Quiz | ||
fields = "__all__" | ||
read_only_fields = ['id', 'module'] | ||
|
||
|
||
class ContentBlockSerializer(serializers.ModelSerializer): | ||
|
||
class Meta: | ||
model = ContentBlock | ||
fields = "__all__" | ||
read_only_fields = ['id', 'module'] | ||
|
||
|
||
class ModuleSerializer(serializers.ModelSerializer): | ||
quizzes = QuizSerializer(many=True) | ||
contents = ContentBlockSerializer(many=True) | ||
|
||
class Meta: | ||
model = Module | ||
fields = "__all__" | ||
read_only_fields = ['id', 'training'] | ||
|
||
|
||
class OnPlatformTrainingSerializer(serializers.ModelSerializer): | ||
modules = ModuleSerializer(many=True) | ||
|
||
class Meta: | ||
model = OnPlatformTraining | ||
fields = "__all__" | ||
read_only_fields = ['id', 'training_type'] | ||
|
||
|
||
class TrainingTypeSerializer(serializers.ModelSerializer): | ||
op_trainings = OnPlatformTrainingSerializer() | ||
|
||
class Meta: | ||
model = TrainingType | ||
fields = "__all__" | ||
read_only_fields = ['id'] | ||
|
||
def update_training_for_major_version_change(self, instance): | ||
""" | ||
If it is a major version change, it sets all former user trainings | ||
to a reduced date, and informs them all. | ||
""" | ||
|
||
trainings = Training.objects.filter( | ||
training_type=instance, | ||
process_datetime__gte=timezone.now() - instance.valid_duration) | ||
_ = trainings.update( | ||
process_datetime=( | ||
timezone.now() - (instance.valid_duration - timezone.timedelta( | ||
days=NUMBER_OF_DAYS_SET_TO_EXPIRE)))) | ||
|
||
for training in trainings: | ||
notify_users_of_training_expiry( | ||
training.user, instance.name, NUMBER_OF_DAYS_SET_TO_EXPIRE) | ||
|
||
def update(self, instance, validated_data): | ||
|
||
with transaction.atomic(): | ||
op_training = validated_data.pop('op_trainings') | ||
modules = op_training.pop('modules') | ||
|
||
op_training['training_type'] = instance | ||
|
||
op_training_instance = OnPlatformTraining.objects.create(**op_training) | ||
|
||
for module in modules: | ||
quizzes = module.pop('quizzes') | ||
contents = module.pop('contents') | ||
|
||
module['training'] = op_training_instance | ||
module_instance = Module.objects.create(**module) | ||
|
||
choice_bulk = [] | ||
for quiz in quizzes: | ||
choices = quiz.pop('choices') | ||
|
||
quiz['module'] = module_instance | ||
q = Quiz(**quiz) | ||
q.save() | ||
|
||
for choice in choices: | ||
choice['quiz'] = q | ||
choice_bulk.append(QuizChoice(**choice)) | ||
|
||
QuizChoice.objects.bulk_create(choice_bulk) | ||
|
||
content_bulk = [] | ||
for content in contents: | ||
content['module'] = module_instance | ||
content_bulk.append(ContentBlock(**content)) | ||
ContentBlock.objects.bulk_create(content_bulk) | ||
|
||
if op_training.get("version"): | ||
if str(op_training.get("version")).endswith("0"): | ||
self.update_training_for_major_version_change(instance) | ||
|
||
return op_training_instance | ||
|
||
def create(self, validated_data): | ||
|
||
with transaction.atomic(): | ||
op_training = validated_data.pop('op_trainings') | ||
modules = op_training.pop('modules') | ||
|
||
op_training['training_type'] = instance = TrainingType.objects.create(**validated_data) | ||
|
||
op_training_instance = OnPlatformTraining.objects.create(**op_training) | ||
|
||
for module in modules: | ||
quizzes = module.pop('quizzes') | ||
contents = module.pop('contents') | ||
|
||
module['training'] = op_training_instance | ||
module_instance = Module.objects.create(**module) | ||
|
||
choice_bulk = [] | ||
for quiz in quizzes: | ||
choices = quiz.pop('choices') | ||
|
||
quiz['module'] = module_instance | ||
q = Quiz(**quiz) | ||
q.save() | ||
|
||
for choice in choices: | ||
choice['quiz'] = q | ||
choice_bulk.append(QuizChoice(**choice)) | ||
|
||
QuizChoice.objects.bulk_create(choice_bulk) | ||
|
||
content_bulk = [] | ||
for content in contents: | ||
content['module'] = module_instance | ||
content_bulk.append(ContentBlock(**content)) | ||
ContentBlock.objects.bulk_create(content_bulk) | ||
|
||
return instance |
9 changes: 9 additions & 0 deletions
9
physionet-django/training/templates/training/email/training_notification.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{% load i18n %}{% autoescape off %}{% filter wordwrap:70 %} | ||
Dear {{ name }}, | ||
|
||
Your training {{ training }} on {{ domain }} will be expiring in {{ expiry }} days. To retain the access it provides, kindly login to your account to retake it. | ||
|
||
|
||
Regards | ||
The {{ SITE_NAME }} Team | ||
{% endfilter %}{% endautoescape %} |