Browse Source

feat: app certificate

master
alireza 1 year ago
parent
commit
4ffa8f149c
  1. 0
      apps/certificate/__init__.py
  2. 13
      apps/certificate/admin.py
  3. 6
      apps/certificate/apps.py
  4. 31
      apps/certificate/migrations/0001_initial.py
  5. 0
      apps/certificate/migrations/__init__.py
  6. 30
      apps/certificate/models.py
  7. 37
      apps/certificate/serializers.py
  8. 3
      apps/certificate/tests.py
  9. 11
      apps/certificate/urls.py
  10. 24
      apps/certificate/views.py
  11. 1
      config/settings/base.py
  12. 2
      config/urls.py

0
apps/certificate/__init__.py

13
apps/certificate/admin.py

@ -0,0 +1,13 @@
from django.contrib import admin
from apps.certificate.models import Certificate
@admin.register(Certificate)
class CertificateAdmin(admin.ModelAdmin):
list_display = ['student', 'course', 'status', 'created_at']
list_filter = ['status', 'created_at']
search_fields = ['user__username', 'course__title']
readonly_fields = ['created_at', 'updated_at']

6
apps/certificate/apps.py

@ -0,0 +1,6 @@
from django.apps import AppConfig
class CertificateConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'apps.certificate'

31
apps/certificate/migrations/0001_initial.py

@ -0,0 +1,31 @@
# Generated by Django 3.2.7 on 2024-12-14 08:35
from django.db import migrations, models
import django.db.models.deletion
import filer.fields.file
class Migration(migrations.Migration):
initial = True
dependencies = [
('course', '0005_participant_unread_messages_count'),
('account', '0005_user_city'),
('filer', '0015_auto_20241214_0835'),
]
operations = [
migrations.CreateModel(
name='Certificate',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('status', models.CharField(choices=[('pending', 'در حال بررسی'), ('approved', 'تایید شده'), ('canceled', 'لغو شده')], default='pending', max_length=10)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('certificate_file', filer.fields.file.FilerFileField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='filer.file', verbose_name='certificate_file')),
('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='course_certificates', to='course.course')),
('student', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='certificates', to='account.studentuser')),
],
),
]

0
apps/certificate/migrations/__init__.py

30
apps/certificate/models.py

@ -0,0 +1,30 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
from filer.fields.file import FilerFileField
from apps.course.models import Course
from apps.account.models import StudentUser
class Certificate(models.Model):
STATUS_CHOICES = [
('pending', _('pending')),
('approved', _('approved')),
('canceled', _('canceled')),
]
student = models.ForeignKey(StudentUser, on_delete=models.CASCADE, related_name='certificates')
course = models.ForeignKey(Course, on_delete=models.CASCADE, related_name='course_certificates')
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='pending')
certificate_file = FilerFileField(
related_name='+', on_delete=models.PROTECT, null=True, blank=True, verbose_name=_('certificate_file')
)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return f"Certificate {self.student.fullname} - {self.course.title}"

37
apps/certificate/serializers.py

@ -0,0 +1,37 @@
from rest_framework import serializers
from apps.certificate.models import Certificate
class CertificateSerializer(serializers.ModelSerializer):
course = serializers.SerializerMethodField()
class Meta:
model = Certificate
fields = ['id', 'student', 'course', 'status', 'created_at', 'updated_at',]
read_only_fields = ['id', 'student', 'status', 'created_at', 'updated_at',]
def get_course(self, obj):
return obj.course.title
class CertificateRequestSerializer(serializers.ModelSerializer):
class Meta:
model = Certificate
fields = ['id', 'course']
read_only_fields = ['id']
def create(self, validated_data):
user = self.context['request'].user
course = validated_data['course']
if Certificate.objects.filter(student=user, course=course, status__in=['pending', 'approved']).exists():
raise serializers.ValidationError({"course": "Passwords do not match."})
return Certificate.objects.create(student=user, course=course)

3
apps/certificate/tests.py

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

11
apps/certificate/urls.py

@ -0,0 +1,11 @@
from django.urls import path
from .views import CertificateRequestView, UserCertificatesListView
urlpatterns = [
path('request/', CertificateRequestView.as_view(), name='certificate-request'),
path('my-certificates/', UserCertificatesListView.as_view(), name='user-certificates'),
]

24
apps/certificate/views.py

@ -0,0 +1,24 @@
from rest_framework import generics, permissions
from apps.certificate.models import Certificate
from apps.certificate.serializers import CertificateRequestSerializer, CertificateSerializer
class CertificateRequestView(generics.CreateAPIView):
queryset = Certificate.objects.all()
serializer_class = CertificateRequestSerializer
permission_classes = [permissions.IsAuthenticated]
def perform_create(self, serializer):
serializer.save(student=self.request.user)
class UserCertificatesListView(generics.ListAPIView):
serializer_class = CertificateSerializer
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
return Certificate.objects.filter(student=self.request.user).order_by('-created_at')

1
config/settings/base.py

@ -46,6 +46,7 @@ LOCAL_APPS = [
'apps.chat.apps.ChatConfig', 'apps.chat.apps.ChatConfig',
'apps.quiz.apps.QuizConfig', 'apps.quiz.apps.QuizConfig',
'apps.transaction.apps.TransactionConfig', 'apps.transaction.apps.TransactionConfig',
'apps.certificate.apps.CertificateConfig',
'dynamic_preferences', 'dynamic_preferences',
] ]

2
config/urls.py

@ -38,6 +38,8 @@ api_patterns = [
path('courses/', include('apps.course.urls')), path('courses/', include('apps.course.urls')),
path('quiz/', include('apps.quiz.urls')), path('quiz/', include('apps.quiz.urls')),
path('transaction/', include('apps.transaction.urls')), path('transaction/', include('apps.transaction.urls')),
path('certificates/', include('apps.certificate.urls')),
path('settings/', include('dynamic_preferences.urls')), path('settings/', include('dynamic_preferences.urls')),
path('upload-tmp-media/', UploadTmpMedia.as_view()), path('upload-tmp-media/', UploadTmpMedia.as_view()),

Loading…
Cancel
Save