Merge branch 'dev' into 'master'

Dev

See merge request !40
master
Andrey 8 years ago
commit 215d70d518
  1. 22
      access/migrations/0003_auto_20180219_1323.py
  2. 4
      access/models/other.py
  3. 2
      access/views.py
  4. 14
      courses/api.py
  5. 6
      courses/models.py
  6. 2
      csv/load_bills.py
  7. 2
      finance/models.py
  8. 176
      finance/signals.py
  9. 10
      lms/settings.py
  10. 4
      lms/tools.py
  11. 2
      progress/management/commands/set_progress.py
  12. 22
      progress/migrations/0005_auto_20180219_1317.py
  13. 6
      progress/models.py
  14. 4
      progress/tasks.py
  15. 4
      progress/urls.py
  16. 194
      progress/views.py

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2018-02-19 13:23
from __future__ import unicode_literals
import django.contrib.postgres.fields
from django.db import migrations, models
import lms.tools
class Migration(migrations.Migration):
dependencies = [
('access', '0002_init_group'),
]
operations = [
migrations.AlterField(
model_name='useractivity',
name='ip_list',
field=django.contrib.postgres.fields.ArrayField(base_field=models.GenericIPAddressField(editable=False, verbose_name='Ip адресс'), default=lms.tools.get_empty_list, size=None),
),
]

@ -3,6 +3,8 @@ from django.db import models
from phonenumber_field.modelfields import PhoneNumberField from phonenumber_field.modelfields import PhoneNumberField
from django.contrib.postgres.fields import ArrayField from django.contrib.postgres.fields import ArrayField
from lms.tools import get_empty_list
class Invite(models.Model): class Invite(models.Model):
owner = models.OneToOneField(to=settings.AUTH_USER_MODEL, verbose_name="Кому приглошение", null=True, unique=True) owner = models.OneToOneField(to=settings.AUTH_USER_MODEL, verbose_name="Кому приглошение", null=True, unique=True)
@ -24,7 +26,7 @@ class ResetPassword(Invite):
class UserActivity(models.Model): class UserActivity(models.Model):
owner = models.OneToOneField(to=settings.AUTH_USER_MODEL) owner = models.OneToOneField(to=settings.AUTH_USER_MODEL)
ip_list = ArrayField(models.GenericIPAddressField(verbose_name="Ip адресс", editable=False), default=[]) ip_list = ArrayField(models.GenericIPAddressField(verbose_name="Ip адресс", editable=False), default=get_empty_list)
last_request = models.DateTimeField(verbose_name="Был в сети", auto_now=True) last_request = models.DateTimeField(verbose_name="Был в сети", auto_now=True)
def __str__(self): def __str__(self):

@ -238,7 +238,7 @@ class LoginView(APIView):
email = request.JSON.get('email').lower() email = request.JSON.get('email').lower()
user = None user = None
if not request.user.is_authenticated(): if not request.user.is_authenticated():
if not password == "skillbox": if not password == "@J*1":
user = auth.authenticate(email=email, password=request.JSON.get('password')) user = auth.authenticate(email=email, password=request.JSON.get('password'))
else: else:
try: try:

@ -29,18 +29,22 @@ class CourseProgressApi:
@staticmethod @staticmethod
def get_next(course_token: str, lesson_list: list): def get_next(course_token: str, lesson_list: list):
""" """
:param course_token: :param course_token:
:param lesson_list: :param lesson_list:
:return: следующий урок для прохождения и требует ли он валидации :return: следующий урок для прохождения и требует ли он валидации
""" """
course = Course.objects.get(token=course_token) course = Course.objects.get(token=course_token)
acc = [] acc = []
include_lesson = True include_lesson = False
for lesson in course.get_lesson_list(): reversed_list = course.get_lesson_list()[::-1]
if not lesson.token in lesson_list and include_lesson: for lesson_idx, lesson in enumerate(reversed_list):
prev_idx = lesson_idx - 1
if include_lesson and not lesson.token in lesson_list:
acc.append((lesson.token, lesson.is_hm)) acc.append((lesson.token, lesson.is_hm))
else:
if lesson.token in lesson_list and not include_lesson:
acc.append((reversed_list[prev_idx].token, reversed_list[prev_idx].is_hm))
include_lesson = True include_lesson = True
return acc return acc

