You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
160 lines
12 KiB
160 lines
12 KiB
# Generated by Django 4.2.30 on 2026-09-15 12:58
|
|
|
|
from django.conf import settings
|
|
from django.db import migrations, models
|
|
import django.db.models.deletion
|
|
import django.utils.timezone
|
|
import uuid
|
|
|
|
|
|
class Migration(migrations.Migration):
|
|
|
|
initial = True
|
|
|
|
dependencies = [
|
|
('profiles', '0001_initial'),
|
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
]
|
|
|
|
operations = [
|
|
migrations.CreateModel(
|
|
name='Course',
|
|
fields=[
|
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
('title', models.CharField(max_length=255, verbose_name='Course Title')),
|
|
('slug', models.SlugField(allow_unicode=True, blank=True, max_length=280, null=True, unique=True, verbose_name='Slug / URL Identifier')),
|
|
('category', models.CharField(choices=[('razavi_teachings', 'Razavi Teachings & Lifestyle'), ('cultural_diplomacy', 'Cultural Diplomacy & Interfaith'), ('center_management', 'Center & Mosque Management'), ('international_media', 'International Media & Content'), ('specialized_languages', 'Specialized Languages & Translation'), ('general', 'General Religious Studies')], default='razavi_teachings', max_length=50, verbose_name='Category')),
|
|
('language', models.CharField(choices=[('fa', 'Persian'), ('ar', 'Arabic'), ('en', 'English'), ('ur', 'Urdu'), ('fr', 'French')], default='en', max_length=10, verbose_name='Language')),
|
|
('level', models.CharField(choices=[('introductory', 'Introductory'), ('intermediate', 'Intermediate'), ('advanced', 'Advanced')], default='introductory', max_length=20, verbose_name='Difficulty Level')),
|
|
('cover_image', models.ImageField(blank=True, null=True, upload_to='lms/covers/%Y/%m/', verbose_name='Cover Image')),
|
|
('instructor_name', models.CharField(max_length=255, verbose_name='Instructor Name')),
|
|
('instructor_title', models.CharField(blank=True, max_length=255, null=True, verbose_name='Instructor Title / Specialty')),
|
|
('instructor_avatar', models.ImageField(blank=True, null=True, upload_to='lms/instructors/%Y/%m/', verbose_name='Instructor Avatar')),
|
|
('organization_name', models.CharField(blank=True, max_length=255, null=True, verbose_name='Organization / Academy Name')),
|
|
('description', models.TextField(verbose_name='Course Description & Syllabus Summary')),
|
|
('duration_hours', models.FloatField(default=1.0, verbose_name='Duration (Hours)')),
|
|
('rating', models.FloatField(default=5.0, verbose_name='Average Rating')),
|
|
('reviews_count', models.PositiveIntegerField(default=0, verbose_name='Reviews Count')),
|
|
('is_published', models.BooleanField(default=True, verbose_name='Is Published')),
|
|
('is_featured', models.BooleanField(default=False, verbose_name='Is Featured')),
|
|
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')),
|
|
('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated At')),
|
|
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_courses', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
|
|
('institution', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='courses', to='profiles.institution', verbose_name='Partner Institution / Center')),
|
|
],
|
|
options={
|
|
'verbose_name': 'Course',
|
|
'verbose_name_plural': 'Courses',
|
|
'ordering': ('-is_featured', '-created_at'),
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name='CourseModule',
|
|
fields=[
|
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
('title', models.CharField(max_length=255, verbose_name='Module Title')),
|
|
('description', models.TextField(blank=True, null=True, verbose_name='Module Description')),
|
|
('order', models.IntegerField(default=0, verbose_name='Display Order')),
|
|
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')),
|
|
('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='modules', to='lms.course', verbose_name='Course')),
|
|
],
|
|
options={
|
|
'verbose_name': 'Course Module',
|
|
'verbose_name_plural': 'Course Modules',
|
|
'ordering': ('order', 'id'),
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name='Lesson',
|
|
fields=[
|
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
('title', models.CharField(max_length=255, verbose_name='Lesson Title')),
|
|
('slug', models.SlugField(allow_unicode=True, blank=True, max_length=280, null=True, verbose_name='Slug')),
|
|
('lesson_type', models.CharField(choices=[('video', 'Video Lesson'), ('reading', 'Reading & Text'), ('quiz', 'Interactive Quiz'), ('assignment', 'Practical Assignment')], default='video', max_length=20, verbose_name='Lesson Type')),
|
|
('duration_minutes', models.PositiveIntegerField(default=15, verbose_name='Duration (Minutes)')),
|
|
('video_url', models.URLField(blank=True, max_length=500, null=True, verbose_name='Video URL (YouTube, Vimeo, HLS, MP4)')),
|
|
('content', models.TextField(blank=True, null=True, verbose_name='Lesson Content / Notes (Markdown)')),
|
|
('slides_attachment', models.FileField(blank=True, null=True, upload_to='lms/slides/%Y/%m/', verbose_name='Slides / PDF Handout')),
|
|
('order', models.IntegerField(default=0, verbose_name='Display Order')),
|
|
('is_preview', models.BooleanField(default=False, verbose_name='Is Free Preview (Public)')),
|
|
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')),
|
|
('module', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='lessons', to='lms.coursemodule', verbose_name='Module')),
|
|
],
|
|
options={
|
|
'verbose_name': 'Lesson',
|
|
'verbose_name_plural': 'Lessons',
|
|
'ordering': ('order', 'id'),
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name='QuizQuestion',
|
|
fields=[
|
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
('question_text', models.TextField(verbose_name='Question Text')),
|
|
('options', models.JSONField(default=list, help_text='List of multiple-choice strings: ["Option A", "Option B", "Option C", "Option D"]', verbose_name='Options Array')),
|
|
('correct_option_index', models.PositiveSmallIntegerField(default=0, verbose_name='Correct Option Index (0-indexed)')),
|
|
('explanation', models.TextField(blank=True, null=True, verbose_name='Explanation / Reference for Correct Answer')),
|
|
('order', models.IntegerField(default=0, verbose_name='Display Order')),
|
|
('lesson', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='quiz_questions', to='lms.lesson', verbose_name='Lesson')),
|
|
],
|
|
options={
|
|
'verbose_name': 'Quiz Question',
|
|
'verbose_name_plural': 'Quiz Questions',
|
|
'ordering': ('order', 'id'),
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name='LessonProgress',
|
|
fields=[
|
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
('is_completed', models.BooleanField(default=False, verbose_name='Is Completed')),
|
|
('completed_at', models.DateTimeField(blank=True, null=True, verbose_name='Completed At')),
|
|
('quiz_score', models.FloatField(blank=True, null=True, verbose_name='Quiz Score (Percentage)')),
|
|
('lesson', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='user_progresses', to='lms.lesson', verbose_name='Lesson')),
|
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='lesson_progresses', to=settings.AUTH_USER_MODEL, verbose_name='User')),
|
|
],
|
|
options={
|
|
'verbose_name': 'Lesson Progress',
|
|
'verbose_name_plural': 'Lesson Progresses',
|
|
'unique_together': {('user', 'lesson')},
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name='DigitalCertificate',
|
|
fields=[
|
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
('certificate_code', models.CharField(help_text='e.g. CERT-RAZAVI-2026-AB12CD', max_length=100, unique=True, verbose_name='Verification Code')),
|
|
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True, verbose_name='Unique UUID')),
|
|
('issue_date', models.DateField(default=django.utils.timezone.now, verbose_name='Issue Date')),
|
|
('final_score', models.FloatField(default=100.0, verbose_name='Final Score (%)')),
|
|
('certificate_file', models.FileField(blank=True, null=True, upload_to='lms/certificates/%Y/%m/', verbose_name='Certificate PDF Document')),
|
|
('is_revoked', models.BooleanField(default=False, verbose_name='Is Revoked')),
|
|
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')),
|
|
('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='certificates', to='lms.course', verbose_name='Course')),
|
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='certificates', to=settings.AUTH_USER_MODEL, verbose_name='Student / User')),
|
|
],
|
|
options={
|
|
'verbose_name': 'Digital Certificate',
|
|
'verbose_name_plural': 'Digital Certificates',
|
|
'ordering': ('-created_at',),
|
|
'unique_together': {('user', 'course')},
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name='CourseEnrollment',
|
|
fields=[
|
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
('enrolled_at', models.DateTimeField(auto_now_add=True, verbose_name='Enrolled At')),
|
|
('completed_at', models.DateTimeField(blank=True, null=True, verbose_name='Completed At')),
|
|
('progress_percentage', models.PositiveSmallIntegerField(default=0, verbose_name='Progress Percentage (0-100)')),
|
|
('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='enrollments', to='lms.course', verbose_name='Course')),
|
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='course_enrollments', to=settings.AUTH_USER_MODEL, verbose_name='User')),
|
|
],
|
|
options={
|
|
'verbose_name': 'Course Enrollment',
|
|
'verbose_name_plural': 'Course Enrollments',
|
|
'ordering': ('-enrolled_at',),
|
|
'unique_together': {('user', 'course')},
|
|
},
|
|
),
|
|
]
|