diff --git a/lmsege/lms/admin.py b/lmsege/lms/admin.py
index 8fbe1d6..923e4d5 100644
--- a/lmsege/lms/admin.py
+++ b/lmsege/lms/admin.py
@@ -133,6 +133,7 @@ class SubmissionAdmin(ModelAdmin):
earned = float(parts[0].strip())
total = float(parts[1].strip())
percentage = (earned / total) * 100 if total > 0 else 0
+ percentage_str = f"{percentage:.1f}"
is_passed = percentage >= 40
threshold_text = "Выше порога" if is_passed else "Ниже порога (Мин: 40%)"
@@ -156,11 +157,11 @@ class SubmissionAdmin(ModelAdmin):
- Выполнение: {percentage:.1f}%
+ Выполнение: {percentage_str}%
{threshold_text}
0 б
@@ -172,14 +173,18 @@ class SubmissionAdmin(ModelAdmin):
''',
grade=obj.grade,
- percentage=percentage,
+ percentage_str=percentage_str,
threshold_text=threshold_text,
color=color,
total_int=total_int,
threshold_points=threshold_points
)
- except Exception:
- return format_html('
Оценка имеет неверный формат. Используйте формат "X/Y" (например, "3/27").
')
+ except Exception as e:
+ return format_html(
+ '
Оценка имеет неверный формат. Ошибка: {error}
Значение: "{val}"
',
+ error=str(e),
+ val=obj.grade
+ )
def get_queryset(self, request):
qs = super().get_queryset(request)
diff --git a/lmsege/lms/migrations/0011_assignment_allow_late_submissions_and_more.py b/lmsege/lms/migrations/0011_assignment_allow_late_submissions_and_more.py
new file mode 100644
index 0000000..598fa82
--- /dev/null
+++ b/lmsege/lms/migrations/0011_assignment_allow_late_submissions_and_more.py
@@ -0,0 +1,70 @@
+# Generated by Django 5.1.1 on 2026-09-28 19:57
+
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('lms', '0010_question_table_rows_alter_question_correct_answer_and_more'),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='assignment',
+ name='allow_late_submissions',
+ field=models.BooleanField(default=True, help_text='Если включено, ученики смогут сдавать задание после дедлайна с пометкой "После дедлайна".', verbose_name='Разрешить дорешивание'),
+ ),
+ migrations.AddField(
+ model_name='assignment',
+ name='assign_to_all',
+ field=models.BooleanField(default=True, help_text='Если включено, задание будет доступно всем ученикам.', verbose_name='Назначить всем'),
+ ),
+ migrations.AddField(
+ model_name='assignment',
+ name='assigned_students',
+ field=models.ManyToManyField(blank=True, help_text='Выберите учеников, если задание не для всех.', limit_choices_to={'role': 'STUDENT'}, related_name='assigned_assignments', to=settings.AUTH_USER_MODEL, verbose_name='Назначенные ученики'),
+ ),
+ migrations.AddField(
+ model_name='assignment',
+ name='deadline',
+ field=models.DateTimeField(blank=True, help_text='После этого времени ответы не принимаются.', null=True, verbose_name='Дедлайн'),
+ ),
+ migrations.AddField(
+ model_name='assignment',
+ name='is_published',
+ field=models.BooleanField(default=True, help_text='Снимите галочку, чтобы скрыть задание (как черновик).', verbose_name='Опубликовано'),
+ ),
+ migrations.AddField(
+ model_name='assignment',
+ name='short_description',
+ field=models.TextField(blank=True, help_text='Отображается на главной странице в карточке задания. Если пусто, используется начало полного описания.', null=True, verbose_name='Краткое описание (для карточки)'),
+ ),
+ migrations.AddField(
+ model_name='assignment',
+ name='time_limit',
+ field=models.PositiveIntegerField(blank=True, help_text='Например, 235 для 3ч 55м. Оставьте пустым, если без таймера.', null=True, verbose_name='Лимит времени (минуты)'),
+ ),
+ migrations.AddField(
+ model_name='submission',
+ name='is_late',
+ field=models.BooleanField(default=False, verbose_name='Сдано после дедлайна'),
+ ),
+ migrations.AddField(
+ model_name='submission',
+ name='is_time_expired',
+ field=models.BooleanField(default=False, verbose_name='Время вышло'),
+ ),
+ migrations.AddField(
+ model_name='submission',
+ name='started_at',
+ field=models.DateTimeField(blank=True, null=True, verbose_name='Время начала'),
+ ),
+ migrations.AlterField(
+ model_name='submission',
+ name='status',
+ field=models.CharField(choices=[('IN_PROGRESS', 'В процессе выполнения'), ('PENDING', 'Ожидает проверки'), ('GRADED', 'Проверено')], default='PENDING', max_length=20, verbose_name='Статус'),
+ ),
+ ]