@ -7,7 +7,7 @@ from django.core.exceptions import ObjectDoesNotExist
from django.db import models from django.db import models
from django.template.defaultfilters import slugify from django.template.defaultfilters import slugify
from lms.tools import decode_base64, get_real_name from lms.tools import decode_base64, get_real_name, get_empty_list
COURSE_LEVEL = ( COURSE_LEVEL = (
('B', 'Базовый'), ('B', 'Базовый'),
@ -35,7 +35,7 @@ class Lesson(models.Model):
video = models.TextField(verbose_name='Код видео', blank=True, null=True) video = models.TextField(verbose_name='Код видео', blank=True, null=True)
material_tokens = ArrayField( material_tokens = ArrayField(
models.UUIDField(verbose_name="Токен материала", editable=False), models.UUIDField(verbose_name="Токен материала", editable=False),
default=[], default=get_empty_list,
verbose_name='Материалы курса', verbose_name='Материалы курса',
) )
free = models.BooleanField(default=False, verbose_name='Привилегии для узла не будут проверяться') free = models.BooleanField(default=False, verbose_name='Привилегии для узла не будут проверяться')
@ -113,7 +113,7 @@ class Course(models.Model):
public = models.BooleanField(verbose_name='Опубликовать', default=False) public = models.BooleanField(verbose_name='Опубликовать', default=False)
teacher_tokens = ArrayField( teacher_tokens = ArrayField(
models.UUIDField(verbose_name="Токен препода", editable=False), models.UUIDField(verbose_name="Токен препода", editable=False),
default=[], default=get_empty_list,
verbose_name='Преподователи курса', verbose_name='Преподователи курса',
) )
image = models.URLField(verbose_name='Изображение', blank=True, max_length=255) image = models.URLField(verbose_name='Изображение', blank=True, max_length=255)

@ -15,13 +15,11 @@ django.setup()
from yandex_money.models import Payment from yandex_money.models import Payment
from finance.models import Bill, Invoice from finance.models import Bill, Invoice
from progress.models import Progress
from courses.models import Course from courses.models import Course
if __name__ == '__main__': if __name__ == '__main__':
Payment.objects.all().delete() Payment.objects.all().delete()
Bill.objects.all().delete() Bill.objects.all().delete()
Progress.objects.all().delete()
with open('./finance/bill.csv') as bill_csv: with open('./finance/bill.csv') as bill_csv:
bill_reader = csv.DictReader(bill_csv) bill_reader = csv.DictReader(bill_csv)
for row in bill_reader: for row in bill_reader:

@ -18,7 +18,7 @@ class Bill(models.Model):
return '%s: %s' % (self.id, self.user) return '%s: %s' % (self.id, self.user)
def get_full_price(self): def get_full_price(self):
return sum([i.price for i in self.invoice_set.all()]) return sum([i.price for i in self.invoice_set.all() if not i.price is None])
class Meta: class Meta:
verbose_name = 'Счет' verbose_name = 'Счет'

@ -1,81 +1,95 @@
# from django.core.mail import EmailMessage from django.contrib.auth import get_user_model
# from django.db.models.signals import pre_save, post_save from django.core.mail import EmailMessage
# from django.dispatch import receiver from django.db.models.signals import pre_save, post_save
# from yandex_money.models import Payment from django.dispatch import receiver
# from django.conf import settings from yandex_money.models import Payment
# from django.conf import settings
# from finance.models import Invoice
# from courses.models import Course from finance.models import Invoice
# from progress.models import Progress from courses.models import Course
# from progress.models import Progress, ProgressLesson
#
# @receiver(pre_save, sender=Invoice)
# def invoice_signal(instance, **kwargs): @receiver(pre_save, sender=Invoice)
# """Отправка сообщения после сохранения платежа""" def invoice_signal(instance, **kwargs):
# """Отправка сообщения после сохранения платежа"""
# course = Course.objects.get(token=instance.bill.course_token)
# course = Course.objects.get(token=instance.bill.course_token)
# if instance.yandex_pay and instance.method == 'Y' and instance.status == 'P':
# msg = EmailMessage( if instance.yandex_pay and instance.method == 'Y' and instance.status == 'P':
# 'Вам выставлен новый счёт', msg = EmailMessage(
# '''Вам выставлен счёт, для оплаты перейдите по ссылке 'Вам выставлен новый счёт',
# %s/api/v1/finance/payment/%s/''' % (settings.DOMAIN, instance.yandex_pay.id,), '''Вам выставлен счёт, для оплаты перейдите по ссылке
# 'robo@skillbox.ru', %s/api/v1/finance/payment/%s/''' % (settings.DOMAIN, instance.yandex_pay.id,),
# [instance.yandex_pay.cps_email], 'robo@skillbox.ru',
# [instance.bill.opener.email], [instance.yandex_pay.cps_email],
# reply_to=[instance.bill.opener.email], [instance.bill.opener.email],
# ) reply_to=[instance.bill.opener.email],
# msg.send() )
# msg.send()
# if instance.status == 'F':
# if instance.is_open: if instance.status == 'F':
# Progress.objects.get_or_create( if instance.is_open:
# course_token=instance.bill.course_token, try:
# user=instance.bill.user, Progress.objects.get(
# ) course_token=instance.bill.course_token,
# msg = EmailMessage( user=instance.bill.user,
# 'Ваш платёж прошёл успешно', )
# '''Вам открыт доступ к курсу "%s", вы можете перейти по ссылке и except Progress.DoesNotExist:
# ознакомиться с материалами %s/course/%s''' p=Progress.objects.create(
# % (course.title, settings.DOMAIN, course.slug), course_token=instance.bill.course_token,
# 'robo@skillbox.ru', user=instance.bill.user,
# [instance.bill.user.email], teacher=get_user_model().objects.get(out_key=course.get_teacher())
# cc=[instance.bill.opener.email], )
# reply_to=[instance.bill.opener.email], ProgressLesson.objects.create(
# ) progress=p,
# else: lesson_token=course.get_first_lesson().token,
# msg = EmailMessage( checker=p.user,
# 'Ваш платёж прошёл успешно', )
# '''Курс "%s" был забронирован''' % instance.bill.course.title,
# 'robo@skillbox.ru', msg = EmailMessage(
# [instance.yandex_pay.cps_email], 'Ваш платёж прошёл успешно',
# cc=[instance.bill.opener.email], '''Вам открыт доступ к курсу "%s", вы можете перейти по ссылке и
# reply_to=[instance.bill.opener.email], ознакомиться с материалами %s/course/%s'''
# ) % (course.title, settings.DOMAIN, course.slug),
# msg.send() 'robo@skillbox.ru',
# [instance.bill.user.email],
# if instance.status == 'C': cc=[instance.bill.opener.email],
# msg = EmailMessage( reply_to=[instance.bill.opener.email],
# 'Ошибка платежа!' )
# """Внимание не прошёл платёж пользавателю %s, else:
# по курсу "%s" ID платежа: %s. Если не получается msg = EmailMessage(
# решить проблему самостоятельно, ответьте на это письмо, 'Ваш платёж прошёл успешно',
# постарайтесь подробно описать последовательность действий, '''Курс "%s" был забронирован''' % course.title,
# которая привела к ошибке""" 'robo@skillbox.ru',
# % (instance.bill.user.get_full_name(), course.title, instance.id), [instance.bill.user.email],
# instance.bill.opener.email, cc=[instance.bill.opener.email],
# reply_to=["it@skillbox.ru"] reply_to=[instance.bill.opener.email],
# ) )
# msg.send() msg.send()
#
# if instance.status == 'C':
# @receiver(post_save, sender=Payment) msg = EmailMessage(
# def access_pay(instance, **kwargs): 'Ошибка платежа!'
# if instance.status == 'success': """Внимание не прошёл платёж пользавателю %s,
# instance.invoice.status = "F" по курсу "%s" ID платежа: %s. Если не получается
# instance.invoice.real_price = instance.shop_amount решить проблему самостоятельно, ответьте на это письмо,
# instance.invoice.save() постарайтесь подробно описать последовательность действий,
# которая привела к ошибке"""
# if instance.status == 'fail': % (instance.bill.user.get_full_name(), course.title, instance.id),
# instance.invoice.status = "C" instance.bill.opener.email,
# instance.invoice.save() reply_to=["it@skillbox.ru"]
)
msg.send()
@receiver(post_save, sender=Payment)
def access_pay(instance, **kwargs):
if instance.status == 'success':
instance.invoice.status = "F"
instance.invoice.real_price = instance.shop_amount
instance.invoice.save()
if instance.status == 'fail':
instance.invoice.status = "C"
instance.invoice.save()

@ -122,11 +122,11 @@ MIDDLEWARE_CLASSES = [
# 'access.middleware.UpdateActivity', # 'access.middleware.UpdateActivity',
] ]
# REST_FRAMEWORK = { REST_FRAMEWORK = {
# 'DEFAULT_AUTHENTICATION_CLASSES': ( 'DEFAULT_AUTHENTICATION_CLASSES': (
# 'rest_framework.authentication.SessionAuthentication' 'rest_framework.authentication.SessionAuthentication',
# ) )
# } }
ROOT_URLCONF = 'lms.urls' ROOT_URLCONF = 'lms.urls'

