Skip to content

Commit fbba784

Browse files
authored
Merge pull request #606 from PROCOLLAB-github/feature/program-courses
Feature/program courses
2 parents bcf7616 + db83a2c commit fbba784

28 files changed

+4343
-0
lines changed

courses/__init__.py

Whitespace-only changes.

courses/admin.py

Lines changed: 711 additions & 0 deletions
Large diffs are not rendered by default.

courses/apps.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from django.apps import AppConfig
2+
3+
4+
class CoursesConfig(AppConfig):
5+
default_auto_field = "django.db.models.BigAutoField"
6+
name = "courses"
7+
verbose_name = "Курсы"

courses/migrations/0001_initial.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Generated by Django 4.2.11 on 2026-02-20 05:56
2+
3+
import django.core.validators
4+
from django.db import migrations, models
5+
import django.db.models.deletion
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
initial = True
11+
12+
dependencies = [
13+
('partner_programs', '0016_partnerprogram_is_distributed_evaluation'),
14+
('files', '0007_auto_20230929_1727'),
15+
]
16+
17+
operations = [
18+
migrations.CreateModel(
19+
name='Course',
20+
fields=[
21+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
22+
('title', models.CharField(max_length=45, verbose_name='Название курса')),
23+
('description', models.TextField(blank=True, default='', validators=[django.core.validators.MaxLengthValidator(600)], verbose_name='Описание')),
24+
('access_type', models.CharField(choices=[('all_users', 'Для всех пользователей'), ('program_members', 'Для участников программы'), ('subscription_stub', 'По подписке')], default='all_users', max_length=32, verbose_name='Тип доступа')),
25+
('start_date', models.DateField(blank=True, null=True, verbose_name='Дата старта')),
26+
('end_date', models.DateField(blank=True, null=True, verbose_name='Дата окончания')),
27+
('status', models.CharField(choices=[('draft', 'Черновик'), ('published', 'Опубликован'), ('completed', 'Завершен')], default='draft', max_length=16, verbose_name='Статус курса')),
28+
('is_completed', models.BooleanField(default=False, verbose_name='Курс завершен')),
29+
('completed_at', models.DateTimeField(blank=True, null=True, verbose_name='Дата завершения')),
30+
('datetime_created', models.DateTimeField(auto_now_add=True, verbose_name='Дата создания')),
31+
('datetime_updated', models.DateTimeField(auto_now=True, verbose_name='Дата обновления')),
32+
('avatar_file', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='course_avatars', to='files.userfile', verbose_name='Аватар курса')),
33+
('card_cover_file', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='course_card_covers', to='files.userfile', verbose_name='Обложка карточки курса')),
34+
('header_cover_file', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='course_header_covers', to='files.userfile', verbose_name='Обложка шапки курса')),
35+
('partner_program', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='courses', to='partner_programs.partnerprogram', verbose_name='Программа')),
36+
],
37+
options={
38+
'verbose_name': 'Курс',
39+
'verbose_name_plural': 'Курсы',
40+
'ordering': ('-datetime_created',),
41+
},
42+
),
43+
]
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Generated by Django 4.2.11 on 2026-02-20 06:13
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('courses', '0001_initial'),
10+
]
11+
12+
operations = [
13+
migrations.AddConstraint(
14+
model_name='course',
15+
constraint=models.CheckConstraint(check=models.Q(models.Q(('access_type', 'program_members'), _negated=True), ('partner_program__isnull', False), _connector='OR'), name='courses_program_members_requires_program'),
16+
),
17+
migrations.AddConstraint(
18+
model_name='course',
19+
constraint=models.CheckConstraint(check=models.Q(models.Q(('end_date__isnull', True), ('start_date__isnull', True)), models.Q(('end_date__isnull', False), ('start_date__isnull', False)), _connector='OR'), name='courses_dates_must_be_set_together'),
20+
),
21+
migrations.AddConstraint(
22+
model_name='course',
23+
constraint=models.CheckConstraint(check=models.Q(('start_date__isnull', True), ('end_date__gte', models.F('start_date')), _connector='OR'), name='courses_end_date_gte_start_date'),
24+
),
25+
migrations.AddConstraint(
26+
model_name='course',
27+
constraint=models.CheckConstraint(check=models.Q(models.Q(('status', 'completed'), _negated=True), ('is_completed', True), _connector='OR'), name='courses_completed_status_implies_flag'),
28+
),
29+
migrations.AddConstraint(
30+
model_name='course',
31+
constraint=models.CheckConstraint(check=models.Q(('is_completed', False), ('status', 'completed'), _connector='OR'), name='courses_completed_flag_implies_status'),
32+
),
33+
]
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Generated by Django 4.2.11 on 2026-02-20 06:45
2+
3+
from django.db import migrations, models
4+
import django.db.models.deletion
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
('files', '0007_auto_20230929_1727'),
11+
('courses', '0002_course_courses_program_members_requires_program_and_more'),
12+
]
13+
14+
operations = [
15+
migrations.CreateModel(
16+
name='CourseModule',
17+
fields=[
18+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19+
('title', models.CharField(max_length=40, verbose_name='Название модуля')),
20+
('start_date', models.DateField(verbose_name='Дата старта модуля')),
21+
('status', models.CharField(choices=[('draft', 'Черновик'), ('published', 'Опубликован')], default='draft', max_length=16, verbose_name='Статус модуля')),
22+
('order', models.PositiveIntegerField(default=1, verbose_name='Порядковый номер')),
23+
('datetime_created', models.DateTimeField(auto_now_add=True, verbose_name='Дата создания')),
24+
('datetime_updated', models.DateTimeField(auto_now=True, verbose_name='Дата обновления')),
25+
('avatar_file', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='course_module_avatars', to='files.userfile', verbose_name='Аватар модуля')),
26+
('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='modules', to='courses.course', verbose_name='Курс')),
27+
],
28+
options={
29+
'verbose_name': 'Модуль курса',
30+
'verbose_name_plural': 'Модули курса',
31+
'ordering': ('course_id', 'order', 'id'),
32+
},
33+
),
34+
migrations.AddConstraint(
35+
model_name='coursemodule',
36+
constraint=models.UniqueConstraint(fields=('course', 'order'), name='courses_module_unique_course_order'),
37+
),
38+
migrations.AddConstraint(
39+
model_name='coursemodule',
40+
constraint=models.CheckConstraint(check=models.Q(('order__gte', 1)), name='courses_module_order_gte_1'),
41+
),
42+
]
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Generated by Django 4.2.11 on 2026-02-20 06:50
2+
3+
from django.db import migrations, models
4+
import django.db.models.deletion
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
('courses', '0003_coursemodule_and_more'),
11+
]
12+
13+
operations = [
14+
migrations.CreateModel(
15+
name='CourseLesson',
16+
fields=[
17+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
18+
('title', models.CharField(max_length=45, verbose_name='Название урока')),
19+
('status', models.CharField(choices=[('draft', 'Черновик'), ('published', 'Опубликован')], default='draft', max_length=16, verbose_name='Статус урока')),
20+
('order', models.PositiveIntegerField(default=1, verbose_name='Порядковый номер')),
21+
('datetime_created', models.DateTimeField(auto_now_add=True, verbose_name='Дата создания')),
22+
('datetime_updated', models.DateTimeField(auto_now=True, verbose_name='Дата обновления')),
23+
('module', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='lessons', to='courses.coursemodule', verbose_name='Модуль курса')),
24+
],
25+
options={
26+
'verbose_name': 'Урок курса',
27+
'verbose_name_plural': 'Уроки курса',
28+
'ordering': ('module_id', 'order', 'id'),
29+
},
30+
),
31+
migrations.AddConstraint(
32+
model_name='courselesson',
33+
constraint=models.UniqueConstraint(fields=('module', 'order'), name='courses_lesson_unique_module_order'),
34+
),
35+
migrations.AddConstraint(
36+
model_name='courselesson',
37+
constraint=models.CheckConstraint(check=models.Q(('order__gte', 1)), name='courses_lesson_order_gte_1'),
38+
),
39+
]

0 commit comments

Comments
 (0)