Commit 3cbf80bd authored by Bruno Martin's avatar Bruno Martin
Browse files

Merge branch 'develop'

parents 5d7f8d82 e506169c
...@@ -4,12 +4,10 @@ from .models import ( ...@@ -4,12 +4,10 @@ from .models import (
CourseCertification, CourseCertification,
CertificateTemplate, CertificateTemplate,
CertificationProcess, CertificationProcess,
CertificateData,
Evaluation, Evaluation,
) )
admin.site.register(CourseCertification) admin.site.register(CourseCertification)
admin.site.register(CertificateTemplate) admin.site.register(CertificateTemplate)
admin.site.register(CertificationProcess) admin.site.register(CertificationProcess)
admin.site.register(CertificateData)
admin.site.register(Evaluation) admin.site.register(Evaluation)
...@@ -3,3 +3,6 @@ from django.apps import AppConfig ...@@ -3,3 +3,6 @@ from django.apps import AppConfig
class CoursesCertificationConfig(AppConfig): class CoursesCertificationConfig(AppConfig):
name = 'courses.certification' name = 'courses.certification'
def ready(self):
import courses.certification.signals
\ No newline at end of file
# Generated by Django 2.2.13 on 2020-07-01 02:23
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('certification', '0002_certificatedata'),
]
operations = [
migrations.AlterField(
model_name='certificatedata',
name='workspace',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='courses.Workspace'),
),
]
# Generated by Django 2.2.13 on 2020-07-03 23:23
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('courses', '0009_auto_20200609_1453'),
('certification', '0003_auto_20200630_2323'),
]
operations = [
migrations.AddField(
model_name='certificatetemplate',
name='document_type',
field=models.CharField(choices=[('receipt', 'Receipt'), ('certificate', 'Certificate')], default='receipt', max_length=127, verbose_name='Certificate Type'),
),
migrations.AddField(
model_name='certificatetemplate',
name='site_logo',
field=models.ImageField(blank=True, null=True, upload_to='certificates_files', verbose_name='Site Logo'),
),
migrations.AddField(
model_name='certificatetemplate',
name='text',
field=models.TextField(default='', verbose_name='Content'),
),
migrations.AddField(
model_name='certificatetemplate',
name='workspace',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='courses.Workspace'),
),
migrations.AlterUniqueTogether(
name='certificatetemplate',
unique_together={('workspace', 'course', 'document_type')},
),
migrations.DeleteModel(
name='CertificateData',
),
]
...@@ -197,6 +197,10 @@ class CertificationProcess(models.Model): ...@@ -197,6 +197,10 @@ class CertificationProcess(models.Model):
class CertificateTemplate(models.Model): class CertificateTemplate(models.Model):
TYPES = (
('receipt', _('Receipt')),
('certificate', _('Certificate')),
)
course = models.ForeignKey( course = models.ForeignKey(
Course, Course,
...@@ -233,15 +237,36 @@ class CertificateTemplate(models.Model): ...@@ -233,15 +237,36 @@ class CertificateTemplate(models.Model):
blank=True, blank=True,
upload_to=hash_name('signature', 'organization_name'), upload_to=hash_name('signature', 'organization_name'),
) )
site_logo = models.ImageField(
_('Site Logo'),
null=True,
blank=True,
upload_to='certificates_files'
)
organization_name = models.CharField( organization_name = models.CharField(
_('Name'), _('Name'),
max_length=255, max_length=255,
blank=True, blank=True,
null=True, null=True,
) )
text = models.TextField(_('Content'), default='')
document_type = models.CharField(
_('Certificate Type'),
choices=TYPES,
max_length=127,
default=TYPES[0][0]
)
workspace = models.ForeignKey(
Workspace,
models.CASCADE,
null=True
)
class Meta: class Meta:
verbose_name = _('Certificate Template') verbose_name = _('Certificate Template')
unique_together = ('workspace', 'course', 'document_type')
def __unicode__(self): def __unicode__(self):
return '({0})'.format(self.course) return '({0})'.format(self.course)
...@@ -267,39 +292,6 @@ class CertificateTemplate(models.Model): ...@@ -267,39 +292,6 @@ class CertificateTemplate(models.Model):
return self.signature.url return self.signature.url
return '' return ''
class CertificateData(models.Model):
site_logo = models.ImageField(_('Site Logo'), null=True, blank=True,
upload_to='certificates_files')
text = models.TextField(_('Content'), default='')
TYPES = (
('receipt', _('Receipt')),
('certificate', _('Certificate')),
)
type = models.CharField(
_('Certificate Type'),
choices=TYPES,
max_length=127,
)
workspace = models.ForeignKey(
Workspace,
models.CASCADE,
)
certificate_template = models.ForeignKey(
CertificateTemplate,
models.CASCADE,
)
class Meta:
verbose_name = _('Certificate Data')
unique_together = ('workspace', 'certificate_template', 'type')
def __str__(self):
return 'Data of {0} ({1})'.format(self.workspace, self.type)
@property @property
def site_logo_url(self): def site_logo_url(self):
if self.site_logo: if self.site_logo:
...@@ -307,5 +299,5 @@ class CertificateData(models.Model): ...@@ -307,5 +299,5 @@ class CertificateData(models.Model):
return '' return ''
@property @property
def contrat(self): def contract(self):
return self.workspace return self.workspace
...@@ -3,7 +3,6 @@ from rest_framework import serializers, status ...@@ -3,7 +3,6 @@ from rest_framework import serializers, status
from courses.workspaces.serializers import SimpleWorkspaceSerializer from courses.workspaces.serializers import SimpleWorkspaceSerializer
from courses.certification.models import ( from courses.certification.models import (
CertificateData,
CertificateTemplate, CertificateTemplate,
CertificationProcess, CertificationProcess,
Evaluation, Evaluation,
...@@ -12,68 +11,48 @@ from courses.certification.models import ( ...@@ -12,68 +11,48 @@ from courses.certification.models import (
class CertificateTemplateSerializer(serializers.ModelSerializer): class CertificateTemplateSerializer(serializers.ModelSerializer):
course_name = serializers.SerializerMethodField(read_only=True,)
# course = serializers.PrimaryKeyRelatedField(read_only=True)
class Meta:
model = CertificateTemplate
fields = (
'id', 'course', 'course_name', 'organization_name',
'base_logo_url', 'cert_logo_url', 'role', 'name',
'signature_url',
)
def get_course_name(self, obj):
return obj.course.name
class CertificateDataSerializer(serializers.ModelSerializer):
workspace = SimpleWorkspaceSerializer(read_only=True) workspace = SimpleWorkspaceSerializer(read_only=True)
certificate_template = CertificateTemplateSerializer()
associate = serializers.SerializerMethodField() associate = serializers.SerializerMethodField()
course_name = serializers.SerializerMethodField(read_only=True,)
# TODO: Legacy compat field, remove in the future # TODO: Legacy compat field, remove in the future
contract = serializers.SerializerMethodField() contract = serializers.SerializerMethodField()
class Meta: class Meta:
model = CertificateData model = CertificateTemplate
fields = ( fields = ('id', 'text', 'base_logo_url', 'cert_logo_url', 'role', 'name',
'id', 'text', 'type', 'site_logo_url', 'course_name', 'contract', 'associate', 'workspace', 'document_type',
'certificate_template', 'associate', 'workspace', 'contract', 'organization_name', 'site_logo_url', 'signature_url', 'course',)
)
def get_associate(self, obj): def get_associate(self, obj):
if obj.type == 'receipt': filters = {
type = 'certificate' 'document_type' : 'certificate' if obj.document_type == 'receipt' else 'receipt',
else: 'course': obj.course,
type = 'receipt' 'workspace': obj.workspace
a = CertificateData.objects.filter( }
type=type, if CertificateTemplate.objects.filter(**filters).exists():
certificate_template__course=obj.certificate_template.course, return CertificateTemplate.objects.filter(**filters).first().id
workspace=obj.workspace, return None
)
if len(a) > 0:
return a[0].id
else:
return None
def get_contract(self, obj): def get_contract(self, obj):
return SimpleWorkspaceSerializer(obj.workspace).data if obj.workspace:
return SimpleWorkspaceSerializer(obj.workspace).data
return None
def get_course_name(self, obj):
return obj.course.name
def update(self, instance, validated_data):
ct = dict(validated_data.pop('certificate_template'))
ct['course'] = ct['course'].id
cts = CertificateTemplateSerializer(instance=instance.certificate_template, data=ct)
cts.is_valid(raise_exception=True)
cts.save()
return super().update(instance, validated_data)
class CertificateTemplateCreateSerializer(serializers.ModelSerializer):
class Meta:
model = CertificateTemplate
fields = ('course', 'document_type', 'workspace')
class CertificateImageDataSerializer(serializers.ModelSerializer): class CertificateTemplateImageSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = CertificateData model = CertificateTemplate
fields = ('site_logo',) fields = ('base_logo', 'cert_logo', 'signature', 'site_logo')
class CertificationProcessSerializer(serializers.ModelSerializer): class CertificationProcessSerializer(serializers.ModelSerializer):
...@@ -123,17 +102,3 @@ class EvaluationSerializer(serializers.ModelSerializer): ...@@ -123,17 +102,3 @@ class EvaluationSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Evaluation model = Evaluation
class CertificateTemplateSerializer(serializers.ModelSerializer):
class Meta:
model = CertificateTemplate
fields = ('id', 'course', 'organization_name', 'base_logo_url', 'cert_logo_url', 'role', 'name', 'signature_url', )
class CertificateTemplateImageSerializer(serializers.ModelSerializer):
class Meta:
model = CertificateTemplate
fields = ('base_logo', 'cert_logo', 'signature', )
from django.db.models.signals import post_save from django.db.models.signals import post_save
from django.dispatch import receiver
from base64 import urlsafe_b64encode as ub64 from base64 import urlsafe_b64encode as ub64
from hashlib import sha1 from hashlib import sha1
from time import time from time import time
from courses.models import CourseStudent from courses.models import Course, CourseStudent
from courses.certification.models import CourseCertification from courses.certification.models import CourseCertification, CertificateTemplate
@receiver(post_save, sender=CourseStudent) @receiver(post_save, sender=CourseStudent)
def course_student_created_or_updated(sender, created, instance, **kwargs): def course_student_created_or_updated(sender, created, instance: CourseStudent, **kwargs):
if created: if created:
link_hash = ub64(sha1(str(time()) + instance.user.last_name.encode('utf-8')).digest()[0:6]) link_hash = ub64(sha1((str(time()) + instance.user.last_name).encode('utf-8')).digest()[0:6])
receipt = CourseCertification(course_student=instance, receipt = CourseCertification(course_student=instance,
course=instance.course, type=CourseCertification.TYPES[0][0],
type=CourseCertification.TYPES[0][0], is_valid=True, link_hash=link_hash.decode())
is_valid=True, link_hash=link_hash.decode()) receipt.save()
receipt.save()
\ No newline at end of file
@receiver(post_save, sender=Course)
def course_created(sender, created, instance, **kwargs):
if created:
for type_ in CertificateTemplate.TYPES:
ct = CertificateTemplate(course=instance, document_type=type_[0])
ct.save()
...@@ -9,16 +9,14 @@ from django.http import Http404 ...@@ -9,16 +9,14 @@ from django.http import Http404
from courses.permissions import IsProfessorCoordinatorOrAdminPermissionOrReadOnly from courses.permissions import IsProfessorCoordinatorOrAdminPermissionOrReadOnly
from courses.certification.serializers import ( from courses.certification.serializers import (
CertificateDataSerializer,
CertificateImageDataSerializer,
CertificationProcessSerializer, CertificationProcessSerializer,
CourseCertificationSerializer, CourseCertificationSerializer,
CertificateTemplateSerializer, CertificateTemplateSerializer,
CertificateTemplateCreateSerializer,
CertificateTemplateImageSerializer, CertificateTemplateImageSerializer,
) )
from courses.certification.models import ( from courses.certification.models import (
CertificateData,
CertificationProcess, CertificationProcess,
CourseCertification, CourseCertification,
CertificateTemplate, CertificateTemplate,
...@@ -30,12 +28,12 @@ from courses.workspaces.models import Workspace ...@@ -30,12 +28,12 @@ from courses.workspaces.models import Workspace
class CertificateDataMixin(viewsets.ModelViewSet): class CertificateDataMixin(viewsets.ModelViewSet):
def get_queryset(self): def get_queryset(self):
queryset = CertificateData.objects.all() queryset = CertificateTemplate.objects.all()
course = self.request.query_params.get('course', None) course = self.request.query_params.get('course', None)
if course: if course:
queryset = queryset.filter(certificate_template__course=course) queryset = queryset.filter(course=course)
workspace = self.request.query_params.get('contract', None) workspace = self.request.query_params.get('workspace', None)
if workspace: if workspace:
queryset = queryset.filter(workspace=workspace) queryset = queryset.filter(workspace=workspace)
...@@ -43,41 +41,13 @@ class CertificateDataMixin(viewsets.ModelViewSet): ...@@ -43,41 +41,13 @@ class CertificateDataMixin(viewsets.ModelViewSet):
class CertificateDataViewSet(CertificateDataMixin, viewsets.ModelViewSet): class CertificateDataViewSet(CertificateDataMixin, viewsets.ModelViewSet):
model = CertificateData model = CertificateTemplate
serializer_class = CertificateDataSerializer
permission_classes = (IsProfessorCoordinatorOrAdminPermissionOrReadOnly, ) permission_classes = (IsProfessorCoordinatorOrAdminPermissionOrReadOnly, )
def create(self, request, *args, **kwargs): def get_serializer_class(self):
generate = request.data.get('generate', False) if self.action == 'create':
if generate: return CertificateTemplateCreateSerializer
data = request.data return CertificateTemplateSerializer
current = CertificateData.objects.filter(certificate_template__course__id=data.get('course', None),
workspace__id=data.get('workspace', None))
if len(current) >= 2:
return Response({'error' : 'Os templates já existem'}, status=status.HTTP_400_BAD_REQUEST)
else:
course = Course.objects.get(pk=data.get('course', None))
workspace = Workspace.objects.get(pk=data.get('contract', None))
if len(current) > 0:
ct = CertificateTemplate(course=course)
ct.save()
t = CertificateData.TYPES[0]
if 'receipt' == current[0].type:
t = CertificateData.TYPES[1]
cd = CertificateData(type=t[0], workspace=workspace, certificate_template=ct)
cd.save()
return Response({'message' : 'Os templates foram criados com sucesso'})
else:
for t in CertificateData.TYPES:
ct = CertificateTemplate(course=course)
ct.save()
cd = CertificateData(type=t[0], workspace=workspace, certificate_template=ct)
cd.save()
return Response({'message' : 'Os templates foram criados com sucesso'})
else:
super().create(request, *args, **kwargs)
@action(detail=True, methods=['get', 'post']) @action(detail=True, methods=['get', 'post'])
def images(self, request, pk=None): def images(self, request, pk=None):
...@@ -85,37 +55,22 @@ class CertificateDataViewSet(CertificateDataMixin, viewsets.ModelViewSet): ...@@ -85,37 +55,22 @@ class CertificateDataViewSet(CertificateDataMixin, viewsets.ModelViewSet):
errors = [] errors = []
clear_logos = ( clear_logos = (
('cert_logo', request.data.get('cert_logo_clear', None)),
('base_logo', request.data.get('base_logo_clear', None)), ('base_logo', request.data.get('base_logo_clear', None)),
('signature', request.data.get('signature_clear', None)), ('signature', request.data.get('signature_clear', None)),
('cert_logo', request.data.get('cert_logo_clear', None)), ('site_logo', request.data.get('site_logo_clear', None)),
) )
for cl in clear_logos: for cl in clear_logos:
if(cl[1]): if(cl[1]):
setattr(obj.certificate_template, cl[0], None) setattr(obj, cl[0], None)
ct_serializer = CertificateTemplateImageSerializer( serializer = CertificateTemplateImageSerializer(obj, request.FILES)
obj.certificate_template, request.FILES)
if ct_serializer.is_valid():
ct_serializer.save()
else:
errors += ct_serializer.errors
cl = ('site_logo', request.data.get('site_logo_clear', None))
if(cl[1]):
setattr(obj, cl[0], None)
serializer = CertificateImageDataSerializer(obj, request.FILES)
if serializer.is_valid(): if serializer.is_valid():
serializer.save() serializer.save()
return Response(CertificateTemplateSerializer(obj).data,
status=status.HTTP_200_OK)
else: else:
errors += serializer.errors return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
if len(errors) > 0:
return Response(serializer.errors,
status=status.HTTP_400_BAD_REQUEST)
else:
s = CertificateDataSerializer(obj)
return Response(s.data, status=status.HTTP_200_OK)
class CertificationProcessViewSet(viewsets.ModelViewSet): class CertificationProcessViewSet(viewsets.ModelViewSet):
model = CertificationProcess model = CertificationProcess
...@@ -173,8 +128,8 @@ class CertificateTemplateImageViewSet(viewsets.ModelViewSet): ...@@ -173,8 +128,8 @@ class CertificateTemplateImageViewSet(viewsets.ModelViewSet):
def post(self, request, **kwargs): def post(self, request, **kwargs):
certificate_template = self.get_object() certificate_template = self.get_object()
serializer = CertificateTemplateImageSerializer( serializer = CertificateTemplateImageSerializer(certificate_template,
certificate_template, request.FILES) request.FILES)
if serializer.is_valid(): if serializer.is_valid():
serializer.save() serializer.save()
...@@ -199,9 +154,9 @@ class CourseCertificationDetailView(DetailView): ...@@ -199,9 +154,9 @@ class CourseCertificationDetailView(DetailView):
raise Http404 raise Http404
if certificate: if certificate:
context['cert_template'] = CertificateData.objects.get( context['cert_template'] = CertificateTemplate.objects.get(
certificate_template__course=certificate.course_student.course, course=certificate.course_student.course,
type=certificate.type, document_type=certificate.document_type,
workspace=workspace workspace=workspace
) )
# Interpolate data into text string # Interpolate data into text string
......
...@@ -34,7 +34,8 @@ class CourseStudentClassSerializer(serializers.ModelSerializer): ...@@ -34,7 +34,8 @@ class CourseStudentClassSerializer(serializers.ModelSerializer):
class ClassSerializer(WorkspaceBaseSerializerMixin, serializers.ModelSerializer): class ClassSerializer(WorkspaceBaseSerializerMixin, serializers.ModelSerializer):
students_details = CourseStudentClassSerializer(source='get_students', many=True, read_only=True) enrolled_students = CourseStudentClassSerializer(source='get_students', many=True, read_only=True)