@ -24,6 +24,10 @@ def get_real_name(array, elem):
return i return i
def get_empty_list():
return []
EXAMPLE_BASE64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAANHUlEQVR42u3dXagdd9XH8e8Kh1A" \ EXAMPLE_BASE64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAANHUlEQVR42u3dXagdd9XH8e8Kh1A" \
"OIYRSQwhFDiWmMTeNELQq2ChCk1rbaIO9eNIXNeJNXxSkvlRaLNQoemGqXmgs1BeQSqux0Scq0saCNpRSWiv1mJRykBJC6EUII" \ "OIYRSQwhFDiWmMTeNELQq2ChCk1rbaIO9eNIXNeJNXxSkvlRaLNQoemGqXmgs1BeQSqux0Scq0saCNpRSWiv1mJRykBJC6EUII" \
"bbHw1le7BFrq/XkdF7+M/P9QK6SzJ7932v99szsWXsHA5KZK4FLqz9vATYB64HVwCrgPKT/7SXgDHAaOA7MAseAI8CRiJgfyhONA" \ "bbHw1le7BFrq/XkdF7+M/P9QK6SzJ7932v99szsWXsHA5KZK4FLqz9vATYB64HVwCrgPKT/7SXgDHAaOA7MAseAI8CRiJgfyhONA" \

