uchill/backend/apps/schedule/migrations/0001_initial.py

702 lines
27 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Generated by Django 4.2.7 on 2025-12-09 21:02
import apps.schedule.models
from django.conf import settings
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
("materials", "0001_initial"),
("users", "0001_initial"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name="Lesson",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"start_time",
models.DateTimeField(db_index=True, verbose_name="Время начала"),
),
(
"end_time",
models.DateTimeField(db_index=True, verbose_name="Время окончания"),
),
(
"duration",
models.IntegerField(
default=60,
help_text="Длительность занятия в минутах (15-480)",
validators=[
django.core.validators.MinValueValidator(15),
django.core.validators.MaxValueValidator(480),
],
verbose_name="Длительность (минуты)",
),
),
(
"title",
models.CharField(
help_text="Краткое название занятия",
max_length=200,
verbose_name="Название",
),
),
(
"description",
models.TextField(
blank=True,
help_text="Подробное описание занятия",
verbose_name="Описание",
),
),
(
"subject",
models.CharField(
blank=True,
help_text="Предмет обучения (математика, физика и т.д.)",
max_length=100,
verbose_name="Предмет",
),
),
(
"status",
models.CharField(
choices=[
("scheduled", "Запланировано"),
("in_progress", "В процессе"),
("completed", "Завершено"),
("cancelled", "Отменено"),
("rescheduled", "Перенесено"),
],
db_index=True,
default="scheduled",
max_length=20,
verbose_name="Статус",
),
),
(
"cancellation_reason",
models.TextField(blank=True, verbose_name="Причина отмены"),
),
(
"cancelled_at",
models.DateTimeField(
blank=True, null=True, verbose_name="Дата отмены"
),
),
(
"meeting_url",
models.URLField(
blank=True,
help_text="Ссылка на видеоконференцию",
max_length=500,
verbose_name="Ссылка на встречу",
),
),
(
"mentor_notes",
models.TextField(
blank=True,
help_text="Приватные заметки ментора о занятии",
verbose_name="Заметки ментора",
),
),
(
"homework_text",
models.TextField(
blank=True,
help_text="Описание домашнего задания, выданного по результатам занятия",
verbose_name="Домашнее задание",
),
),
(
"mentor_grade",
models.IntegerField(
blank=True,
help_text="Оценка работы студента на занятии (0-100)",
null=True,
verbose_name="Оценка ментора",
),
),
(
"school_grade",
models.IntegerField(
blank=True,
help_text="Текущая оценка студента в школе (0-100)",
null=True,
verbose_name="Оценка в школе",
),
),
(
"price",
models.DecimalField(
blank=True,
decimal_places=2,
help_text="Стоимость занятия в рублях",
max_digits=10,
null=True,
verbose_name="Стоимость",
),
),
(
"reminder_sent",
models.BooleanField(
default=False, verbose_name="Напоминание отправлено"
),
),
(
"created_at",
models.DateTimeField(
auto_now_add=True, null=True, verbose_name="Дата создания"
),
),
(
"updated_at",
models.DateTimeField(auto_now=True, verbose_name="Дата обновления"),
),
(
"cancelled_by",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="cancelled_lessons",
to=settings.AUTH_USER_MODEL,
verbose_name="Отменено пользователем",
),
),
(
"client",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="lessons",
to="users.client",
verbose_name="Клиент",
),
),
(
"group",
models.ForeignKey(
blank=True,
help_text="Учебная группа, если занятие групповое",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="lessons",
to="users.group",
verbose_name="Группа",
),
),
(
"mentor",
models.ForeignKey(
limit_choices_to={"role": "mentor"},
on_delete=django.db.models.deletion.CASCADE,
related_name="mentor_lessons",
to=settings.AUTH_USER_MODEL,
verbose_name="Ментор",
),
),
(
"rescheduled_from",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="rescheduled_to",
to="schedule.lesson",
verbose_name="Перенесено из",
),
),
],
options={
"verbose_name": "Занятие",
"verbose_name_plural": "Занятия",
"db_table": "lessons",
"ordering": ["start_time"],
},
),
migrations.CreateModel(
name="LessonTemplate",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("title", models.CharField(max_length=200, verbose_name="Название")),
("description", models.TextField(blank=True, verbose_name="Описание")),
(
"subject",
models.CharField(
blank=True, max_length=100, verbose_name="Предмет"
),
),
(
"duration",
models.IntegerField(
default=60,
validators=[
django.core.validators.MinValueValidator(15),
django.core.validators.MaxValueValidator(480),
],
verbose_name="Длительность (минуты)",
),
),
(
"is_active",
models.BooleanField(default=True, verbose_name="Активен"),
),
(
"meeting_url",
models.URLField(
blank=True, max_length=500, verbose_name="Ссылка на встречу"
),
),
(
"color",
models.CharField(
default="#3B82F6",
help_text="HEX код цвета для отображения в календаре",
max_length=7,
verbose_name="Цвет",
),
),
(
"created_at",
models.DateTimeField(
auto_now_add=True, null=True, verbose_name="Дата создания"
),
),
(
"updated_at",
models.DateTimeField(auto_now=True, verbose_name="Дата обновления"),
),
(
"mentor",
models.ForeignKey(
limit_choices_to={"role": "mentor"},
on_delete=django.db.models.deletion.CASCADE,
related_name="lesson_templates",
to=settings.AUTH_USER_MODEL,
verbose_name="Ментор",
),
),
],
options={
"verbose_name": "Шаблон занятия",
"verbose_name_plural": "Шаблоны занятий",
"db_table": "lesson_templates",
"ordering": ["mentor", "title"],
},
),
migrations.CreateModel(
name="LessonFile",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"file",
models.FileField(
blank=True,
max_length=500,
null=True,
upload_to=apps.schedule.models.lesson_file_upload_path,
validators=[
django.core.validators.FileExtensionValidator(
allowed_extensions=[
"pdf",
"doc",
"docx",
"txt",
"jpg",
"jpeg",
"png",
"zip",
"rar",
]
)
],
verbose_name="Файл",
),
),
(
"source",
models.CharField(
choices=[
("uploaded", "Загружен при завершении"),
("material", "Из учебных материалов"),
],
default="uploaded",
max_length=20,
verbose_name="Источник",
),
),
(
"filename",
models.CharField(max_length=255, verbose_name="Название файла"),
),
(
"file_size",
models.BigIntegerField(
blank=True, null=True, verbose_name="Размер файла (bytes)"
),
),
("description", models.TextField(blank=True, verbose_name="Описание")),
(
"created_at",
models.DateTimeField(
auto_now_add=True, verbose_name="Дата создания"
),
),
(
"lesson",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="files",
to="schedule.lesson",
verbose_name="Урок",
),
),
(
"material",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="lesson_files",
to="materials.material",
verbose_name="Учебный материал",
),
),
(
"uploaded_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="uploaded_lesson_files",
to=settings.AUTH_USER_MODEL,
verbose_name="Загрузил",
),
),
],
options={
"verbose_name": "Файл урока",
"verbose_name_plural": "Файлы уроков",
"db_table": "lesson_files",
"ordering": ["-created_at"],
},
),
migrations.AddField(
model_name="lesson",
name="template",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="lessons",
to="schedule.lessontemplate",
verbose_name="Шаблон",
),
),
migrations.CreateModel(
name="Availability",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"day_of_week",
models.IntegerField(
blank=True,
choices=[
(0, "Понедельник"),
(1, "Вторник"),
(2, "Среда"),
(3, "Четверг"),
(4, "Пятница"),
(5, "Суббота"),
(6, "Воскресенье"),
],
help_text="Для еженедельного повторения",
null=True,
verbose_name="День недели",
),
),
(
"specific_date",
models.DateField(
blank=True,
help_text="Для разовой доступности",
null=True,
verbose_name="Конкретная дата",
),
),
("start_time", models.TimeField(verbose_name="Время начала")),
("end_time", models.TimeField(verbose_name="Время окончания")),
(
"is_recurring",
models.BooleanField(
default=True,
help_text="Повторяется ли еженедельно",
verbose_name="Повторяющаяся",
),
),
(
"is_active",
models.BooleanField(default=True, verbose_name="Активна"),
),
(
"exception_dates",
models.JSONField(
blank=True,
default=list,
help_text="Список дат в формате YYYY-MM-DD",
verbose_name="Даты исключений",
),
),
("notes", models.TextField(blank=True, verbose_name="Заметки")),
(
"created_at",
models.DateTimeField(
auto_now_add=True, verbose_name="Дата создания"
),
),
(
"updated_at",
models.DateTimeField(auto_now=True, verbose_name="Дата обновления"),
),
(
"mentor",
models.ForeignKey(
limit_choices_to={"role": "mentor"},
on_delete=django.db.models.deletion.CASCADE,
related_name="availabilities",
to=settings.AUTH_USER_MODEL,
verbose_name="Ментор",
),
),
],
options={
"verbose_name": "Доступность",
"verbose_name_plural": "Доступность",
"db_table": "availabilities",
"ordering": ["mentor", "day_of_week", "start_time"],
},
),
migrations.CreateModel(
name="TimeSlot",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"start_time",
models.DateTimeField(db_index=True, verbose_name="Время начала"),
),
(
"end_time",
models.DateTimeField(db_index=True, verbose_name="Время окончания"),
),
(
"is_available",
models.BooleanField(
default=True,
help_text="Свободен ли слот для бронирования",
verbose_name="Доступен",
),
),
(
"is_booked",
models.BooleanField(default=False, verbose_name="Забронирован"),
),
(
"is_recurring",
models.BooleanField(
default=False,
help_text="Повторяется ли этот слот еженедельно",
verbose_name="Повторяющийся",
),
),
(
"recurring_day",
models.IntegerField(
blank=True,
help_text="0=Понедельник, 6=Воскресенье",
null=True,
validators=[
django.core.validators.MinValueValidator(0),
django.core.validators.MaxValueValidator(6),
],
verbose_name="День недели",
),
),
(
"created_at",
models.DateTimeField(
auto_now_add=True, null=True, verbose_name="Дата создания"
),
),
(
"updated_at",
models.DateTimeField(auto_now=True, verbose_name="Дата обновления"),
),
(
"lesson",
models.OneToOneField(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="time_slot",
to="schedule.lesson",
verbose_name="Занятие",
),
),
(
"mentor",
models.ForeignKey(
limit_choices_to={"role": "mentor"},
on_delete=django.db.models.deletion.CASCADE,
related_name="time_slots",
to=settings.AUTH_USER_MODEL,
verbose_name="Ментор",
),
),
],
options={
"verbose_name": "Временной слот",
"verbose_name_plural": "Временные слоты",
"db_table": "time_slots",
"ordering": ["start_time"],
"indexes": [
models.Index(
fields=["mentor", "start_time"],
name="time_slots_mentor__87e9a7_idx",
),
models.Index(
fields=["is_available", "is_booked"],
name="time_slots_is_avai_b83db3_idx",
),
models.Index(
fields=["start_time", "end_time"],
name="time_slots_start_t_7c83d2_idx",
),
],
},
),
migrations.AddConstraint(
model_name="timeslot",
constraint=models.CheckConstraint(
check=models.Q(("end_time__gt", models.F("start_time"))),
name="timeslot_end_after_start",
),
),
migrations.AddIndex(
model_name="lessonfile",
index=models.Index(
fields=["lesson"], name="lesson_file_lesson__d6fb1a_idx"
),
),
migrations.AddIndex(
model_name="lessonfile",
index=models.Index(
fields=["material"], name="lesson_file_materia_35443f_idx"
),
),
migrations.AddIndex(
model_name="lesson",
index=models.Index(
fields=["mentor", "start_time"], name="lessons_mentor__e6e1ba_idx"
),
),
migrations.AddIndex(
model_name="lesson",
index=models.Index(
fields=["client", "start_time"], name="lessons_client__6fbdab_idx"
),
),
migrations.AddIndex(
model_name="lesson",
index=models.Index(
fields=["status", "start_time"], name="lessons_status_a82e95_idx"
),
),
migrations.AddIndex(
model_name="lesson",
index=models.Index(
fields=["start_time", "end_time"], name="lessons_start_t_f960c9_idx"
),
),
migrations.AddConstraint(
model_name="lesson",
constraint=models.CheckConstraint(
check=models.Q(("end_time__gt", models.F("start_time"))),
name="lesson_end_after_start",
),
),
migrations.AddIndex(
model_name="availability",
index=models.Index(
fields=["mentor", "is_active"], name="availabilit_mentor__4001a0_idx"
),
),
migrations.AddIndex(
model_name="availability",
index=models.Index(
fields=["day_of_week", "start_time"],
name="availabilit_day_of__7b54ec_idx",
),
),
migrations.AddIndex(
model_name="availability",
index=models.Index(
fields=["specific_date"], name="availabilit_specifi_49965a_idx"
),
),
migrations.AddConstraint(
model_name="availability",
constraint=models.CheckConstraint(
check=models.Q(("end_time__gt", models.F("start_time"))),
name="availability_end_after_start",
),
),
]