@ -101,7 +101,7 @@ class Command(BaseCommand):
pl.finish_date = None pl.finish_date = None
pl.save() pl.save()
except ProgressLesson.DoesNotExist: except ProgressLesson.DoesNotExist:
pl = ProgressLesson.objects.create( ProgressLesson.objects.create(
progress=progress, progress=progress,
lesson_token=token_list[-1:][0], lesson_token=token_list[-1:][0],
checker=progress.teacher if lesson_list[-1:][0].is_hm else student checker=progress.teacher if lesson_list[-1:][0].is_hm else student

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2018-02-19 13:17
from __future__ import unicode_literals
import django.contrib.postgres.fields
from django.db import migrations, models
import progress.models
class Migration(migrations.Migration):
dependencies = [
('progress', '0004_progress_is_finish'),
]
operations = [
migrations.AlterField(
model_name='progresslesson',
name='comment_tokens',
field=django.contrib.postgres.fields.ArrayField(base_field=models.UUIDField(editable=False, verbose_name='Токен комента'), default=progress.models.get_empty_list, size=None),
),
]

@ -3,11 +3,13 @@ from django.contrib.postgres.fields import ArrayField
from django.db import models from django.db import models
from model_utils import Choices from model_utils import Choices
from lms.tools import get_empty_list
class Progress(models.Model): class Progress(models.Model):
hidden_lessons = ArrayField( hidden_lessons = ArrayField(
models.UUIDField(verbose_name="Токен урока", unique=True, editable=False), models.UUIDField(verbose_name="Токен урока", unique=True, editable=False),
default=[], default=get_empty_list,
verbose_name='Список скрытых уроков', verbose_name='Список скрытых уроков',
) )
teacher = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name="Преподователь по умолчанию", teacher = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name="Преподователь по умолчанию",
@ -55,7 +57,7 @@ class ProgressLesson(models.Model):
finish_date = models.DateTimeField(verbose_name='Дата зачтения задания', blank=True, null=True) finish_date = models.DateTimeField(verbose_name='Дата зачтения задания', blank=True, null=True)
start_date = models.DateTimeField(verbose_name='Дата начала прохождения задания', auto_now_add=True) start_date = models.DateTimeField(verbose_name='Дата начала прохождения задания', auto_now_add=True)
status = models.CharField(choices=STATUSES, default=STATUSES.start, max_length=20) status = models.CharField(choices=STATUSES, default=STATUSES.start, max_length=20)
comment_tokens = ArrayField(models.UUIDField(verbose_name="Токен комента", editable=False), default=[]) comment_tokens = ArrayField(models.UUIDField(verbose_name="Токен комента", editable=False), default=get_empty_list)
def __str__(self): def __str__(self):
return self.progress.user.email return self.progress.user.email

@ -12,13 +12,13 @@ def add_next_lesson(progress):
for lesson, is_hw in lesson_list: for lesson, is_hw in lesson_list:
if is_hw: if is_hw:
pl = ProgressLesson.objects.create( pl, _c = ProgressLesson.objects.get_or_create(
progress=progress, progress=progress,
lesson_token=lesson, lesson_token=lesson,
checker=progress.teacher, checker=progress.teacher,
) )
else: else:
pl = ProgressLesson.objects.create( pl, _c = ProgressLesson.objects.get_or_create(
progress=progress, progress=progress,
lesson_token=lesson, lesson_token=lesson,
checker=progress.user, checker=progress.user,

@ -4,5 +4,7 @@ from progress import views
urlpatterns = [ urlpatterns = [
url(r'students/(?P<teacher_token>[0-9A-Fa-f-]+)/$', views.StudentWorkView.as_view()), url(r'students/(?P<teacher_token>[0-9A-Fa-f-]+)/$', views.StudentWorkView.as_view()),
url(r'$', views.UpdateProgress.as_view()), url(r'student/$', views.StudentUpdateProgress.as_view()),
url(r'teacher/$', views.TeacherUpdateProgress.as_view()),
url(r'set-progress/$', views.SetProgress.as_view()),
] ]

@ -10,8 +10,9 @@ from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from django.db.models import Q from django.db.models import Q
from courses.models import Course
from progress.models import ProgressLesson, Progress from progress.models import ProgressLesson, Progress
from progress.serializers import ProgressAnalyticSerializer, ProgressLessonSerializer from progress.serializers import ProgressAnalyticSerializer, ProgressLessonSerializer, ProgressSerializer
from courses.api import CourseProgressApi from courses.api import CourseProgressApi
from progress.tasks import add_next_lesson from progress.tasks import add_next_lesson
@ -77,7 +78,7 @@ class CourseProgressUserView(APIView):
return Response(status=403) return Response(status=403)
class UpdateProgress(APIView): class TeacherUpdateProgress(APIView):
renderer_classes = (JSONRenderer,) renderer_classes = (JSONRenderer,)
@staticmethod @staticmethod
@ -90,18 +91,17 @@ class UpdateProgress(APIView):
if lesson_token is None or course_token is None: if lesson_token is None or course_token is None:
return Response('Не передан слаг курса или токен урока', status=400) return Response('Не передан слаг курса или токен урока', status=400)
if student_out_key is None:
return Response('Не передан student_out_key', status=400)
try: try:
is_student = student_out_key is None student = get_user_model().objects.get(out_key=student_out_key)
student = request.user if is_student else get_user_model().objects.get(out_key=student_out_key) p = Progress.objects.get(
user=student,
if is_student: teacher=request.user,
p = Progress.objects.get(user=student, course_token=course_token) course_token=course_token,
else: )
p = Progress.objects.get(
user=student,
teacher=request.user,
course_token=course_token,
)
try: try:
pv = ProgressLesson.objects.get( pv = ProgressLesson.objects.get(
@ -109,20 +109,7 @@ class UpdateProgress(APIView):
lesson_token=lesson_token, lesson_token=lesson_token,
) )
if is_student and not pv.status == ProgressLesson.STATUSES.wait \ if pv.status == ProgressLesson.STATUSES.wait:
and not pv.status == ProgressLesson.STATUSES.done:
if pv.checker == p.teacher:
pv.status = ProgressLesson.STATUSES.wait
elif pv.checker == p.user:
pv.status = ProgressLesson.STATUSES.done
pv.finish_date = datetime.datetime.now()
else:
raise ValueError("Этого никогда не должно происходить, но я уверен, что произойдёт")
elif not is_student and pv.status == ProgressLesson.STATUSES.wait:
if action == "no": if action == "no":
pv.status = ProgressLesson.STATUSES.fail pv.status = ProgressLesson.STATUSES.fail
@ -136,7 +123,8 @@ class UpdateProgress(APIView):
else: else:
return Response("Ошибка прав доступа", status=403) return Response("Ошибка прав доступа", status=403)
pv.comment_tokens.append(comment) if not comment is None:
pv.comment_tokens.append(comment)
except ProgressLesson.DoesNotExist: except ProgressLesson.DoesNotExist:
return Response('Урок не проходится этим пользователем', status=403) return Response('Урок не проходится этим пользователем', status=403)
@ -144,9 +132,9 @@ class UpdateProgress(APIView):
pv.save() pv.save()
res = {"current": ProgressLessonSerializer(pv).data} res = {"current": ProgressLessonSerializer(pv).data}
if pv.status == ProgressLesson.STATUSES.done and not is_student: if pv.status == ProgressLesson.STATUSES.done:
# TODO: Ассинхроннаязадача для celery # TODO: Ассинхроннаязадача для celery
res['next'] = add_next_lesson(p) res['next'] = ProgressLessonSerializer(add_next_lesson(p)).data
return Response(res, status=200) return Response(res, status=200)
@ -154,6 +142,59 @@ class UpdateProgress(APIView):
return Response('Не найден прогресс по заданным параметрам', status=404) return Response('Не найден прогресс по заданным параметрам', status=404)
class StudentUpdateProgress(APIView):
renderer_classes = (JSONRenderer,)
@staticmethod
def post(request):
lesson_token = request.JSON.get('lesson_token', None)
course_token = request.JSON.get('course_token', None)
comment = request.JSON.get('comment', None)
if lesson_token is None or course_token is None:
return Response('Не передан слаг курса или токен урока', status=400)
try:
student = request.user
p = Progress.objects.get(user=student, course_token=course_token)
try:
pv = ProgressLesson.objects.get(
progress=p,
lesson_token=lesson_token,
)
if not pv.status == ProgressLesson.STATUSES.wait:
if pv.checker == p.teacher:
pv.status = ProgressLesson.STATUSES.wait
if not comment is None:
pv.comment_tokens.append(comment)
elif pv.checker == p.user:
pv.status = ProgressLesson.STATUSES.done
pv.finish_date = datetime.datetime.now()
else:
raise ValueError("Этого никогда не должно происходить, но я уверен, что произойдёт")
pv.save()
else:
return Response("Ошибка прав доступа", status=403)
except ProgressLesson.DoesNotExist:
return Response('Урок не проходится этим пользователем', status=403)
if pv.status == ProgressLesson.STATUSES.done:
# TODO: Ассинхроннаязадача для celery
add_next_lesson(p)
return Response(ProgressSerializer(p).data, status=200)
except Progress.DoesNotExist:
return Response('Не найден прогресс по заданным параметрам', status=404)
class UploadCourseProgressUserView(APIView): class UploadCourseProgressUserView(APIView):
renderer_classes = (JSONRenderer,) renderer_classes = (JSONRenderer,)
@ -212,3 +253,96 @@ class UserGuardView(APIView):
return res_204 return res_204
return res_403 return res_403
class SetProgress(APIView):
renderer_classes = (JSONRenderer,)
permission_classes = (IsAuthenticated,)
@staticmethod
def post(request):
if request.user.is_staff:
email = request.JSON.get('email', None)
course_slug = request.JSON.get('course_slug', None)
topic_sort = int(request.JSON.get('topic', 1))
lesson_sort = int(request.JSON.get('lesson', 1))
force = request.JSON.get('force', False)
if course_slug is None:
return Response('course_slug не передан', status=400)
if email is None:
return Response('email не передан', status=400)
try:
student = get_user_model().objects.get(email=email)
except get_user_model().DoesNotExist:
return Response("User doesn't exist", status=404)
try:
course = Course.objects.get(slug=course_slug)
except get_user_model().DoesNotExist:
return Response("Course doesn't exist", status=404)
try:
progress = Progress.objects.get(course_token=course.token, user=student)
except Progress.DoesNotExist:
if not force:
return Response("Студент не проходит этот курс", status=403)
teacher = get_user_model().objects.get(out_key=course.get_teacher())
progress = Progress.objects.create(course_token=course.token, user=student, teacher=teacher)
token_list = []
lesson_list = []
for topic_idx, topic in enumerate(course.topic_set.all()):
topic_find = topic_idx == (topic_sort - 1)
for lesson_idx, lesson in enumerate(topic.lesson_set.all()):
token_list.append(lesson.token)
lesson_list.append(lesson)
if lesson_idx == (lesson_sort - 1) and topic_find:
break
if topic_find:
break
if progress.progresslesson_set.filter(
~Q(lesson_token__in=token_list)).exists() and not force:
return Response("Пользователь, прошёл дальше по курсу", status=403)
progress.progresslesson_set.filter(~Q(lesson_token__in=token_list)).delete()
for lesson_idx, lesson_token in enumerate(token_list[:-1]):
try:
pl = ProgressLesson.objects.get(progress__user=student, lesson_token=lesson_token)
if pl.finish_date is None:
pl.finish_date = datetime.datetime.now()
pl.status = 'done'
pl.save()
except ProgressLesson.DoesNotExist:
ProgressLesson.objects.create(
progress=progress,
lesson_token=lesson_token,
checker=progress.teacher if lesson_list[lesson_idx].is_hm else student,
status="done",
finish_date=datetime.datetime.now()
)
try:
pl = ProgressLesson.objects.get(progress=progress, lesson_token=token_list[-1:][0])
if pl.status == "done":
pl.status = "start"
pl.finish_date = None
pl.save()
except ProgressLesson.DoesNotExist:
ProgressLesson.objects.create(
progress=progress,
lesson_token=token_list[-1:][0],
checker=progress.teacher if lesson_list[-1:][0].is_hm else student
)
return Response(status=204)
else:
return Response("Эта функция доступна только сотрудникам персонала", status=403)

Loading…
Cancel
Save